@ansonlai/docx-redline-js 0.7.2 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/AGENTS.md +15 -10
  2. package/ARCHITECTURE.md +30 -10
  3. package/CHANGELOG.md +539 -431
  4. package/README.md +331 -309
  5. package/adapters/xml-adapter.js +84 -56
  6. package/core/sha256.js +120 -0
  7. package/dist/docx-redline-js.esm.js +8982 -693
  8. package/dist/docx-redline-js.esm.js.map +4 -4
  9. package/dist/docx-redline-js.esm.min.js +102 -89
  10. package/dist/docx-redline-js.esm.min.js.map +4 -4
  11. package/dist/docx-redline.bundle.cjs +28305 -0
  12. package/dist/docx-redline.bundle.cjs.map +7 -0
  13. package/dist/docx-redline.bundle.js +28296 -0
  14. package/dist/docx-redline.bundle.js.map +7 -0
  15. package/docs/AGENT_FAST_START.md +2 -1
  16. package/docs/AGENT_KNOWLEDGE_BASE.md +480 -393
  17. package/docs/SKILL_AUTHORING.md +5 -2
  18. package/docs/TESTING.md +2 -1
  19. package/docs/schemas/document-operations.schema.json +29 -0
  20. package/document/docx-document.d.ts +39 -0
  21. package/document/docx-document.js +1010 -0
  22. package/document/zip-archive.js +258 -0
  23. package/engine/reconstruction-writer.js +18 -0
  24. package/index.d.ts +598 -531
  25. package/index.js +349 -340
  26. package/node/cli-help.js +5 -5
  27. package/node/cli.js +760 -754
  28. package/node/docx-document.js +11 -355
  29. package/node/index.d.ts +1 -1
  30. package/node/zip-archive.js +28 -38
  31. package/package.json +14 -11
  32. package/scripts/build.mjs +40 -5
  33. package/scripts/generate-word-comment-edge-case-fixture.ps1 +58 -0
  34. package/scripts/generate-word-comment-thread-fixture.ps1 +36 -0
  35. package/scripts/generate-word-header-footer-fixture.ps1 +32 -0
  36. package/scripts/generate-word-multi-section-fixture.ps1 +27 -0
  37. package/scripts/generate-word-package-integrity-cases.mjs +141 -0
  38. package/scripts/generate-word-thread-state-fixtures.ps1 +50 -0
  39. package/scripts/word-com-package-integrity.ps1 +98 -0
  40. package/services/batch-operation-orchestrator.js +262 -259
  41. package/services/comment-replies.js +96 -95
  42. package/services/comment-thread-parts.js +280 -0
  43. package/services/document-inspection.js +366 -365
  44. package/services/document-operation-applier.js +230 -202
  45. package/services/document-operation-contract.js +17 -2
  46. package/services/error-recovery.js +6 -0
  47. package/services/headers-footers.js +206 -0
  48. package/services/operation-batch-compiler.js +1 -0
  49. package/services/operation-preflight.js +231 -218
  50. package/services/package-parts.js +80 -0
  51. package/services/revision-token.js +11 -7
  52. package/services/standalone-docx-plumbing.js +631 -569
  53. package/services/standalone-operation-runner.d.ts +19 -3
package/CHANGELOG.md CHANGED
@@ -1,431 +1,539 @@
1
- # Changelog
2
-
3
- ## Unreleased
4
-
5
- - Localized replacement matching now tries exact case-sensitive text first,
6
- then a narrow ASCII-space/non-breaking-space equivalent match. Ambiguous
7
- equivalent matches still fail closed, and unchanged boundary NBSPs are
8
- retained to avoid incidental whitespace redlines.
9
-
10
- - Added a narrow single-paragraph restore shortcut. A restore with a strong
11
- rejected-view target may omit `modified` for verbatim restoration or provide
12
- exact `replacements`; the CLI exposes the same path through `apply --restore
13
- --target-id ID`. Ranges, captures, weak targets, and inferred companion
14
- content remain excluded.
15
-
16
- - Fixed rejected-view restore receipts so `resolvedTarget` text, fingerprint,
17
- revision view, and match diagnostics describe the view actually used to
18
- resolve the target.
19
- - Fixed alternate-view search hints to honor `--revised`, `--table`, and
20
- `--body`, and retained compact revision authors plus `deleted`/`inserted` cues
21
- in `extract` output so empty revision-view paragraphs are self-explanatory.
22
-
23
- ## 0.7.0
24
-
25
- ### Agent Performance and Localized Editing
26
-
27
- - **Localized exact replacements:** `redline`/`replace` operations may provide
28
- `replacements: [{ find, replace, occurrence? }]` instead of a complete
29
- `modified` paragraph. The compiler resolves the accepted-view source once,
30
- applies non-overlapping exact replacements simultaneously, synthesizes the
31
- canonical desired paragraph, and delegates to the unchanged OOXML engine.
32
- - **One-turn speculative apply:** `docx-redline apply --find ... --replace ...`
33
- can resolve a globally unique source literal without preliminary extraction.
34
- `--search` plus signed `--context-range START:END` scopes visible headings and
35
- nearby content; `--around N` is symmetric shorthand. Longer, distinctive
36
- anchors are recommended because generic or repeated phrases widen the unioned
37
- scope and may cost an ambiguity-recovery turn.
38
- - **Fail-closed selection:** Missing anchors and patch sources, multiple eligible
39
- paragraphs, ambiguous occurrences, overlaps, conflicts, and unsupported
40
- localized shapes refuse mutation. A failed speculative command never writes
41
- or truncates its output path.
42
- - **Verified change evidence:** Localized operation results include a compact
43
- `change` object with target location, contextual anchor/range, exact
44
- replacement entries, bounded before/after excerpts, commit disposition, and
45
- post-mutation accepted-view verification. Atomic rollback marks the evidence
46
- non-committed and `rolled_back`.
47
- - **CLI contract version 8:** Adds `localized-replacements-v1`,
48
- `speculative-search-apply-v1`, and `localized-change-summary-v1`. Skills and
49
- harnesses should pin version 0.7.0 and negotiate only the capabilities used.
50
- - **Measured workflow reduction:** The checked benchmark records 50% fewer tool
51
- turns and a 64.77%–78.98% smaller deterministic request-token proxy across
52
- three literal-edit cases. Median native engine/I/O time remained effectively
53
- neutral; provider reasoning and network latency were not estimated.
54
-
55
- ### Compatibility
56
-
57
- - Existing `modified` operations, strong targets, operations files/stdin,
58
- tracked-change generation, package validation, rollback, comments,
59
- Accept/Reject, and revision policies remain supported.
60
- - Localized replacement fields and successful `change` evidence are additive.
61
- Wrappers that adopt them must require CLI contract 8; integrations using only
62
- earlier capabilities can continue using their existing operation shapes.
63
- - The implementation remains OOXML-only and adds no runtime dependency or Word,
64
- Office automation, COM, or proprietary document API requirement.
65
-
66
- ## 0.6.0–0.6.2
67
-
68
- ### Safety Fixes
69
-
70
- - **Foreign deleted-paragraph resurrection guard**: Refuses non-empty same-paragraph edits when another author owns the paragraph-mark deletion and all existing paragraph content is deleted. The operation now returns `FOREIGN_PARAGRAPH_MARK_DELETION` with the owning author instead of emitting lifecycle-unsafe OOXML; atomic document operations roll back byte-for-byte. `validateRedlineOoxml` reports already-authored instances as warnings.
71
- - **Source-truth whitespace replacement alignment (WP09a)**: Strict target resolution may equate ordinary spaces with NBSPs, but mutation offsets now always come from the resolved paragraph's exact accepted view. Space-equivalent word replacement hunks are refined to character-local edits, and multiple plain-text edits are applied right-to-left against refreshed live spans. This tracks NBSP-to-space substitutions exactly while preserving unchanged hyperlinks and prevents earlier run splits from invalidating later anchors.
72
- - **Exact mismatch diagnostics**: `PATCH_ROUNDTRIP_MISMATCH` now includes the expected and actual code points at the first mismatch. Document-operation results also report bounded `targetTextMatch` diagnostics when target selection used equivalent whitespace.
73
- - **Baseline-delta validation (WP09c)**: Restoration, operation, and package validation now compare issue multisets against the source. Unchanged legacy defects remain visible without blocking safe work, while any added occurrence or mutation-envelope error fails closed with `GENERATED_OOXML_INVALID` before an operation is reported as applied.
74
- - **Revision identity sanitation (WP09d)**: New paragraph/list builders inherit effective `pPr`/`rPr` formatting without cloning historical revision descendants. Operation-level whole-document validation catches duplicate revision IDs and rolls back the operation savepoint before committing its receipt.
75
- - **View-consistent restore targeting**: `restore` targets now default to the rejected view, where a wholly deleted paragraph's source text exists. Rejected-view inspection now computes fingerprints from rejected-view text and reports the view beside each paragraph. Explicit cross-view text or fingerprint mistakes retain strict refusal while returning an actionable view hint.
76
-
77
- ### New Features
78
-
79
- - **Self-describing and bounded agent discovery (WP-00–WP-02)**: CLI contract version 6 adds command-specific JSON help, canonical redline/comment/restore examples, case-insensitive contextual search with `--around`/`--context`/`-C`, direct-hit pagination through `--limit` and `--after`, and deliberate `--all` opt-out. Unscoped inspection is capped at 20 direct records and a 48 KiB soft budget without truncating any returned `exactText`; extraction now distinguishes matches from context and prioritizes human-facing provision/heading references over machine paragraph ordinals.
80
- - **Composable agent safety and compact output (WP-03–WP-04)**: CLI contract version 7 replaces the atomic-coupled agent profile capability with `agent-safety-profile-v2`. `--profile agent` now enforces complete-success exits while preserving progressive execution and the ordinary revision policy; `--atomic` and `--existing-revisions` compose explicitly. Compact CLI JSON keeps receipts only in the authoritative top-level array, omits exact-match diagnostics, summarizes successful equivalent-whitespace matches, and supports one-line `--compact` output without changing Node or standalone-runner results.
81
- - **Packaged skill-authoring contract (WP-05)**: `docs/SKILL_AUTHORING.md` separates automation invariants from transaction/revision policy, file-versus-stdin transport, reviewer preferences, recovery-envelope behavior, and human-facing presentation. It requires contract/capability negotiation, focused contextual extraction, and library delegation while retaining the visible `AI Redliner` fallback without a new author guard.
82
- - **Batch-start source binding (WP-04)**: Strong document-operation targets are compiled once against the immutable source DOM and carried through structural index/fingerprint drift with rollback-aware session identities. Independent edits no longer need manual bottom-up sorting; same-source writes, incompatible revision/format combinations, and unsafe capture fan-out fail before mutation with causal conflict codes. Unique references to paragraph text created elsewhere in the same batch become explicit internal capture dependencies.
83
- - **Machine-actionable recovery (WP-05)**: Operation, package-facade, example-session, and compact CLI failures now carry recovery envelope version 1 with stable stage/category/action metadata, bounded corrective context, and authorization flags. Failed and partial mutation results include an explicit original-vs-output retry plan and operation indexes. `apply --require-complete` exits with code 3 for partial work while preserving legacy behavior without the flag.
84
- - **Compact shell-agent protocol (WP-06)**: CLI contract version 5 adds `operations-stdin` and `agent-profile-v1`. `--operations -` accepts UTF-8 operation arrays/envelopes without a temporary operations file, while explicit `--profile agent` combines atomic rollback and complete-success exit behavior and reports its effective settings. `AGENTS.md` is now a 527-word routing card, and the 349-word `docs/AGENT_FAST_START.md` carries the ordinary edit contract. Ambient project configuration was deliberately deferred because it would save only the profile flag while adding hidden state.
85
- - **Agent rollout audit (WP-07)**: The observational benchmark now compares canonical Node, legacy file-based CLI, compact stdin/profile CLI, and the development session example while verifying accepted/rejected text, comment preservation, independent batch permutations, recovery behavior, and cross-author attribution. The checked run records 82.75% fewer ordinary instruction words, one fewer shell tool turn (33.33%), and 82.22–89.96% smaller localized session requests than canonical Node envelopes without claiming unmeasured provider/model latency.
86
- - **Explicit paragraph restoration (`type: 'restore'`)**: Restores or counterproposes another reviewer's pending whole-paragraph deletion as a separately tracked sibling paragraph. The source deletion remains untouched; the restored paragraph receives its own inserted paragraph mark, content insertion, sanitized paragraph properties, and fresh `w14:paraId`. Single paragraphs and contiguous ranges are supported, with full Accept/Reject lifecycle verification and structured refusals at unsafe table-row, move, section-break, and terminal-paragraph boundaries.
87
- - **Compact mutation CLI contract (WP09b)**: CLI contract version 3 removes `documentXml`, OOXML/package artifacts, full inspection data, and full validation issue arrays from normal `apply`, `accept`, `reject`, and `delete-comments` stdout. Mutation responses retain actionable errors, per-operation receipts, output durability fields, code/count validation summaries, and a derived `completion` flag that cannot report success for failed, partial, or unwritten work.
88
- - **Word-native deleted-section editing (WP09e)**: An explicit rejected-view `insert` operation can split a foreign deletion at an exact anchor-relative offset into sibling `del(A) / ins(B) / del(A)` carriers. Contiguous paragraph restorations now follow their untouched deleted source block, matching Microsoft Word's ordering. Ambiguous anchors and unsupported structural split boundaries remain fail-closed.
89
-
90
- ## 0.5.1
91
-
92
- ### Highlights & New Features
93
-
94
- - **Cross-Author Revision Slicing (`existingRevisions: 'slice-cross-author'`)**: Adds native support for editing text inside another reviewer's pending tracked insertion without erasing their attribution or requiring prior acceptance.
95
- - **Word-Native Insertion Slicing**: When inserting text inside another author's pending `<w:ins>`, the engine splits the outer carrier into sibling `<w:ins>` elements at the paragraph level (`[ins(A), ins(B), ins(A)]`), ensuring strict ECMA-376 schema compliance without illegal `ins/ins` nesting.
96
- - **Word-Native Deletion Slicing**: When deleting text inside another author's pending `<w:ins>`, the engine nests `<w:del>` directly inside `<w:ins>` per ECMA-376 Part 1 `CT_RunTrackChange` Section 17.13.5.21 and Microsoft Word Desktop 365 native behavior.
97
- - **Boundary & Straddle Deletions**: Deletions straddling baseline text and pending insertions cleanly partition into separate top-level and nested `<w:del>` containers while sharing unified event/author attribution.
98
- - **Multi-Author Stacked Revisions**: Multiple reviewers can independently delete or insert content within the same carrier insertion without cross-author interference.
99
- - **Cascading & Coalescing Lifecycles**: Full round-trip lifecycle parity with Microsoft Word Desktop:
100
- - Rejecting Author A cleanly discards Author A's insertion and any dependent nested deletions by Author B.
101
- - Accepting Author A unwraps the insertion into baseline text while leaving Author B's deletions pending against the baseline.
102
- - Rejecting Author B restores Author B's deleted text within Author A's insertion, and coalesces adjacent split `<w:ins>` fragments back into a single continuous carrier.
103
- - **CLI & Facade Integration**: Fully exposed via the `docx-redline` CLI (`--existing-revisions slice-cross-author`), Node facade (`openDocx`), and batch operation runner.
104
-
105
- ### Non-breaking Changes & Improvements
106
-
107
- - **Validation Update (`validateRedlineOoxml`)**: Refined `NESTED_REVISION` checks to permit direct `<w:ins><w:del>...</w:del></w:ins>` nesting (standard ECMA-376 and Word Desktop behavior), while continuing to strictly reject `ins/ins`, `del/del`, and `del/ins` nesting.
108
- - **Slicing Round-Trip Guard**: Cross-author surgical edits now preserve whitespace-only insertions (including ordinary-space replacements for NBSP characters beside hyperlinks) and verify the exact accepted-view text before reporting success. A mismatch fails closed with `PATCH_ROUNDTRIP_MISMATCH` and returns the original OOXML unchanged.
109
- - **Hyperlink-Adjacent Replacement Anchoring**: Paired replacements immediately before or after a hyperlink now retain a stable insertion point after the deletion run is split, preventing qualifiers from being relocated past the hyperlink or following formatted runs.
110
- - **Multiple Same-Run Insertions**: Insertion-only slicing operations with multiple edit points now apply from right to left against a refreshed live span index, preventing an earlier run split from relocating later insertions.
111
- - **Insertion Stress Hardening**: Slicing now detects edge whitespace changes exactly, uses a character-local insertion-only diff when the original text is an exact subsequence of the modified text, and coalesces new text into an existing same-author carrier when foreign revisions are also present. This prevents repeated phrases from relocating insertions and prevents invalid `w:ins/w:ins` nesting in mixed-author paragraphs.
112
- - **Preflight Inspection**: `preflightOperations` now inspects and validates `slice-cross-author` batches, reporting pending foreign-author carrier targets as `ready` instead of `EXISTING_REVISIONS`.
113
- - **Test Suite Expansion**: Added 7 new test suites covering 36 Word Desktop COM golden fixtures, carrier splitting invariants, the SYN-01..12d synthetic test matrix, PKG-01..06 strict package differential replay, the repeated-text/hyperlink whitespace regression, 76 deterministic insertion stress scenarios, and 12 replacement-anchor lifecycle scenarios (expanding the suite from 88 to 95 passing suites).
114
-
115
- ## 0.5.0
116
-
117
- ### ⚠️ Breaking changes
118
-
119
- The following changes can require caller or contributor updates. No public
120
- export or valid existing function signature was removed.
121
-
122
- #### Runtime and result-contract changes
123
-
124
- - **Canonical paragraph text:** `getParagraphText(...)` now returns the
125
- accepted/current view instead of the earlier simplified `w:t`/`w:tab`
126
- concatenation. It excludes deleted and `w:moveFrom` content and includes
127
- structural breaks, soft hyphens, and non-breaking hyphens.
128
- **Migration:** regenerate compared/cached text with the upgraded library. Use
129
- `extractCanonicalParagraphText(...)` when accepted/rejected-view semantics
130
- are intended; integrations that require the former raw traversal must retain
131
- their own legacy extractor before upgrading.
132
- - **Paragraph fingerprints:** fingerprints now incorporate canonical paragraph
133
- text. Stored fingerprints can become stale for paragraphs containing
134
- revisions, moves, breaks, soft hyphens, or non-breaking hyphens.
135
- **Migration:** do not carry fingerprints across this upgrade; re-extract the
136
- document and regenerate target descriptors.
137
- - **Invalid operations:** malformed or field-incompatible document-operation
138
- objects now return a structured `INVALID_OPERATION` error at the runner
139
- boundary instead of reaching later failure/no-op paths.
140
- **Migration:** validate operation files against the published schema and
141
- handle `status === 'error'` plus `error.code === 'INVALID_OPERATION'`.
142
- - **Commented paragraph deletion:** deleting a complete paragraph that contains
143
- an existing comment now fails with `COMMENTED_CONTENT_DELETE` instead of
144
- producing OOXML with dangling comment references.
145
- **Migration:** preserve or deliberately remove/relocate the comment before
146
- deleting the paragraph, and handle the structured error. Atomic callers keep
147
- the original document unchanged.
148
- - **Comment anchor failures:** missing or ambiguous comment anchors now return
149
- `ANCHOR_NOT_FOUND` or `AMBIGUOUS_ANCHOR` and fail/roll back an atomic batch;
150
- they are no longer reported as successful `no_change` operations.
151
- **Migration:** treat these codes as failed operations and use a unique exact
152
- anchor or stricter target descriptor before retrying.
153
- - **Stricter package validation:** DOCX package validation now rejects
154
- unbalanced comment ranges, dangling references/usages, orphan definitions,
155
- and duplicate comment-definition IDs that earlier validation could allow.
156
- **Migration:** repair the comment anchors and `word/comments.xml` definitions
157
- before applying or validating further changes.
158
-
159
- #### Development workflow change
160
-
161
- - **Parallel tests by default:** `npm test` now runs up to four isolated child
162
- processes concurrently. This does not change the published runtime API, but
163
- contributor automation that depends on test execution order or shared files
164
- must be updated. **Migration:** make tests independent or set
165
- `DOCX_TEST_CONCURRENCY=1` for the previous serial scheduling behavior.
166
-
167
- Strict targeting remains opt-in on existing low-level mutation APIs; it is the
168
- default only on the newly added Node facade and CLI.
169
-
170
- ### Deprecations and future breaking changes
171
-
172
- - Replacing an existing numbering part without a merge callback now emits a
173
- deprecation warning. The Node facade and CLI already merge safely by default.
174
- **This remains supported in this release but will become an error in the next
175
- major version.** Migrate low-level callers to
176
- `mergeNumberingXmlBySchemaOrder` before that release.
177
- - **Permissive target resolution deprecation (`AMBIGUOUS_TARGET_HEURISTIC_USED`):**
178
- Lower-level document operation runners currently default to permissive targeting.
179
- In v1.0.0, application will default to `strictTargets: true`. In this release,
180
- when permissive resolution encounters multiple identical candidate paragraphs and
181
- heuristically chooses the first candidate, it emits an `AMBIGUOUS_TARGET_HEURISTIC_USED`
182
- warning with candidate count and migration guidance.
183
- **Migration:** Disambiguate operations using `paragraphId`, `index`, `occurrence`,
184
- or `fingerprint` and pass `{ strictTargets: true }`.
185
-
186
- ### ℹ️ Noteworthy Default & Usability Changes (Non-breaking)
187
-
188
- The following improvements update default behaviors to maximize agent speed, reduce friction, and eliminate unnecessary errors during iterative editing. These changes are **not technically breaking changes** (no public APIs or exports were removed, and all existing options remain configurable), but represent important behavioral refinements that callers should note:
189
-
190
- - **Fallback Author Default (`'AI Redliner'`):** `setDefaultAuthor`, `node/cli.js`, and `openDocx` now default to `'AI Redliner'` (configurable via the `DOCX_REDLINE_AUTHOR` environment variable or `--author`). The CLI `apply` command and core APIs no longer error with `AUTHOR_REQUIRED` when operations omit an author.
191
- - **Output Overwrite by Default:** Destination files provided via `--output` now overwrite by default instead of failing with `OUTPUT_EXISTS`. Callers wanting protection against accidental overwrites can pass `--no-overwrite` or `--no-clobber`. The source document remains protected and is never overwritten unless `--in-place` is explicitly passed.
192
- - **Replacement Event Pairing (`pairReplacements: true` by default):** Adjacent `<w:del>` and `<w:ins>` revisions now default to sharing linked revision metadata and identical timestamps so Microsoft Word groups them as a single replacement in the Reviewing Pane. Pass `pairReplacements: false` for independent revision timestamps.
193
- - **Structured Content Auto-Detection (`structuredContent: true` by default):** Markdown tables, headings (`#`), and lists in replacement text automatically render as native Word elements (`w:tbl`, `w:pStyle`, `w:numPr`). Single outline-numbered legal clauses (e.g. `13.2.1.1`) continue to be treated as ordinary paragraphs without spurious list conversion. Pass `structuredContent: false` to treat replacement text strictly as plain text.
194
- - **Progressive Batch Mode (`atomic: false` default, `atomic: true` opt-in):** Batch operations and CLI `apply` now apply edits progressively by default (`atomic: false`): valid edits commit directly, while failing edits report structured errors in `results` for faster debugging. Pass `{ atomic: true }` (or `--atomic` on the CLI) for all-or-nothing rollback when any operation fails.
195
- - **Clean Direct Edits (`generateRedlines: false` / `--no-redlines`):** Prominently documented that tracked redlines are not always the preferred method. Callers can pass `generateRedlines: false` (or `--no-redlines` on the CLI) for clean execution drafts, document restructuring, or minor typo fixes without tracked changes markup.
196
- - **Existing Revisions Policy (`existingRevisions: 'merge-same-author'` by default):** When editing a paragraph that already contains tracked changes from the same author, prior revisions by that author are merged against the pre-revision baseline (prior changes by that author are reverted and re-diffed to the new modified text), avoiding revision accumulation and nested markup. If a paragraph contains tracked changes from another reviewer, the operation fails closed with `EXISTING_REVISIONS` to protect third-party review marks. Commented revision content fails closed with `COMMENTED_CONTENT_MERGE` so comment anchors cannot be removed or orphaned. Callers can explicitly pass `'accept-all-first'` to normalize prior revisions or `'reject-input'` to refuse editing any revised paragraph.
197
- - **Inline One-Liner CLI Edits:** Added `--target <text>` with `--modified <text>` or `--comment <text>` on `docx-redline apply` for fast 1–2 edit workflows without creating a JSON operations file.
198
-
199
- ### Added
200
-
201
- - Added **Mutation Receipts** (`receipt` on `DocumentOperationResult` and `receipts`
202
- on `BatchOperationResult`). Every operation execution returns structured,
203
- commit-aware telemetry capturing durable revision IDs (with kind and target part),
204
- comment IDs, numbering IDs, relationship IDs, affected targets, and warnings.
205
- Supports `not_attempted`, `applied`, `refused`, `no_change`, and `rolled_back`
206
- dispositions.
207
- - Added **Commit-Aware Output Reconciliation Oracle** (`reconcileReceiptsAgainstOutput`).
208
- Before completing any transaction, reported durable IDs are checked against a
209
- fresh parse of the generated output OOXML parts. Any reconciliation discrepancy
210
- immediately fails the transaction and triggers atomic rollback.
211
- - Exported receipt primitives: `ReceiptCollector`, `createEmptyReceipt`, and
212
- `reconcileReceiptsAgainstOutput` along with `MutationReceipt` and
213
- `MutationReceiptRevisionItem` TypeScript declarations.
214
- - Added **Paragraph Mark Revisions** (`w:pPrChange`, `markParagraphMarkInserted`,
215
- `markParagraphMarkDeleted`) ensuring whole-paragraph deletions and insertions
216
- cleanly track paragraph mark lifecycles for full Accept All / Reject All symmetry.
217
- - Added **Paragraph Boundary Mutation Validation** (`validateParagraphBoundaryMutation`)
218
- guarding against invalid cross-paragraph boundary merges.
219
-
220
- - Added `analyzeStructuredContent(...)` and `planStructuredReplacement(...)`
221
- for agent-authored attachments and schedules containing mixed headings,
222
- paragraphs, lists, and tables. The planner returns typed blocks and produces
223
- one atomic `structuredContent` operation only when the Markdown is valid.
224
-
225
- - Added session-scoped paragraph metadata indexing for canonical text,
226
- normalized text, paragraph IDs, fingerprints, table context, and document
227
- indexes, plus deterministic targeting and route-profiling benchmarks.
228
- - Added a shared list-marker grammar and parsed list-item vocabulary used by
229
- pipeline analysis, orchestration, normalization, and list targeting.
230
- - Added an internal reconciliation capability matrix and opt-in route
231
- instrumentation. Public reconciliation result shapes and route selection
232
- policy remain unchanged.
233
-
234
- - Added `scripts/extract_text.mjs` and `scripts/apply_changes.mjs` as thin
235
- compatibility entrypoints for legacy skill installations. They delegate to
236
- the supported CLI, retain strict atomic validated writes, and accept legacy
237
- operation files with a top-level `changes` array.
238
- - Added typed operations, per-operation authors, strict target descriptors,
239
- deterministic preflight diagnostics, and auditable resolution metadata.
240
- - Added `inspectDocumentParts(...)`, a structured document inventory using the
241
- same canonical text extractor as targeting and ingestion.
242
- - Added `@ansonlai/docx-redline-js/node`. `openDocx(...)` applies batches to
243
- complete DOCX buffers transactionally and validates before commit.
244
- - Added the cross-platform `docx-redline` CLI with JSON `inspect`, `extract`,
245
- `preflight`, `apply`, `accept`, `reject`, `delete-comments`, and `validate`
246
- commands, plus a published operation-file JSON Schema.
247
-
248
- ### Behavior and reliability
249
-
250
- - Explicit structured replacements now reject missing Markdown table separator
251
- - Generated Markdown tables repeat their header row and prevent logical data rows from splitting across pages.
252
- rows, missing data rows, and inconsistent column counts with
253
- `STRUCTURED_CONTENT_INVALID` instead of inserting literal pipe-delimited text.
254
- - Tables created inside mixed replacements are tracked once at block scope,
255
- avoiding nested revisions while keeping Accept All and Reject All symmetric.
256
-
257
- - Target preflight and live mutation reuse one document-scoped paragraph index;
258
- strict duplicate detection and resolution metadata retain their prior
259
- semantics while avoiding repeated whole-document text traversal.
260
- - Revision-ID seeding now walks the DOM with child/sibling pointers instead of
261
- allocating an array containing every element.
262
- - Single-source-paragraph list expansion uses the focused list generator
263
- directly. Multi-paragraph marked-list edits deliberately retain the legacy
264
- run-aware reconciliation pipeline for structural parity.
265
- - Fixed paragraph-to-list expansion when a manually numbered heading carries
266
- `w:numId w:val="0"`. Numbering suppression is no longer reused as a generated
267
- list ID, so inserted bullet and numbered items receive valid positive IDs.
268
- - Tracked heading-to-list replacements now keep the deleted source heading in
269
- its own paragraph and track the paragraph marks of every inserted list item.
270
- This prevents deleted heading text from joining the first item and preserves
271
- exact Accept/Reject structure without adding a full-document sentinel
272
- paragraph.
273
- - Inserted list items now inherit source font family, size, language, and
274
- related script typography without inheriting heading-only bold, underline,
275
- italic, or strike formatting unless requested by the replacement markdown.
276
- - Canonical-only table-cell targeting now consumes the shared paragraph-text
277
- extractor, while offset- and sentinel-producing walkers remain specialized.
278
- Their accepted visible projections now agree on soft hyphens as well as tabs,
279
- breaks, hyperlinks, and non-breaking hyphens.
280
-
281
- - Comment preflight and application now share one anchor resolver. Exact
282
- matches take priority, unique ordinary-space/NBSP differences preserve raw
283
- offsets, and missing or repeated anchors return structured
284
- `ANCHOR_NOT_FOUND` or `AMBIGUOUS_ANCHOR` errors.
285
- - Full-document operation batches now share one live DOM and revision-ID
286
- allocator, reducing complete-document parsing and serialization from once per
287
- operation to once per changed batch. Scoped reconciliation engines and their
288
- targeting decisions are unchanged.
289
- - Each live-session operation uses a DOM and allocator savepoint. Errors and
290
- reported no-ops restore the savepoint; atomic failures and all-no-op batches
291
- still return the exact original XML without serializing it.
292
- - Decomposed the standalone document-operation runner into a stable 13-line
293
- compatibility facade plus focused session, applier, batch-orchestrator,
294
- heuristic, and OOXML-mutation modules. Runtime exports and declarations are
295
- unchanged, and operation internals now use leaf imports instead of importing
296
- the root entry point.
297
- - Package comment IDs are seeded from existing anchors and definitions, and
298
- the Node facade merges numbering without discarding prior definitions.
299
- - Canonical paragraph text consistently handles revisions, moves, tabs,
300
- breaks, soft hyphens, and non-breaking hyphens; see the breaking-change note
301
- above for `getParagraphText(...)` and fingerprint compatibility.
302
- - Structured inspection now explicitly supports the `current` view as the
303
- accepted/current document view and resolves comment ranges spanning multiple
304
- paragraphs as one exact anchor string.
305
- - Transactional no-op results preserve the original DOCX bytes exactly,
306
- including when the same facade instance has already committed an edit.
307
-
308
- ### Testing and development
309
-
310
- - Added focused and semantic visual-failure regressions for suppressed
311
- numbering, paragraph separation, paragraph-mark revisions, selective
312
- typography inheritance, and exact accepted/rejected paragraph sequences,
313
- plus seeded fuzz variants across list length, marker, font, and size.
314
- Added the independently specified
315
- `legal-suppressed-heading-to-bullet-list` and
316
- `legal-structured-attachment-mixed-blocks` Microsoft Word differential
317
- fixtures; the synthetic catalogue now contains 49 cases and 49 task types.
318
-
319
- - The JavaScript test runner now uses bounded asynchronous subprocess workers,
320
- capped at four by default, while retaining one fresh Node process per file,
321
- sorted reporting, timeouts, captured diagnostics, and failure-marker checks.
322
- Set `DOCX_TEST_CONCURRENCY=1` for serial reproduction.
323
- - Added `npm run benchmark:tests` and a Phase 6 runner regression. The checked
324
- benchmark reduced median suite time from 18.02 seconds to 7.96 seconds
325
- (55.80%); 20 consecutive parallel runs and a separate serial run passed all
326
- 63 files. Parallel c8 collection remains valid at 89.90% statements/lines,
327
- 77.40% branches, and 93.10% functions.
328
-
329
- - Added Phase 3 targeting/traversal, Phase 4 list/text parity, and Phase 5 route
330
- compatibility regressions. Together with the Phase 6 runner regression, the
331
- suite now contains 63 passing test files.
332
- - Added `npm run benchmark:targeting` and `npm run profile:routes`. The checked
333
- 10,000-paragraph benchmark showed no single-operation regression and a 47.16x
334
- Node median improvement for 100 cached resolutions. The equivalent native
335
- Chrome benchmark showed no single-operation regression and a 36.45x batch
336
- improvement. All 47 Microsoft Word differential fixtures and all 60 real-
337
- document Word corpus scenarios passed after the routing changes.
338
-
339
- - Added subprocess coverage for legacy wrapper selection, operation-file
340
- compatibility, successful output, atomic anchor failure, source-byte
341
- preservation, and protection of pre-existing output files.
342
- - Added a live-session accuracy and instrumentation suite covering accepted and
343
- rejected text, structural validity, sequential equivalence, comments, lists,
344
- tables, highlights, one-parse/one-serialize execution, exact no-ops, and
345
- atomic rollback. Added `npm run benchmark:session`; the checked accuracy-first
346
- benchmark reduced parse/serialize counts from 10/10 to 1/1 and measured a
347
- 1.58x median speedup with per-operation savepoints retained.
348
- - Added a Phase 2 architecture regression covering facade export identity,
349
- direct leaf imports, exact session rollback, isolated context commit, and
350
- stable comment-first scheduling.
351
- - Added five edge-case suites for canonical text views, cross-paragraph comment
352
- inspection, table/list/reference context, sequential package transactions,
353
- selective multi-author cleanup, ZIP rejection behavior, CLI filters, JSON
354
- exit contracts, and destructive-output safeguards. Together with the Phase 2
355
- Phase 1 and Phase 2 regressions, these established the earlier 57-file
356
- baseline expanded by the subsequent performance phases.
357
-
358
- ## 0.3.0
359
-
360
- ### Breaking changes
361
-
362
- - Malformed OOXML no longer escapes public transform APIs as a raw parser
363
- exception. In particular, revision accept/reject and comment-deletion callers
364
- that previously used `try`/`catch` must now inspect `status === 'error'` and
365
- `error.code === 'PARSE_ERROR'` on the returned result.
366
- - Caller content is no longer sanitized by default. Pass `sanitizeInput: true`
367
- to remove a standalone leading assistant-preface line. Dollar-delimited text
368
- and literal `\\n` / `\\r\\n` sequences are never removed implicitly.
369
- - The exported `sanitizeAiResponse` helper no longer removes dollar-delimited
370
- spans or converts literal `\\n` / `\\r\\n` sequences. Direct callers that
371
- relied on those transformations must perform them explicitly.
372
- - `applyOperationsToDocumentXml` is atomic by default. Failed batches return
373
- the original document with `rolledBack: true`; pass `atomic: false` to retain
374
- partial-result behavior.
375
- - Missing multi-line targets now return `TARGET_NOT_FOUND` instead of being
376
- indistinguishable from a no-op. Stale batch anchors also return
377
- `TARGET_NOT_FOUND` instead of falling back to a visibly different paragraph.
378
-
379
- ### Behavior changes and fixes
380
-
381
- - Revision IDs are now allocated per document. Near-limit prior IDs restart in
382
- a safe low range, and unrelated bookmark/relationship IDs no longer seed the
383
- revision counter.
384
- - Concurrent calls with explicit authors keep their revision attribution
385
- isolated from process-global defaults.
386
- - `existingRevisions: 'accept-all-first'` now preserves the original OOXML when
387
- the requested edit is a no-op.
388
- - Added `existingRevisions: 'accept-all-first-keep-normalized'` for callers that
389
- explicitly want accepted existing revisions returned even when no redline is
390
- added.
391
- - Diff output is deterministic by default. Inputs exceeding 262,144 unique
392
- tokens return `DIFF_TOKEN_LIMIT` with the original OOXML unchanged instead of
393
- risking truncated text; leading whitespace is preserved exactly.
394
- - Reconstruction preserves structural line breaks and body section-property
395
- placement. A target that names only part of a reconstruction range now
396
- returns `PARTIAL_TARGET` instead of risking deletion of untargeted content.
397
- - Paragraph targeting and reconstruction now preserve leading, middle, and
398
- trailing `w:tab` elements as literal tab characters instead of omitting or
399
- trimming them.
400
- - Adjacent redline edits now preserve complex-field instructions, begin/
401
- separate/end markers, and unchanged cached display results in their original
402
- field boundary. Field instructions remain inert and are not evaluated.
403
- - Added structured XML parse results and result-returning ingestion helpers.
404
- - Hardened deterministic diff token handling and leading-whitespace fidelity.
405
-
406
- ### Testing and development
407
-
408
- - Expanded the desktop Word differential from 20 to 25 cases, adding structural
409
- checks for bookmarks, internal hyperlinks, mixed formatting, content
410
- controls, and tables.
411
- - Expanded the desktop Word differential from 25 to 28 cases with structural
412
- tabs and a locked PAGE field, and added tab/field shapes to focused and fuzz
413
- regression testing.
414
- - Expanded the desktop Word differential from 28 to 33 cases with comments,
415
- footnotes, endnotes, headers/footers, and an external hyperlink.
416
- - Extended the deterministic script-only DOCX packager with opt-in related
417
- parts, relationship/content-type validation, reusable fixture constructors,
418
- and SHA-256 verification that supplied parts remain byte-identical. Runtime
419
- library code and dependencies are unchanged.
420
- - Added validated task, structure, oracle, and manual-review metadata across the
421
- 33 synthetic and 20 SuperDoc Word cases. `npm run report:word:coverage`
422
- produces a deterministic coverage matrix with explicit high-priority gap
423
- dispositions, while `npm run review:word:prepare` creates a pending rotating
424
- human-review manifest without self-certifying visual results.
425
- - Added detailed production-function coverage reporting and a checked per-file
426
- regression baseline. Five behavior-focused Phase 3 suites exercise numbering
427
- collisions/remapping, every reconciliation route, list construction and
428
- fallback, patch/format boundaries, table decisions, pipeline modes, and
429
- standalone rollback/highlight paths. Production function coverage moved from
430
- 437/540 to 496/542 and all reachable P0 functions are covered; no runtime
431
- behavior or compatibility contract changed.
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ### Added
6
+
7
+ - **Header and footer editing:** add `part` to an operation (a selector `{ kind, type?, section? }` or a part path) to edit a
8
+ header or footer; `inspect().headersFooters` lists the parts with their text, the sections they apply to (including
9
+ inherited ones) and whether they contain fields. Body edits are unchanged and headers/footers are opt-in. Fields such as
10
+ PAGE are atomic (`FIELD_EDIT_REFUSED`), comments are refused (`COMMENT_IN_HEADER_FOOTER`), bad selectors fail closed
11
+ (`PART_NOT_FOUND`, `PART_AMBIGUOUS`), atomic batches roll back across body and parts, revision ids stay unique across the
12
+ package, receipts name the part, `accept`/`reject` also resolve revisions inside headers and footers, and
13
+ `validateDocxPackage` checks header/footer references, relationships and content types.
14
+ - **Resolve and reopen comment threads:** `doc.resolveComment(id, { resolved })` and the batch operation
15
+ `{ "type": "comment_resolve", "commentId": "0", "resolved": true }`, so the CLI can resolve through `apply --operations`.
16
+ Word resolves whole threads, so the root and every reply change together, whichever id is given. Only
17
+ `word/commentsExtended.xml` changes; `document.xml` stays byte-identical. Unknown ids fail with `COMMENT_NOT_FOUND`
18
+ (also in `preflight`).
19
+ - **Delete comments by id:** `doc.deleteComments({ ids })` and `docx-redline delete-comments --comment-id 3,4`. Deleting a
20
+ thread root also deletes its replies; unknown ids fail closed with `COMMENT_NOT_FOUND`.
21
+ - CLI capabilities `comment-resolve-operation-v1`, `delete-comments-by-id-v1` and `header-footer-parts-v1` (additive; the
22
+ contract version is unchanged).
23
+ - `services/package-parts.js`, a registry of package part paths, content types and relationship types checked against
24
+ Word-saved fixtures (`tests/fixtures/word-authored/`), and `npm run test:word:package`, which opens generated outputs in
25
+ real Word with repair disabled and checks comment counts, thread parents, resolved state and header/footer revisions
26
+ through Word's object model.
27
+
28
+ ### Fixed
29
+
30
+ - **Word "unreadable content" prompt on commented documents:** `word/commentsExtended.xml` was relabeled
31
+ `application/vnd.ms-word.commentsExtended+xml` on every save of any document that already had comments.
32
+ Word expects `application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml` and
33
+ offered to repair the file. The constant is corrected, an edit that does not change comment threading no
34
+ longer rewrites the extended part or its content type/relationship, and files already damaged by earlier
35
+ versions are repaired on the next save (`repairKnownContentTypes`, also exported). `validateDocxPackage`
36
+ now rejects the wrong type instead of accepting it. `tests/package_content_type_contract_tests.mjs` checks this
37
+ against a Word-authored content-type table on every OS.
38
+ - **Comment threads keyed on the last paragraph:** Word joins `comments.xml` to `commentsExtended.xml` and
39
+ `commentsIds.xml` through the `w14:paraId` of a comment's LAST paragraph. Inspection, package validation,
40
+ replies and delete-cascade used the first, so Word's own multi-paragraph threaded documents failed
41
+ validation and replies to them attached to the wrong key.
42
+ - **Edits no longer drop comment anchors:** a mid-paragraph edit of a commented paragraph dropped the trailing
43
+ `commentRangeEnd` and `commentReference` (markers at the very end of the paragraph text were only emitted when the
44
+ last diff part was an insert), leaving the comment unanchored and failing package validation. Found by
45
+ opening our output in real Word; covered by `tests/comment_marker_preservation_tests.mjs`.
46
+ - **Replies are now visible in Word:** `comment_reply` only wrote `comments.xml`/`commentsExtended.xml`, and Word
47
+ does not show a reply that has no body markers. Replies now get their own `commentRangeStart`/`commentRangeEnd`/
48
+ `commentReference` next to the thread's, laid out like Word writes them. A reply to a reply joins the root thread.
49
+ A parent with no body anchor fails with `PARENT_ANCHOR_NOT_FOUND`.
50
+ - **Replies to a resolved thread are resolved too**, as Word writes them (`reply-to-resolved.docx` fixture). They were
51
+ written open, leaving a thread that was half resolved.
52
+ - `commentsIds.xml` and `commentsExtensible.xml` are kept consistent with `comments.xml` on add/delete when present.
53
+ - `deleteComments` and `resolveRevisions` report `artifactsChanged` from a real diff of the package (they listed a fixed
54
+ set of parts and missed `commentsIds.xml`, `commentsExtensible.xml` and `[Content_Types].xml`).
55
+
56
+ ## 0.8.0
57
+
58
+ ### Universal Document Facade & Zero-Node Architecture
59
+
60
+ - **Universal `DocxDocument` & `openDocx`:** Implemented complete-DOCX lifecycle operations
61
+ (`openDocx`, `doc.inspect()`, `doc.applyOperations()`, `doc.resolveRevisions()`, `doc.deleteComments()`,
62
+ `doc.toUint8Array()`, `doc.getRevisionToken()`) on standard `Uint8Array` in `document/docx-document.js`,
63
+ re-exported directly from `index.js`. Enables complete-document redline workflows in any JavaScript
64
+ runtime without Node.js dependencies.
65
+ - **Pure-JS ZIP container (`fflate`):** Replaced `node:zlib` with lightweight, zero-dependency `fflate`
66
+ in `document/zip-archive.js`, providing cross-runtime raw DEFLATE / INFLATE compression and decompression
67
+ with full OOXML archive compatibility.
68
+ - **Pure-JS FIPS 180-4 SHA-256:** Created zero-dependency, synchronous SHA-256 implementation in
69
+ `core/sha256.js`, removing `node:crypto` from package revision token calculations while retaining
70
+ exact deterministic hash parity with standard NIST vectors.
71
+ - **Transparent XML DOM fallback:** Added `resolveDomParserConstructor()` and
72
+ `resolveXmlSerializerConstructor()` in `adapters/xml-adapter.js`, automatically utilizing native
73
+ `globalThis.DOMParser`/`globalThis.XMLSerializer` when present and falling back transparently to
74
+ `@xmldom/xmldom` in headless, server, edge, and sandbox environments without requiring manual provider setup.
75
+ - **Zero-dependency sandbox bundles:** Configured `scripts/build.mjs` with `esbuild` (`platform: 'neutral'`)
76
+ to produce single-file, zero-dependency standalone bundles in both ESM (`dist/docx-redline.bundle.js`)
77
+ and CommonJS (`dist/docx-redline.bundle.cjs`), exported as `@ansonlai/docx-redline-js/bundle` for direct
78
+ use in workflow engines (e.g., n8n Code nodes), Cloudflare Workers, AWS Lambda, Deno, and QuickJS sandboxes.
79
+ - **Strict runtime boundary enforcement:** Removed `node:zlib` and `node:crypto` from allowed external
80
+ imports in `tests/no_word_api_index_check.mjs`. Automated sandbox isolation tests
81
+ (`tests/sandbox_bundle_isolation_tests.mjs`) verify zero Node built-in imports and full document
82
+ reconciliation in restricted VM contexts without `process`, `Buffer`, or `require`.
83
+ - **Backward compatibility:** Preserved full API and `Buffer` compatibility for `@ansonlai/docx-redline-js/node`
84
+ consumers and `doc.toBuffer()`.
85
+
86
+ ## 0.7.2
87
+
88
+ ### Agent Surface Simplification
89
+
90
+ - **Extraction-first golden path:** Re-established the single deterministic two-turn
91
+ "extract-then-apply" sequence as the default agent workflow across `AGENTS.md`,
92
+ `docs/AGENT_FAST_START.md`, and `docs/SKILL_AUTHORING.md`. Eliminates the
93
+ upfront "choice tax" and model deliberation overhead.
94
+ - **Localized replacements after inspection:** Decoupled localized patching from
95
+ speculation. Agents inspect the target paragraph first, then supply compact
96
+ `replacements` instructions, achieving 60.6%–90.8% payload reductions without
97
+ speculative ambiguity risk.
98
+ - **Computed success gate:** Consolidated standard success verification onto
99
+ `completion: true` and non-null `outputPath`, removing multi-field verification
100
+ checklists from primary prompts while retaining full `change` audit evidence.
101
+ - **Advanced features relocated:** Speculative 1-turn apply, directional context
102
+ windows (`--context-range`), and anchor diagnostics are relocated to
103
+ `docs/AGENT_KNOWLEDGE_BASE.md` and CLI help as opt-in harness policies.
104
+ - **Observed-state restoration:** Restructured restoration as a clean request-
105
+ or hint-driven branch (`--view rejected` or `selection.hint`) rather than an
106
+ upfront classification decision.
107
+ - **Empirical surface evaluation:** Added synthetic replay benchmark
108
+ (`npm run benchmark:agent-surface`) and validation report documenting 100%
109
+ first-attempt task correctness and payload savings across three workflow policies.
110
+
111
+ ## 0.7.1
112
+
113
+ ### Reliability and Discovery Refinements
114
+
115
+ - Localized replacement matching now tries exact case-sensitive text first,
116
+ then a narrow ASCII-space/non-breaking-space equivalent match. Ambiguous
117
+ equivalent matches still fail closed, and unchanged boundary NBSPs are
118
+ retained to avoid incidental whitespace redlines.
119
+ - Added a narrow single-paragraph restore shortcut. A restore with a strong
120
+ rejected-view target may omit `modified` for verbatim restoration or provide
121
+ exact `replacements`; the CLI exposes the same path through `apply --restore
122
+ --target-id ID`. Ranges, captures, weak targets, and inferred companion
123
+ content remain excluded.
124
+ - Fixed rejected-view restore receipts so `resolvedTarget` text, fingerprint,
125
+ revision view, and match diagnostics describe the view actually used to
126
+ resolve the target.
127
+ - Fixed alternate-view search hints to honor `--revised`, `--table`, and
128
+ `--body`, and retained compact revision authors plus `deleted`/`inserted` cues
129
+ in `extract` output so empty revision-view paragraphs are self-explanatory.
130
+
131
+ ## 0.7.0
132
+
133
+ ### Agent Performance and Localized Editing
134
+
135
+ - **Localized exact replacements:** `redline`/`replace` operations may provide
136
+ `replacements: [{ find, replace, occurrence? }]` instead of a complete
137
+ `modified` paragraph. The compiler resolves the accepted-view source once,
138
+ applies non-overlapping exact replacements simultaneously, synthesizes the
139
+ canonical desired paragraph, and delegates to the unchanged OOXML engine.
140
+ - **One-turn speculative apply:** `docx-redline apply --find ... --replace ...`
141
+ can resolve a globally unique source literal without preliminary extraction.
142
+ `--search` plus signed `--context-range START:END` scopes visible headings and
143
+ nearby content; `--around N` is symmetric shorthand. Longer, distinctive
144
+ anchors are recommended because generic or repeated phrases widen the unioned
145
+ scope and may cost an ambiguity-recovery turn.
146
+ - **Fail-closed selection:** Missing anchors and patch sources, multiple eligible
147
+ paragraphs, ambiguous occurrences, overlaps, conflicts, and unsupported
148
+ localized shapes refuse mutation. A failed speculative command never writes
149
+ or truncates its output path.
150
+ - **Verified change evidence:** Localized operation results include a compact
151
+ `change` object with target location, contextual anchor/range, exact
152
+ replacement entries, bounded before/after excerpts, commit disposition, and
153
+ post-mutation accepted-view verification. Atomic rollback marks the evidence
154
+ non-committed and `rolled_back`.
155
+ - **CLI contract version 8:** Adds `localized-replacements-v1`,
156
+ `speculative-search-apply-v1`, and `localized-change-summary-v1`. Skills and
157
+ harnesses should pin version 0.7.0 and negotiate only the capabilities used.
158
+ - **Measured workflow reduction:** The checked benchmark records 50% fewer tool
159
+ turns and a 64.77%–78.98% smaller deterministic request-token proxy across
160
+ three literal-edit cases. Median native engine/I/O time remained effectively
161
+ neutral; provider reasoning and network latency were not estimated.
162
+
163
+ ### Compatibility
164
+
165
+ - Existing `modified` operations, strong targets, operations files/stdin,
166
+ tracked-change generation, package validation, rollback, comments,
167
+ Accept/Reject, and revision policies remain supported.
168
+ - Localized replacement fields and successful `change` evidence are additive.
169
+ Wrappers that adopt them must require CLI contract 8; integrations using only
170
+ earlier capabilities can continue using their existing operation shapes.
171
+ - The implementation remains OOXML-only and adds no runtime dependency or Word,
172
+ Office automation, COM, or proprietary document API requirement.
173
+
174
+ ## 0.6.0–0.6.2
175
+
176
+ ### Safety Fixes
177
+
178
+ - **Foreign deleted-paragraph resurrection guard**: Refuses non-empty same-paragraph edits when another author owns the paragraph-mark deletion and all existing paragraph content is deleted. The operation now returns `FOREIGN_PARAGRAPH_MARK_DELETION` with the owning author instead of emitting lifecycle-unsafe OOXML; atomic document operations roll back byte-for-byte. `validateRedlineOoxml` reports already-authored instances as warnings.
179
+ - **Source-truth whitespace replacement alignment (WP09a)**: Strict target resolution may equate ordinary spaces with NBSPs, but mutation offsets now always come from the resolved paragraph's exact accepted view. Space-equivalent word replacement hunks are refined to character-local edits, and multiple plain-text edits are applied right-to-left against refreshed live spans. This tracks NBSP-to-space substitutions exactly while preserving unchanged hyperlinks and prevents earlier run splits from invalidating later anchors.
180
+ - **Exact mismatch diagnostics**: `PATCH_ROUNDTRIP_MISMATCH` now includes the expected and actual code points at the first mismatch. Document-operation results also report bounded `targetTextMatch` diagnostics when target selection used equivalent whitespace.
181
+ - **Baseline-delta validation (WP09c)**: Restoration, operation, and package validation now compare issue multisets against the source. Unchanged legacy defects remain visible without blocking safe work, while any added occurrence or mutation-envelope error fails closed with `GENERATED_OOXML_INVALID` before an operation is reported as applied.
182
+ - **Revision identity sanitation (WP09d)**: New paragraph/list builders inherit effective `pPr`/`rPr` formatting without cloning historical revision descendants. Operation-level whole-document validation catches duplicate revision IDs and rolls back the operation savepoint before committing its receipt.
183
+ - **View-consistent restore targeting**: `restore` targets now default to the rejected view, where a wholly deleted paragraph's source text exists. Rejected-view inspection now computes fingerprints from rejected-view text and reports the view beside each paragraph. Explicit cross-view text or fingerprint mistakes retain strict refusal while returning an actionable view hint.
184
+
185
+ ### New Features
186
+
187
+ - **Self-describing and bounded agent discovery (WP-00–WP-02)**: CLI contract version 6 adds command-specific JSON help, canonical redline/comment/restore examples, case-insensitive contextual search with `--around`/`--context`/`-C`, direct-hit pagination through `--limit` and `--after`, and deliberate `--all` opt-out. Unscoped inspection is capped at 20 direct records and a 48 KiB soft budget without truncating any returned `exactText`; extraction now distinguishes matches from context and prioritizes human-facing provision/heading references over machine paragraph ordinals.
188
+ - **Composable agent safety and compact output (WP-03–WP-04)**: CLI contract version 7 replaces the atomic-coupled agent profile capability with `agent-safety-profile-v2`. `--profile agent` now enforces complete-success exits while preserving progressive execution and the ordinary revision policy; `--atomic` and `--existing-revisions` compose explicitly. Compact CLI JSON keeps receipts only in the authoritative top-level array, omits exact-match diagnostics, summarizes successful equivalent-whitespace matches, and supports one-line `--compact` output without changing Node or standalone-runner results.
189
+ - **Packaged skill-authoring contract (WP-05)**: `docs/SKILL_AUTHORING.md` separates automation invariants from transaction/revision policy, file-versus-stdin transport, reviewer preferences, recovery-envelope behavior, and human-facing presentation. It requires contract/capability negotiation, focused contextual extraction, and library delegation while retaining the visible `AI Redliner` fallback without a new author guard.
190
+ - **Batch-start source binding (WP-04)**: Strong document-operation targets are compiled once against the immutable source DOM and carried through structural index/fingerprint drift with rollback-aware session identities. Independent edits no longer need manual bottom-up sorting; same-source writes, incompatible revision/format combinations, and unsafe capture fan-out fail before mutation with causal conflict codes. Unique references to paragraph text created elsewhere in the same batch become explicit internal capture dependencies.
191
+ - **Machine-actionable recovery (WP-05)**: Operation, package-facade, example-session, and compact CLI failures now carry recovery envelope version 1 with stable stage/category/action metadata, bounded corrective context, and authorization flags. Failed and partial mutation results include an explicit original-vs-output retry plan and operation indexes. `apply --require-complete` exits with code 3 for partial work while preserving legacy behavior without the flag.
192
+ - **Compact shell-agent protocol (WP-06)**: CLI contract version 5 adds `operations-stdin` and `agent-profile-v1`. `--operations -` accepts UTF-8 operation arrays/envelopes without a temporary operations file, while explicit `--profile agent` combines atomic rollback and complete-success exit behavior and reports its effective settings. `AGENTS.md` is now a 527-word routing card, and the 349-word `docs/AGENT_FAST_START.md` carries the ordinary edit contract. Ambient project configuration was deliberately deferred because it would save only the profile flag while adding hidden state.
193
+ - **Agent rollout audit (WP-07)**: The observational benchmark now compares canonical Node, legacy file-based CLI, compact stdin/profile CLI, and the development session example while verifying accepted/rejected text, comment preservation, independent batch permutations, recovery behavior, and cross-author attribution. The checked run records 82.75% fewer ordinary instruction words, one fewer shell tool turn (33.33%), and 82.22–89.96% smaller localized session requests than canonical Node envelopes without claiming unmeasured provider/model latency.
194
+ - **Explicit paragraph restoration (`type: 'restore'`)**: Restores or counterproposes another reviewer's pending whole-paragraph deletion as a separately tracked sibling paragraph. The source deletion remains untouched; the restored paragraph receives its own inserted paragraph mark, content insertion, sanitized paragraph properties, and fresh `w14:paraId`. Single paragraphs and contiguous ranges are supported, with full Accept/Reject lifecycle verification and structured refusals at unsafe table-row, move, section-break, and terminal-paragraph boundaries.
195
+ - **Compact mutation CLI contract (WP09b)**: CLI contract version 3 removes `documentXml`, OOXML/package artifacts, full inspection data, and full validation issue arrays from normal `apply`, `accept`, `reject`, and `delete-comments` stdout. Mutation responses retain actionable errors, per-operation receipts, output durability fields, code/count validation summaries, and a derived `completion` flag that cannot report success for failed, partial, or unwritten work.
196
+ - **Word-native deleted-section editing (WP09e)**: An explicit rejected-view `insert` operation can split a foreign deletion at an exact anchor-relative offset into sibling `del(A) / ins(B) / del(A)` carriers. Contiguous paragraph restorations now follow their untouched deleted source block, matching Microsoft Word's ordering. Ambiguous anchors and unsupported structural split boundaries remain fail-closed.
197
+
198
+ ## 0.5.1
199
+
200
+ ### Highlights & New Features
201
+
202
+ - **Cross-Author Revision Slicing (`existingRevisions: 'slice-cross-author'`)**: Adds native support for editing text inside another reviewer's pending tracked insertion without erasing their attribution or requiring prior acceptance.
203
+ - **Word-Native Insertion Slicing**: When inserting text inside another author's pending `<w:ins>`, the engine splits the outer carrier into sibling `<w:ins>` elements at the paragraph level (`[ins(A), ins(B), ins(A)]`), ensuring strict ECMA-376 schema compliance without illegal `ins/ins` nesting.
204
+ - **Word-Native Deletion Slicing**: When deleting text inside another author's pending `<w:ins>`, the engine nests `<w:del>` directly inside `<w:ins>` per ECMA-376 Part 1 `CT_RunTrackChange` Section 17.13.5.21 and Microsoft Word Desktop 365 native behavior.
205
+ - **Boundary & Straddle Deletions**: Deletions straddling baseline text and pending insertions cleanly partition into separate top-level and nested `<w:del>` containers while sharing unified event/author attribution.
206
+ - **Multi-Author Stacked Revisions**: Multiple reviewers can independently delete or insert content within the same carrier insertion without cross-author interference.
207
+ - **Cascading & Coalescing Lifecycles**: Full round-trip lifecycle parity with Microsoft Word Desktop:
208
+ - Rejecting Author A cleanly discards Author A's insertion and any dependent nested deletions by Author B.
209
+ - Accepting Author A unwraps the insertion into baseline text while leaving Author B's deletions pending against the baseline.
210
+ - Rejecting Author B restores Author B's deleted text within Author A's insertion, and coalesces adjacent split `<w:ins>` fragments back into a single continuous carrier.
211
+ - **CLI & Facade Integration**: Fully exposed via the `docx-redline` CLI (`--existing-revisions slice-cross-author`), Node facade (`openDocx`), and batch operation runner.
212
+
213
+ ### Non-breaking Changes & Improvements
214
+
215
+ - **Validation Update (`validateRedlineOoxml`)**: Refined `NESTED_REVISION` checks to permit direct `<w:ins><w:del>...</w:del></w:ins>` nesting (standard ECMA-376 and Word Desktop behavior), while continuing to strictly reject `ins/ins`, `del/del`, and `del/ins` nesting.
216
+ - **Slicing Round-Trip Guard**: Cross-author surgical edits now preserve whitespace-only insertions (including ordinary-space replacements for NBSP characters beside hyperlinks) and verify the exact accepted-view text before reporting success. A mismatch fails closed with `PATCH_ROUNDTRIP_MISMATCH` and returns the original OOXML unchanged.
217
+ - **Hyperlink-Adjacent Replacement Anchoring**: Paired replacements immediately before or after a hyperlink now retain a stable insertion point after the deletion run is split, preventing qualifiers from being relocated past the hyperlink or following formatted runs.
218
+ - **Multiple Same-Run Insertions**: Insertion-only slicing operations with multiple edit points now apply from right to left against a refreshed live span index, preventing an earlier run split from relocating later insertions.
219
+ - **Insertion Stress Hardening**: Slicing now detects edge whitespace changes exactly, uses a character-local insertion-only diff when the original text is an exact subsequence of the modified text, and coalesces new text into an existing same-author carrier when foreign revisions are also present. This prevents repeated phrases from relocating insertions and prevents invalid `w:ins/w:ins` nesting in mixed-author paragraphs.
220
+ - **Preflight Inspection**: `preflightOperations` now inspects and validates `slice-cross-author` batches, reporting pending foreign-author carrier targets as `ready` instead of `EXISTING_REVISIONS`.
221
+ - **Test Suite Expansion**: Added 7 new test suites covering 36 Word Desktop COM golden fixtures, carrier splitting invariants, the SYN-01..12d synthetic test matrix, PKG-01..06 strict package differential replay, the repeated-text/hyperlink whitespace regression, 76 deterministic insertion stress scenarios, and 12 replacement-anchor lifecycle scenarios (expanding the suite from 88 to 95 passing suites).
222
+
223
+ ## 0.5.0
224
+
225
+ ### ⚠️ Breaking changes
226
+
227
+ The following changes can require caller or contributor updates. No public
228
+ export or valid existing function signature was removed.
229
+
230
+ #### Runtime and result-contract changes
231
+
232
+ - **Canonical paragraph text:** `getParagraphText(...)` now returns the
233
+ accepted/current view instead of the earlier simplified `w:t`/`w:tab`
234
+ concatenation. It excludes deleted and `w:moveFrom` content and includes
235
+ structural breaks, soft hyphens, and non-breaking hyphens.
236
+ **Migration:** regenerate compared/cached text with the upgraded library. Use
237
+ `extractCanonicalParagraphText(...)` when accepted/rejected-view semantics
238
+ are intended; integrations that require the former raw traversal must retain
239
+ their own legacy extractor before upgrading.
240
+ - **Paragraph fingerprints:** fingerprints now incorporate canonical paragraph
241
+ text. Stored fingerprints can become stale for paragraphs containing
242
+ revisions, moves, breaks, soft hyphens, or non-breaking hyphens.
243
+ **Migration:** do not carry fingerprints across this upgrade; re-extract the
244
+ document and regenerate target descriptors.
245
+ - **Invalid operations:** malformed or field-incompatible document-operation
246
+ objects now return a structured `INVALID_OPERATION` error at the runner
247
+ boundary instead of reaching later failure/no-op paths.
248
+ **Migration:** validate operation files against the published schema and
249
+ handle `status === 'error'` plus `error.code === 'INVALID_OPERATION'`.
250
+ - **Commented paragraph deletion:** deleting a complete paragraph that contains
251
+ an existing comment now fails with `COMMENTED_CONTENT_DELETE` instead of
252
+ producing OOXML with dangling comment references.
253
+ **Migration:** preserve or deliberately remove/relocate the comment before
254
+ deleting the paragraph, and handle the structured error. Atomic callers keep
255
+ the original document unchanged.
256
+ - **Comment anchor failures:** missing or ambiguous comment anchors now return
257
+ `ANCHOR_NOT_FOUND` or `AMBIGUOUS_ANCHOR` and fail/roll back an atomic batch;
258
+ they are no longer reported as successful `no_change` operations.
259
+ **Migration:** treat these codes as failed operations and use a unique exact
260
+ anchor or stricter target descriptor before retrying.
261
+ - **Stricter package validation:** DOCX package validation now rejects
262
+ unbalanced comment ranges, dangling references/usages, orphan definitions,
263
+ and duplicate comment-definition IDs that earlier validation could allow.
264
+ **Migration:** repair the comment anchors and `word/comments.xml` definitions
265
+ before applying or validating further changes.
266
+
267
+ #### Development workflow change
268
+
269
+ - **Parallel tests by default:** `npm test` now runs up to four isolated child
270
+ processes concurrently. This does not change the published runtime API, but
271
+ contributor automation that depends on test execution order or shared files
272
+ must be updated. **Migration:** make tests independent or set
273
+ `DOCX_TEST_CONCURRENCY=1` for the previous serial scheduling behavior.
274
+
275
+ Strict targeting remains opt-in on existing low-level mutation APIs; it is the
276
+ default only on the newly added Node facade and CLI.
277
+
278
+ ### Deprecations and future breaking changes
279
+
280
+ - Replacing an existing numbering part without a merge callback now emits a
281
+ deprecation warning. The Node facade and CLI already merge safely by default.
282
+ **This remains supported in this release but will become an error in the next
283
+ major version.** Migrate low-level callers to
284
+ `mergeNumberingXmlBySchemaOrder` before that release.
285
+ - **Permissive target resolution deprecation (`AMBIGUOUS_TARGET_HEURISTIC_USED`):**
286
+ Lower-level document operation runners currently default to permissive targeting.
287
+ In v1.0.0, application will default to `strictTargets: true`. In this release,
288
+ when permissive resolution encounters multiple identical candidate paragraphs and
289
+ heuristically chooses the first candidate, it emits an `AMBIGUOUS_TARGET_HEURISTIC_USED`
290
+ warning with candidate count and migration guidance.
291
+ **Migration:** Disambiguate operations using `paragraphId`, `index`, `occurrence`,
292
+ or `fingerprint` and pass `{ strictTargets: true }`.
293
+
294
+ ### ℹ️ Noteworthy Default & Usability Changes (Non-breaking)
295
+
296
+ The following improvements update default behaviors to maximize agent speed, reduce friction, and eliminate unnecessary errors during iterative editing. These changes are **not technically breaking changes** (no public APIs or exports were removed, and all existing options remain configurable), but represent important behavioral refinements that callers should note:
297
+
298
+ - **Fallback Author Default (`'AI Redliner'`):** `setDefaultAuthor`, `node/cli.js`, and `openDocx` now default to `'AI Redliner'` (configurable via the `DOCX_REDLINE_AUTHOR` environment variable or `--author`). The CLI `apply` command and core APIs no longer error with `AUTHOR_REQUIRED` when operations omit an author.
299
+ - **Output Overwrite by Default:** Destination files provided via `--output` now overwrite by default instead of failing with `OUTPUT_EXISTS`. Callers wanting protection against accidental overwrites can pass `--no-overwrite` or `--no-clobber`. The source document remains protected and is never overwritten unless `--in-place` is explicitly passed.
300
+ - **Replacement Event Pairing (`pairReplacements: true` by default):** Adjacent `<w:del>` and `<w:ins>` revisions now default to sharing linked revision metadata and identical timestamps so Microsoft Word groups them as a single replacement in the Reviewing Pane. Pass `pairReplacements: false` for independent revision timestamps.
301
+ - **Structured Content Auto-Detection (`structuredContent: true` by default):** Markdown tables, headings (`#`), and lists in replacement text automatically render as native Word elements (`w:tbl`, `w:pStyle`, `w:numPr`). Single outline-numbered legal clauses (e.g. `13.2.1.1`) continue to be treated as ordinary paragraphs without spurious list conversion. Pass `structuredContent: false` to treat replacement text strictly as plain text.
302
+ - **Progressive Batch Mode (`atomic: false` default, `atomic: true` opt-in):** Batch operations and CLI `apply` now apply edits progressively by default (`atomic: false`): valid edits commit directly, while failing edits report structured errors in `results` for faster debugging. Pass `{ atomic: true }` (or `--atomic` on the CLI) for all-or-nothing rollback when any operation fails.
303
+ - **Clean Direct Edits (`generateRedlines: false` / `--no-redlines`):** Prominently documented that tracked redlines are not always the preferred method. Callers can pass `generateRedlines: false` (or `--no-redlines` on the CLI) for clean execution drafts, document restructuring, or minor typo fixes without tracked changes markup.
304
+ - **Existing Revisions Policy (`existingRevisions: 'merge-same-author'` by default):** When editing a paragraph that already contains tracked changes from the same author, prior revisions by that author are merged against the pre-revision baseline (prior changes by that author are reverted and re-diffed to the new modified text), avoiding revision accumulation and nested markup. If a paragraph contains tracked changes from another reviewer, the operation fails closed with `EXISTING_REVISIONS` to protect third-party review marks. Commented revision content fails closed with `COMMENTED_CONTENT_MERGE` so comment anchors cannot be removed or orphaned. Callers can explicitly pass `'accept-all-first'` to normalize prior revisions or `'reject-input'` to refuse editing any revised paragraph.
305
+ - **Inline One-Liner CLI Edits:** Added `--target <text>` with `--modified <text>` or `--comment <text>` on `docx-redline apply` for fast 1–2 edit workflows without creating a JSON operations file.
306
+
307
+ ### Added
308
+
309
+ - Added **Mutation Receipts** (`receipt` on `DocumentOperationResult` and `receipts`
310
+ on `BatchOperationResult`). Every operation execution returns structured,
311
+ commit-aware telemetry capturing durable revision IDs (with kind and target part),
312
+ comment IDs, numbering IDs, relationship IDs, affected targets, and warnings.
313
+ Supports `not_attempted`, `applied`, `refused`, `no_change`, and `rolled_back`
314
+ dispositions.
315
+ - Added **Commit-Aware Output Reconciliation Oracle** (`reconcileReceiptsAgainstOutput`).
316
+ Before completing any transaction, reported durable IDs are checked against a
317
+ fresh parse of the generated output OOXML parts. Any reconciliation discrepancy
318
+ immediately fails the transaction and triggers atomic rollback.
319
+ - Exported receipt primitives: `ReceiptCollector`, `createEmptyReceipt`, and
320
+ `reconcileReceiptsAgainstOutput` along with `MutationReceipt` and
321
+ `MutationReceiptRevisionItem` TypeScript declarations.
322
+ - Added **Paragraph Mark Revisions** (`w:pPrChange`, `markParagraphMarkInserted`,
323
+ `markParagraphMarkDeleted`) ensuring whole-paragraph deletions and insertions
324
+ cleanly track paragraph mark lifecycles for full Accept All / Reject All symmetry.
325
+ - Added **Paragraph Boundary Mutation Validation** (`validateParagraphBoundaryMutation`)
326
+ guarding against invalid cross-paragraph boundary merges.
327
+
328
+ - Added `analyzeStructuredContent(...)` and `planStructuredReplacement(...)`
329
+ for agent-authored attachments and schedules containing mixed headings,
330
+ paragraphs, lists, and tables. The planner returns typed blocks and produces
331
+ one atomic `structuredContent` operation only when the Markdown is valid.
332
+
333
+ - Added session-scoped paragraph metadata indexing for canonical text,
334
+ normalized text, paragraph IDs, fingerprints, table context, and document
335
+ indexes, plus deterministic targeting and route-profiling benchmarks.
336
+ - Added a shared list-marker grammar and parsed list-item vocabulary used by
337
+ pipeline analysis, orchestration, normalization, and list targeting.
338
+ - Added an internal reconciliation capability matrix and opt-in route
339
+ instrumentation. Public reconciliation result shapes and route selection
340
+ policy remain unchanged.
341
+
342
+ - Added `scripts/extract_text.mjs` and `scripts/apply_changes.mjs` as thin
343
+ compatibility entrypoints for legacy skill installations. They delegate to
344
+ the supported CLI, retain strict atomic validated writes, and accept legacy
345
+ operation files with a top-level `changes` array.
346
+ - Added typed operations, per-operation authors, strict target descriptors,
347
+ deterministic preflight diagnostics, and auditable resolution metadata.
348
+ - Added `inspectDocumentParts(...)`, a structured document inventory using the
349
+ same canonical text extractor as targeting and ingestion.
350
+ - Added `@ansonlai/docx-redline-js/node`. `openDocx(...)` applies batches to
351
+ complete DOCX buffers transactionally and validates before commit.
352
+ - Added the cross-platform `docx-redline` CLI with JSON `inspect`, `extract`,
353
+ `preflight`, `apply`, `accept`, `reject`, `delete-comments`, and `validate`
354
+ commands, plus a published operation-file JSON Schema.
355
+
356
+ ### Behavior and reliability
357
+
358
+ - Explicit structured replacements now reject missing Markdown table separator
359
+ - Generated Markdown tables repeat their header row and prevent logical data rows from splitting across pages.
360
+ rows, missing data rows, and inconsistent column counts with
361
+ `STRUCTURED_CONTENT_INVALID` instead of inserting literal pipe-delimited text.
362
+ - Tables created inside mixed replacements are tracked once at block scope,
363
+ avoiding nested revisions while keeping Accept All and Reject All symmetric.
364
+
365
+ - Target preflight and live mutation reuse one document-scoped paragraph index;
366
+ strict duplicate detection and resolution metadata retain their prior
367
+ semantics while avoiding repeated whole-document text traversal.
368
+ - Revision-ID seeding now walks the DOM with child/sibling pointers instead of
369
+ allocating an array containing every element.
370
+ - Single-source-paragraph list expansion uses the focused list generator
371
+ directly. Multi-paragraph marked-list edits deliberately retain the legacy
372
+ run-aware reconciliation pipeline for structural parity.
373
+ - Fixed paragraph-to-list expansion when a manually numbered heading carries
374
+ `w:numId w:val="0"`. Numbering suppression is no longer reused as a generated
375
+ list ID, so inserted bullet and numbered items receive valid positive IDs.
376
+ - Tracked heading-to-list replacements now keep the deleted source heading in
377
+ its own paragraph and track the paragraph marks of every inserted list item.
378
+ This prevents deleted heading text from joining the first item and preserves
379
+ exact Accept/Reject structure without adding a full-document sentinel
380
+ paragraph.
381
+ - Inserted list items now inherit source font family, size, language, and
382
+ related script typography without inheriting heading-only bold, underline,
383
+ italic, or strike formatting unless requested by the replacement markdown.
384
+ - Canonical-only table-cell targeting now consumes the shared paragraph-text
385
+ extractor, while offset- and sentinel-producing walkers remain specialized.
386
+ Their accepted visible projections now agree on soft hyphens as well as tabs,
387
+ breaks, hyperlinks, and non-breaking hyphens.
388
+
389
+ - Comment preflight and application now share one anchor resolver. Exact
390
+ matches take priority, unique ordinary-space/NBSP differences preserve raw
391
+ offsets, and missing or repeated anchors return structured
392
+ `ANCHOR_NOT_FOUND` or `AMBIGUOUS_ANCHOR` errors.
393
+ - Full-document operation batches now share one live DOM and revision-ID
394
+ allocator, reducing complete-document parsing and serialization from once per
395
+ operation to once per changed batch. Scoped reconciliation engines and their
396
+ targeting decisions are unchanged.
397
+ - Each live-session operation uses a DOM and allocator savepoint. Errors and
398
+ reported no-ops restore the savepoint; atomic failures and all-no-op batches
399
+ still return the exact original XML without serializing it.
400
+ - Decomposed the standalone document-operation runner into a stable 13-line
401
+ compatibility facade plus focused session, applier, batch-orchestrator,
402
+ heuristic, and OOXML-mutation modules. Runtime exports and declarations are
403
+ unchanged, and operation internals now use leaf imports instead of importing
404
+ the root entry point.
405
+ - Package comment IDs are seeded from existing anchors and definitions, and
406
+ the Node facade merges numbering without discarding prior definitions.
407
+ - Canonical paragraph text consistently handles revisions, moves, tabs,
408
+ breaks, soft hyphens, and non-breaking hyphens; see the breaking-change note
409
+ above for `getParagraphText(...)` and fingerprint compatibility.
410
+ - Structured inspection now explicitly supports the `current` view as the
411
+ accepted/current document view and resolves comment ranges spanning multiple
412
+ paragraphs as one exact anchor string.
413
+ - Transactional no-op results preserve the original DOCX bytes exactly,
414
+ including when the same facade instance has already committed an edit.
415
+
416
+ ### Testing and development
417
+
418
+ - Added focused and semantic visual-failure regressions for suppressed
419
+ numbering, paragraph separation, paragraph-mark revisions, selective
420
+ typography inheritance, and exact accepted/rejected paragraph sequences,
421
+ plus seeded fuzz variants across list length, marker, font, and size.
422
+ Added the independently specified
423
+ `legal-suppressed-heading-to-bullet-list` and
424
+ `legal-structured-attachment-mixed-blocks` Microsoft Word differential
425
+ fixtures; the synthetic catalogue now contains 49 cases and 49 task types.
426
+
427
+ - The JavaScript test runner now uses bounded asynchronous subprocess workers,
428
+ capped at four by default, while retaining one fresh Node process per file,
429
+ sorted reporting, timeouts, captured diagnostics, and failure-marker checks.
430
+ Set `DOCX_TEST_CONCURRENCY=1` for serial reproduction.
431
+ - Added `npm run benchmark:tests` and a Phase 6 runner regression. The checked
432
+ benchmark reduced median suite time from 18.02 seconds to 7.96 seconds
433
+ (55.80%); 20 consecutive parallel runs and a separate serial run passed all
434
+ 63 files. Parallel c8 collection remains valid at 89.90% statements/lines,
435
+ 77.40% branches, and 93.10% functions.
436
+
437
+ - Added Phase 3 targeting/traversal, Phase 4 list/text parity, and Phase 5 route
438
+ compatibility regressions. Together with the Phase 6 runner regression, the
439
+ suite now contains 63 passing test files.
440
+ - Added `npm run benchmark:targeting` and `npm run profile:routes`. The checked
441
+ 10,000-paragraph benchmark showed no single-operation regression and a 47.16x
442
+ Node median improvement for 100 cached resolutions. The equivalent native
443
+ Chrome benchmark showed no single-operation regression and a 36.45x batch
444
+ improvement. All 47 Microsoft Word differential fixtures and all 60 real-
445
+ document Word corpus scenarios passed after the routing changes.
446
+
447
+ - Added subprocess coverage for legacy wrapper selection, operation-file
448
+ compatibility, successful output, atomic anchor failure, source-byte
449
+ preservation, and protection of pre-existing output files.
450
+ - Added a live-session accuracy and instrumentation suite covering accepted and
451
+ rejected text, structural validity, sequential equivalence, comments, lists,
452
+ tables, highlights, one-parse/one-serialize execution, exact no-ops, and
453
+ atomic rollback. Added `npm run benchmark:session`; the checked accuracy-first
454
+ benchmark reduced parse/serialize counts from 10/10 to 1/1 and measured a
455
+ 1.58x median speedup with per-operation savepoints retained.
456
+ - Added a Phase 2 architecture regression covering facade export identity,
457
+ direct leaf imports, exact session rollback, isolated context commit, and
458
+ stable comment-first scheduling.
459
+ - Added five edge-case suites for canonical text views, cross-paragraph comment
460
+ inspection, table/list/reference context, sequential package transactions,
461
+ selective multi-author cleanup, ZIP rejection behavior, CLI filters, JSON
462
+ exit contracts, and destructive-output safeguards. Together with the Phase 2
463
+ Phase 1 and Phase 2 regressions, these established the earlier 57-file
464
+ baseline expanded by the subsequent performance phases.
465
+
466
+ ## 0.3.0
467
+
468
+ ### Breaking changes
469
+
470
+ - Malformed OOXML no longer escapes public transform APIs as a raw parser
471
+ exception. In particular, revision accept/reject and comment-deletion callers
472
+ that previously used `try`/`catch` must now inspect `status === 'error'` and
473
+ `error.code === 'PARSE_ERROR'` on the returned result.
474
+ - Caller content is no longer sanitized by default. Pass `sanitizeInput: true`
475
+ to remove a standalone leading assistant-preface line. Dollar-delimited text
476
+ and literal `\\n` / `\\r\\n` sequences are never removed implicitly.
477
+ - The exported `sanitizeAiResponse` helper no longer removes dollar-delimited
478
+ spans or converts literal `\\n` / `\\r\\n` sequences. Direct callers that
479
+ relied on those transformations must perform them explicitly.
480
+ - `applyOperationsToDocumentXml` is atomic by default. Failed batches return
481
+ the original document with `rolledBack: true`; pass `atomic: false` to retain
482
+ partial-result behavior.
483
+ - Missing multi-line targets now return `TARGET_NOT_FOUND` instead of being
484
+ indistinguishable from a no-op. Stale batch anchors also return
485
+ `TARGET_NOT_FOUND` instead of falling back to a visibly different paragraph.
486
+
487
+ ### Behavior changes and fixes
488
+
489
+ - Revision IDs are now allocated per document. Near-limit prior IDs restart in
490
+ a safe low range, and unrelated bookmark/relationship IDs no longer seed the
491
+ revision counter.
492
+ - Concurrent calls with explicit authors keep their revision attribution
493
+ isolated from process-global defaults.
494
+ - `existingRevisions: 'accept-all-first'` now preserves the original OOXML when
495
+ the requested edit is a no-op.
496
+ - Added `existingRevisions: 'accept-all-first-keep-normalized'` for callers that
497
+ explicitly want accepted existing revisions returned even when no redline is
498
+ added.
499
+ - Diff output is deterministic by default. Inputs exceeding 262,144 unique
500
+ tokens return `DIFF_TOKEN_LIMIT` with the original OOXML unchanged instead of
501
+ risking truncated text; leading whitespace is preserved exactly.
502
+ - Reconstruction preserves structural line breaks and body section-property
503
+ placement. A target that names only part of a reconstruction range now
504
+ returns `PARTIAL_TARGET` instead of risking deletion of untargeted content.
505
+ - Paragraph targeting and reconstruction now preserve leading, middle, and
506
+ trailing `w:tab` elements as literal tab characters instead of omitting or
507
+ trimming them.
508
+ - Adjacent redline edits now preserve complex-field instructions, begin/
509
+ separate/end markers, and unchanged cached display results in their original
510
+ field boundary. Field instructions remain inert and are not evaluated.
511
+ - Added structured XML parse results and result-returning ingestion helpers.
512
+ - Hardened deterministic diff token handling and leading-whitespace fidelity.
513
+
514
+ ### Testing and development
515
+
516
+ - Expanded the desktop Word differential from 20 to 25 cases, adding structural
517
+ checks for bookmarks, internal hyperlinks, mixed formatting, content
518
+ controls, and tables.
519
+ - Expanded the desktop Word differential from 25 to 28 cases with structural
520
+ tabs and a locked PAGE field, and added tab/field shapes to focused and fuzz
521
+ regression testing.
522
+ - Expanded the desktop Word differential from 28 to 33 cases with comments,
523
+ footnotes, endnotes, headers/footers, and an external hyperlink.
524
+ - Extended the deterministic script-only DOCX packager with opt-in related
525
+ parts, relationship/content-type validation, reusable fixture constructors,
526
+ and SHA-256 verification that supplied parts remain byte-identical. Runtime
527
+ library code and dependencies are unchanged.
528
+ - Added validated task, structure, oracle, and manual-review metadata across the
529
+ 33 synthetic and 20 SuperDoc Word cases. `npm run report:word:coverage`
530
+ produces a deterministic coverage matrix with explicit high-priority gap
531
+ dispositions, while `npm run review:word:prepare` creates a pending rotating
532
+ human-review manifest without self-certifying visual results.
533
+ - Added detailed production-function coverage reporting and a checked per-file
534
+ regression baseline. Five behavior-focused Phase 3 suites exercise numbering
535
+ collisions/remapping, every reconciliation route, list construction and
536
+ fallback, patch/format boundaries, table decisions, pipeline modes, and
537
+ standalone rollback/highlight paths. Production function coverage moved from
538
+ 437/540 to 496/542 and all reachable P0 functions are covered; no runtime
539
+ behavior or compatibility contract changed.