@ansonlai/docx-redline-js 0.7.1 → 0.8.0
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.
- package/AGENTS.md +38 -49
- package/ARCHITECTURE.md +30 -10
- package/CHANGELOG.md +63 -3
- package/README.md +35 -23
- package/adapters/xml-adapter.js +84 -56
- package/core/sha256.js +120 -0
- package/dist/docx-redline-js.esm.js +7969 -600
- package/dist/docx-redline-js.esm.js.map +4 -4
- package/dist/docx-redline-js.esm.min.js +115 -102
- package/dist/docx-redline-js.esm.min.js.map +4 -4
- package/dist/docx-redline.bundle.cjs +27385 -0
- package/dist/docx-redline.bundle.cjs.map +7 -0
- package/dist/docx-redline.bundle.js +27376 -0
- package/dist/docx-redline.bundle.js.map +7 -0
- package/docs/AGENT_FAST_START.md +32 -34
- package/docs/AGENT_KNOWLEDGE_BASE.md +408 -380
- package/docs/SKILL_AUTHORING.md +85 -101
- package/docs/TESTING.md +2 -1
- package/docs/validation-reports/2026-09-14-agent-surface-simplification.md +75 -0
- package/document/docx-document.d.ts +39 -0
- package/document/docx-document.js +616 -0
- package/document/zip-archive.js +258 -0
- package/index.d.ts +45 -1
- package/index.js +8 -0
- package/node/cli-help.js +1 -1
- package/node/cli.js +12 -4
- package/node/docx-document.js +11 -355
- package/node/zip-archive.js +28 -38
- package/package.json +16 -11
- package/scripts/build.mjs +40 -5
- package/services/localized-replacement-compiler.js +73 -7
- package/services/revision-token.js +11 -7
- package/services/standalone-operation-runner.d.ts +1 -0
package/AGENTS.md
CHANGED
|
@@ -11,8 +11,8 @@ or an installed plugin bundle to infer public behavior.
|
|
|
11
11
|
| Edit or review a complete `.docx` | [Agent Fast Start](docs/AGENT_FAST_START.md) and the `docx-redline` CLI |
|
|
12
12
|
| Build or update an agent skill/tool wrapper | [Skill Authoring Contract](docs/SKILL_AUTHORING.md), then [README wrapper example](README.md#example-agent-session-wrapper-development-only) |
|
|
13
13
|
| Change paragraph/range reconciliation | `index.js` → `engine/oxml-engine.js` → selected `engine/*-mode.js` |
|
|
14
|
-
| Change complete-document operations | `services/standalone-operation-runner.js` → `services/document-operation-*.js` |
|
|
15
|
-
| Change DOCX ZIP or CLI behavior | `node/index.js`, `node/docx-document.js`, `node/cli.js` |
|
|
14
|
+
| Change complete-document operations | `document/docx-document.js` → `services/standalone-operation-runner.js` → `services/document-operation-*.js` |
|
|
15
|
+
| Change DOCX ZIP or CLI behavior | `document/zip-archive.js`, `node/index.js`, `node/docx-document.js`, `node/cli.js` |
|
|
16
16
|
| Choose or add tests | Closest `tests/*.mjs`, then [Testing Guide](docs/TESTING.md) |
|
|
17
17
|
| Understand ownership/dependencies | [Architecture](ARCHITECTURE.md) |
|
|
18
18
|
|
|
@@ -21,82 +21,71 @@ specific advanced operation, API, or recovery topic you need.
|
|
|
21
21
|
|
|
22
22
|
## Ordinary document edits
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
docx-redline apply contract.docx --search "distinctive nearby heading or phrase" --context-range 1:3 --find "thirty (30) days" --replace "sixty (60) days" --profile agent --output reviewed.docx
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Generic or repeated anchors widen the unioned scope and may return
|
|
33
|
-
`AMBIGUOUS_TARGET`, costing a recovery turn. On success, treat
|
|
34
|
-
`results[i].change.context.anchorMatchCount > 1` as a signal to confirm the
|
|
35
|
-
returned location and excerpts.
|
|
36
|
-
|
|
37
|
-
For semantic drafting, inspect once and apply once. With a structured wrapper,
|
|
38
|
-
use revision-bound handles. For shell-only work, use serializer-backed stdin:
|
|
24
|
+
Use one focused extraction and one apply call. With a structured wrapper, use
|
|
25
|
+
its revision-bound target handles. For shell-only work, use serializer-backed
|
|
26
|
+
stdin and the explicit agent profile:
|
|
39
27
|
|
|
40
28
|
```bash
|
|
41
29
|
docx-redline extract contract.docx --search "termination" --around 3
|
|
42
30
|
node emit-operations.mjs | docx-redline apply contract.docx --operations - --profile agent --compact --output reviewed.docx
|
|
43
31
|
```
|
|
44
32
|
|
|
45
|
-
|
|
46
|
-
`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Require `completion: true
|
|
57
|
-
per-operation errors. Localized edits also require
|
|
58
|
-
`results[i].change.committed: true`, `finalDisposition: "applied"`, and
|
|
59
|
-
`verification.acceptedViewMatchesCompiledText: true`. Follow
|
|
33
|
+
Retain inspected `exactText` for drafting and target with its compact
|
|
34
|
+
`paragraphId` plus `fingerprint`. Use complete `modified` text for a broad
|
|
35
|
+
semantic revision; for a small literal change, use `replacements` so the apply
|
|
36
|
+
payload need not repeat the whole paragraph. Independent strong targets bind to the batch start, so do
|
|
37
|
+
not manually sort around structural edits. Consolidate incompatible writes to
|
|
38
|
+
one source; use captures only for intentional created-content dependencies.
|
|
39
|
+
|
|
40
|
+
If the user requests restoration, search `--view rejected` directly. Otherwise
|
|
41
|
+
follow `selection.hint` if extraction identifies an alternate revision view.
|
|
42
|
+
Restore only the inspected strong target; do not infer adjacent content.
|
|
43
|
+
|
|
44
|
+
Require `completion: true` and a non-null output path. Follow
|
|
60
45
|
`error.recovery.action` and `retryPlan`; never retry unchanged failed arguments.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
46
|
+
Do not accept/reject another reviewer's work or remove comments without explicit
|
|
47
|
+
user authorization. The source is never overwritten unless `--in-place` is
|
|
48
|
+
explicit.
|
|
64
49
|
|
|
65
50
|
The agent profile preserves progressive execution and the ordinary revision
|
|
66
51
|
policy. Add `--atomic` or `--existing-revisions slice-cross-author` only when
|
|
67
52
|
that policy is intended, and confirm the resolved `effectiveOptions`.
|
|
68
53
|
|
|
69
|
-
|
|
70
|
-
revision policies, and failure
|
|
54
|
+
Speculative apply, directional search ranges, advanced restore, rejected-view
|
|
55
|
+
insertion, list, table, formatting, comments, revision policies, and failure
|
|
56
|
+
examples live in the
|
|
71
57
|
[knowledge base](docs/AGENT_KNOWLEDGE_BASE.md#agent-document-workflow-cli) and
|
|
72
58
|
[operation schema](docs/schemas/document-operations.schema.json).
|
|
73
59
|
|
|
74
60
|
## Thin wrappers
|
|
75
61
|
|
|
76
|
-
Wrap the CLI for shell hosts or `openDocx` from
|
|
77
|
-
`@ansonlai/docx-redline-js/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
62
|
+
Wrap the CLI for shell hosts or `openDocx` from `@ansonlai/docx-redline-js`
|
|
63
|
+
(or `@ansonlai/docx-redline-js/bundle` for zero-dependency sandboxes, or
|
|
64
|
+
`@ansonlai/docx-redline-js/node` for backward-compatible Node hosts) for
|
|
65
|
+
byte-oriented hosts. A wrapper should inspect, translate narrow ergonomic inputs
|
|
66
|
+
into canonical operations, call the facade once, and return its structured result.
|
|
67
|
+
Do not reproduce ZIP handling, targeting, revision allocation, comments, numbering,
|
|
68
|
+
validation, or rollback.
|
|
81
69
|
|
|
82
70
|
The stateful wrapper in `examples/agent-session-wrapper.mjs` is a testable
|
|
83
71
|
development demonstration only. It is excluded from package files and exports.
|
|
84
72
|
Production harnesses own their transport and negotiate the minimum CLI
|
|
85
|
-
`contractVersion
|
|
86
|
-
|
|
87
|
-
capabilities; the narrow restore shortcut additionally requires
|
|
88
|
-
`restore-shortcuts-v1`.
|
|
73
|
+
`contractVersion` and capabilities they actually use. Optional capabilities do
|
|
74
|
+
not belong in an ordinary editing prompt merely because the CLI supports them.
|
|
89
75
|
|
|
90
76
|
## Code map
|
|
91
77
|
|
|
92
78
|
```text
|
|
93
|
-
index.js host-independent public API
|
|
94
|
-
|
|
79
|
+
index.js host-independent public API & universal document facade
|
|
80
|
+
adapters/ DOM/XML parser provider with automatic pure-JS fallback
|
|
81
|
+
core/ OOXML primitives, text views, targeting, SHA-256, validation
|
|
82
|
+
document/ universal Uint8Array DOCX facade & fflate ZIP container
|
|
95
83
|
pipeline/ ingestion, diffing, Markdown, lists, serialization
|
|
96
84
|
engine/ reconciliation modes and run-level mutation
|
|
97
85
|
orchestration/ route planning and structural conversion
|
|
98
86
|
services/ document operations, comments, receipts, artifacts
|
|
99
|
-
node/ Node
|
|
87
|
+
node/ Node CLI and backward-compatibility re-exports
|
|
88
|
+
dist/ universal ESM and zero-dependency sandbox bundles
|
|
100
89
|
tests/*.mjs directly runnable suites
|
|
101
90
|
```
|
|
102
91
|
|
package/ARCHITECTURE.md
CHANGED
|
@@ -8,11 +8,12 @@ This repository contains only the publishable package surface:
|
|
|
8
8
|
|
|
9
9
|
- `adapters/`
|
|
10
10
|
- `core/`
|
|
11
|
+
- `document/` (universal complete-DOCX facade & ZIP archive layer)
|
|
11
12
|
- `engine/`
|
|
12
13
|
- `pipeline/`
|
|
13
14
|
- `services/`
|
|
14
15
|
- `orchestration/`
|
|
15
|
-
- `node/` (
|
|
16
|
+
- `node/` (Node CLI & backward-compatibility facade)
|
|
16
17
|
- `index.js`
|
|
17
18
|
- `index.d.ts`
|
|
18
19
|
- `dist/`
|
|
@@ -22,8 +23,9 @@ No Word add-in entrypoints or host-specific integration layers are part of this
|
|
|
22
23
|
## Goals
|
|
23
24
|
|
|
24
25
|
- Preserve Word-compatible redlines by editing OOXML directly.
|
|
25
|
-
- Keep core logic host-independent (no Office.js globals, no Word API calls).
|
|
26
|
-
-
|
|
26
|
+
- Keep core logic and document-level operations host-independent (no Office.js globals, no Word API calls, no runtime Node built-ins like `node:zlib` or `node:crypto`).
|
|
27
|
+
- Standardize complete-document packages on `Uint8Array` binary payloads, pure-JS SHA-256 revision tokens, and `fflate` ZIP container manipulation.
|
|
28
|
+
- Reuse the same engine across Node.js, browsers, Cloudflare Workers, Deno, Bun, and sandboxed runtimes (e.g. n8n Code nodes).
|
|
27
29
|
- Keep generated OOXML schema-safe through shared Word element creation and
|
|
28
30
|
centralized revision metadata helpers.
|
|
29
31
|
|
|
@@ -37,7 +39,12 @@ No Word add-in entrypoints or host-specific integration layers are part of this
|
|
|
37
39
|
│ └── xml-adapter.js
|
|
38
40
|
├── core/
|
|
39
41
|
│ ├── paragraph-text.js
|
|
42
|
+
│ ├── sha256.js
|
|
40
43
|
│ └── word-xml.js
|
|
44
|
+
├── document/
|
|
45
|
+
│ ├── docx-document.js
|
|
46
|
+
│ ├── docx-document.d.ts
|
|
47
|
+
│ └── zip-archive.js
|
|
41
48
|
├── engine/
|
|
42
49
|
│ ├── oxml-engine.js
|
|
43
50
|
│ ├── surgical-mode.js
|
|
@@ -63,16 +70,22 @@ No Word add-in entrypoints or host-specific integration layers are part of this
|
|
|
63
70
|
│ ├── cli.js
|
|
64
71
|
│ ├── zip-archive.js
|
|
65
72
|
│ └── index.js
|
|
73
|
+
├── dist/
|
|
74
|
+
│ ├── docx-redline-js.esm.js
|
|
75
|
+
│ ├── docx-redline.bundle.js
|
|
76
|
+
│ └── docx-redline.bundle.cjs
|
|
66
77
|
├── index.js
|
|
67
78
|
└── index.d.ts
|
|
68
79
|
```
|
|
69
80
|
|
|
70
81
|
## Entry Points
|
|
71
82
|
|
|
72
|
-
- `index.js`: primary host-independent exports for OOXML reconciliation.
|
|
83
|
+
- `index.js`: primary host-independent exports for OOXML reconciliation and universal complete-document operations (`openDocx`, `DocxDocument`, `computePackageRevisionToken`).
|
|
84
|
+
- `document/docx-document.js`: universal `Uint8Array`-based document facade and package-level operation runner.
|
|
85
|
+
- `dist/docx-redline.bundle.js` / `dist/docx-redline.bundle.cjs`: zero-dependency standalone sandbox bundles, exported via `@ansonlai/docx-redline-js/bundle`.
|
|
73
86
|
- `services/standalone-operation-runner.js`: stable complete-document XML
|
|
74
87
|
operations, exported as `@ansonlai/docx-redline-js/standalone-runner`.
|
|
75
|
-
- `node/index.js`: Node-
|
|
88
|
+
- `node/index.js`: Node-compatible complete-DOCX facade re-exports, exported as
|
|
76
89
|
`@ansonlai/docx-redline-js/node`.
|
|
77
90
|
- `bin/docx-redline.js`: CLI launcher; command implementation lives in
|
|
78
91
|
`node/cli.js` and shared operation behavior lives in `services/`.
|
|
@@ -181,11 +194,18 @@ No Word add-in entrypoints or host-specific integration layers are part of this
|
|
|
181
194
|
- `services/document-inspection.js`
|
|
182
195
|
- Read-only paragraphs/comments inventory with target identity, headings,
|
|
183
196
|
revision authors, table context, and advisory visible numbering.
|
|
184
|
-
- `
|
|
185
|
-
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
197
|
+
- `document/docx-document.js`
|
|
198
|
+
- Universal transactional whole-DOCX editing, artifact wiring, validation, and rollback.
|
|
199
|
+
Standardized on `Uint8Array` binary payloads and pure-JS SHA-256 revision tokens.
|
|
200
|
+
Exposes `openDocx`, `DocxDocument`, and `computePackageRevisionToken` directly across all runtimes.
|
|
201
|
+
- `document/zip-archive.js`
|
|
202
|
+
- Universal, pure-JS ZIP archive reader and writer based on `fflate`. Operates on
|
|
203
|
+
`Uint8Array` byte arrays with zero Node built-ins (`node:zlib`, `Buffer`).
|
|
204
|
+
- `core/sha256.js`
|
|
205
|
+
- Pure-JS synchronous implementation of FIPS 180-4 SHA-256 with zero dependencies,
|
|
206
|
+
enabling deterministic revision tokens in sandboxed runtimes without `node:crypto`.
|
|
207
|
+
- `node/docx-document.js` and `node/zip-archive.js`
|
|
208
|
+
- Node-compatible re-exports maintaining `Buffer` compatibility for `@ansonlai/docx-redline-js/node`.
|
|
189
209
|
- `node/cli.js` and `bin/docx-redline.js`
|
|
190
210
|
- Cross-platform, JSON-only agent command boundary. Read commands never
|
|
191
211
|
mutate; write commands require attribution, use package transactions, and
|
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,73 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
3
|
+
## 0.8.0
|
|
4
|
+
|
|
5
|
+
### Universal Document Facade & Zero-Node Architecture
|
|
6
|
+
|
|
7
|
+
- **Universal `DocxDocument` & `openDocx`:** Implemented complete-DOCX lifecycle operations
|
|
8
|
+
(`openDocx`, `doc.inspect()`, `doc.applyOperations()`, `doc.resolveRevisions()`, `doc.deleteComments()`,
|
|
9
|
+
`doc.toUint8Array()`, `doc.getRevisionToken()`) on standard `Uint8Array` in `document/docx-document.js`,
|
|
10
|
+
re-exported directly from `index.js`. Enables complete-document redline workflows in any JavaScript
|
|
11
|
+
runtime without Node.js dependencies.
|
|
12
|
+
- **Pure-JS ZIP container (`fflate`):** Replaced `node:zlib` with lightweight, zero-dependency `fflate`
|
|
13
|
+
in `document/zip-archive.js`, providing cross-runtime raw DEFLATE / INFLATE compression and decompression
|
|
14
|
+
with full OOXML archive compatibility.
|
|
15
|
+
- **Pure-JS FIPS 180-4 SHA-256:** Created zero-dependency, synchronous SHA-256 implementation in
|
|
16
|
+
`core/sha256.js`, removing `node:crypto` from package revision token calculations while retaining
|
|
17
|
+
exact deterministic hash parity with standard NIST vectors.
|
|
18
|
+
- **Transparent XML DOM fallback:** Added `resolveDomParserConstructor()` and
|
|
19
|
+
`resolveXmlSerializerConstructor()` in `adapters/xml-adapter.js`, automatically utilizing native
|
|
20
|
+
`globalThis.DOMParser`/`globalThis.XMLSerializer` when present and falling back transparently to
|
|
21
|
+
`@xmldom/xmldom` in headless, server, edge, and sandbox environments without requiring manual provider setup.
|
|
22
|
+
- **Zero-dependency sandbox bundles:** Configured `scripts/build.mjs` with `esbuild` (`platform: 'neutral'`)
|
|
23
|
+
to produce single-file, zero-dependency standalone bundles in both ESM (`dist/docx-redline.bundle.js`)
|
|
24
|
+
and CommonJS (`dist/docx-redline.bundle.cjs`), exported as `@ansonlai/docx-redline-js/bundle` for direct
|
|
25
|
+
use in workflow engines (e.g., n8n Code nodes), Cloudflare Workers, AWS Lambda, Deno, and QuickJS sandboxes.
|
|
26
|
+
- **Strict runtime boundary enforcement:** Removed `node:zlib` and `node:crypto` from allowed external
|
|
27
|
+
imports in `tests/no_word_api_index_check.mjs`. Automated sandbox isolation tests
|
|
28
|
+
(`tests/sandbox_bundle_isolation_tests.mjs`) verify zero Node built-in imports and full document
|
|
29
|
+
reconciliation in restricted VM contexts without `process`, `Buffer`, or `require`.
|
|
30
|
+
- **Backward compatibility:** Preserved full API and `Buffer` compatibility for `@ansonlai/docx-redline-js/node`
|
|
31
|
+
consumers and `doc.toBuffer()`.
|
|
32
|
+
|
|
33
|
+
## 0.7.2
|
|
34
|
+
|
|
35
|
+
### Agent Surface Simplification
|
|
36
|
+
|
|
37
|
+
- **Extraction-first golden path:** Re-established the single deterministic two-turn
|
|
38
|
+
"extract-then-apply" sequence as the default agent workflow across `AGENTS.md`,
|
|
39
|
+
`docs/AGENT_FAST_START.md`, and `docs/SKILL_AUTHORING.md`. Eliminates the
|
|
40
|
+
upfront "choice tax" and model deliberation overhead.
|
|
41
|
+
- **Localized replacements after inspection:** Decoupled localized patching from
|
|
42
|
+
speculation. Agents inspect the target paragraph first, then supply compact
|
|
43
|
+
`replacements` instructions, achieving 60.6%–90.8% payload reductions without
|
|
44
|
+
speculative ambiguity risk.
|
|
45
|
+
- **Computed success gate:** Consolidated standard success verification onto
|
|
46
|
+
`completion: true` and non-null `outputPath`, removing multi-field verification
|
|
47
|
+
checklists from primary prompts while retaining full `change` audit evidence.
|
|
48
|
+
- **Advanced features relocated:** Speculative 1-turn apply, directional context
|
|
49
|
+
windows (`--context-range`), and anchor diagnostics are relocated to
|
|
50
|
+
`docs/AGENT_KNOWLEDGE_BASE.md` and CLI help as opt-in harness policies.
|
|
51
|
+
- **Observed-state restoration:** Restructured restoration as a clean request-
|
|
52
|
+
or hint-driven branch (`--view rejected` or `selection.hint`) rather than an
|
|
53
|
+
upfront classification decision.
|
|
54
|
+
- **Empirical surface evaluation:** Added synthetic replay benchmark
|
|
55
|
+
(`npm run benchmark:agent-surface`) and validation report documenting 100%
|
|
56
|
+
first-attempt task correctness and payload savings across three workflow policies.
|
|
57
|
+
|
|
58
|
+
## 0.7.1
|
|
59
|
+
|
|
60
|
+
### Reliability and Discovery Refinements
|
|
61
|
+
|
|
62
|
+
- Localized replacement matching now tries exact case-sensitive text first,
|
|
63
|
+
then a narrow ASCII-space/non-breaking-space equivalent match. Ambiguous
|
|
64
|
+
equivalent matches still fail closed, and unchanged boundary NBSPs are
|
|
65
|
+
retained to avoid incidental whitespace redlines.
|
|
5
66
|
- Added a narrow single-paragraph restore shortcut. A restore with a strong
|
|
6
67
|
rejected-view target may omit `modified` for verbatim restoration or provide
|
|
7
68
|
exact `replacements`; the CLI exposes the same path through `apply --restore
|
|
8
69
|
--target-id ID`. Ranges, captures, weak targets, and inferred companion
|
|
9
70
|
content remain excluded.
|
|
10
|
-
|
|
11
71
|
- Fixed rejected-view restore receipts so `resolvedTarget` text, fingerprint,
|
|
12
72
|
revision view, and match diagnostics describe the view actually used to
|
|
13
73
|
resolve the target.
|
package/README.md
CHANGED
|
@@ -16,18 +16,16 @@ Converts AI-generated or programmatic text/markdown edits into valid Office Open
|
|
|
16
16
|
- Highlights: apply highlight colors to runs
|
|
17
17
|
- Markdown and OOXML conversion in both directions
|
|
18
18
|
- Status/error result fields for parse, targeting, and existing-revision failures
|
|
19
|
-
- Localized exact replacements
|
|
19
|
+
- Localized exact replacements against inspected targets, plus optional fail-closed speculative CLI edits
|
|
20
20
|
- Package plumbing helpers for numbering.xml, comments.xml, content types, and relationships
|
|
21
21
|
- Zero host dependencies: works in Node.js, browsers, Deno, and similar JS runtimes with DOM parsing support
|
|
22
22
|
|
|
23
23
|
## What's New in 0.7.0
|
|
24
24
|
|
|
25
|
-
Version 0.7.0 adds
|
|
26
|
-
|
|
27
|
-
paragraph
|
|
28
|
-
|
|
29
|
-
attempt with a signed directional window. Generic or repeated anchors widen the
|
|
30
|
-
unioned scope and may cause a safe ambiguity failure and another tool turn.
|
|
25
|
+
Version 0.7.0 adds contract-8 localized edits. Agents can send a small
|
|
26
|
+
`find`/`replace` request against an inspected target instead of reproducing a
|
|
27
|
+
complete paragraph. An optional speculative form may omit the strong target
|
|
28
|
+
when the source literal resolves uniquely; advanced scoping is described below.
|
|
31
29
|
|
|
32
30
|
Speculative edits fail without writing when the anchor, paragraph, or source
|
|
33
31
|
span is missing or ambiguous. Successful localized results include a committed
|
|
@@ -249,18 +247,10 @@ latency. Checked comparative results are in the
|
|
|
249
247
|
### Agent CLI
|
|
250
248
|
|
|
251
249
|
```bash
|
|
252
|
-
#
|
|
253
|
-
docx-redline apply contract.docx --find "thirty (30) days" --replace "sixty (60) days" --profile agent --output reviewed.docx
|
|
254
|
-
|
|
255
|
-
# Directional context using a longer phrase with a higher chance of uniqueness
|
|
256
|
-
docx-redline apply contract.docx --search "distinctive nearby heading or phrase" --context-range 1:3 --find "thirty (30) days" --replace "sixty (60) days" --profile agent --output reviewed.docx
|
|
257
|
-
|
|
258
|
-
# Semantic drafting still starts with focused context
|
|
250
|
+
# Default agent workflow: inspect once, then apply once
|
|
259
251
|
docx-redline extract contract.docx --search "termination" --around 3
|
|
260
|
-
docx-redline
|
|
261
|
-
|
|
262
|
-
docx-redline validate reviewed.docx
|
|
263
|
-
```
|
|
252
|
+
node emit-operations.mjs | docx-redline apply contract.docx --operations - --profile agent --compact --output reviewed.docx
|
|
253
|
+
```
|
|
264
254
|
|
|
265
255
|
```bash
|
|
266
256
|
# Inline one-liner edit (no operations file needed)
|
|
@@ -275,9 +265,9 @@ docx-redline apply contract.docx --target "Another author's clause" --modified "
|
|
|
275
265
|
# High-assurance atomic batch with nonzero exit on any incomplete result
|
|
276
266
|
docx-redline apply contract.docx --operations operations.json --atomic --require-complete --output reviewed.docx
|
|
277
267
|
|
|
278
|
-
#
|
|
279
|
-
|
|
280
|
-
```
|
|
268
|
+
# Optional read-only audit before a deliberately staged batch
|
|
269
|
+
docx-redline preflight contract.docx --operations operations.json --author "Editor"
|
|
270
|
+
```
|
|
281
271
|
|
|
282
272
|
All commands emit JSON on stdout. `apply` defaults:
|
|
283
273
|
- **Author**: Defaults to `'AI Redliner'` (or `DOCX_REDLINE_AUTHOR` environment variable).
|
|
@@ -290,7 +280,8 @@ All commands emit JSON on stdout. `apply` defaults:
|
|
|
290
280
|
- **Compact stdout**: `--compact` emits one-line mutation JSON. It changes serialization only, not operation semantics.
|
|
291
281
|
- **Tracked changes**: Defaults to `generateRedlines: true`. Pass `--no-redlines` when clean direct text edits are desired.
|
|
292
282
|
- **Inline edits**: Use `--target <text>` with `--modified <text>` or `--comment <text>` for quick one-liners without creating a JSON file.
|
|
293
|
-
- **Localized edits**:
|
|
283
|
+
- **Localized edits**: After extraction, use `replacements` with the inspected `paragraphId` plus `fingerprint` to avoid restating a long paragraph. Retain `exactText` locally for drafting. Targetless `--find`/`--replace` is an optional speculative path described below.
|
|
284
|
+
- **Invisible spaces**: Localized matching is case-sensitive and tries exact text first. If no exact span exists, ordinary spaces may match DOCX non-breaking spaces; ambiguous equivalent matches still fail closed, and `change.replacements[i].matchMode` reports `space_equivalent` when used.
|
|
294
285
|
- **Compact mutation results**: `apply`, `accept`, `reject`, and `delete-comments` omit full OOXML/package payloads and inspection text from stdout. CLI operation results omit duplicate nested receipt bodies; the ordered top-level `receipts` array is authoritative. Successful exact target-match diagnostics are omitted and equivalent-whitespace matches retain only mode/count. Node and standalone-runner results remain unchanged. Use `validate` when full issue arrays are needed.
|
|
295
286
|
|
|
296
287
|
Inspection commands default to 20 direct matches and a 48 KiB soft response
|
|
@@ -312,10 +303,31 @@ user-facing Word locations; use `humanReference`, `provision`, or
|
|
|
312
303
|
`agent-safety-profile-v2`, `deduplicated-cli-receipts`, and
|
|
313
304
|
`compact-cli-json-v1`, `localized-replacements-v1`,
|
|
314
305
|
`speculative-search-apply-v1`, `localized-change-summary-v1`, and
|
|
315
|
-
`restore-shortcuts-v1` capabilities.
|
|
306
|
+
`restore-shortcuts-v1`, plus `localized-space-equivalence-v1` capabilities.
|
|
316
307
|
Wrappers should negotiate only the
|
|
317
308
|
capabilities they use. Run `docx-redline <command> --help` for that command's
|
|
318
309
|
machine-readable options, behavior, exit codes, canonical GitHub documentation links, and compact examples.
|
|
310
|
+
|
|
311
|
+
#### Optional speculative CLI path
|
|
312
|
+
|
|
313
|
+
Harnesses with a measured confidence policy may attempt a targetless localized
|
|
314
|
+
edit. This is not the default agent workflow:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
# Globally unique literal
|
|
318
|
+
docx-redline apply contract.docx --find "thirty (30) days" --replace "sixty (60) days" --profile agent --output reviewed.docx
|
|
319
|
+
|
|
320
|
+
# Optional directional scope using a longer, fairly unique nearby phrase
|
|
321
|
+
docx-redline apply contract.docx --search "distinctive nearby heading or phrase" --context-range 1:3 --find "thirty (30) days" --replace "sixty (60) days" --profile agent --output reviewed.docx
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Generic or repeated anchors can widen the unioned scope until multiple
|
|
325
|
+
paragraphs contain `find`, causing a safe `AMBIGUOUS_TARGET` failure and a
|
|
326
|
+
recovery turn. `--around 3` is symmetric. On success,
|
|
327
|
+
`change.context.anchorMatchCount > 1` signals a repeated anchor; confirm the
|
|
328
|
+
returned location and bounded evidence. Matching remains case-sensitive and
|
|
329
|
+
exact-first, with a narrow ordinary-space/NBSP fallback that still refuses
|
|
330
|
+
ambiguity.
|
|
319
331
|
|
|
320
332
|
See the [compact agent fast start](./docs/AGENT_FAST_START.md), the
|
|
321
333
|
[skill/harness authoring contract](./docs/SKILL_AUTHORING.md), and the
|
package/adapters/xml-adapter.js
CHANGED
|
@@ -1,64 +1,92 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* XML adapter for parser/serializer portability.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
1
|
+
/**
|
|
2
|
+
* XML adapter for parser/serializer portability.
|
|
3
|
+
*
|
|
4
|
+
* Transparently uses browser-provided DOMParser/XMLSerializer when available in
|
|
5
|
+
* standard web runtimes, automatically falling back to pure-JS @xmldom/xmldom in
|
|
6
|
+
* Node.js and sandbox environments. Consumers can also explicitly override these
|
|
7
|
+
* constructors via configureXmlProvider.
|
|
6
8
|
*/
|
|
7
9
|
|
|
10
|
+
import { DOMParser as XmlDomParser, XMLSerializer as XmlDomSerializer } from '@xmldom/xmldom';
|
|
8
11
|
import { warn as logWarning, error as logError } from './logger.js';
|
|
9
12
|
|
|
10
|
-
let _DOMParser =
|
|
11
|
-
let _XMLSerializer =
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Configures XML provider constructors.
|
|
15
|
-
*
|
|
16
|
-
* @param {Object} [options={}] - Provider overrides
|
|
17
|
-
* @param {typeof DOMParser} [options.DOMParser] - DOMParser constructor
|
|
18
|
-
* @param {typeof XMLSerializer} [options.XMLSerializer] - XMLSerializer constructor
|
|
19
|
-
*/
|
|
20
|
-
export function configureXmlProvider(options = {}) {
|
|
21
|
-
if (options
|
|
22
|
-
if (options
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
|
|
13
|
+
let _DOMParser = null;
|
|
14
|
+
let _XMLSerializer = null;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Configures XML provider constructors.
|
|
18
|
+
*
|
|
19
|
+
* @param {Object} [options={}] - Provider overrides
|
|
20
|
+
* @param {typeof DOMParser} [options.DOMParser] - DOMParser constructor
|
|
21
|
+
* @param {typeof XMLSerializer} [options.XMLSerializer] - XMLSerializer constructor
|
|
22
|
+
*/
|
|
23
|
+
export function configureXmlProvider(options = {}) {
|
|
24
|
+
if ('DOMParser' in options) _DOMParser = options.DOMParser;
|
|
25
|
+
if ('XMLSerializer' in options) _XMLSerializer = options.XMLSerializer;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the active DOMParser constructor.
|
|
30
|
+
*
|
|
31
|
+
* Priority order:
|
|
32
|
+
* 1. Explicitly configured constructor (via configureXmlProvider)
|
|
33
|
+
* 2. Host environment native DOMParser (globalThis.DOMParser)
|
|
34
|
+
* 3. Pure-JS @xmldom/xmldom fallback
|
|
35
|
+
*
|
|
36
|
+
* @returns {typeof DOMParser}
|
|
37
|
+
*/
|
|
38
|
+
export function resolveDomParserConstructor() {
|
|
39
|
+
return _DOMParser || globalThis.DOMParser || XmlDomParser;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Resolves the active XMLSerializer constructor.
|
|
44
|
+
*
|
|
45
|
+
* Priority order:
|
|
46
|
+
* 1. Explicitly configured constructor (via configureXmlProvider)
|
|
47
|
+
* 2. Host environment native XMLSerializer (globalThis.XMLSerializer)
|
|
48
|
+
* 3. Pure-JS @xmldom/xmldom fallback
|
|
49
|
+
*
|
|
50
|
+
* @returns {typeof XMLSerializer}
|
|
51
|
+
*/
|
|
52
|
+
export function resolveXmlSerializerConstructor() {
|
|
53
|
+
return _XMLSerializer || globalThis.XMLSerializer || XmlDomSerializer;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Creates a parser instance.
|
|
58
|
+
*
|
|
59
|
+
* @param {Object} [options={}] - Parser options (e.g. { onError } for xmldom)
|
|
60
|
+
* @returns {DOMParser}
|
|
61
|
+
*/
|
|
30
62
|
export function createParser(options = {}) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
* @param {string} xmlString - XML string
|
|
59
|
-
* @param {string} [contentType='text/xml'] - MIME type
|
|
60
|
-
* @returns {Document}
|
|
61
|
-
*/
|
|
63
|
+
const ParserCtor = resolveDomParserConstructor();
|
|
64
|
+
if (!ParserCtor) {
|
|
65
|
+
throw new Error('DOMParser is not configured and no fallback XML parser is available.');
|
|
66
|
+
}
|
|
67
|
+
return new ParserCtor(options);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Creates a serializer instance.
|
|
72
|
+
*
|
|
73
|
+
* @returns {XMLSerializer}
|
|
74
|
+
*/
|
|
75
|
+
export function createSerializer() {
|
|
76
|
+
const SerializerCtor = resolveXmlSerializerConstructor();
|
|
77
|
+
if (!SerializerCtor) {
|
|
78
|
+
throw new Error('XMLSerializer is not configured and no fallback XML serializer is available.');
|
|
79
|
+
}
|
|
80
|
+
return new SerializerCtor();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Parses XML text into a DOM document.
|
|
85
|
+
*
|
|
86
|
+
* @param {string} xmlString - XML string
|
|
87
|
+
* @param {string} [contentType='text/xml'] - MIME type
|
|
88
|
+
* @returns {Document}
|
|
89
|
+
*/
|
|
62
90
|
export function parseXml(xmlString, contentType = 'text/xml') {
|
|
63
91
|
const result = parseOoxmlSafe(xmlString, contentType);
|
|
64
92
|
if (result.error) {
|