@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.
@@ -1,86 +1,76 @@
1
1
  # Skill and Harness Authoring Contract
2
2
 
3
- Use this page when creating or updating an agent skill, MCP server, or custom
4
- harness for `@ansonlai/docx-redline-js`. Ordinary document-editing agents should
5
- load [Agent Fast Start](AGENT_FAST_START.md), not this design contract.
3
+ Use this page to create or update an agent skill, MCP server, or custom harness
4
+ for `@ansonlai/docx-redline-js`. Ordinary editing agents should load
5
+ [Agent Fast Start](AGENT_FAST_START.md), not this design contract.
6
6
 
7
7
  > [!WARNING]
8
- > Before 1.0, every skill or harness must identify and pin its exact tested
9
- > library release and required CLI contract/capabilities. Treat any different
10
- > release or contract as unverified until compatibility tests pass.
8
+ > Before 1.0, every integration must identify and pin its exact tested library
9
+ > release and required CLI contract/capabilities. Treat any different release or
10
+ > contract as unverified until compatibility tests pass.
11
11
 
12
- For example, an integration authored for the current contract-8 release should
13
- record a compatibility declaration equivalent to:
12
+ Example declaration for a contract-8 shell integration that uses localized
13
+ operations over stdin:
14
14
 
15
15
  ```json
16
16
  {
17
- "testedLibraryRelease": "0.7.0",
17
+ "testedLibraryRelease": "0.7.1",
18
18
  "requiredCliContractVersion": 8,
19
19
  "requiredCapabilities": [
20
- "command-help-v1",
20
+ "operations-stdin",
21
+ "agent-safety-profile-v2",
21
22
  "recovery-envelope-v1",
22
- "localized-replacements-v1",
23
- "speculative-search-apply-v1",
24
- "localized-change-summary-v1"
23
+ "localized-replacements-v1"
25
24
  ]
26
25
  }
27
26
  ```
28
27
 
29
- The package pin anchors the release; runtime negotiation proves the executable
30
- exposes the required contract. A new release cannot inherit an old claim.
31
-
32
28
  ## Runtime negotiation
33
29
 
34
- Run this before the first document operation when the skill vendors or invokes
35
- the CLI:
36
-
37
- ```bash
38
- docx-redline version
39
- ```
30
+ Run `docx-redline version` before the first document operation. Require CLI
31
+ contract version 8 and only the capabilities the integration actually uses. Check once per stable
32
+ runtime, fail closed when a requirement is absent, and never inspect bundles or
33
+ ZIP parts as a fallback.
40
34
 
41
- Require contract version 8 (the currently declared contract) and only the
42
- capabilities the integration uses. A typical shell skill should require
43
- `agent-safety-profile-v2`, `deduplicated-cli-receipts`, and
44
- `recovery-envelope-v1`. Require other capabilities only when used. Fail closed
45
- when one is absent; never inspect bundles or ZIP parts as a fallback.
35
+ Do not expose negotiated but unused capabilities as choices in the editing
36
+ prompt. `command-help-v1`, restore shortcuts, speculative apply, and localized
37
+ change summaries are optional requirements only for integrations that use them.
46
38
 
47
39
  ## Safety invariants
48
40
 
49
- Every generated integration must preserve these rules:
41
+ Every generated integration must:
50
42
 
51
- - Inspect narrowly and copy `exactText` plus `paragraphId` or `fingerprint`.
52
- - Treat `modified` as the complete desired accepted-view target content.
53
- - Use strict targeting, package validation, and a derived output path; never
54
- overwrite the source unless the caller explicitly requests `--in-place`.
55
- - Require `completion: true`, `written: true`, a non-null `outputPath`, and no
56
- per-operation error before reporting completion.
57
- - Never accept or reject another reviewer's work or delete comments without
58
- explicit user authorization.
59
- - Never retry unchanged failed arguments.
43
+ - inspect narrowly, retain `exactText`, and target with `paragraphId` plus
44
+ `fingerprint`;
45
+ - use strict targeting, package validation, and a derived output path;
46
+ - never overwrite the source unless `--in-place` is explicitly requested;
47
+ - require `completion: true` and a non-null `outputPath` before reporting
48
+ success;
49
+ - follow `error.recovery.action` and never retry unchanged failed arguments; and
50
+ - require explicit authorization before accepting/rejecting another reviewer's
51
+ work or deleting comments.
60
52
 
61
- The `agent` profile enables complete-success exit behavior and retains the
62
- ordinary progressive default. It does not select atomic execution or a special
63
- existing-revision policy. A skill must state those choices explicitly when its
64
- workflow needs them.
53
+ The CLI computes `completion` from write status, operation outcomes, commit
54
+ disposition, and localized accepted-view verification. Preserve the detailed
55
+ results for audit and recovery, but do not make the editing agent re-evaluate
56
+ those fields during ordinary success handling.
65
57
 
66
58
  ## Workflow policy choices
67
59
 
68
- Choose and document these separately from safety invariants:
60
+ Keep these exceptions separate from the default workflow:
69
61
 
70
- | Choice | Options | Guidance |
62
+ | Choice | Default | Override only when |
71
63
  |---|---|---|
72
- | Transaction | progressive default or `--atomic` | Use progressive for independent edits; use atomic when partial output is unacceptable. |
73
- | Existing revisions | `merge-same-author` default or explicit policy | Use `slice-cross-author` only when editing inside another reviewer's pending insertion is intended. |
74
- | Reviewer identity | flag, operation author, environment, or fallback | `AI Redliner` is a valid visible fallback. `DOCX_REDLINE_AUTHOR` is an optional harness preference, not a guard. |
75
- | Output naming | derived sibling or explicit destination | Keep source immutability unless in-place mutation is deliberately authorized. |
64
+ | Transaction | progressive | Partial output is unacceptable (`--atomic`). |
65
+ | Existing revisions | `merge-same-author` | Editing inside another reviewer's pending insertion is intended (`slice-cross-author`). |
66
+ | Reviewer identity | `AI Redliner` is a valid visible fallback | The host supplies a preferred flag, operation author, or environment value. |
67
+ | Output | derived sibling | The caller deliberately selects another destination. |
76
68
 
77
- Check `effectiveOptions` rather than assuming the resolved transaction,
78
- revision, author, or redline policy.
69
+ Check `effectiveOptions` when an integration deliberately sets a policy.
79
70
 
80
71
  ## Transport choices
81
72
 
82
- A UTF-8 operations file and serializer-backed stdin are peer transports. Choose
83
- the form the host can construct safely:
73
+ A UTF-8 operations file and serializer-backed stdin are peer transports:
84
74
 
85
75
  ```bash
86
76
  docx-redline apply input.docx --operations operations.json --profile agent --output reviewed.docx
@@ -88,46 +78,49 @@ node emit-operations.mjs | docx-redline apply input.docx --operations - --profil
88
78
  ```
89
79
 
90
80
  Use `JSON.stringify` or a structured tool API. Never demonstrate `echo`, a
91
- heredoc, or shell-interpolated legal text. `--compact` changes stdout formatting,
92
- not result semantics. A Node byte-oriented wrapper should call `openDocx` and
93
- return the full structured result rather than recreating the CLI serializer.
81
+ heredoc, or shell-interpolated document text. In JavaScript/TypeScript runtimes
82
+ (Node.js, browsers, Cloudflare Workers, Deno, Bun, or sandboxed environments like
83
+ n8n), an in-process wrapper should call `openDocx(uint8Array)` directly from
84
+ `@ansonlai/docx-redline-js` (or `@ansonlai/docx-redline-js/bundle` for zero-dependency
85
+ standalone sandboxes) and return the structured result instead of recreating CLI
86
+ serialization, ZIP handling, targeting, validation, or rollback.
94
87
 
95
88
  ## Ordinary generated workflow
96
89
 
97
- For an exact mechanical edit whose existing and replacement literals are known,
98
- the first executable example should use the one-turn fast path:
90
+ The first executable editing example in a generated skill must be focused
91
+ extraction:
99
92
 
100
93
  ```bash
101
- docx-redline apply input.docx --find "thirty (30) days" --replace "sixty (60) days" --profile agent --output reviewed.docx
94
+ docx-redline extract input.docx --search "renewal notice" --around 3
102
95
  ```
103
96
 
104
- If the literal is not globally unique, use a longer, fairly unique nearby phrase
105
- as `--search` context. Generic or repeated anchors widen the unioned scope and
106
- may cause `AMBIGUOUS_TARGET`, wasting a recovery turn. Use a directional window
107
- such as `1:3`; use symmetric `--around 3` only when either side is eligible. On
108
- success, `anchorMatchCount > 1` signals a repeated anchor: confirm the returned
109
- location and excerpts. Require `results[i].change` with `committed: true`,
110
- `finalDisposition: "applied"`, and positive accepted-view verification.
97
+ Then apply once using the inspected strong target. Use complete `modified` text
98
+ for a broad semantic revision or `replacements` for a small literal change in
99
+ that target. Keep requested relative wording relative unless the user asks for
100
+ a concrete value.
111
101
 
112
- Semantic requests such as “make this provision mutual” still begin with focused
113
- contextual extraction because the agent must identify and draft the complete
114
- legal change:
102
+ Follow `selection.nextAfter` when extraction is truncated. Output projections must retain
103
+ `selection`, target descriptors, `humanReference`, and revision
104
+ cues.
115
105
 
116
- ```bash
117
- docx-redline extract input.docx --search "termination" --around 3
118
- ```
106
+ ### Observed restore branch
107
+
108
+ If the user requests restoration, search `--view rejected` first. Otherwise
109
+ follow an alternate-view `selection.hint` when returned. Restore only the
110
+ inspected strong target. Require `restore-shortcuts-v1` only if the integration
111
+ uses inline `--restore`; canonical operations remain available.
112
+
113
+ ### Optional speculative execution
119
114
 
120
- Use `selection.nextAfter` with `--after` when truncated. When a search for
121
- deleted or restorable content yields 0 matches in accepted view, follow
122
- `selection.hint` and re-run with `--view rejected`. Apply once per stable batch.
123
- Run `docx-redline apply --help` for canonical redline, whole-paragraph comment,
124
- and rejected-view restore shapes; CLI help documentation fields return canonical
125
- GitHub URLs. The operation schema remains
126
- [document-operations.schema.json](schemas/document-operations.schema.json).
115
+ Do not make speculative apply part of an ordinary generated workflow. A harness
116
+ may opt into `speculative-search-apply-v1` only when it owns a measured confidence
117
+ policy and accepts the recovery cost of a miss. Keep anchor selection,
118
+ directional windows, occurrence handling, and exact matching semantics out of
119
+ the ordinary editing prompt; link to the knowledge base or CLI help instead.
127
120
 
128
121
  ## Recovery contract
129
122
 
130
- Lead error handling with exactly these runtime fields:
123
+ Lead failure handling with these runtime fields:
131
124
 
132
125
  1. `error.recovery.action`
133
126
  2. `error.recovery.requiresReinspection`
@@ -135,32 +128,23 @@ Lead error handling with exactly these runtime fields:
135
128
  4. `error.recovery.sameArgumentsSafe`
136
129
 
137
130
  Use `retryPlan.base` and its operation indexes to select the original or partial
138
- output package. Do not generate a second prose decision tree for every error
139
- code; error messages and bounded diagnostics explain the cause, while the four
140
- fields above determine the next action.
131
+ output package. Do not reproduce an error-code decision tree in the skill.
141
132
 
142
133
  ## Presentation rules
143
134
 
144
- Use `humanReference`, `provision`, or `nearestHeading` in user-facing completion
145
- reports. `P55`, `index: 55`, and phrases such as “the 55th paragraph” are machine
146
- targeting and pagination coordinates, not locations a Word user can follow.
147
- When no formal heading exists, use the returned short text lead. Never replace
148
- an exact machine target with a human-facing reference.
135
+ Use `humanReference`, `provision`, or `nearestHeading` in completion reports.
136
+ Paragraph indexes and `P55`-style references are machine coordinates, not
137
+ locations a document user can follow. Keep the exact machine target internally.
149
138
 
150
139
  ## Generation checklist
151
140
 
152
- - The exact tested library release is recorded and pinned; floating installs
153
- are rejected while the library remains before 1.0.
154
- - The required CLI contract version and minimum capability set are declared,
155
- checked at runtime, and updated only after compatibility tests pass.
156
- - Runtime version and required capabilities are checked once.
157
- - Literal edits use localized replacements and one-turn speculative apply;
158
- semantic drafting starts with focused extraction.
159
- - Successful localized edits require committed, post-mutation `change`
160
- verification before completion is reported.
161
- - Safety invariants are not mixed with transaction or revision-policy choices.
162
- - Operations-file and stdin examples use structured serialization.
163
- - The four-field recovery contract precedes any diagnostic commentary.
164
- - Completion prose uses legal references rather than machine ordinals.
165
- - The wrapper delegates mutation, validation, rollback, comments, numbering,
166
- receipts, and OOXML packaging to the library.
141
+ - Exact tested release, contract 8, and the minimum capability set are pinned.
142
+ - Runtime compatibility is checked once.
143
+ - The first ordinary command is focused extraction.
144
+ - Apply uses the inspected target with `modified` or localized `replacements`.
145
+ - Restore appears only as a user-requested or observed-view branch.
146
+ - Speculative execution is absent unless the harness owns a measured policy.
147
+ - Ordinary success requires `completion: true` and a non-null `outputPath`.
148
+ - Recovery, authorization, source immutability, and structured serialization
149
+ invariants are preserved.
150
+ - Wrappers delegate mutation and OOXML packaging to the library.
package/docs/TESTING.md CHANGED
@@ -31,7 +31,8 @@ fixtures rarely contain.
31
31
  | Live-session accuracy and instrumentation | `node tests/performance_phase1_session_tests.mjs` | One full parse/serialization, sequential semantic equivalence, exact accepted/rejected text, valid revisions, list/table/comment/highlight preservation, savepoint no-ops, and zero-serialization rollback | Desktop Word rendering |
32
32
  | Target hot-path parity | `node tests/performance_phase3_target_hot_paths_tests.mjs` | Cached and uncached resolution metadata parity, duplicate safety, snapshots, session invalidation, and pointer-based revision-ID seeding | Machine-independent latency thresholds |
33
33
  | List and text-walker parity | `node tests/performance_phase4_list_and_text_parity_tests.mjs` | One shared marker vocabulary and canonical/specialized visible-text agreement across structural characters and revision views | That all specialized mappings are interchangeable |
34
- | Route compatibility | `node tests/performance_phase5_route_consolidation_tests.mjs` | Direct/legacy list accepted-rejected parity, numbering artifacts, route selection, capability records, and stable public exports | Permission to migrate the retained multi-paragraph compatibility route |
34
+ | Universal document facade & ZIP | `node tests/universal_docx_document_tests.mjs`, `node tests/universal_zip_archive_tests.mjs`, `node tests/universal_facade_edge_cases_tests.mjs` | Universal `Uint8Array` binary handling, `fflate` compression/decompression, optimistic concurrency, and complete-DOCX operations without Node built-ins | Desktop Word rendering |
35
+ | Sandbox bundle isolation | `node tests/sandbox_bundle_isolation_tests.mjs` | Zero-dependency standalone ESM/CJS bundles execute in restricted VM sandboxes without `process`, `Buffer`, or `require`, with zero Node built-in imports | Web Worker latency |
35
36
  | Cross-author revision slicing | `node tests/cross_author_slicing_fixtures_tests.mjs`, `node tests/cross_author_carrier_splitting_tests.mjs`, `node tests/cross_author_slicing_synthetic_tests.mjs`, `node tests/cross_author_slicing_real_tests.mjs`, `node tests/cross_author_slicing_hyperlink_roundtrip_tests.mjs`, `node tests/cross_author_slicing_insertion_stress_tests.mjs` | Word-native `<w:ins>` splitting, `<w:del>` nesting, multi-author stacking, straddle boundaries, synthetic matrix (SYN-01..12d), strict package differential replay (PKG-01..06), exact hyperlink/NBSP round trips, and 76 insertion stress scenarios | Non-Word consumers beyond OpenXML XSD validation |
36
37
 
37
38
  The package-facade regression opens a real ZIP buffer, adds a comment beside an
@@ -0,0 +1,75 @@
1
+ # Agent Surface Simplification Replay
2
+
3
+ **Date:** 2026-09-14
4
+ **Runtime:** Node.js 24.11.1 on Windows x64
5
+ **Engine:** Current post-0.7.1 source for every policy
6
+ **Command:** `npm run benchmark:agent-surface`
7
+ **Configuration:** 7 measured iterations and 1 warmup per scenario/policy
8
+
9
+ ## Scope
10
+
11
+ This repository-controlled replay compares three workflow policies without
12
+ changing the underlying engine:
13
+
14
+ 1. `v0.6.2-extract-full`: extraction followed by complete modified text.
15
+ 2. `v0.7.1-speculation-led`: speculative literal edits with extraction/apply
16
+ recovery, and extraction for semantic or batch work.
17
+ 3. `simplified-extract-localized`: extraction followed by a compact localized
18
+ operation against `paragraphId` plus `fingerprint`.
19
+
20
+ The six wholly synthetic scenarios cover a long literal edit, semantic drafting,
21
+ repeated visible text, rejected-view restoration, an NBSP-bearing target, and an
22
+ independent two-target batch. Every output is re-extracted and compared with its
23
+ predetermined accepted-view text. Benchmark-only verification calls are not
24
+ counted as workflow calls.
25
+
26
+ ## Aggregate Results
27
+
28
+ | Policy | Correct runs | Total calls | Calls/run | Failed calls | Edit request bytes | Median local ms |
29
+ |---|---:|---:|---:|---:|---:|---:|
30
+ | v0.6.2 extract/full | 42/42 | 84 | 2.00 | 0 | 27,034 | 3.86 |
31
+ | v0.7.1 speculation-led | 42/42 | 77 | 1.83 | 7 | 8,988 | 3.86 |
32
+ | simplified extract/localized | 42/42 | 84 | 2.00 | 0 | 10,661 | 3.77 |
33
+
34
+ The simplified policy reduced generated edit-request bytes by 60.6% relative to
35
+ the complete-paragraph baseline while preserving a fixed two-call workflow and
36
+ zero failed calls. On the long-paragraph case, its median edit request was 193
37
+ bytes rather than 2,104 bytes, a 90.8% reduction.
38
+
39
+ The speculation-led policy saved seven total calls because two unique literal
40
+ scenarios completed in one call. The repeated-text scenario cost three calls and
41
+ one failure on every iteration. This demonstrates both the legitimate one-turn
42
+ benefit and the recovery cost that the simplified default is intended to avoid.
43
+
44
+ The localized form is not always smaller for a short paragraph. In the NBSP
45
+ scenario it used 344 bytes versus 343 bytes for complete modified text. The
46
+ benefit is strongest when the inspected source is long relative to the changed
47
+ span.
48
+
49
+ ## Interpretation
50
+
51
+ The repository evidence supports the surface decision:
52
+
53
+ - keep speculative apply as an available expert/harness capability;
54
+ - do not make ordinary agents classify whether to use it;
55
+ - lead with deterministic extraction and one apply;
56
+ - retain localized replacements after inspection to avoid long output payloads;
57
+ - use compact `paragraphId` plus `fingerprint` targets for localized requests,
58
+ while retaining extracted text locally for drafting; and
59
+ - keep restoration as a request/hint-driven branch.
60
+
61
+ Local execution time is effectively neutral at this scale and remains far below
62
+ agent deliberation or provider latency. No performance claim should be based on
63
+ the small local timing differences in this report.
64
+
65
+ ## Limitations
66
+
67
+ This is a deterministic workflow replay, not a model evaluation. It cannot
68
+ measure reasoning tokens, provider tokenization, transport latency, stochastic
69
+ instruction following, or subjective drafting quality. Repeated external agent
70
+ runs using the same model, prompt, document, and engine are still required before
71
+ claiming end-to-end latency improvement.
72
+
73
+ The machine-readable output is written to
74
+ `tmp/benchmarks/agent-surface-simplification-latest.json` and is intentionally
75
+ not committed.
@@ -0,0 +1,39 @@
1
+ import type { DocumentOperation, DocumentOperationBatchResult, OperationPreflightResult, StandaloneRunnerOptions } from '../services/standalone-operation-runner.js';
2
+ import type { DocumentInspectionOptions, DocumentInspectionResult, RevisionToken } from '../index.js';
3
+
4
+ export interface DocxApplyOptions extends StandaloneRunnerOptions {
5
+ author?: string;
6
+ validate?: boolean;
7
+ }
8
+
9
+ export interface DocxApplyResult extends DocumentOperationBatchResult {
10
+ written: boolean;
11
+ uint8Array: Uint8Array;
12
+ buffer: Uint8Array;
13
+ inspection?: DocumentInspectionResult;
14
+ artifactsChanged?: string[];
15
+ validation?: { originalIssues: unknown[]; generatedIssues: unknown[] };
16
+ issues?: unknown[];
17
+ toUint8Array(): Uint8Array;
18
+ toBuffer(): Uint8Array;
19
+ }
20
+
21
+ export class DocxDocument {
22
+ constructor(input: Uint8Array | ArrayBuffer | string);
23
+ readonly originalBytes: Uint8Array;
24
+ readonly originalBuffer: Uint8Array;
25
+ readonly entries: Map<string, Uint8Array>;
26
+ inspect(options?: DocumentInspectionOptions): DocumentInspectionResult;
27
+ getRevisionToken(): RevisionToken;
28
+ readonly revisionToken: RevisionToken;
29
+ preflight(operations: DocumentOperation[], author?: string, options?: StandaloneRunnerOptions): OperationPreflightResult;
30
+ applyOperations(operations: DocumentOperation[], options?: DocxApplyOptions): Promise<DocxApplyResult>;
31
+ resolveRevisions(action: 'accept' | 'reject', options?: { author?: string; allAuthors?: boolean; validate?: boolean }): Promise<DocxApplyResult>;
32
+ deleteComments(options?: { author?: string; allAuthors?: boolean; validate?: boolean }): Promise<DocxApplyResult>;
33
+ toUint8Array(): Uint8Array;
34
+ toBuffer(): Uint8Array;
35
+ }
36
+
37
+ export function computePackageRevisionToken(input: unknown): RevisionToken;
38
+
39
+ export function openDocx(input: Uint8Array | ArrayBuffer | string): DocxDocument;