Skip to main content
Glama

doc-control

Built with claude-arsenal

doc-control MCP server – quality and maintenance score on Glama

Status: file engine working (pre-1.0; the API may still change). The live engine drives LibreOffice Writer and Microsoft Word (Windows). See status/specification.md and status/plan.md.

A deterministic tool that lets AI agents work on Word documents quickly, precisely and safely, ideally live in the Word window the writer has open. Every content change is a tracked change the writer can accept or reject.

For anyone — writers and editors first — who wants an AI agent's help inside a Word document without a single silent change.

Install without Python (Windows)

No Python needed. Every release on the latest release page carries a Claude Desktop extension and an installer. Both install for the current Windows user only, need no admin rights, and work with any Claude account, the free plan included. They drive Microsoft Word live; LibreOffice live control still needs the Python install below. The full guide (checksums, updates, uninstalling, moving from uvx) is docs/install-windows.md.

Claude Desktop extension (.mcpb)

  1. Download doc-control-X.Y.Z-windows-x64.mcpb from the latest release.

  2. Drag the file onto Claude Desktop's Settings > Extensions page and click Install.

Claude Desktop then warns, in red, that the extension can access everything on your computer. Every local extension gets that warning; it is expected. Double-clicking the file does not install it: Windows only asks which program should open it.

Installer (-setup.exe), for the command line

  1. Download doc-control-X.Y.Z-windows-x64-setup.exe from the latest release.

  2. Double-click it.

  3. If Windows SmartScreen says "Windows protected your PC", click More info, then Run anyway (the installer is not code-signed).

  4. Click Install, Next and Finish, and open a new terminal: doc-control server.capabilities works there.

To update, install the newer release the same way. To uninstall, remove the extension from Settings > Extensions, or the installer's copy from Windows Settings > Apps ("doc-control X.Y.Z"). A winget package is coming.

Related MCP server: word-mcp-live

Usage

Install with pip install doc-control (or run it without installing: uvx doc-control). Python 3.11+, no other dependencies. To drive the Word that is open on Windows, install doc-control[live] (it adds pywin32); LibreOffice needs no extra package.

Command line, JSON in and JSON out:

doc-control doc.outline --json '{"doc": "Novela.docx"}'
doc-control text.find --json '{"doc": "Novela.docx", "query": "lluvia"}'
doc-control doc.batch --json '{"doc": "Novela.docx", "ops": [
  {"op": "text.replace", "at": "p12#a7b2a7b2:4-10", "text": "nieve"},
  {"op": "comment.add", "at": "p40#c0ffee00", "text": "¿Seguro?"}]}'
doc-control server.help doc.batch   # the JSON Schema of any operation

Every write is a tracked change by DOC_CONTROL_AUTHOR (default Claude), made after a backup and verified, with history.undo and history.* to go back. Addresses like p12#a7b2a7b2 come from read results and fail loudly if the paragraph changed. One edit can also go straight to its own operation (text.replace, para.insert, para.delete, comment.add, revision.accept, revision.reject), which runs it as a one-edit doc.batch.

For a change the writer has already approved in the chat, batch, term.rename and restore take "tracked": false: the same edit with this call's own revisions accepted in the same verified write, so no revision mark is left (other tracked changes stay; a paragraph that holds one is refused). Tracked stays the default. undo of a plain write restores the backup, so it works only while the document is exactly as that write left it (later edits must be undone first; otherwise BATCH_CONFLICT). A plain edit inside a tracked-inserted table row is allowed; rejecting that row later removes the plain text too. File engine only for now.

From Python, a document can be held open for many reads, with whole results:

from doc_control import api

with api.open("Novela.docx") as doc:
    for p in doc.paragraphs(normalized=True, pages=True):
        print(p["at"], p["style_name"], p["page"], p["text"][:40])
    chapters = doc.run("doc.segment", {"unit": "chapters"})["chapters"]

Recipes propose batches of fixes (Spanish typography, quotes, dashes, spacing, empty paragraphs and more): recipe.list, then recipe.run returns a batch to review and apply.

Notes, headers, footers and tables

Reads cover the body only unless asked; stories opts in to the rest ("notes" for footnotes and endnotes, "headers" for headers and footers) on para.list, text.find, para.locate, para.get, doc.outline, doc.stats and revision.list. Their paragraphs carry an address with a prefix (fn3/p1#0c9e0c9e, en2/…, hdr1.default/…, ftr1.first/…) that the edit operations accept, so a tracked edit inside a footnote or a running header works like one in the body. A body read stays as fast as before.

doc-control para.list --json '{"doc": "Tesis.docx", "stories": ["body", "notes"]}'
doc-control text.replace --json '{"doc": "Tesis.docx", "at": "fn3/p1#0c9e0c9e:4-10", "text": "2019"}'
doc-control note.add --json '{"doc": "Tesis.docx", "at": "p40#c0ffee00:17", "kind": "footnote", "text": "Ver el cap. 2."}'
doc-control section.list --json '{"doc": "Tesis.docx"}'
doc-control table.get --json '{"doc": "Tesis.docx", "table": 1}'
doc-control table.row.insert --json '{"doc": "Tesis.docx", "table": 1, "after_row": 2, "cells": ["a", "b"]}'
doc-control table.row.delete --json '{"doc": "Tesis.docx", "table": 1, "row": 4}'

note.add inserts the reference mark and the note as tracked insertions (rejecting them removes both); the row operations write tracked row insertions and deletions. All of it is backed up, verified and undoable like any other write. scripts/real_word_stories.py checks it in real Word (see docs/real-word-check.md).

Page layout: front matter, numbering, headers and fields

layout.get returns the document's page plan: per section where it starts (from), its break, its page numbering and its header and footer text per kind (default, first, even; null inherits the previous section's). layout.apply takes a plan in the same shape and brings the document to it. This one gives a novel an unnumbered title page, then starts chapter 1 on a right-hand page numbered 1, with the chapter title in the odd headers and the book title in the even ones:

doc-control layout.get --json '{"doc": "Novela.docx"}'
doc-control layout.apply --json '{"doc": "Novela.docx", "untracked": true, "plan": {
  "version": 1, "two_sided": true, "mirror_margins": true,
  "sections": [
    {"from": "p1#ea7412aa", "break": "nextPage",
     "numbering": {"shown": false, "start": 1, "format": "lowerRoman"},
     "header": {"default": "", "even": ""}, "footer": {"default": "", "even": ""}},
    {"from": "p2#5fac7aad", "break": "oddPage",
     "numbering": {"shown": true, "start": 1, "format": "decimal"},
     "header": {"default": "{chapter}", "even": "La casa del río"},
     "footer": {"default": "{PAGE}", "even": "{PAGE}"}}]}}'

Each from is the address of the paragraph the section starts at (from doc.outline or para.list). {PAGE}, {NUMPAGES} and {chapter} (the current Heading 1) become fields. Keys left out stay as they are. Breaks and numbering go in as tracked changes; a new header or footer part and the two-sided and mirror settings cannot be tracked in Word, so the plan needs untracked: true (without it the answer names what needs it). Run it with "dry_run": true first to see the changes; nothing is written unless the plan read back from the result equals the request. A new section break adds a paragraph to carry it, so the addresses after it renumber: read them again with layout.get.

Fields: field.list shows every field (TOC, PAGE, SEQ, REF, citations) and whether its result is stale; toc.insert, caption.add, xref.add, index.mark and index.insert add them as tracked insertions; field.update refreshes the TOC, page, sequence and reference results through headless LibreOffice (ENGINE_UNAVAILABLE without it; set_update_on_open asks Word to refresh them on open instead). An index is built by Word (F9); citation fields are never changed. scripts/real_word_layout.py checks the result in real Word (see docs/real-word-check.md).

Live: the document the writer has open

With LibreOffice Writer installed, the same front doors work on the open window: the writer sees each comment and tracked change appear, and saves when they choose.

doc-control live.open --json '{"doc": "Novela.docx"}'
doc-control live.select --json '{"doc": "Novela.docx", "find_phrase": "lluvia fina"}'
doc-control doc.batch --json '{"doc": "Novela.docx", "engine": "live", "ops": [
  {"op": "comment.add", "at": "p40#c0ffee00", "text": "¿Seguro?"}]}'
doc-control live.close --json '{"doc": "Novela.docx", "save": true}'

Live doc.batch takes comment.add, text.replace and para.insert; anything else, or a machine with no app to drive, answers ENGINE_UNAVAILABLE with the reason (live.status lists the apps found). LibreOffice needs a Python its own bridge was built for: the system Python with python3-uno for a distribution's package, the Python version the snap bundles for the snap (live.status names it). Closing never drops unsaved work: a changed document needs save or discard.

Operations are named resource.action (doc.outline, text.find, para.list); the names used before 0.7.0 (outline, find, paragraphs.list…) still run but are no longer listed (renamed operations).

References: operations · errors.

Planned shape

  • One core, two engines, one API

    • File engine: edits a closed .docx with the Python standard library only, rewriting only the parts it touches. Read operations also take a .txt, .md or .odt file (hard-wrapped text detected; Markdown # headings and OpenDocument headings become Heading styles); writes refuse it.

    • Live engine: controls the open document (LibreOffice Writer, and Word on Windows over COM; Mac later).

  • Two front doors: a CLI with JSON in/out, and an MCP server (doc-control mcp, stdio) for Claude Desktop / Cowork and other MCP clients.

  • Safety first: lock-file and on-disk change detection, backup before every write, verification, automatic restore, operation log with undo, and unintended_changes == 0 as a gate.

  • No AI inside. Judgment belongs to the agent; approval belongs to the writer.

It will replace docx-fixer, whose rules become packs built on this tool, and serve literary-critic as its first downstream consumer.

MCP server

doc-control mcp serves every operation as an MCP tool over stdio, one tool per operation (para.move becomes para_move), with the same JSON Schemas and the same response envelope as the CLI. Every tool also declares an outputSchema, and a successful call returns the envelope as structuredContent too (an error has none). It needs nothing beyond the package itself:

{
  "mcpServers": {
    "doc-control": { "command": "uvx", "args": ["doc-control", "mcp"] }
  }
}

To drive the Word a writer has open on Windows, the server needs the live extra: "args": ["--from", "doc-control[live]", "doc-control", "mcp"].

Privacy and the update notice

Everything runs on your machine and nothing leaves it, with one opt-in exception. If you set DOC_CONTROL_UPDATE_CHECK=1 (the .mcpb setting "Check for updates"), it asks the GitHub Releases API for the latest version at most once a day, caches the answer in your local app data (%LOCALAPPDATA%\doc-control on Windows), and reports update: {current, latest, mcpb_url, checked_at} in server.capabilities and live.status. It never downloads or installs anything. Left off (the default), it makes no request.

Documents

Development

This repo uses claude-arsenal (spec-driven workflow, gated tasks in arsenal/tasks/). See CLAUDE.md.

Same author:

  • claude-arsenal — a Claude Code skill and plugin marketplace: specs before code, failing tests first, gates with numbers.

  • literary-critic — lets an LLM index, analyse and advise on a full novel manuscript the way a professional editor would; doc-control's first planned consumer.

  • drawspec — declarative diagram spec → clean, themeable SVG; JSON with no coordinates, so an LLM can write it.

  • integral-job-search — a candidate-centred job search run as a conversation in Claude Code.

License

Apache-2.0

Available Tools

67 tools
anchor_createA
Read-onlyIdempotent

Make an anchor for a passage so it can be found again after edits shift or change addresses: the quoted text, context characters before and after (default 32, max 200), and the paragraph's number and fingerprint then. at is a range in one paragraph (p142#a7b2a7b2:10-15), a whole paragraph (p142#a7b2a7b2) or a sentence (p142#a7b2a7b2.s3). Use it to bookmark passages you will come back to; find them later with anchor.resolve (text.find searches for any text instead). Read-only; STALE_ADDRESS when at is outdated, SCHEMA_INVALID for a range across paragraphs.

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesRange inside one paragraph, e.g. p142#a7b2a7b2:10-15, or a whole paragraph or sentence (p142#a7b2a7b2.s3).
docYesPath to the .docx file.
contextNoCharacters of prefix and of suffix to keep.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnlyHint, idempotentHint, openWorldHint=false), and the description confirms 'Read-only' plus adds what the anchor captures (quoted text, context window, paragraph number and fingerprint). It also discloses two specific failure conditions (STALE_ADDRESS, SCHEMA_INVALID), which is useful beyond the annotations, though return/persistence behavior is only lightly implied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose before the format details and alternatives, and every clause carries information. It is dense but not padded, using semicolons to pack parallel facts efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. The description covers purpose, input formats, alternatives, read-only nature, and error codes, leaving nothing an agent needs to call it correctly unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters, including the `at` format examples and the context default/max. The description largely restates these (context default 32, max 200; range vs whole-paragraph vs sentence forms) with no additional syntax beyond the schema, so it lands at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Make an anchor for a passage') and immediately explains purpose ('so it can be found again after edits shift or change addresses'). It clearly distinguishes itself from the sibling anchor_resolve by describing the create-vs-find relationship.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly instructs when to use it ('bookmark passages you will come back to') and names both alternatives by function: find them later with anchor.resolve, and text.find searches for any text instead. The routing decision is fully specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

anchor_resolveA
Read-onlyIdempotent

Find an anchor's passage in the document as it is now: its current range, a 0-1 score and the match kind (exact, normalized or fuzzy). Pass the anchor object anchor.create returned, or just {exact, prefix, suffix}. mode best (default) falls back to a fuzzy match scoring at least 0.80; mode exact accepts only verbatim, normalised or folded (match_level, default default: case, accents, punctuation) matches. Fails with ANCHOR_NOT_FOUND, or ANCHOR_AMBIGUOUS listing up to 5 tied candidates. Use it to re-address a passage after edits; doc.diff maps addresses between two files instead. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx file.
modeNobest: verbatim matches first, then fuzzy ones (match says which). exact: only places holding the quote verbatim or, when none does, in the normalised text (soft hyphens and zero-width characters ignored, whitespace collapsed, as text.normalize) or at a fold level of match_level; anything else is ANCHOR_NOT_FOUND.best
anchorYesAn anchor from anchor.create, or just {exact, prefix, suffix}.
match_levelNoHow far the quote is folded when neither it nor its normalised text occurs. exact: today's rule (verbatim, then normalised, then fuzzy in mode best). default: then ignoring case, accents and punctuation (case, then default level), and failing that symbols too (loose). loose: the same ladder. The reply's match_level is the strictest level at which the quote equals the matched text (exact: character for character; case: normalised text with case ignored), with matched_text when it is not exact; a fuzzy match has neither. Not the reply's match kind `match` (exact, normalized, fuzzy), which keeps its meaning.default

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover read-only/idempotent, and the description goes well beyond them: the 0.80 fuzzy threshold, the failure modes ANCHOR_NOT_FOUND and ANCHOR_AMBIGUOUS (listing up to 5 tied candidates), and the strictest-level resolution rule. This is exactly the behavioral detail an agent needs before invoking a fuzzy matcher.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and return shape are front-loaded, and almost every sentence carries load (thresholds, error codes, ladder semantics). The prose is dense and dash-heavy, making a few sentences harder to parse than necessary, which keeps it just below the top mark.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex resolver with nested anchor input, two enums and fuzzy behavior, the description covers inputs, default modes, fallback thresholds, and both failure paths. An output schema exists, so return-value documentation is correctly left out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all four parameters and both enums, establishing a baseline of 3. The description adds real value on top by stating the 0.80 fallback threshold for mode=best and explicitly disambiguating the reply's `match_level` from the `match` kind, which the schema does not spell out as clearly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (find/resolve) plus resource (an anchor's passage) and states exactly what is returned: current range, a 0-1 score, and the match kind. It also distinguishes itself from siblings by naming anchor.create (input source) and doc.diff (address mapping between files).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the triggering condition ('re-address a passage after edits'), the exact alternative with a different job ('doc.diff maps addresses between two files instead'), and the accepted input forms (full anchor.create object or minimal {exact, prefix, suffix}).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

caption_addA

Add a numbered caption next to a body paragraph (a table, figure or equation), as tracked insertions: label, a SEQ field with the number, and text (e.g. label Table, text "Results" gives "Table 3 Results"). position defaults to above for Table, below for Figure and Equation. A hidden bookmark wraps label and number so xref.add can point at it; field.update renumbers after later inserts. Backed up and undoable (history.undo); dry_run previews; expect.sha256 refuses a changed file. Returns the caption's address; UNSUPPORTED_CONTENT for a paragraph in a text box.

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesAddress of the body paragraph the caption goes next to.
docYesPath to the .docx.
tagNoAppended to the author.
textYesCaption text after the number; may be empty.
labelYesThe caption label.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
positionNoDefault: above for a Table, below for a Figure or Equation.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations only covering the safety profile, the description adds substantial behavioral detail: tracked insertions, a hidden bookmark, backup plus undoability via history.undo, dry_run previewing, the expect.sha256 write guard, and a specific UNSUPPORTED_CONTENT failure for text-box paragraphs. This is far beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then semicolon-delimited supporting facts. It is dense but every clause carries information; slightly packed/run-on phrasing keeps it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be spelled out, yet the description still notes it returns the caption's address. Combined with undo/safety, dry_run, and error disclosure, an agent has everything needed to call this write tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3. The description adds real meaning on top: a concrete worked example for `text` ('label Table, text "Results" gives "Table 3 Results"'), the position default rule tied to label, and how expect.sha256 behaves when a file changed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Add a numbered caption next to a body paragraph') and immediately scopes it to tables, figures, or equations. It names related siblings (xref.add, field.update) so an agent can distinguish this insertion tool from cross-reference or field-update tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operating context: position defaults per label type, that xref.add points at the created bookmark, and that field.update renumbers later. It does not state explicit when-not conditions or name a sibling to prefer, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

comment_addA

Add one comment on a range: at is a paragraph (p3#a1b2c3d4), part of one (p3#a1b2c3d4:10-15) or a span across paragraphs (p3#a1b2c3d4:10..p5#e5f6a7b8:2); a newline in text starts a new comment paragraph. Author defaults to DOC_CONTROL_AUTHOR. File engine: backed up first, dry_run previews, expect.sha256 refuses a file changed since, logged for history.undo. engine live adds it in the open Word/LibreOffice window (after live.open). Use doc.batch to add several, or with comment.reply/comment.resolve, all or nothing. Returns the new comment id.

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesRange to comment on: p3#fp, p3#fp:10-15 or across.
docYesPath to the .docx (live: or the file name of one open in a live app).
tagNoAppended to the author.
textYesComment text; a newline starts a new paragraph.
authorNoRevision author.
engineNo`live` edits the document open in Word or LibreOffice (see live.open).
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the safety profile; the description goes well beyond them by disclosing the backup-first behavior, dry_run preview, expect.sha256 guard with its DOC_CHANGED_ON_DISK failure, history.undo logging, and the live-window side effect. This is exactly the mutation context an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the `at` syntax, then engine/guard behavior. Dense but every clause carries information; only the long example list for `at` borders on over-length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-param mutation tool with nested expect, dual engines and an output schema, the description covers invocation formats, guards, side effects and the return value. An agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so baseline is 3, but the description adds real format semantics: the three `at` forms with concrete examples, the newline-starts-a-new-paragraph rule for `text`, and the DOC_CONTROL_AUTHOR author default — none of which the terse schema descriptions spell out.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource ('Add one comment on a range') with the target scoping made explicit, and it is clearly distinguishable from comment_list, comment_reply and comment.resolve. The 'one comment' vs doc.batch split is stated outright.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names alternatives and the conditions that select them: doc.batch for several comments, comment.reply/comment.resolve for bundled all-or-nothing work, and live.open required before engine live. No explicit 'when not to use', but the routing guidance is concrete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

comment_listA
Read-onlyIdempotent

List the comments in thread order (each root comment, then its replies) with id, author, date, text (clipped at 1,000 characters), resolved state and the address where each starts, including comments in notes and headers. Filter with resolved (true or false) and author (exact). Use the ids to reply or resolve with doc.batch (comment.reply, comment.resolve); use revision.list for tracked changes instead. Read-only; paged: a reply is capped at about 8,000 bytes (limit up to 1,000), continue with cursor set to the reply's next.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
limitNoMost items to return; a response is also capped at about 8,000 bytes.
authorNoOnly this author.
cursorNoThe `next` value of the previous response, to continue the list.
resolvedNoOnly resolved (true) or open (false).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds real behavioral context beyond that: comments include those in notes and headers, text is clipped at 1,000 characters, and responses are paged with a ~8,000-byte cap and `cursor` continuation. The only repetition is the 'Read-only' statement, which annotations already supply.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and return shape are front-loaded, and nearly every clause carries information (ordering, clipping, filters, paging, sibling routing). It reads as one long run-on sentence, so structure is dense rather than broken into scannable units.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with an output schema present and 100% schema coverage, the description covers the remaining agent-critical facts: ordering semantics, content clipping, paging continuation, and where to go next for related operations. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds matching semantics the schema leaves implicit: `author` is an exact match, and `cursor` must be set to the previous reply's `next` value. The `resolved` true/false explanation largely restates the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening clause gives a specific verb and resource ('List the comments') plus the ordering model ('thread order: each root comment, then its replies') and the exact fields returned. It explicitly separates itself from revision.list for tracked changes, so an agent can distinguish it from siblings without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the filters (`resolved` true/false, `author` exact) and routes the agent onward: use the returned ids to reply/resolve via doc.batch (comment.reply, comment.resolve), and use revision.list instead for tracked changes. The when-not condition (tracked changes) and the alternative are named explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doc_batchA

The main editing tool: apply several edits in one verified write, as tracked changes, all or nothing. One family per batch: text.replace, para.insert, para.delete, para.move, style.apply, format.apply, comment.add/reply/resolve; or table.row.insert/delete; or style.create/update/rename/merge; or revision.accept/reject. Example ops: [{"op": "text.replace", "at": "p3#a1b2c3d4:10-15", "text": "new"}]. Every address is as read; overlapping edits are BATCH_CONFLICT, outdated ones STALE_ADDRESS. File engine: backed up first, dry_run previews, expect.sha256 refuses a changed file, history.undo takes the batch back. tracked: false writes approved text plainly, on either engine. engine live edits the open app (comment.add, text.replace, para.insert only; no dry_run or rollback). server.help gives each kind's fields.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx (live: or the file name of one open in a live app).
opsYesOperations, applied together. Every address refers to the document as read; an operation placed relative to a paragraph another operation deletes or moves is a BATCH_CONFLICT. Kinds: text.replace ['at', 'text']; para.insert ['after', 'before', 'text']; para.delete ['at']; para.move ['after', 'at', 'before']; style.apply ['at', 'style']; format.apply ['align', 'at', 'bold', 'font', 'indent_first_line_cm', 'indent_left_cm', 'indent_right_cm', 'italic', 'line_spacing', 'size_pt', 'small_caps', 'spacing_after_pt', 'spacing_before_pt', 'underline']; comment.add ['at', 'text']; comment.reply ['comment', 'text']; comment.resolve ['comment', 'resolved']; style.create ['based_on', 'custom', 'default', 'id', 'link', 'name', 'next', 'paragraph', 'quick', 'run', 'type']; style.update ['based_on', 'link', 'next', 'paragraph', 'quick', 'run', 'style']; style.rename ['id', 'name', 'style']; style.merge ['from', 'into']; revision.accept ['all', 'at', 'author', 'ids']; revision.reject ['all', 'at', 'author', 'ids']; table.row.insert ['after_row', 'cells', 'table']; table.row.delete ['row', 'table'].
tagNoAppended to the author.
authorNoRevision author.
engineNo`live` edits the document open in Word or LibreOffice (see live.open).
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
trackedNotrue (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations). engine live: the app's change tracking is off for the edit and put back after; text.replace and para.insert, refused (UNSUPPORTED_CONTENT) next to another unresolved tracked change; the app's undo takes it back. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the safe-mutation profile (readOnly=false, destructive=false), while the description carries all the real load: backup-then-write, dry_run preview, expect.sha256 refusal (DOC_CHANGED_ON_DISK), undo semantics, BATCH_CONFLICT/STALE_ADDRESS errors, and detailed tracked:false behavior including UNSUPPORTED_CONTENT refusals and out-of-order-undo limits. Exceptionally rich and non-contradictory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One dense paragraph that front-loads the core purpose, then families, then engine/tracked nuances. Every clause carries information (error codes, engine limits, undo rules), though the compression makes it heavy reading for a first-pass selection.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 8-parameter, nested, multi-op write tool with an output schema already present, the description covers the engine choice, tracking semantics, write guard, backup/undo, and refusal modes. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters are already documented, but the description adds value beyond the schema: the concrete address form ('p3#a1b2c3d4:10-15'), the family-grouping rule, and the tracked:false consequences that the schema only names. It stops short of fully explaining every op's fields (deferring to server.help), so it sits above the 3 baseline but not maximal.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('apply several edits in one verified write, as tracked changes, all or nothing') and enumerates the exact op families it covers. This lets an agent distinguish it from the many single-op siblings (text_replace, para_delete, style_update, revision_accept, comment_add) without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the key selection rule ('One family per batch') plus preview/guard behavior and the live-engine restriction to comment.add/text.replace/para.insert. It implies the batch-vs-single-op choice rather than stating it outright ('use this when you have multiple edits, otherwise the single-op tools'), so it falls just short of explicit when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doc_compareA

Write a redline: a new .docx at output (which must not exist) holding the new version with every difference from old as a tracked change (author default Claude, date ISO 8601 with time zone, default now), so a writer reviews and accepts or rejects them in Word. The input files are never modified; the redline is verified (accepting every change gives the new text) or removed (VERIFY_FAILED_RESTORED). Use doc.diff for the alignment as data without writing a file. Returns the output path and hash, per-kind paragraph counts and the revision count.

ParametersJSON Schema
NameRequiredDescriptionDefault
newYesPath of the later version (.docx).
oldYesPath of the earlier version (.docx).
tagNoAppended to the author as `author (tag)`.
dateNoRevision date, ISO 8601 with time zone.
authorNoRevision author (default Claude).
outputYesPath of the redline to create (must not exist).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations present, it adds substantial behavioral context beyond them: the output must not already exist, input files are never modified, defaults (author Claude, date now), and the verify-or-restore outcome (VERIFY_FAILED_RESTORED). These are exactly the side-effect and failure-mode details an agent needs for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and packs defaults, verification, and the alternative into a dense but single-purpose block. Slightly long with stacked parentheticals, but nearly every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is optional, yet the description summarizes it (path, hash, per-kind counts, revision count). Combined with the side-effect and failure semantics, an agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds a genuinely new default ('date ... default now') and reinforces the must-not-exist constraint on `output`. It mostly mirrors the schema, hence not a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and artifact: 'Write a redline: a new .docx at `output` ... with every difference from `old` as a tracked change.' It explicitly distinguishes itself from the sibling doc.diff, so an agent can tell the two apart without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative and the condition that selects it: 'Use doc.diff for the alignment as data without writing a file.' It also frames the human workflow (writer reviews and accepts/rejects in Word), making the intended use unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doc_diffA
Read-onlyIdempotent

Align the paragraphs of two versions (old, new; .docx, or .txt/.md/.odt): which are unchanged, modified, moved, split, merged, inserted or deleted, with a map from old addresses to new ones (null for deleted). Use it to carry addresses read from an older version over to the current one, or to see what changed; doc.compare writes the same differences as a redline .docx instead. collapse_runs folds runs of shifted unchanged paragraphs into one record. Read-only; paged at about 8,000 bytes with limit and cursor (the next of the previous reply).

ParametersJSON Schema
NameRequiredDescriptionDefault
newYesPath of the later version (.docx).
oldYesPath of the earlier version (.docx).
limitNoMost items to return; a response is also capped at about 8,000 bytes.
cursorNoThe `next` value of the previous response, to continue the list.
collapse_runsNoList runs of shifted unchanged paragraphs as one record each.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotentHint/openWorldHint=false, so the safety profile is covered, but the description adds genuinely new behavior: paging at ~8,000 bytes with limit and cursor carried forward from the previous reply's `next`, and that deleted paragraphs map to null. A minor gap is that it doesn't describe error behavior on missing/mismatched files.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core verb+resource, then alternatives, then pagination mechanics. No filler sentences, though the single dense paragraph packs several distinct ideas (output, alternatives, siblings, pagination) that could be split for faster scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return shape need not be spelled out, yet the description still explains the address map and null-for-deleted semantics. Combined with read-only disclosure, sibling routing, and pagination rules, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema documents each parameter, so the baseline is 3. The description still adds value by tying limit+cursor together as a pagination mechanism ('the `next` of the previous reply') and explaining collapse_runs as folding shifted-unchanged runs into one record, which the schema only states in one line.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Align the paragraphs of two versions') and enumerates the exact change categories (unchanged, modified, moved, split, merged, inserted, deleted) plus the old-to-new address map. It also names the sibling doc.compare and how it differs, so an agent can select correctly without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly gives the two intended uses ('carry addresses read from an older version over to the current one, or to see what changed') and routes the alternative case to doc.compare ('writes the same differences as a redline .docx instead'). It also notes when to reach for collapse_runs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doc_infoA
Read-onlyIdempotent

Cheap first look at a file: size, sha256 (pass it as expect.sha256 to a later write so it is refused if the file changed meanwhile), core properties (title, author, dates), whether Track Changes is on, whether Word holds it open (a ~$ lock file) and which parts exist (comments, notes, headers). The envelope's doc gives the paragraph count. Use doc.stats for word, heading and revision counts, doc.outline for the headings. Read-only; DOC_NOT_FOUND or NOT_A_DOCX for a bad path.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, but the description adds substantial context beyond them: the lock-file detection for an open document, the staleness-check contract around sha256, and the specific error outcomes (DOC_NOT_FOUND, NOT_A_DOCX). This is far richer than the safety profile alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense paragraph, front-loaded with the 'cheap first look' framing followed by the payload contents and routing hints. Nearly every clause carries information, though the sha256/expect.sha256 aside is a touch embedded and could be tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present the description needn't explain returns, yet it still previews the envelope (doc paragraph count), states the error codes, and routes to alternatives. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is one parameter and schema description coverage is 100%, so the schema already fully documents 'doc' as the path to the .docx. The description adds no syntax or format detail beyond that. Per the baseline rule for high coverage, a 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Cheap first look at a file') and enumerates exactly what it returns: size, sha256, core properties, Track Changes state, lock file, and existing parts. It explicitly distinguishes itself from doc.stats and doc.outline, so an agent can tell it apart from those siblings without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternatives explicitly ('Use doc.stats for word, heading and revision counts, doc.outline for the headings') and frames itself as the cheap first-pass call. It also describes the intended downstream workflow (pass sha256 as expect.sha256 so a later write is refused if the file changed), giving concrete when-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doc_openA

Start a session on a document: back it up into its store (.doc-control// next to it; the newest 20 backups or 30 days are kept) and note it in the undo log if it changed since the last logged write. Call it once before editing; the document itself is not changed. If the document has no history yet, adoptable lists orphaned stores (it was moved or renamed) that history.adopt can re-attach. Returns the backup path, the log entry and the store folder.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Richly discloses side effects that annotations do not cover: backup location (.doc-control/<file name>/), retention policy (20 backups or 30 days kept), undo-log behavior, and that the document is not modified. With destructiveHint=false and readOnlyHint=false, the description meaningfully explains what the tool actually does behind the scenes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: starts with the core action, parenthetically provides backup mechanics, then the adoption edge case, then the return shape. No fluff; every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists, the description still helpfully names what is returned (backup path, log entry, store folder) and explains the adoption route. For a single-param tool with output schema and annotations, this is thorough.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single param 'doc' is documented as 'Path to the .docx.' The description's mention of orphaned stores and adoptable adds contextual meaning about output, though not about the parameter itself.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (start a session) on a specific resource (a document), and explicitly clarifies the counterintuitive behavior: 'the document itself is not changed' and 'Call it once before editing'. This distinguishes it from doc_batch, doc_compare, and live_open without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear timing guidance ('Call it once before editing') and conditional logic ('If the document has no history yet...'), routing the agent to history.adopt. It stops short of explicitly naming when NOT to use it vs. siblings like live_open or doc_diff.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doc_outlineA
Read-onlyIdempotent

List the headings (levels 1-9, by style or outline level) in document order, each with its address, level, style and text: the table-of-contents view. max_level 2 keeps levels 1-2; stories ["body", "notes"] adds headings in notes. Use doc.segment for chapters that are not styled as headings, para.list for every paragraph, para.get to read one heading in full. Read-only; paged: about 8,000 bytes per reply (limit up to 1,000), continue with cursor set to the reply's next.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
limitNoMost items to return; a response is also capped at about 8,000 bytes.
cursorNoThe `next` value of the previous response, to continue the list.
storiesNoStories to read (default ["body"]): "notes" adds footnotes and endnotes, each after the paragraph holding its mark; "headers" adds headers and footers, after the body. Their addresses carry a prefix (fn3/p1#…, hdr1.default/p1#…).
max_levelNoOnly headings up to this level.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent annotations by disclosing paging mechanics (about 8,000 bytes per reply, limit up to 1,000, continue with `cursor` set to `next`). It also names what each item contains (address, level, style, text), giving concrete behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose and is dense but mostly earns its words. It is a little packed with clauses, but no sentence is pure filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description is not obligated to describe returns, and it still covers filtering, story selection, paging/continuation, and alternatives. An agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (baseline 3), but the description adds real semantic value: "max_level 2 keeps levels 1-2" clarifies the parameter's effect and stories ["body","notes"] is shown with example values and behavior. It stops short of explaining the `headers` story option present in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("List") and resource ("headings"), with scope (levels 1-9, by style or outline level, in document order) and the returned fields. It effectively distinguishes itself from siblings doc.segment, para.list, and para.get by name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to alternatives: doc.segment for chapters not styled as headings, para.list for every paragraph, para.get to read one heading in full. It names both the conditions and the sibling tools, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doc_segmentA
Read-onlyIdempotent

Split a manuscript into units with stable ids: unit chapters (default), parts or scenes (detected from headings, numerals, centring, scene markers; signals say which), or sentences or dialogue lines within range (an address, p24#a1b2c3d4..p60#e5f6a7b8, or a unit id such as ch-d5a3930d). chapter limits scenes to one chapter; language (default es) sets sentence rules; profile and overrides tune detection. Use it to work chapter by chapter or to get sentence addresses (p142#a7b2a7b2.s3); doc.outline lists only styled headings. Read-only; paged at about 8,000 bytes with cursor.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
unitNoWhat to list (default chapters).
limitNoMost items to return; a response is also capped at about 8,000 bytes.
rangeNosentences and dialogue only: what to cover — a paragraph address or range, a run of whole paragraphs (p24#fp..p60#fp), or a chapter, scene or part id (ch-…, sc-…, pt-…; same profile and overrides).
cursorNoThe `next` value of the previous response, to continue the list.
chapterNoscenes only: the chapter id whose scenes to list.
profileNoDetection settings for this document.
languageNoSentence rules (default es).
overridesNoForce or deny a chapter or scene at paragraphs by fingerprint.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/closed-world, but the description adds real value beyond them: pagination behavior ('paged at about 8,000 bytes with `cursor`') and the fact that detection is signal-driven. It doesn't disclose limits on what splits, but the pagination detail is useful context the annotations don't cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but well front-loaded: the core action and unit list come first, then range syntax, then modifiers, then routing. Nearly every clause carries information, though the sentence is long and slightly burdensome to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter tool with nested objects and an output schema, the description covers the main flows, id semantics, pagination and sibling contrast, so an agent can invoke it correctly. Detection internals live in the schema, which is appropriate, but a note on default output ordering/shape would make it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds examples beyond the schema: concrete address/range syntaxes (p24#a1b2c3d4..p60#e5f6a7b8, ch-d5a3930d, p142#a7b2a7b2.s3) and the meaning of `chapter`, `language`, `profile` and `overrides`. This meaningfully enriches otherwise-documented params.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('split a manuscript into units with stable ids') and enumerates the outputs (chapters, parts, scenes, sentences, dialogue). It also explicitly distinguishes itself from the sibling 'doc.outline lists only styled headings'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context ('Use it to work chapter by chapter or to get sentence addresses') and points to the alternative doc.outline. It lacks an explicit when-not or a fuller routing list among the many sibling segmentation/inspection tools, so it stops just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doc_statsA
Read-onlyIdempotent

Count what the body holds: paragraphs (and empty ones), words, characters, headings, tables, comments, footnotes, tracked changes by type, styles in use and the 20 most used fonts. stories ["notes", "headers"] adds separate counts for notes and for headers/footers (the body counts stay the body's). Use it to size a document or check for leftover revisions; doc.info gives file facts and the hash, revision.list the changes themselves. Read-only; one reply, not paged.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
storiesNoStories to read (default ["body"]): "notes" adds footnotes and endnotes, each after the paragraph holding its mark; "headers" adds headers and footers, after the body. Their addresses carry a prefix (fn3/p1#…, hdr1.default/p1#…).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and openWorldHint=false, so the safety profile is covered before the description starts. The description still adds genuine behavioral context: 'one reply, not paged' (a pagination guarantee) and the scoping rule that requesting notes/headers does not change the body counts. It does not discuss cost, limits, or behavior with malformed files, so it is solid but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the counted resource, then the parameter caveat, then the routing sentence, then the operational note – a logical order with no filler sentences. The long enumeration of counted items is dense but each item earns its place because it defines the tool's surface; slightly heavy for a single paragraph.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the return shape need not be described, and the description still pre-announces the returned categories and the non-paged single reply. Combined with annotations covering safety and idempotency, an agent has everything needed to select and call this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description goes further by explaining the semantics of 'stories' that the schema only implies – that notes and headers are counted separately and 'the body counts stay the body's'. The schema supplies the address-prefix detail for the extra stories, so the description sensibly does not repeat it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (count) and resource (body contents of a .docx) and enumerates exactly what is counted: paragraphs, empty paragraphs, words, characters, headings, tables, comments, footnotes, tracked changes by type, styles, top fonts. It is clearly distinguishable from the listed siblings doc.info (file facts/hash) and revision.list (the changes themselves).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names two use cases ('size a document or check for leftover revisions') and routes the agent to the right alternatives with the differentiator for each: doc.info for file facts and hash, revision.list for the changes themselves. That is when-to-use plus when-to-use-something-else.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

field_listA
Read-onlyIdempotent

List every field (PAGE, TOC, REF, SEQ, XE, citations such as ADDIN ZOTERO_ITEM...) with its address, story, code, type, shown result and whether it is stale (needs updating). stories defaults to all: body, notes, headers and comments; type keeps one type ("TOC"). Covers nested, split and simple fields and fields in text boxes. Use it before field.update to see what is stale, or to find citations; it never changes anything. Read-only; one reply, not paged.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
typeNoOnly fields of this type, e.g. "TOC" or "ADDIN ZOTERO_ITEM".
storiesNoStories to read (default all): "body", "notes", "headers" and "comments".

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so safety is partly covered, but the description adds behavioral context beyond them: it never changes anything, covers nested/split/simple fields and text boxes, and crucially notes a single reply with no pagination. It stops short of describing auth or failure behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then scope, then usage routing in a compact run of sentences. The enumeration of field codes and stories is dense but earns its place; slightly longer than strictly necessary but no filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Though an output schema exists (so return values needn't be documented), the description still names the returned attributes (address, story, code, type, shown result, staleness) and the read-only/no-pagination contract. For a 3-param listing tool with rich annotations, nothing an agent needs is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the baseline is 3, but the description adds meaning on top: stories defaults to all with the enum members spelled out, and type's single-value filtering is explained with a concrete example ('TOC'). This clarifies intent beyond the schema's own description text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a specific verb+resource ('List every field') and enumerates exactly which field kinds are covered (PAGE, TOC, REF, SEQ, XE, citations) plus the scope of stories and field shapes. An agent can distinguish this from field_update and other list tools without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it ('before field.update to see what is stale, or to find citations'), names the sibling it precedes, and clarifies the negative ('it never changes anything'). The condition selecting this tool is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

field_updateA

Recompute the body's TOC, PAGE, NUMPAGES, SEQ and REF/PAGEREF results with headless LibreOffice and write only those result runs, as tracked changes (old result struck, new inserted). Needs LibreOffice (soffice): without it, ENGINE_UNAVAILABLE names the stale fields; set_update_on_open instead sets w:updateFields so Word updates them on opening. Citations are never changed; INDEX, SECTIONPAGES, SECTION, NOTEREF and unresolvable REFs are left and listed under skipped. Run after toc.insert, caption.add or xref.add. Backed up and undoable; dry_run previews; slow (seconds).

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
tagNoAppended to the author.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
set_update_on_openNoOnly set w:updateFields in settings.xml (no LibreOffice).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses which fields are rewritten, that citations are never changed, the exact 'skipped' set (INDEX, SECTIONPAGES, SECTION, NOTEREF, unresolvable REFs), the ENGINE_UNAVAILABLE failure mode, that it is backed up and undoable, and that it is slow. Annotations only supply the safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is dense but front-loaded, leading with the recompute action and its scope, with zero filler sentences. The single-block layout without sub-structure costs it a point but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with several optional params and an output schema, everything an agent needs is present: prerequisites, ordering, alternatives, error semantics, performance expectation, and the skipped-field contract. No reliance on return-value explanation is needed since an output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value by framing set_update_on_open as a cheap alternative to the full recompute and by tying dry_run and error codes to behavior, rather than merely restating field names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb ('Recompute ... results') and an exact resource set (TOC, PAGE, NUMPAGES, SEQ, REF/PAGEREF), and names the write behavior (tracked changes). An agent can tell this apart from field_list, toc_insert, and xref_add without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit ordering ('Run after toc.insert, caption.add or xref.add') and a named alternative path ('set_update_on_open instead sets w:updateFields so Word updates them on opening'), plus the prerequisite (needs soffice). This is when-to-use, when-not, and alternative all in one.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

history_adoptA

Re-attach a moved or renamed document to its old undo history, so history.undo and history.restore work again. It finds the orphaned store whose last recorded state is this file's sha256 (doc.open lists them as adoptable, history.orphans lists all) and moves it, backups and log, to where this document's store lives now. Pass store when several match (the reply lists candidates); force adopts a file edited since; a document that already has history is never overwritten (BATCH_CONFLICT). dry_run moves nothing.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
forceNoAdopt although the document's sha256 is not the store's last.
storeNoThe orphan store to adopt (see doc.open's `adoptable` or history.orphans); needed when several match or the old folder is far away.
dry_runNoSay what would move; move nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses exactly what moves (the store, backups and log), that existing history is never overwritten (BATCH_CONFLICT), and that dry_run moves nothing. These are the mutation semantics an agent needs and are not derivable from readOnlyHint=false/destructiveHint=false alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose in the first sentence, then layers the mechanism and parameter conditions. It is dense and multi-clause, but each clause carries actionable information about behavior or parameters, so little waste remains.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the description still usefully names reply fields (`adoptable`, `candidates`) and the BATCH_CONFLICT conflict state. For a filesystem-mutating tool this is complete enough to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the baseline is 3, but the description adds real meaning: it explains that `store` is needed when several candidates match and points to the reply's `candidates`, and frames `force`/`dry_run` in operational terms. Minor value-add beyond the already-thorough schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Re-attach a moved or renamed document to its old undo history') with a clear downstream consequence ('so history.undo and history.restore work again'). This distinguishes it cleanly from history_restore, history_undo, and history_orphans without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit trigger conditions (moved or renamed document), names the discovery alternatives (doc.open's `adoptable`, history.orphans), and specifies when each param is needed ('store when several match', 'force adopts a file edited since', dry_run). An agent knows exactly when to reach for this versus siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

history_listA
Read-onlyIdempotent

List the document's undo log, newest first: each write's op_id, kind, time, author, the operations it ran, whether it was undone, and the deleted paragraphs history.restore can bring back (change numbers). Filter with kind (batch, restore, undo, open, purge, adopt); store reads an orphaned store instead. Use it to find the op_id for history.undo or history.restore; history.search finds a quote in the log. Read-only; paged with limit (default 20) and cursor (the reply's next).

ParametersJSON Schema
NameRequiredDescriptionDefault
docNoPath to the .docx.
kindNoOnly entries of this kind (batch: every logged edit).
limitNoMost entries per page (default 20).
storeNoA store folder (see history.orphans) to read instead of the document's own.
cursorNoThe `next` of the previous response.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only, idempotent, closed-world profile, but the description adds real behavior: newest-first ordering, pagination with default limit 20 and cursor taken from the reply's `next`, and the orphaned-store read path. It slightly over-specifies return fields that the output schema already defines, and repeats 'read-only' from the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded, leading with the verb, resource, and ordering before filters and alternatives. It wastes a little space repeating 'read-only' (already in annotations) and listing return fields the output schema covers.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only paged list tool with an output schema, the description covers scope, ordering, filtering, pagination, the alternative read mode, and sibling routing. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters including the `kind` enum and the cursor/limit semantics. The description mostly restates these (enum values, default 20, cursor = reply's `next`), adding only a marginal gloss on `store` reading an orphaned store, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List the document's undo log') plus ordering ('newest first') and enumerates what each entry contains. This distinguishes it cleanly from history_search, history_undo, and history_restore, which are named as different tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says what it is for ('Use it to find the op_id for history.undo or history.restore') and names the contrasting alternative ('history.search finds a quote in the log'). It also explains the `kind` filter and the `store` orphaned-store case, giving the agent clear routing conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

history_orphansA
Read-onlyIdempotent

List undo stores whose document is gone (moved, renamed or deleted): the app-data stores, plus dir/.doc-control when dir is given, each with its folder, last document path, entry count and last time; unknown holds stores that name no document. Their history is never deleted automatically. Use history.adopt to re-attach one to a moved document, history.list or history.restore with store to read from it, history.purge with store to delete it. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoAlso scan this folder.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and closed-world, so the safety profile is given. The description still adds real behavioral context beyond them: orphaned history 'is never deleted automatically', and it names the fields each entry carries. It does not add auth or rate-limit caveats, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core definition, then the scope extension, then the routing sentence, ending with 'Read-only.' No sentence is filler, though the first sentence is heavily packed with clause-nested enumerations that take a second read to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no prose, and the description uses the space for what the schema cannot carry: orphan classification, the `dir`/`unknown` edge cases, non-deletion behavior, and next-step siblings. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema only says 'Also scan this folder'. The description adds meaning the schema lacks: when `dir` is supplied, the scan covers `dir`/.doc-control in addition to the app-data stores. That is genuine semantic enrichment beyond the one-param baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List undo stores whose document is gone') and immediately enumerates what counts as an orphan (moved, renamed, deleted) plus the special `dir`/.doc-control case and the `unknown` bucket. This cleanly separates it from siblings like history_list, history_search and history_purge.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: history.adopt to re-attach to a moved document, history.list/history.restore with `store` to read from it, history.purge with `store` to delete it. It also scopes when the optional `dir` matters, so both when-to-use and what-to-use-next are covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

history_purgeA
Destructive

Delete undo history for privacy: the whole log (all) or entries before a date (before, ISO 8601, UTC), of the document or of an orphaned store. Two steps: run with dry_run to see what would go and get a confirm token, then repeat with confirm; a log that changed in between is refused. Leaves a tombstone entry; backups are not removed by it. Destructive: purged entries can no longer be undone or restored. Use history.list first to check what you remove.

ParametersJSON Schema
NameRequiredDescriptionDefault
allNoRemove the whole log.
docNoPath to the .docx.
storeNoA store folder (see history.orphans) to read instead of the document's own.
beforeNoRemove entries older than this ISO date or time (UTC).
confirmNoFrom the dry run.
dry_runNoList what would go; returns confirm.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, and the description goes well beyond them: it discloses the two-step confirm protocol, the mid-flight change refusal, that a tombstone entry remains, that backups are NOT removed, and that purged entries can no longer be undone or restored. This is exactly the behavioral context a mutation tool needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense paragraph that front-loads the mode selection and then the destructive/confirm mechanics. Every sentence carries information, though the level of detail makes it slightly heavier than needed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, six-parameter mutation tool, the description covers scope, safety workflow, side effects, and prerequisites. An output schema exists, so return-value explanation is legitimately omitted. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds genuine meaning: `before` is ISO 8601 in UTC, `store` is an orphaned store (pointing to history.orphans), and `confirm`/`dry_run` are coupled as a token round-trip. It clarifies interaction between params rather than merely restating them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (delete undo history) and immediately scopes the two modes (whole log via `all` vs entries before a date via `before`), plus the doc-vs-store targeting. An agent can distinguish it from history_undo, history_restore, and history_list without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Prescribes the exact workflow: run with dry_run first to see what would go and obtain a confirm token, then repeat with confirm. It also recommends history.list as a pre-check and warns that a log changed between steps is refused. Explicit when/how-to-use with an alternative named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

history_restoreA

Bring back paragraphs a logged write deleted or changed, as a tracked insertion (tracked: false: plainly, for a change the writer approved). Give the op_id (from history.list or history.search); without change, every paragraph that op deleted comes back after the paragraph now holding its old place; change picks one (also an edited one) and after (p12#a1b2c3d4) places it when that place was edited (BATCH_CONFLICT otherwise). Use history.undo to revert a whole write instead. Backed up, logged, undoable; dry_run previews.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
tagNoAppended to the author.
afterNoInsert after this paragraph address instead of the old place (needed when that place was edited, or the history comes from `store`).
op_idYesThe logged op the paragraph was changed by.
storeNoA store folder (see history.orphans) to read instead of the document's own.
authorNoRevision author.
changeNoIndex of one change of the op (history.list shows them).
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
trackedNofalse: a plain write for a change the writer already approved: the paragraph comes back without revision marks (this call's own insertion accepted in the same verified write).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations (readOnlyHint=false, destructiveHint=false) already establish this is a non-destructive write, and the description is consistent with that. It goes further by disclosing that changes are backed up, logged and undoable, that dry_run previews, and that a specific BATCH_CONFLICT error arises when a placement was edited. Minor gaps remain (no mention of permission requirements or return behavior, though an output schema exists).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core operation and then the routing/parameter rules; almost no wasted words. It is a dense single paragraph with stacked parentheticals (e.g. "tracked: false: plainly, for a change the writer approved") that take effort to parse, keeping it just short of a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter mutation tool with full schema coverage and an output schema, the description covers the operational flow, the main alternative, and the key error conditions. Slightly ambiguous phrasing around tracked:false leaves a small interpretive gap, but nothing essential for a correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real semantics beyond the schema: the consequence of omitting `change`, the role of `after` as an override of the old place, and the meaning of `tracked: false`. This is meaningfully more than the per-parameter schema text alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: bring back paragraphs a logged write deleted or changed, and specifies the default form (tracked insertion). It also names a sibling it is not (history.undo reverts a whole write instead), so an agent can distinguish it without opening other schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says where op_id comes from (history.list or history.search), what happens without `change` (every deleted paragraph returns after the paragraph now holding its old place), what `change` selects, when `after` is required, and the alternative (history.undo). When-to-use and when-to-use-something-else are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

history_undoA

Take back one logged write (doc.batch, text.replace and the other direct writes, comment and style writes, styleset.install, term.rename, field and note inserts, layout.apply, history.restore), returning its paragraphs and parts to their state before it: by default the latest one still in effect, or the op_id from history.list. Refused with BATCH_CONFLICT if a paragraph or part it changed was edited since (undo the later write first). Use history.restore to bring back single deleted paragraphs, revision.reject to drop tracked changes by author or id. The undo is itself logged; dry_run checks without writing; expect.sha256 refuses a changed file.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
op_idNoThe op to undo (default: the latest in effect).
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoCheck and preview; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare it is not read-only and not destructive; the description adds substantial behavior: the undo is itself logged, BATCH_CONFLICT if a touched paragraph/part was edited since, dry_run previews without writing, and expect.sha256 guards against a changed file. This is context beyond the annotation set, with no contradiction of destructiveHint=false (it restores prior state rather than destroying it).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and family of covered writes, then constraints, then alternatives. Dense parenthetical enumeration is efficient though the long run-on sentence carries a lot; nearly every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, and the description fully covers scope, default behavior, conflict handling, write-guard, preview mode, and sibling alternatives. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real semantics: op_id comes from history.list and defaults to the latest write still in effect, dry_run means check-without-write, and expect.sha256 refuses a changed file. It complements rather than merely restates the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (take back/undo) and resource (a logged write), enumerating the operation classes it covers and the scope of restoration (paragraphs and parts to their pre-write state). It is immediately distinguishable from history.restore and revision.reject, which are named as different tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit selection logic: undo the latest write in effect by default, or specify an op_id from history.list. It names alternatives and their conditions (history.restore for bringing back single deleted paragraphs, revision.reject for tracked changes by author/id) and explains the BATCH_CONFLICT refusal path.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

index_insertA

Insert an index (an INDEX field) after a body paragraph after (p40#a1b2c3d4), as tracked insertions: a title (default "Index", "" for none), the field with a placeholder result, and a closing paragraph. Mark entries first with index.mark; Word builds the entries and page numbers when the field is updated there (F9), since field.update leaves indexes alone. Backed up and undoable (history.undo); dry_run previews; expect.sha256 refuses a changed file. Returns the field paragraph's address.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
tagNoAppended to the author.
afterYesAddress of the body paragraph it goes after.
titleNoTitle paragraph above it (default "Index"); "" for none.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare the safety profile (readOnlyHint=false, destructiveHint=false) and the description adds real behavioral context beyond them: the insert is tracked as revisions, it is backed up and revertible via history.undo, dry_run previews without writing, and expect.sha256 rejects a file changed on disk. It stops short of describing pagination/output shape, though that is largely covered elsewhere.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: the core action and placement come first, then prerequisites, then safety/undo guarantees. Every clause carries information, though the single run-on sentence packs several concerns together and could be segmented for faster scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with 7 parameters, an output schema, and nested objects, the description covers prerequisites, tracked-revision semantics, undo, write guarding, and the returned address. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description still adds value by clarifying that `after` is a body-paragraph address (with the p40#a1b2c3d4 format), that `title` defaults to "Index" and "" suppresses it, and what expect.sha256 does on mismatch. That is genuine meaning beyond the field names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Insert an index (an INDEX field)") plus the exact placement scope ("after a body paragraph `after`"), and the tracked-insertion nature. It also implicitly distinguishes itself from index_mark, which only marks entries, so an agent can route between the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit sequencing guidance ("Mark entries first with index.mark") and names the alternative that will NOT work ("field.update leaves indexes alone"), redirecting the agent to Word/F9 instead. It further states when to use dry_run and expect.sha256, so both the normal and guarded invocation paths are spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

index_markA

Mark an index entry: insert an XE field, as a tracked insertion, right after a range (p8#a1b2c3d4:10-15) so that word or phrase is indexed on its page. entry is "Term", or "Term:Sub" / "Term:Sub:Detail" for sub-entries. Mark every occurrence you want listed, then insert the index once with index.insert. Backed up and undoable (history.undo); dry_run previews; expect.sha256 refuses a changed file. Returns the paragraph address and field code.

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesA range inside one paragraph; the mark goes after it.
docYesPath to the .docx.
tagNoAppended to the author.
entryYesThe index entry, e.g. "Term" or "Term:Sub".
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (readOnlyHint=false, destructiveHint=false) by disclosing that the write is a tracked insertion, that it is backed up and reversible via history.undo, that dry_run previews without writing, and that a stale sha256 yields DOC_CHANGED_ON_DISK. It also states what the call returns, which is real behavioral context for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and scoping, and the workflow sentence follows naturally. It is information-dense with back-to-back clauses, but each sentence carries distinct, non-redundant content rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with nested objects and an output schema, the description covers ordering against the sibling index_insert, the entry-format grammar, safety (backup/undo/dry_run/sha256 guard), and the return payload. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3; the description adds value by expanding the entry syntax to the three-level 'Term:Sub:Detail' form and by showing the range address shape (p8#a1b2c3d4:10-15) that `at` requires. It does not explain tag/author or the expect object's semantics beyond the guard behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Mark an index entry: insert an XE field') and pins down the exact insertion point ('right after a range') with a concrete address example. It is clearly distinguishable from the sibling index_insert, which only finalizes the index once marks exist.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit workflow guidance: 'Mark every occurrence you want listed, then insert the index once with index.insert' tells the agent both the per-occurrence usage and the correct sequencing against the alternative. It also names dry_run as the preview path and expect.sha256 as the write guard condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

layout_applyA

Bring the document to a page plan, the shape layout.get returns: per section its start (from address), break, page-number start and format, first-page difference, and header/footer text per kind ({PAGE}, {NUMPAGES}, {chapter} become fields; null inherits). Keys left out stay as they are. Edit the layout.get result and send it back. Breaks, numbering and header text are tracked changes; a new header part, a dropped reference, two_sided or mirror_margins need untracked: true. All or nothing: UNSUPPORTED_CONTENT if the result would differ from the plan or a section has a pending setup change. dry_run lists the changes.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
tagNoAppended to the author.
planYesThe page plan, as layout.get returns it: version 1, two_sided, mirror_margins and sections, each with a `from` address; keys left out stay as they are, and numbering.shown is checked, not set. Every section already in the document must be kept. A header/footer text a section already prints changes nothing; a shared part is rewritten only when every section using it asks the same text, else the section gets a new part. Changing a header or footer that a later section inherits is refused. A split-off section keeps the number format of the one it came from unless the plan states one.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
untrackedNoAllow a change Word cannot track (LAYOUT D-L2).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite annotations already flagging a non-read-only write, the description discloses substantial behavior beyond them: which edits are tracked vs. require untracked: true, header-sharing/rewrite rules, inheritance refusal, and the all-or-nothing UNSUPPORTED_CONTENT failure mode. This is unusually rich disclosure for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded and nearly every clause carries needed operational detail (tracking rules, error semantics, flag conditions). The long run-on sentences with dense parentheticals reduce readability, but little is genuinely redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with nested objects and an output schema, the description covers the workflow, tracking model, guards, and failure behavior. Return values are delegated to the output schema, and nothing an agent needs to invoke it correctly appears missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds interpretation: '{PAGE}, {NUMPAGES}, {chapter} become fields; null inherits' and 'dry_run lists the changes' go beyond the schema's terse 'Preview only; write nothing.' It largely mirrors the plan schema's inheritance rules, keeping it at 4 rather than 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening clause ('Bring the document to a page plan, the shape layout.get returns') states a specific action and resource and explicitly anchors the tool to its read sibling, so an agent can distinguish it from layout_get. It is slightly indirect in phrasing rather than a crisp verb+resource, but the target (per-section start, break, numbering, header/footer text) is concrete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It supplies a clear workflow: 'Edit the layout.get result and send it back,' and gives conditions for the optional flags (untracked: true for new header parts, dropped references, two_sided, mirror_margins; dry_run lists changes). It names the source tool rather than a competing sibling, so alternatives are contextualized but no explicit when-not guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

layout_getA
Read-onlyIdempotent

Read the page plan: per section where it starts (from address), its break, page numbering (shown, start, format), first-page difference, and header/footer text per kind (default, first, even) with fields as {PAGE}, {NUMPAGES} and {chapter}; null means inherited from the previous section. Edit it and pass it to layout.apply to change the layout; section.list gives the same setup with header/footer part names instead of text. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotentHint/openWorldHint, so the safety profile is covered; the trailing 'Read-only' largely restates it. The description adds genuine behavioral context beyond the annotations: 'null means inherited from the previous section' and the coupling to layout.apply.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action ('Read the page plan') and packs the field inventory into one dense sentence. It is information-dense rather than padded, though some return-field detail borders on duplicating the output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a dedicated output schema present, the description needn't explain return structure, yet it still gives enough about scope, inheritance semantics, and sibling relationships for correct invocation. Nothing critical for calling the tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single 'doc' parameter is fully documented ('Path to the .docx.'). The description adds no parameter-level detail (formats, constraints) beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read the page plan') and enumerates exactly what it returns: per-section start address, break, page numbering, first-page difference, and header/footer text. It also names the sibling it differs from (section.list gives part names instead of text), so an agent can distinguish it without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'Edit it and pass it to layout.apply to change the layout' describes the round-trip workflow, and 'section.list gives the same setup with header/footer part names instead of text' gives the alternative. It stops short of an explicit when/when-not conditional, but the tool relationships are clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

live_closeA
Destructive

Close the document in its Word or LibreOffice window (attached with live.open). With unsaved changes it is refused (UNSAVED_CHANGES) unless save (save, then close) or discard (drop them) is given; nothing unsaved is ever lost silently. Use live.save to keep the window open. Returns whether it saved.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the document, or the file name of one open in a live app.
saveNoSave, then close.
engineNoAlways the live engine; may be left out.
discardNoClose and drop the unsaved changes.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true but give no detail; the description adds the specific failure mode (UNSAVED_CHANGES), the two ways to proceed (save vs discard), and a safety guarantee ('nothing unsaved is ever lost silently'). This is meaningful behavioral context well beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action and each subsequent sentence adding decision-relevant information (refusal condition, alternative tool, return value). No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the description still notes 'Returns whether it saved.' Combined with the error-code disclosure, safety guarantee, and sibling routing, nothing needed to invoke this tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description's gloss on save ('save, then close') and discard ('drop them') largely restates the schema; the added value is the interaction rule with the UNSAVED_CHANGES refusal, which is more usage guidance than parameter detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Close the document in its Word or LibreOffice window') and ties it to the live_open attachment context, which cleanly separates it from sibling live_save. An agent can distinguish it from the other live_* tools without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the when: refused with UNSAVED_CHANGES if there are unsaved changes, unless save or discard is passed. It also names the alternative ('Use live.save to keep the window open'), giving a clear routing decision between close and save.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

live_get_selectionA
Read-onlyIdempotent

Read what the user has selected in Word or LibreOffice right now, and the paragraph the selection starts in with its address (p12#a1b2c3d4), to edit with doc.batch or text.replace. Use it when the user points at text ("this paragraph", "here"); live.select moves the selection instead. The document must be attached with live.open (ENGINE_UNAVAILABLE otherwise). Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the document, or the file name of one open in a live app.
engineNoAlways the live engine; may be left out.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry readOnlyHint, idempotentHint and openWorldHint=false, so 'Read-only' is somewhat redundant. The description adds real value beyond the annotations, however: it discloses the prerequisite (document must be attached via live.open, else ENGINE_UNAVAILABLE) and the address format returned. That prerequisite/error disclosure is the kind of context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then usage trigger, alternative, and prerequisite. Slightly dense with parentheticals, and 'Read-only' duplicates the annotations, but every sentence still earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no elaboration, and the description still covers the prerequisite, the trigger, the alternative, and the downstream consumers. Nothing an agent needs to invoke this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented in the schema, giving a baseline of 3. The description references the live.open attachment requirement but adds no syntax or meaning for 'doc' or 'engine' beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Read') and resource ('what the user has selected in Word or LibreOffice right now'), plus the paragraph address returned. It explicitly distinguishes itself from live.select, so an agent can tell the two apart without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('Use it when the user points at text'), names the alternative ('live.select moves the selection instead'), and points to downstream tools (doc.batch, text.replace). When-to-use and what-not-to-do are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

live_openA

Attach to Word or LibreOffice for live editing: find the window already holding the document, or open it in app (word or libreoffice; default the one reachable, see live.status) and bring it to the front (front: false keeps it behind). Call it before live.select, live.get_selection, live.save, live.close and doc.batch with engine live. Opens or focuses a window; never changes the document. ENGINE_UNAVAILABLE when no app can be driven, DOC_AMBIGUOUS when a file name matches several open documents.

ParametersJSON Schema
NameRequiredDescriptionDefault
appNo`word` or `libreoffice`.
docYesPath to the document, or the file name of one open in a live app.
frontNoBring the app's window to the front (default true); the reply's `front` says whether it came.
engineNoAlways the live engine; may be left out.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds real behavioral context beyond annotations: the error states ENGINE_UNAVAILABLE and DOC_AMBIGUOUS, the app-default resolution, and the assurance it 'never changes the document'. Annotations (readOnlyHint=false, destructiveHint=false) already sketch the safety profile, and the description is consistent with them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action before the conditional and error clauses, and each sentence carries information. It is dense and slightly clause-heavy, but nothing is plainly redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a prerequisite/attach tool with an output schema already covering return values, it supplies prerequisites, error conditions, and sibling ordering. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds defaulting semantics the schema does not: 'app ... default the one reachable, see live.status' and 'front: false keeps it behind'. It enriches the two non-obvious parameters beyond their schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb cluster (attach/find/open/focus) on a specific resource (the Word or LibreOffice window holding a document). It clearly distinguishes itself from the plain doc_open sibling by tying the operation to 'live editing' and window attachment.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly instructs to 'Call it before live.select, live.get_selection, live.save, live.close and doc.batch with engine live', naming both the prerequisites and the dependent siblings. The 'front: false keeps it behind' note and the 'see live.status' pointer give concrete alternative-selection context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

live_placesA
Read-onlyIdempotent

Show the user a list of places as clickable buttons: in a client that renders MCP Apps, a click moves Word's or LibreOffice's cursor there (mode cursor) or selects the paragraph (mode select) by calling live.select, with no assistant turn. Each place has a label and an at address and/or a find_phrase from para.locate. Use it to walk a writer through findings; live.select jumps to one place directly. Other clients just get the list back. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the document, or the file name of one open in a live app.
modeNoWhat a click does: `cursor` (default) puts the cursor at the place's start; `select` selects its paragraph.
engineNoAlways the live engine; may be left out.
placesYesThe buttons, in order: a `label` and `at` or `find_phrase` each (with both, `find_phrase` is tried when `at` fails).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only/idempotent/closed-world, so the description adds the valuable side-effect context: in a rendering client a click performs an in-editor jump with 'no assistant turn', while other clients just receive the list. This is genuine behavioral disclosure beyond the structured hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose in the first clause, then layers client behavior, data shape, and the sibling alternative. Single dense paragraph with no filler, though the nested clauses make it mildly harder to scan than a bulleted form.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full annotation/schema coverage, the description only needs to add call-time semantics, which it does via the mode behavior and the client-dependent click effect. Nothing critical an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and every parameter is documented in the schema itself, including mode, engine, at/find_phrase, and the at-vs-find_phrase fallback. The description only restates that each place has a label plus an at or find_phrase, adding little beyond the heavy schema lifting, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Show the user a list of places as clickable buttons') and differentiates from the sibling live_select by noting it jumps to one place directly versus this tool's list-at-once behavior. An agent can distinguish it from para_locate/para_list without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly frames the use case ('walk a writer through findings') and names the alternative ('live.select jumps to one place directly'), plus notes behavior for non-MCP-App clients. It doesn't spell out when NOT to use it, but the routing to live_select is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

live_saveA

Save the document open in Word or LibreOffice (attached with live.open) to its file, from inside the app. Call it after live edits (doc.batch with engine live) to keep them; live.close with save: true saves and closes in one call. Overwrites the file on disk with the app's version; no backup is taken.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the document, or the file name of one open in a live app.
engineNoAlways the live engine; may be left out.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false, destructiveHint=false, openWorldHint=false. The description adds non-obvious behavior: it overwrites the on-disk file with the app's version and takes no backup, plus the prerequisite that the doc must already be attached with live.open. That is meaningful disclosure beyond the structured fields, and it does not contradict destructiveHint=false since a normal save is not a destructive operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: action first, then the sequencing/alternative, then the risk disclosure. Every sentence carries distinct load with no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, so return values need not be explained. The description covers the prerequisite (live attachment), the persistence workflow, the close-and-save alternative, and the overwrite/no-backup consequence - everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters are documented in the schema (doc path or live-app file name; engine enum with default). The description adds no per-parameter syntax or format detail beyond noting the live.open attachment context, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (save) and resource (the document open in Word/LibreOffice, attached via live.open) and scopes it to acting inside the app. An agent can immediately distinguish this from live_open, live_close, and doc_batch without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit sequencing guidance: call after live edits via doc.batch with engine live to persist them, and the alternative live.close with save: true is named for the save-and-close case. This is exactly the when-to-use-vs-alternative routing an agent needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

live_selectA

Show the user a place in Word or LibreOffice: select a paragraph, or with mode cursor only put the cursor at its start, by address (at, p142#a7b2a7b2) or by a find_phrase from para.locate (matched loosely per match_level). paragraphs_after moves on that many paragraphs. Use it to point at a passage you are discussing; live.places offers several as buttons. Changes only the selection; needs live.open. STALE_ADDRESS when at no longer matches, ANCHOR_NOT_FOUND or ANCHOR_AMBIGUOUS for a phrase.

ParametersJSON Schema
NameRequiredDescriptionDefault
atNoParagraph address, e.g. `p142#a7b2a7b2`.
docYesPath to the document, or the file name of one open in a live app.
modeNo`select` (default) selects the paragraph; `cursor` only puts the cursor at its start, so typing or Delete cannot replace it.
frontNoBring the app's window to the front (default true); the reply's `front` says whether it came.
engineNoAlways the live engine; may be left out.
find_phraseNoA phrase that occurs once in the document (`\r` for a paragraph mark), as `para.locate` gives it.
match_levelNoHow loosely `find_phrase` matches. `default` (the default) ignores case, accents and punctuation; `loose` symbols too. Either tries the levels from verbatim on and takes the first that matches, so one verbatim paragraph beats looser ones. `exact` is `para.locate`'s rule: case ignored, nothing else, no retry. Two meanings of exact: the request's `exact` allows a case difference, the reply's does not. The reply's `match_level` (`exact` character for character, `case`, `default`, `loose`) names the level that matched, with `matched_text` when it is not `exact`.
paragraphs_afterNoSelect the paragraph this many after the one named.
find_phrase_acrossNo`para.locate`'s `find_phrase_across`, for a phrase spanning a mark.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnly=false / destructive=false; the description goes further by disclosing the exact side-effect scope ('Changes only the selection'), the live.open dependency, and the failure modes (STALE_ADDRESS, ANCHOR_NOT_FOUND, ANCHOR_AMBIGUOUS). That is material behavior an agent cannot infer from the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and keeps everything in one dense but purposeful block with no filler sentences. It is slightly run-on with stacked parentheticals, which costs a point on readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the description covers purpose, prerequisites, alternatives and error codes for a 9-parameter tool. Nothing an agent needs in order to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents every parameter, including the match_level nuances. The description restates the at/find_phrase/paragraphs_after mechanics without adding syntax or format beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Show the user a place in Word or LibreOffice: select a paragraph, or ... put the cursor at its start') and gives concrete addressing forms (at `p142#a7b2a7b2`, find_phrase). It distinguishes itself from the live.* family by pointing to live.places for the button variant.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit use case ('Use it to point at a passage you are discussing'), names a related sibling (live.places offers several as buttons) and a prerequisite (needs live.open). It stops short of stating when NOT to use it, so it is clear context rather than a full routing rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

live_statusA
Read-onlyIdempotent

Check the live apps: which of Word and LibreOffice are installed and reachable, and which documents they have open; with doc, which app holds it, whether that app is driven by this server or only a lock file says so, its full path and whether it has unsaved changes. Call it before live.open, or to decide between live editing and the file engine (a file open in Word should be edited live or closed first). Read-only; never fails for a missing app.

ParametersJSON Schema
NameRequiredDescriptionDefault
docNoPath to the document, or the file name of one open in a live app.
engineNoAlways the live engine; may be left out.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and closed-world scope, so the safety profile is covered. The description nonetheless adds behavior beyond the structured fields: it will not fail when an app is missing, and it distinguishes a server-driven app from one inferred only from a lock file, which materially affects how the caller should interpret the result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence and the usage rule follows immediately; nothing is padding. The first sentence is somewhat clause-heavy and could be split for faster scanning, which keeps this short of 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value documentation is not required, yet the description still describes the key result fields (owner app, drive mode, path, dirty state). Combined with annotations covering read-only/idempotency and the explicit decision guidance, an agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline would be 3, but the description adds meaning the schema does not carry: supplying `doc` widens the report to that document's owning app, its path and its unsaved-changes state. The `engine` enum is not explained beyond the schema, which caps this slightly below 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb (check) and resource set (Word/LibreOffice, open documents, lock state, unsaved changes) rather than restating the tool name. The `doc` variant is spelled out in detail: which app holds the document, whether it is server-driven or only lock-file claimed, full path, and dirty state. An agent can distinguish this diagnostic tool from live_open/live_close without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit call sites: 'Call it before live.open' and 'to decide between live editing and the file engine', plus the concrete decision rule that a file open in Word should be edited live or closed first. This is when-to-use guidance with named alternatives and a tie-breaking condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

note_addA

Add a footnote or endnote: the reference mark goes at a body point (p3#a1b2c3d4:10-10, after offset 10), after a range, or at the end of a paragraph (p3#a1b2c3d4); text is the note's one line. Mark and note are tracked insertions, so rejecting them removes the note; the notes part is created when missing. Backed up and undoable (history.undo); dry_run previews; expect.sha256 refuses a changed file. Returns the note's id, displayed number and address (fn5/p1#…).

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesBody point p3#fp:10-10 (the mark goes after the offset), a range inside one paragraph (after it) or a paragraph (at its end).
docYesPath to the .docx.
tagNoAppended to the author.
kindYesfootnote (bottom of the page) or endnote (end of the document).
textYesThe note text, one line.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: states mark/note are tracked insertions (rejecting removes the note), the notes part is created when missing, changes are backed up and undoable via history.undo, dry_run previews, and expect.sha256 refuses a changed file. This is exactly the mutation context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Densely packed but front-loaded and every clause carries information; the trailing 'returns id/number/address' is slightly redundant against the output schema, keeping it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and annotations covering the safety profile, the description still supplies the addressing syntax, guard semantics, and undo behavior needed to call it correctly. Nothing an agent needs is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3, but the description adds real syntax guidance: the `at` format (p3#a1b2c3d4:10-10 after offset 10, after a range, or paragraph end) and that `text` is the note's one line. Useful elaboration beyond the schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Add a footnote or endnote') and immediately scopes the two supported kinds, distinguishing it from adjacent tools like comment_add. An agent can tell exactly what the tool produces.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear context for use (creating a note whose mark attaches at a body point, range, or paragraph end), but it never names alternatives (e.g. comment_add) or states when-not to use this tool. Slightly short of explicit routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

page_estimateA
Read-onlyIdempotent

Estimate the page each paragraph starts on (and ends on when it spans pages): from Word's rendered page marks and explicit breaks where present, else a words-per-page model; always flagged estimated. at (p142#a7b2a7b2) gives one paragraph; by "page" lists pages with their first and last paragraph instead. Use it to tell a user roughly where text is; para.locate adds chapter, scene and a find phrase. Read-only; paged at about 8,000 bytes with cursor.

ParametersJSON Schema
NameRequiredDescriptionDefault
atNoOnly this paragraph, by address, e.g. p142#a7b2a7b2.
byNoList one row per paragraph (default) or per page.
docYesPath to the .docx.
limitNoMost items to return; a response is also capped at about 8,000 bytes.
cursorNoThe `next` value of the previous response, to continue the list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover safety (readOnly, idempotent, non-open-world), and the description adds real behavioral context beyond them: results are always flagged `estimated`, the two estimation fallbacks, and the ~8,000-byte pagination with `cursor`. It does not discuss accuracy limits of the words-per-page model, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and mechanism, and every clause carries information (fallback model, flag, addressing, pagination). It is densely packed into a few sentences and slightly compressed, but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, and the description covers mechanism, the `estimated` caveat, addressing, sibling routing, and pagination. Only minor gaps remain, such as the practical accuracy of the words-per-page estimate when no page marks exist.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the baseline is 3, but the description adds meaning beyond the schema: `at` accepts the address form p142#a7b2a7b2, `by: "page"` yields pages with their first and last paragraph, and `cursor` is tied to the ~8,000-byte page cap. It complements rather than repeats the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource (estimate the page each paragraph starts/ends on) and explains the estimation basis (rendered page marks, explicit breaks, else a words-per-page model). It distinguishes itself from the closest sibling, para.locate, by naming what that tool adds.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit usage context ("Use it to tell a user roughly where text is") and names an alternative with its differentiating capability (para.locate adds chapter, scene and a find phrase). It stops short of stating when NOT to use it, so it is strong but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

para_deleteA

Delete a paragraph (p3#a1b2c3d4) or a run of paragraphs (p3#a1b2c3d4..p5#e5f6a7b8), as a tracked deletion the writer can reject. File engine: backed up first, logged for history.undo, dry_run previews, expect.sha256 refuses a file changed since; tracked: false deletes plainly (a change the writer approved). STALE_ADDRESS if the paragraph changed since it was read. Use text.replace to delete part of a paragraph, doc.batch for several edits all or nothing. Returns the address_map of shifted paragraphs.

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesParagraph p3#fp or run p3#fp..p5#fp.
docYesPath to the .docx (live: or the file name of one open in a live app).
tagNoAppended to the author.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
trackedNotrue (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations). engine live: the app's change tracking is off for the edit and put back after; text.replace and para.insert, refused (UNSUPPORTED_CONTENT) next to another unresolved tracked change; the app's undo takes it back. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial behavioral context beyond annotations: file engine backup, history.undo logging, dry_run preview, expect.sha256 guard, STALE_ADDRESS error, tracked vs plain deletion semantics, engine-live specifics, and refusal conditions. Annotations already declare write/safety profile, and the description enriches it without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose, then packs operational details into a compact paragraph. Every sentence carries useful information about behavior, alternatives, or error handling, with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a write tool with a rich schema and output schema. It explains mutation semantics, reversibility, guards, errors, and alternatives, and notes the return value (address_map of shifted paragraphs) even though an output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter thoroughly, including at, doc, tag, author, expect, dry_run, and tracked. The description repeats most of that information (address format, tracked false behavior, expect guard) and adds only minor examples, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Delete) and resource (paragraph or run of paragraphs), with concrete address examples that distinguish it from siblings like text.replace and doc.batch. The scope and tracked-deletion nature are immediately clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names alternatives and selection conditions: use text.replace to delete part of a paragraph, doc.batch for several edits all or nothing. Also explains when to use tracked:false versus the default tracked deletion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

para_getA
Read-onlyIdempotent

Read one paragraph in full by address (p142#a7b2a7b2, or fn3/p1#… in a note): text, style, direct paragraph formatting, character-formatted spans (bold, italic, font...) and layout facts (heading_level is null for a body paragraph, 1-9 for a heading). Use it before editing a paragraph or to check its formatting; para.list reads many paragraphs, style.get a style. Read-only; a very long text is paged (limit characters, cursor from the reply's next). STALE_ADDRESS if it changed since read.

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesParagraph address from a read result, e.g. p142#a7b2a7b2.
docYesPath to the .docx.
limitNoMost characters of text to return.
cursorNoThe `next` value of the previous response, to continue the list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotentHint, so safety is covered; the description goes further by disclosing paging behavior (limit characters, cursor from the reply's next) and the STALE_ADDRESS error condition when the address has changed. "Read-only" repeats the annotation, but the paging and staleness semantics are genuine additions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then return contents, alternatives, and behavioral caveats in a logical order. The heavy parentheticals make it dense, but each clause carries distinct information rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers the address format, what is returned, paging, error semantics, and sibling routing. An output schema exists so return values need not be enumerated, yet the description's brief summary of returned fields (text, style, formatting spans, layout facts) is helpful and complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description adds value beyond the schema by illustrating the address syntax (including note addresses like fn3/p1#…) and explaining that limit/cursor drive paging. It also clarifies heading_level semantics (null for body, 1-9 for heading), which the schema does not.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Read one paragraph in full by address") with the exact address formats shown. It distinguishes itself from siblings by naming para.list (many paragraphs) and style.get (a style). An agent can select this tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use it ("before editing a paragraph or to check its formatting") and routes to alternatives for other cases ("para.list reads many paragraphs, style.get a style"). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

para_insertA

Insert one new paragraph with text after or before an existing one (give after or before, e.g. p3#a1b2c3d4), as a tracked insertion (style it with style.apply in doc.batch). File engine: backed up first, logged for history.undo, dry_run previews, expect.sha256 refuses a changed file. tracked: false inserts plainly, on either engine. engine live inserts in the open Word/LibreOffice window (after live.open). Use doc.batch for several edits all or nothing. Returns the address_map of shifted paragraphs.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx (live: or the file name of one open in a live app).
tagNoAppended to the author.
textYesText of the new paragraph.
afterNoInsert after this paragraph (or before).
authorNoRevision author.
beforeNoInsert before this paragraph (or after).
engineNo`live` edits the document open in Word or LibreOffice (see live.open).
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
trackedNotrue (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations). engine live: the app's change tracking is off for the edit and put back after; text.replace and para.insert, refused (UNSUPPORTED_CONTENT) next to another unresolved tracked change; the app's undo takes it back. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the safety triad; the description goes far beyond it by disclosing backup-before-write, history.undo logging, dry_run preview, the expect.sha256 guard failing as DOC_CHANGED_ON_DISK, tracked:false semantics with UNSUPPORTED_CONTENT refusals, and live-engine tracking toggling. This is exactly the behavioral context an agent needs for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the action and placement, then mode/guard details. Dense and semi-colon heavy but nearly every sentence carries distinct information; a few clauses (e.g. the tracked:false rationale) shade into what the schema's tracked description already says.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter tool with nested expect object and an existing output schema, the description covers engines, backup/undo, guards, tracked vs plain writes, and even names the return value kind, so the agent has enough to call it correctly without further reading.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds specifics the schema lacks: the concrete paragraph-address example (p3#a1b2c3d4), the either/or relationship of after/before, and the practical meaning of tracked:false and engine live. It goes modestly beyond the structured fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Insert one new paragraph with `text`') plus the placement model (after/before an existing one), which cleanly separates it from para_delete, para_get, para_list and text_replace. An agent can identify the tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives real routing guidance: 'Use doc.batch for several edits all or nothing', 'style it with style.apply in doc.batch', 'engine live ... after live.open'. It does not explicitly contrast with the nearest sibling (text_replace) but the mode-selection guidance is strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

para_listA
Read-onlyIdempotent

List every paragraph in document order with its address, text, style, heading level and layout facts (centred, page break before, blank paragraphs before, empty, table cell); heading_level is null for a body paragraph. normalized adds normalised text, pages the estimated page, stories notes or headers. Use it to index or scan a whole document; para.get reads one paragraph with formatting, doc.outline only headings, text.find searches. Read-only; paged: about 8,000 bytes per reply (limit up to 1,000), continue with cursor set to the reply's next.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
limitNoMost items to return; a response is also capped at about 8,000 bytes.
pagesNoAdd the estimated `page` and `page_label` per paragraph, and `page_basis`, `rendered_marks` and `page_count` (see page.estimate).
cursorNoThe `next` value of the previous response, to continue the list.
storiesNoStories to read (default ["body"]): "notes" adds footnotes and endnotes, each after the paragraph holding its mark; "headers" adds headers and footers, after the body. Their addresses carry a prefix (fn3/p1#…, hdr1.default/p1#…).
normalizedNoAdd `normalized`, the text as `text.normalize` gives it.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotentHint/openWorldHint=false, and the description reinforces 'Read-only' while adding genuinely new operational context: paging at ~8,000 bytes per reply, limit up to 1,000, and resumption via `cursor` set to the reply's `next`. It also clarifies the null semantics of heading_level. It stops short of stating prerequisites (e.g. whether doc_open is required first) or error behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the resource and the returned fields before the routing guidance and paging caveat, and every clause carries information. The middle sentence is dense and semicolon-packed, which slightly hurts scanability, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, field-level return documentation is not required, and the description still covers scope, flags, pagination and alternatives for a 6-parameter tool with one required arg. The only real omission is whether the document must be opened via doc_open before calling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: it explains what the flags yield (normalized adds normalised text, pages adds the estimated page, stories adds notes or headers), which tells the agent the output shape each flag unlocks rather than just its boolean type.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource ('List every paragraph in document order') plus an enumeration of exactly what each item carries (address, text, style, heading level, layout facts). It also names and distinguishes the nearest siblings (para.get, doc.outline, text.find), so an agent can identify it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the use case ('index or scan a whole document') and names three alternatives with the condition that selects each: para.get for one paragraph with formatting, doc.outline for headings only, text.find for searching. This is exactly the when/when-not/alternative structure.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

para_locateA
Read-onlyIdempotent

Say where paragraphs are, in terms a person can follow: for one paragraph, a range (p40#a1b2c3d4:0..p45#e5f6a7b8:0, offsets ignored) or the whole document, each one's chapter, scene, estimated page, shortest unique first … last words phrase, and a phrase Word's Find meets exactly once (for Ctrl+F or live.select). A phrase can be null with a reason (empty, duplicate). structure: false skips chapter detection for speed. Use it to tell a writer where a passage is; page.estimate gives only pages. Read-only; paged at about 8,000 bytes with cursor.

ParametersJSON Schema
NameRequiredDescriptionDefault
atNoParagraph address or range (offsets ignored), e.g. p142#a7b2a7b2; default the whole document (empty paragraphs left out).
docYesPath to the .docx.
limitNoMost items to return; a response is also capped at about 8,000 bytes.
cursorNoThe `next` value of the previous response, to continue the list.
profileNoDetection settings for this document.
overridesNoForce or deny a chapter or scene at paragraphs by fingerprint.
structureNofalse: skip chapter, part and scene detection (they come back null), for callers that keep their own structure; faster on a single paragraph. Default true.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotentHint/openWorldHint=false, but the description adds real behavioral context: pagination at ~8,000 bytes with a `cursor`, that phrases may be null with a `reason` (empty, duplicate), and that structure:false skips detection to gain speed. It even flags the small annotation overlap ('Read-only') rather than contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core capability and reasonably sized for a seven-parameter tool, with no filler sentences. It is, however, a single dense paragraph of stacked clauses and jargon-heavy tokens (p40#a1b2c3d4:0..) that slow parsing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be spelled out, yet the description still covers paging, null/duplicate phrase handling, the structure toggle, and the relationship to page.estimate. The dense profile/overrides detection semantics are left to the schema, which is acceptable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter including at, cursor, profile, overrides and structure. The description only lightly reinforces a few of these (offsets ignored, whole-document default, structure:false effect), so the baseline 3 for high coverage is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and resource ('say where paragraphs are') and enumerates the specific artifacts it returns: chapter, scene, estimated page, unique phrase, and a Word's-Find-safe phrase. It also names and distinguishes a sibling ('page.estimate gives only pages'), so an agent can tell it apart without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly frames the use case ('Use it to tell a writer where a passage is') and contrasts with one alternative (page.estimate). It does not address when to prefer it over the nearer siblings para_list, para_get, or text_find, so the routing guidance is strong but incomplete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

recipe_listA
Read-onlyIdempotent

List the cleanup recipes recipe.run can apply: the bundled ones and the user's own, each with name, version, description and source, plus any recipe files that failed validation and why. Call it to pick a recipe before recipe.run. Read-only; needs no document.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and closed-world, so the safety profile is covered; 'Read-only' is largely redundant. However, the description adds genuine value by disclosing that failed-validation recipe files and their reasons are included, which annotations do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences, front-loaded with the core listing behavior followed by the routing directive. Slight redundancy in restating 'Read-only' which the annotation already declares, but otherwise tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, yet the description helpfully summarizes the entry fields and the validation-failure reporting. For a no-arg read tool feeding recipe.run, nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the baseline is 4 and there is nothing for the description to compensate for. The description appropriately says nothing about inputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (cleanup recipes recipe.run can apply), and names the sibling it feeds into (recipe.run). It also enumerates what each entry contains (name, version, description, source), so an agent can distinguish it from every other list tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Call it to pick a recipe before recipe.run,' giving both the when (prerequisite discovery step) and the alternative/consumer (recipe.run). No inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

recipe_runA
Read-onlyIdempotent

Run a cleanup recipe (a name from recipe.list, or an inline definition) over the document and return the edits it proposes as a ready doc.batch request (batch, guarded by expect.sha256), repeating until the text is stable. Writes nothing itself: review the proposal, then apply it with doc.batch (dry_run there to preview). RECIPE_INVALID for an unknown or invalid recipe; edits that would touch unsupported content are listed under skipped. Refused for .txt/.md/.odt sources, which cannot be written.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx file.
recipeNoName from recipe.list.
dry_runNoAccepted for symmetry; recipe.run never writes.
definitionNoAn inline declarative recipe (same schema as a stored one).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly/idempotent/openWorld, but the description adds substantial behavioral context beyond them: it writes nothing itself, iterates until text is stable, guards the proposal with expect.sha256, surfaces RECIPE_INVALID, lists unsupported-content edits under 'skipped', and refuses non-.docx sources. These are concrete operational traits not derivable from the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The action and output are front-loaded, and every sentence carries operative information (output form, safety, errors, refusals). It is text-dense but largely waste-free, though the parenthetical workflow clauses add some stacking.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return format need not be explained, and the description still covers the full calling context: idempotent iteration, the external apply step, error codes, skipped edits, and unsupported source types. Nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds value by unifying the two recipe inputs conceptually ('a name from recipe.list, or an inline definition') and framing doc/batch inside the workflow. It stops short of syntax-level detail, which the schema already supplies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb 'Run' plus specific resource 'cleanup recipe' scoped over the document, with the exact output shape named (a ready doc.batch request). It distinguishes itself from the closest siblings recipe_list (source of names) and doc_batch (the applier), so an agent can route without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit workflow guidance: review the proposal, then apply it with doc_batch, using dry_run there to preview. It also states the exclusion (refused for .txt/.md/.odt sources) and where recipe names come from (recipe.list). When-to-use vs alternatives is fully spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

revision_acceptA

Accept tracked changes, making them plain text: by ids (from revision.list), by revision author, in a paragraph or run (at, p3#a1b2c3d4..p9#e5f6a7b8), or all. Not itself a tracked change: on the file engine the file is backed up first and the write is logged for history.undo; dry_run previews counts; expect.sha256 refuses a changed file. Use revision.reject to drop changes instead, doc.batch to accept and reject in one write. Returns counts and the revisions resolved.

ParametersJSON Schema
NameRequiredDescriptionDefault
atNoParagraph p3#fp or run p3#fp..p9#fp.
allNotrue: every revision in the document.
docYesPath to the .docx (live: or the file name of one open in a live app).
idsNoAccept the revisions with these ids (from revision.list).
authorNoExact revision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as a non-read-only, non-destructive, closed-world write; the description goes well beyond that by disclosing that the file is backed up first, the write is logged for history.undo, dry_run previews counts, and expect.sha256 refuses stale files (DOC_CHANGED_ON_DISK). These are the operational details an agent needs before mutating a document.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then selection modes, then safety/guard semantics, then siblings. Every clause carries distinct information (selector sources, backup/log behavior, preview, hash guard, alternatives) with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with nested objects, an output schema, and safety annotations, the description covers selection semantics, write-guard behavior, preview mode, and sibling routing. Nothing essential to correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema does not: it tells the agent where ids come from (revision.list), that author matching is exact, gives a concrete range example format, and explains the dry_run/expect behaviors that map to those params. It stops short of fully documenting every parameter, but exceeds the schema-only baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Accept tracked changes, making them plain text') and immediately enumerates the four selection modes (ids, author, at-range, all). It also names the sibling revision.reject as the inverse operation, so an agent can distinguish it without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes to alternatives with conditions: 'Use revision.reject to drop changes instead, doc.batch to accept and reject in one write.' Combined with the enumerated selection modes, the agent knows both when to pick this tool and when not to.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

revision_listA
Read-onlyIdempotent

List the tracked changes (insertions, deletions, moves, formatting, table rows and cells) in document order, each with id, type, author, date, paragraph address and text (clipped at 200 characters). Filter by author or type; stories notes or headers adds their changes. Use the ids with revision.accept or revision.reject; doc.stats counts changes by type. Read-only; paged: about 8,000 bytes per reply (limit up to 1,000), continue with cursor set to the reply's next.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
typeNoOnly this type.
limitNoMost items to return; a response is also capped at about 8,000 bytes.
authorNoOnly this author.
cursorNoThe `next` value of the previous response, to continue the list.
storiesNoStories to list (default ["body"]): "notes" adds footnotes and endnotes, "headers" headers and footers, after the body's revisions; their addresses carry a prefix (fn3/p1#…, hdr1.default/p1#…). Row and cell revisions are listed for the body's tables only.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/idempotent annotations, it discloses non-obvious behavior: output is document-ordered, text is clipped at 200 characters, replies are paged at about 8,000 bytes with a 1,000 limit, and continuation uses the reply's `next` as `cursor`. It also notes that row/cell revisions are only listed for the body's tables and that note/header addresses carry prefixes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: purpose first, then return fields, then filtering, then cross-tool routing, then pagination. Every clause carries information (clipping length, byte cap, cursor source), though the single unbroken paragraph is heavy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations and a rich output schema already present, the description need not restate return values, yet it still covers filtering, story scoping, paging, clipping and hand-off to accept/reject. Nothing an agent needs to invoke it correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description still adds value beyond the schema: it explains that `author`/`type` act as filters, that `stories` defaults to body and appends notes/headers after body revisions, and it clarifies the cursor/limit pagination contract in prose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('tracked changes') and enumerates the revision kinds covered (insertions, deletions, moves, formatting, table rows/cells), plus the exact returned fields. An agent can distinguish this from revision_accept, revision_reject and doc_stats immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly routes the agent: 'Use the ids with revision.accept or revision.reject; doc.stats counts changes by type', which explains the downstream workflow. It also explains story scoping ('notes' adds footnotes/endnotes, 'headers' adds headers/footers). It stops short of stating when-not to use it (e.g., versus doc_diff or comment_list), so it is clear context rather than a full decision rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

revision_rejectA

Reject tracked changes, undoing them in the text (insertions removed, deletions restored): by ids (from revision.list), by revision author, in a paragraph or run (at, p3#a1b2c3d4..p9#e5f6a7b8), or all. Not itself a tracked change: on the file engine the file is backed up first and the write is logged for history.undo; dry_run previews counts; expect.sha256 refuses a changed file. Use revision.accept to keep changes instead, doc.batch to accept and reject in one write. Returns counts and the revisions resolved.

ParametersJSON Schema
NameRequiredDescriptionDefault
atNoParagraph p3#fp or run p3#fp..p9#fp.
allNotrue: every revision in the document.
docYesPath to the .docx (live: or the file name of one open in a live app).
idsNoReject the revisions with these ids (from revision.list).
authorNoExact revision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the write/safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=false), and the description is consistent with them by explaining why rejecting is non-destructive. It adds real context: backup on the file engine, history.undo logging, dry_run previewing counts, and expect.sha256 refusing a changed file. However, this is context beyond what annotations carry but not a complete behavioral picture (e.g. error cases beyond DOC_CHANGED_ON_DISK), so it sits at a solid 3–4; credit is given for the backup/logging disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One dense paragraph that front-loads the core action and effect before listing selectors, guards, and alternatives. Every clause earns its place, though the packed parentheticals and clause stacking make it slightly heavier than ideal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with an output schema, the description covers the action, all selection modes, the safety guards, the undo relationship, and alternatives. With the output schema present, return-value explanation ('returns counts and the revisions resolved') is a bonus rather than a gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter, setting a baseline of 3. The description adds marginal value by tying `ids` to its source (revision.list) and giving a concrete `at` example range (p3#a1b2c3d4..p9#e5f6a7b8), which clarifies the address format beyond the schema's terse wording.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (reject tracked changes) plus the concrete effect (insertions removed, deletions restored), and immediately distinguishes itself from revision_accept. An agent can tell exactly what this does versus its nearest sibling without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Enumerates every selection mode (ids, author, at, all) and names the alternatives explicitly: revision.accept to keep changes, doc.batch to combine accept and reject in one write. The when-to-use and when-to-use-something-else routing is fully specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

section_listA
Read-onlyIdempotent

List each section's page setup: break type, title page, even/odd headers, page-number start and format, and which header and footer story (hdr1.default, ftr2.first...) it uses per kind; null means inherited. Use the story keys to read header text with para.list (stories headers) or para.get; layout.get gives the same setup with the header and footer text, in the form layout.apply takes. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so safety is covered and the trailing 'Read-only' adds nothing. The description does add real behavioral insight beyond structured data, notably that 'null means inherited' and how the story keys (hdr1.default, ftr2.first...) map to header/footer stories, which is not derivable from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with the returned fields and stays dense but earns its words, since every clause describes output content or routing. The final 'Read-only.' is redundant with the annotations, a minor bit of waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be spelled out, yet the description still explains the inheritance semantics and key formats. For a single-param read-only tool with full schema coverage, nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single parameter at 100% schema description coverage ('Path to the .docx.'), so the schema already carries the semantics and the baseline is 3. The description adds no further detail about the doc parameter itself.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource ('List each section's page setup') and then enumerates exactly what is reported: break type, title page, even/odd headers, page-number start and format, and the header/footer story keys. It is unmistakably distinct from para_list, para_get, and layout_get, which it names explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It routes the agent clearly: use the returned story keys with para.list or para.get to read header text, and use layout_get instead when you want the same setup plus the header/footer text. This gives an explicit alternative and the condition that selects it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

server_capabilitiesA
Read-onlyIdempotent

Describe this doc-control server: API and package version, engines (file, live), which live apps are reachable, feature support per engine, every operation with its kind and summary, every error code, and whether it is a frozen build. Call it once at the start of a session; server.help gives one operation's full request and result schemas. Read-only; needs no document.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is covered; the description's 'Read-only' clause is largely redundant. It does add genuine context beyond annotations by disclosing the shape and breadth of the response (engine list, reachable live apps, per-engine feature support, error codes, frozen-build flag) and the no-document precondition.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the verb and the enumeration in the first sentence, then adds two short routing/precondition sentences with no filler. The return-field list is dense but each clause maps to a distinct capability, so it earns its length; only slight tightness is lost in the run-on enumeration.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only discovery tool with an output schema, the description does more than required by naming the response categories and the session-start timing. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4 and there is no parameter meaning the description needs to compensate for. It correctly implies invocation is unconditional and requires no input document.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Describe this doc-control server') and enumerates exactly what is described: version, engines, reachable apps, feature support, operations, error codes, frozen-build status. It also explicitly differentiates itself from the sibling server_help, so an agent can tell the two apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit timing ('Call it once at the start of a session') and names the alternative with its disambiguating condition ('server.help gives one operation's full request and result schemas'). When-to-use and when-to-use-something-else are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

server_helpA
Read-onlyIdempotent

Get the JSON Schemas of one operation (op, e.g. "para.get": its request schema and its result's output_schema), or of every operation when op is left out. A doc.batch kind ("comment.reply", "para.move"...) gives the fields it takes inside ops, under batch_operations; a name that is both gets both. Old names (before 0.7.0) give the renamed operation. Call it before using an operation whose fields you are unsure of; server.capabilities lists the operations. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
opNoOperation or batch operation kind.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and closed-world, so the safety profile is covered. The description adds non-obvious behavior: batch kinds return batch_operations fields, old pre-0.7.0 names resolve to renamed operations, and names that are both return both. It is transparent about resolution edge cases beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose and packs high information density with no filler. The semicolon-heavy, parenthetical-laden second half is dense but every clause (batch kinds, legacy names, the call-first advice) earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be re-explained, yet the description still clarifies what the schema contains (request schema and result output_schema). For a one-optional-param meta tool, the definition covers everything an agent needs to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description enriches `op` well beyond the schema's terse 'Operation or batch operation kind': it gives example values ("para.get", "comment.reply"), covers batch-kind resolution, legacy names, and the omitted-`op` default. This corrects a schema that would otherwise under-describe a flexible param.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb (Get the JSON Schemas) and resource (one operation or every operation), and clarifies the dual behavior when `op` is omitted. It also distinguishes itself from server_capabilities, which lists operations rather than returning schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent to call it before using an operation whose fields it is unsure of, and names the sibling alternative (server_capabilities lists the operations). The when-to-use and the routing to a sibling are both stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

style_createA

Add a new paragraph, character, table or numbering style with its parent (based_on), next and linked styles and run and paragraph formatting (e.g. run {"bold": true, "size_pt": 14}; paragraph in twips). id defaults from name. Refused (STYLE_CONFLICT) when the id or name exists: use style.update to change a style, style.rename to rename one, styleset.install to add many. Not a tracked change, but history.undo takes it back: the file is backed up first (backup); dry_run previews.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoStyle id (default: from the name).
docYesPath to the .docx.
runNoCharacter formatting: bold, italic, small_caps, strike, underline, font, size_pt, color, highlight, vertical_align; null removes a key.
linkNoLinked paragraph/character style; '' for none.
nameYesDisplay name.
nextNoStyle of the next paragraph; '' for none.
typeNoKind of style (default paragraph).
quickNoShow in the quick-style gallery.
customNoA user-defined (not built-in) style.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
defaultNoThe default style of its type.
dry_runNoPreview only; write nothing.
based_onNoParent style id or name; '' for none.
paragraphNoParagraph formatting (twips): alignment, indent{left,right,first_line,hanging}, spacing{before,after,line,line_rule}, keep_next, keep_lines, page_break_before, outline_level; null removes a key.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say write, non-destructive, closed-world. The description goes further: names the STYLE_CONFLICT refusal condition, discloses that the file is backed up first, clarifies it is not a tracked change yet history.undo reverses it, and offers dry_run. That is substantial behavioral context beyond annotations, with no contradiction of destructiveHint=false.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and tightly packed, and every clause carries load-bearing information (conflict routing, backup, undo, preview). It is dense multi-clause prose rather than maximally scannable, so not a clean 5, but there is no waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation. The description covers creation semantics, conflict handling, alternates, backup/undo behavior, and preview mode — everything needed to call a 14-param mutation tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all 14 params are already documented. The description's parameter content (id defaults from name, run example, paragraph in twips) largely restates the schema, adding only a concrete formatting example. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Add) and resource (style) with the four style kinds enumerated, and explicitly contrasts itself with style.update, style.rename, and styleset.install. An agent can distinguish it from every relevant sibling without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing: 'Refused (STYLE_CONFLICT) when the id or name exists: use style.update to change a style, style.rename to rename one, styleset.install to add many.' It also names dry_run for preview and history.undo for reversal, giving both when-to-use and what-not-to-use conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

style_getA
Read-onlyIdempotent

Read one style by id or name ("Heading1" or "heading 1"): its type, parent chain, next and linked styles, how often it is used, heading level, the formatting it sets itself and its effective formatting after inheritance. Use it before style.update, or to see why text looks as it does; style.list lists all styles, para.get a paragraph's direct formatting. Read-only; STYLE_NOT_FOUND for an unknown style.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
styleYesStyle id or name.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotent/openWorld=false, so safety is covered; the description still adds value by naming the failure mode ('STYLE_NOT_FOUND for an unknown style'), which annotations cannot convey. It does not discuss doc-open prerequisites or error behavior for a bad doc path.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the operation and its return shape, then routing cues. It is dense but nearly every clause carries information; the long enumeration is justified by the multi-part return value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still summarizes the return contents and adds the not-found error code and mutation-preparation use case. For a two-parameter read tool with full annotation coverage, nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real semantics beyond the schema by showing that style accepts flexible identifiers ('Heading1' or 'heading 1'), implying case/space-insensitive lookup. The doc parameter gains nothing extra.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read one style by id or name') and enumerates the exact payload: type, parent chain, next/linked styles, usage count, heading level, direct vs effective formatting. This is clearly distinguishable from style.list (all styles) and para.get (paragraph direct formatting).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit trigger conditions ('before style.update', 'to see why text looks as it does') and names both alternatives with the condition that selects each. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

style_listA
Read-onlyIdempotent

List the styles defined in the document with id, name, type, parent and how many times each is used in the body. type keeps one kind (paragraph, character, table, numbering); used_only drops unused ones. Use it to find styles to clean up or reuse; style.get gives one style's full and inherited formatting. Read-only; paged: about 8,000 bytes per reply (limit up to 1,000), continue with cursor set to the reply's next.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
typeNoOnly this kind of style.
limitNoMost items to return; a response is also capped at about 8,000 bytes.
cursorNoThe `next` value of the previous response, to continue the list.
used_onlyNoOnly styles used at least once.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and the closed-world profile, so the safety story is set. The description adds genuinely new behavioral context: pagination size (~8,000 bytes/reply), the limit ceiling (1,000), and how to continue with `cursor` set to the reply's `next`.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the list purpose, then parameters, then routing and paging. Every sentence carries weight, though the field enumeration (id, name, type, parent, count) overlaps with the existing output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with an output schema and full annotation coverage, nothing an agent needs to call it correctly is missing. Pagination, filtering, alternatives and the return-shape gist are all present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter is already documented. The description restates the semantics of `type` (one kind) and `used_only` (drops unused) but adds no syntax or interaction detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (list) and resource (styles defined in the document) and enumerates the returned fields. It explicitly distinguishes itself from the sibling style.get, which returns one style's full and inherited formatting.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete use case (find styles to clean up or reuse) and names the alternative (style.get) with the condition that selects it. Both when-to-use and when-not-to-use are covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

style_mergeA
Destructive

Merge styles: re-point every use of the from style or styles (ids or names) to into in the body, notes, headers and other styles, then delete the from styles. Use it to clean up duplicate styles; style.rename only renames, style.update changes formatting. Not a tracked change, but history.undo takes it back; it removes style definitions, so the file is backed up first (backup); check with dry_run first. STYLE_NOT_FOUND for an unknown style.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
fromYesStyle id or name, or a list of them (they are removed).
intoYesStyle id or name.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the destructiveHint=true annotation: it discloses that this is not a tracked change, that history.undo reverses it, that the file is backed up first, that it removes style definitions, and that STYLE_NOT_FOUND is raised for unknown styles. This is rich behavioral context an agent cannot get from the annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The primary action is front-loaded, followed by usage, reversibility, and error semantics, and every sentence carries information. It is dense with parentheticals (the file is backed up first (`backup`); check with dry_run first), which slightly hurts readability but not to the point of waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, nested-object, multi-parameter tool with an output schema, the description covers exactly the gaps the structured fields cannot: side effects, reversibility via history.undo, backup behavior, dry_run, and the failure code. Return values are appropriately left to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the schema already documents each parameter, but the description still adds meaning: `from` is described as 'ids or names' and its re-pointing scope ('every use ... in the body, notes, headers and other styles') is spelled out, which clarifies the effect of the two core parameters beyond their schema text. The advantage over the baseline 3 is modest since expect/dry_run are fully covered by the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Merge styles') and precisely defines the operation: re-point every use of `from` to `into` across body, notes, headers, and other styles, then delete `from`. It explicitly distinguishes itself from siblings style.rename and style.update, so an agent can select it without inspecting either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the when-to-use ('clean up duplicate styles'), names the two nearest alternatives and why they differ (rename only renames, update changes formatting), and prescribes the safe workflow ('check with dry_run first'). Nothing about tool selection is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

style_renameA

Rename a style's display name and/or id (id defaults from the name); every reference follows: paragraphs, runs, headers, notes, numbering, and based_on, next and link in other styles. STYLE_CONFLICT if the new name or id is taken. Use style.merge to fold one style into another instead. Not a tracked change, but history.undo takes it back: the file is backed up first (backup); dry_run previews.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoStyle id (default: from the name).
docYesPath to the .docx.
nameNoDisplay name.
styleYesStyle id or name.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: discloses the STYLE_CONFLICT error condition, that it is not a tracked change but is reversible via history.undo, that the file is backed up first, and that dry_run previews. The cascading-reference scope is exactly the kind of behavioral detail the destructiveHint=false annotation alone cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and cascading scope, then handles errors, alternatives, and reversibility efficiently. A couple of clauses pack multiple concepts per sentence, but every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation with an output schema (returns needn't be explained), it covers scope, error behavior, reversibility, backup, dry-run, and the alternative tool. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter is already documented. The description's note that id defaults from the name duplicates the schema and adds no new syntax or format meaning. Baseline 3 is appropriate when the schema carries the load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (rename) plus the exact resource and fields affected (display `name` and/or `id`), and enumerates the cascading references. An agent can distinguish it from style_create, style_update, and style_merge without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent away from this tool for a related need: 'Use style.merge to fold one style into another instead.' This is a concrete exclusion naming a sibling. It lacks guidance on rename-vs-style_update, so it falls short of full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

styleset_exportA

Export the document's style definitions (all, the styles named, or custom_only) as a JSON style set, returned and also written to out when given (never overwrites an existing file). Feed it to styleset.install on another document to copy the look; styleset.export_dotx writes a Word template instead. The document is not changed.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
outNoAlso write the JSON here.
nameNoSet name.
stylesNoOnly these styles (ids or names).
custom_onlyNoOnly user-defined styles.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, destructiveHint=false), the description discloses output behavior ('returned and also written to `out`'), a non-overwrite safety guarantee, and that the source document is unchanged. This resolves the ambiguity of readOnlyHint=false by clarifying that only the output file is written.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action, followed by the routing guidance and the safety note. No redundant or filler text; every clause carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't explain return values, and it covers the remaining essentials: scoping modes, output-file behavior, sibling routing, and non-mutation guarantee. Complete for a 5-parameter export tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaningful semantics by framing the export mode selection ('all, the `styles` named, or custom_only') and explaining the `out` write behavior, which enriches the plain schema by describing how parameters interact.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Export) and resource (document's style definitions) with the exact scope options (all, `styles`, custom_only). It explicitly distinguishes itself from siblings by naming styleset.install and styleset.export_dotx and their different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit usage direction: 'Feed it to styleset.install on another document to copy the look' and contrasts with 'styleset.export_dotx writes a Word template instead.' The agent knows both when to use this tool and which alternative fits a different need.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

styleset_export_dotxA

Write the document's style definitions (all, the styles named, or custom_only) to a new .dotx Word template at out (must not exist), for Word users to attach or base documents on. The document itself is never changed. styleset.import_dotx brings a template's styles into a document; styleset.export gives a JSON style set instead. Returns the path, style count and size.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
outYesNew .dotx to create.
nameNoSet name.
stylesNoOnly these styles (ids or names).
custom_onlyNoOnly user-defined styles.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and destructiveHint=false; the description reconciles this by stating 'The document itself is never changed', so the agent knows the write targets a new file rather than mutating the source. It also adds a constraint annotations do not carry ('out must not exist') and reports the return payload. It stops short of anything like failure/overwrite behavior, so not a full 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences: action and output first, the non-mutation guarantee second, sibling routing third. Every clause earns its place, no filler or restated field labels.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still summarizes the return (path, style count, size) at no cost. Combined with the mode selection, the out-file precondition, and sibling disambiguation, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds the 'must not exist' precondition on `out` and frames the three selection modes (all / `styles` named / custom_only) that the schema only lists flatly. That is meaningful semantics beyond the field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (write) and resource (the document's style definitions) plus the output artifact (.dotx at `out`). It explicitly names the two closest siblings (styleset.import_dotx and styleset.export) and how they differ, so an agent can disambiguate without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: use this when you want a template, styleset.export when you want a JSON style set, styleset.import_dotx when pulling a template's styles into a document. The 'for Word users to attach or base documents on' clause names the situation that selects this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

styleset_import_dotxA

Install the styles of a .dotx Word template (path) into the document: new styles are added, existing ids replaced (on_conflict replace, default), kept (skip) or refused (error: STYLE_CONFLICT). Use it to apply a house template; styleset.install takes a JSON style set, style.create adds one style. Not a tracked change, but history.undo takes it back: the file is backed up first (backup); dry_run previews.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
pathYesThe .dotx to read.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
on_conflictNoA style id already in the document (default replace).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false/destructiveHint=false, and the description adds substantial context beyond them: new styles are added, existing ids are replaced/skipped/errored, the STYLE_CONFLICT error code is named, it is not a tracked change, history.undo reverses it, the file is backed up first, and dry_run previews. This is a rich behavioral disclosure that goes well past the annotations and does not contradict them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose and packs conflict handling, alternatives, reversibility, and preview into a single dense paragraph with little waste. It is slightly crammed, but nearly every clause carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be described, and the description still covers the mutation semantics, conflict modes, error code, reversibility, backup, and dry run. An agent has everything needed to invoke it correctly; only the dangling `backup` reference is a minor imperfection.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: on_conflict's replace default is restated with its outcome (existing ids replaced) and the error mode is tied to the STYLE_CONFLICT code, and dry_run's preview behavior is reinforced. The one blemish is the mention of a `backup` action that has no corresponding parameter in the schema, which could momentarily confuse the agent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (install) and resource (styles from a .dotx template into the document) with the scope of the operation spelled out. It explicitly distinguishes itself from siblings by noting styleset.install takes a JSON style set and style.create adds one style. An agent can tell it apart from styleset_export_dotx and the other style tools without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use ('Use it to apply a house template') and routes to the alternatives (styleset.install for JSON sets, style.create for a single style). This is exactly the sibling-differentiation an agent needs to pick correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

styleset_installA

Install a JSON style set (inline styleset, or a file at path, as styleset.export writes it) into the document: new styles are added, existing ids replaced (on_conflict replace, default), kept (skip) or refused (error: STYLE_CONFLICT). Use it to copy styles between documents; styleset.import_dotx reads a Word template, style.create adds one style. Not a tracked change, but history.undo takes it back: the file is backed up first (backup); dry_run previews.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
pathNoOr a style set file.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
stylesetNoThe style set (inline).
on_conflictNoA style id already in the document (default replace).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations only declaring readOnlyHint=false and destructiveHint=false, the description carries the real behavioral load: not a tracked change, recoverable via history.undo, automatic file backup, dry_run preview, and the concrete error codes STYLE_CONFLICT and DOC_CHANGED_ON_DISK. That is far beyond what the annotations expose and does not contradict them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense paragraph, front-loaded with what the tool does before alternatives and caveats. Every clause earns its place, though the heavy parenthetical compression ("as styleset.export writes it", "backup") makes it slightly harder to scan than an ideal definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, and the description covers everything else an agent needs: input forms, conflict policy, backup/undo behavior, preview mode, and error codes. Nothing required for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description still adds value by spelling out the three on_conflict outcomes and their consequences (replace default, skip, error STYLE_CONFLICT) and by contrasting `styleset` inline with `path`. The `expect` write guard is left to the schema, so it is not a full 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Install) and resource (a JSON style set) plus the two input forms (inline `styleset` or a file at `path` produced by styleset.export). It explicitly distinguishes itself from siblings: styleset.import_dotx reads a Word template and style.create adds a single style.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit use case ("Use it to copy styles between documents") and names the two nearest alternatives with the condition that selects each. It also routes conflict handling via on_conflict and previewing via dry_run, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

style_updateA

Change an existing style: its parent (based_on), next or linked style, quick-gallery flag, or run and paragraph formatting (e.g. run {"italic": true, "font": "Garamond"}; null removes a key; other keys stay). Every paragraph using the style changes with it; to format one paragraph use format.apply in doc.batch. Not a tracked change, but history.undo takes it back: the file is backed up first (backup); dry_run previews. STYLE_NOT_FOUND for an unknown style.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
runNoCharacter formatting: bold, italic, small_caps, strike, underline, font, size_pt, color, highlight, vertical_align; null removes a key.
linkNoLinked paragraph/character style; '' for none.
nextNoStyle of the next paragraph; '' for none.
quickNoShow in the quick-style gallery.
styleYesStyle id or name.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
based_onNoParent style id or name; '' for none.
paragraphNoParagraph formatting (twips): alignment, indent{left,right,first_line,hanging}, spacing{before,after,line,line_rule}, keep_next, keep_lines, page_break_before, outline_level; null removes a key.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial behavioral context beyond the annotations: the change affects 'Every paragraph using the style', it is not a tracked change but is reversible, the file is backed up first, dry_run previews, and STYLE_NOT_FOUND is returned for unknown styles. This is rich disclosure for a mutation tool whose annotations only say non-readonly and non-destructive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the resource and effect, then layers alternatives, reversibility, and error behavior compactly. The heavy parentheticals make it dense but every sentence carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and 100% parameter coverage, the description needn't explain return values and doesn't. For a mutation tool it covers scope of effect, reversibility, backup, preview, and error code – nothing an agent needs is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds useful cross-cutting semantics – the run example and the null-removes-a-key/other-keys-stay merge behavior – which clarifies how partial updates are applied, though most of this is echoed from the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Change an existing style') and enumerates exactly what is mutable: parent, next/linked style, quick-gallery flag, run and paragraph formatting. This clearly distinguishes it from siblings like style_create, style_get, style_rename, and style_merge.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: 'to format one paragraph use format.apply in doc.batch' names the alternative and the condition that selects it. It also notes history.undo reverses the change. It does not address when to prefer style_rename/style_merge for those overlapping operations, keeping it short of a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

table_getA
Read-onlyIdempotent

Read one table's grid: rows of cells, each with its first grid column, span, vertical merge (null, restart, continue) and the addresses of its paragraphs (read their text with para.get or para.list). Name it by table (1-based, body only, the cell.table para.list shows) or by at, any paragraph address in it, also in notes and headers. Use it before table.row.insert/delete or to edit cells with text.replace. Read-only; ANCHOR_NOT_FOUND for no such table.

ParametersJSON Schema
NameRequiredDescriptionDefault
atNoInstead of `table`: any paragraph address in the table, in any story (`fn3/p1#…`, `hdr1.default/p1#…`); the reply's `table` is then numbered within that story.
docYesPath to the .docx.
tableNoTable number in the main story, 1-based in document order (the `cell.table` of a paragraph row); text-box and DrawingML tables are not counted. Tables of notes, headers and footers are reached with `at`.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnlyHint, idempotentHint, openWorldHint=false), so the bar is lower. The description still adds real value: it discloses the per-cell return fields and the ANCHOR_NOT_FOUND error for a missing table, which goes beyond the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the action and return shape, then parameter-naming guidance, then usage. Dense but each clause carries information; only mild redundancy with the schema text on table numbering.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values needn't be re-explained, yet the description still gives a usable summary of the grid. Naming rules, story coverage, usage ordering, and the error code are all present – nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents `table` (1-based, body only, text-box/DrawingML not counted), `at`, and `doc`. The description restates the table/at distinction with minimal additional syntax or format detail, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (read) and resource (one table's grid) and immediately enumerates the returned structure – cells with first grid column, span, vertical merge, and paragraph addresses. Siblings like table_row_insert/table_row_delete are clearly distinguished by this read framing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'Use it before table.row.insert/delete or to edit cells with text.replace', and names para.get/para.list for reading cell text. Clear when-to-use context, though it does not state explicit when-not conditions against other table-adjacent tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

table_row_deleteA

Delete one row of a body table (table as table.get numbers it, row 1-based) as a tracked change the writer can reject. Refused (UNSUPPORTED_CONTENT) for a row with a vertically merged cell. Backed up and logged for history.undo; dry_run previews; expect.sha256 refuses a changed file. Use doc.batch to change several rows at once, para.delete for paragraphs outside tables.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
rowYesThe row, 1-based.
tagNoAppended to the author.
tableYesTable number as `table.get` numbers it: 1-based, in document order, main story only (a table in a note, header or footer cannot be named here).
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses that the delete is a tracked change the writer can reject (which explains destructiveHint=false for a delete operation), that the file is backed up and logged for history.undo, the dry_run preview path, and the expect.sha256 staleness guard. This is rich, non-obvious behavioral context and is consistent with, not contradicting, the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, front-loaded with the action and scope, then refusal behavior, then durability/safety, then alternatives. No filler; every sentence carries routing or behavioral information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described. For a mutating tool with 7 params, the description covers scope, refusal cases, reversibility, safety guards, and sibling routing — nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description still adds meaning by tying `table` to table.get's numbering scheme and by restating the dry_run and expect.sha256 operational contract (what happens on refusal). Marginal but real added value over the schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource ('Delete one row of a body table') and immediately scopes it with the numbering semantics for `table` and `row`. It also explicitly separates itself from siblings ('para.delete for paragraphs outside tables', 'doc.batch to change several rows at once'), so an agent can route correctly without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit alternatives with the condition that selects each: doc.batch for several rows, para.delete for paragraphs outside tables. It also states a when-not condition (refused with UNSUPPORTED_CONTENT for a vertically merged cell), which is exactly the kind of exclusion that prevents failed calls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

table_row_insertA

Insert a row into a body table as a tracked change: after row after_row (0: before the first), with one text per cell in cells (e.g. ["2024", "12.5"]), matching the row it follows (SCHEMA_INVALID otherwise). Refused (UNSUPPORTED_CONTENT) between two rows a vertical merge spans. Backed up and logged for history.undo; dry_run previews; expect.sha256 refuses a changed file. Use doc.batch for several rows at once.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
tagNoAppended to the author.
cellsYesOne text per cell of the row it follows (the first row for after_row 0); a horizontally merged cell is one cell.
tableYesTable number as `table.get` numbers it: 1-based, in document order, main story only (a table in a note, header or footer cannot be named here).
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
after_rowYesInsert after this row (1-based); 0 inserts before the first row.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly/destructive/openWorld hints; the description goes well beyond them by disclosing the tracked-change nature, specific error outcomes (SCHEMA_INVALID, UNSUPPORTED_CONTENT near vertical merges), that the change is backed up and logged for history.undo, and the dry_run/expect guard behaviors.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first clause, followed by error conditions and the batch alternative in one dense but well-ordered sentence. It is information-dense without padding, though the single run-on sentence is slightly heavy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation. The description covers the mutation semantics, error codes, history/backup behavior, preview mode, write guard, and bulk alternative, which is complete for this 8-parameter tracked-change tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents parameters (baseline 3). The description adds a concrete cells example (["2024", "12.5"]), clarifies after_row 0 means before the first row, and explains the match-the-following-row rule, giving meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Insert a row into a body table as a tracked change') and immediately scopes it with the insertion position and cell contract. It is clearly distinguishable from sibling table_row_delete and table_get without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes bulk work to doc.batch ('Use doc.batch for several rows at once') and notes dry_run for preview and expect.sha256 as a write guard. It lacks an explicit when-not condition, but the sibling routing and guard conditions give strong context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

term_renameA

Rename a term or a character's name everywhere (Lucía to Elena) as one tracked batch: whole words by default, case-insensitive with case preserved (LUCÍA becomes ELENA), with optional inflections (["s"] also renames Lucías) and ignore_accents. match_level default/loose folds case, accents and punctuation. Matches inside fields or links are left and counted. Run dry_run first to check counts and the preview, then the same request without it. Use it instead of many text.replace edits. Backed up, undoable; tracked: false writes plainly.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesNew term.
docYesPath to the .docx.
tagNoAppended to the author.
fromYesTerm to rename.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPlan and preview only; write nothing.
trackedNofalse: a plain write for a change the writer already approved: the same edits, with this call's own revisions accepted in the same verified write (no revision marks; undo works). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change.
whole_wordNoWhole words only.
inflectionsNoSuffixes that follow the term: "s" renames Lucías to Elenas; {"from": "o", "to": "a"} renames Lucíao to Elenaa.
match_levelNoFold the search as `text.find` does: `default` ignores case, accents and punctuation (symbols such as `$` still count), `loose` drops symbols too; `exact` is the rename as without it. When passed, Word's Find codes in `from` are read as their characters, each `preview` change and `skipped` row gains `match_level` (the strictest level it meets) and the reply gains `matches_by_level`, adding up to `counts.matches`. No retry at a looser level. Two meanings of exact: without `match_level` the rename is today's, with ^ codes literal and no levels; `match_level: "exact"` keeps that rule but reads the ^ codes and tags each change (`exact` there: character for character). Not with `case_sensitive` or `ignore_accents: false` at a folded level.
preserve_caseNoLUCÍA becomes ELENA, lucía becomes elena, Lucía becomes Elena.
preview_limitNoMost changes echoed back in `preview`.
case_sensitiveNoExact spelling only; `to` is used as written.
ignore_accentsNo`Lucia` also matches `Lucía`.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (destructiveHint=false, readOnlyHint=false): it discloses that the file is backed up and undoable, that matches inside fields/links are left and counted, that a stale file yields DOC_CHANGED_ON_DISK, and that tracked: false is refused with UNSUPPORTED_CONTENT under specific conditions. This is rich mutation-side context the annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose and example before the modifiers, and every sentence carries operational information. The match_level sentence is long and dense, packing several sub-rules into one run-on, which slightly hurts scanability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter mutation tool with nested objects and an output schema, the description covers the safety model (backup, undo, tracked revisions), the guard parameter semantics, and the preview/counts return behavior, leaving nothing an agent needs in order to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds value: an inflection example (["s"] also renames Lucías), the case-preservation rule (LUCÍA becomes ELENA), and the interaction rules for match_level with case_sensitive/ignore_accents. It largely mirrors the schema's own parameter docs rather than exceeding them, keeping it below a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Rename a term or a character's name everywhere') with a concrete example (Lucía to Elena) and names the operation as one tracked batch. It explicitly distinguishes itself from the sibling text_replace by saying to use it instead of many text.replace edits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit workflow: run dry_run first to check counts and preview, then repeat without it. It also names the alternative (many text.replace edits) and states the condition for tracked: false (a change the writer already approved).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

text_findA
Read-onlyIdempotent

Find text or a Python regex (regex) in the document; each match comes back as a range (p8#b72009e4:0-8) with context, ready for text.replace or anchor.create. ignore_case, ignore_accents (maria finds María), whole_word and match_level (default: also ignores punctuation) loosen it; stories adds notes or headers. The first page gives total, and query_word, the query as typed in Word's Find box. Use para.locate to describe where a paragraph is, history.search for removed text. Read-only; limit (default 20) per page, cursor continues; stops after 10 s with more.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx file.
limitNoMost matches to return; more are reached with `cursor`.
queryYesText to find (at most 1000 characters), or a Python regex if `regex`.
regexNoTreat `query` as a regex.
cursorNoThe `next` value of the previous page.
contextNoCharacters of surrounding text on each side of a match.
storiesNoStories to read (default ["body"]): "notes" adds footnotes and endnotes, each after the paragraph holding its mark; "headers" adds headers and footers, after the body. Their addresses carry a prefix (fn3/p1#…, hdr1.default/p1#…).
whole_wordNoMatch only whole words (no letter, digit or mark on either side).
ignore_caseNoIgnore case.
match_levelNoFold a literal query: `default` ignores case, accents and punctuation (symbols such as `$` still count), `loose` drops symbols too; `exact` is the search as without it. When passed, Word's Find codes (^p, ^t, ^l, ^s, ^-, ^~, ^uNNN, ^^) in `query` are read as their characters and each match gains `match_level`, the strictest level it meets. Not with `regex` (unless `exact`), nor with `ignore_case` or `ignore_accents` false at a folded level. Two meanings of exact: plain `text.find` (no `match_level`) matches the query as typed, flags as given, ^ codes literal, and its matches carry no level; `match_level: "exact"` keeps that text rule but reads the ^ codes and tags every match. A match's own `match_level` is `exact` only when it equals the query character for character (`case` when only case differs).
ignore_accentsNoIgnore accents: `maria` finds `María`. A regex must be written without accents then.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and closed-world, so the safety profile is covered. The description still adds real operational context: a default page size of 20, cursor-based continuation, and a 10-second timeout that signals truncation via `more`. It stops short of describing anything about how matches are ordered or what happens on a regex syntax error.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and output format are front-loaded, and every sentence carries content. It is, however, a dense run-on paragraph stitched with semicolons rather than discrete clauses, which makes scanning for a specific flag harder than it needs to be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter tool with complex folding semantics, the description covers the purpose, the output address format, pagination, timeout behavior and sibling alternatives, all of which pair with the presence of an output schema. An agent has everything needed to call it correctly on the first attempt.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and extremely detailed (especially match_level), so the schema does the heavy lifting and baseline 3 applies. The description restates the flag behaviors with a helpful example ('ignore_accents (maria finds María)') but adds little syntax or defaults that aren't already in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Find text or a Python regex in the document') and immediately describes the output shape (a range like p8#b72009e4:0-8 with context). It also names downstream consumers (text.replace, anchor.create), so an agent can distinguish it from siblings such as para_locate or history_search without opening another schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes to alternatives: 'Use para.locate to describe where a paragraph is, history.search for removed text.' It also frames the find-then-act workflow by saying matches are 'ready for text.replace or anchor.create', which tells the agent both when to use this tool and what to do next.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

text_normalizeA
Read-onlyIdempotent

Normalise text (NFC, soft hyphens and zero-width characters removed, whitespace collapsed) and return a two-way offset map to the original code points, for the whole document, one paragraph or range (at, p142#a7b2a7b2:10-15), or a text string (give doc or text). Use it to compare or search text robustly and map found offsets back to addresses for text.replace; para.list normalized adds just the text. Read-only; paged at about 8,000 bytes with cursor; a very long paragraph comes in parts.

ParametersJSON Schema
NameRequiredDescriptionDefault
atNoParagraph address or range, e.g. p142#a7b2a7b2:10-15.
docNoPath to a .docx.
textNoText to normalise instead of `doc`.
limitNoMost items to return; a response is also capped at about 8,000 bytes.
cursorNoThe `next` value of the previous response, to continue the list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/closed-world, but the description adds real operational detail: paging at ~8,000 bytes with `cursor`, and that long paragraphs are returned in parts on CLI/MCP. It doesn't detail failure modes or limits interaction, so it's strong but not complete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and effect, then consumer guidance, then paging. It is dense and somewhat run-on in the middle section, but nearly every clause carries needed information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with complex offset-map semantics and paging, the description covers inputs, output shape, paging, and the two-way offset mapping need (with the result detail carried in the schema). Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description goes beyond the schema by stating the mutual-exclusivity constraint ("give `doc` or `text`") and illustrating the `at` address form, adding genuine selection guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (normalise text) and enumerates the exact transformations (NFC, soft hyphens, zero-width removal, whitespace collapse) plus the returned offset map. It also distinguishes itself from siblings by naming text.replace and para.list as downstream/alternative consumers.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Use it to compare or search text robustly and map found offsets back to addresses for text.replace" gives clear context for when this tool applies. It lacks an explicit when-not or a named alternative tool, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

text_replaceA

Replace one range with new text, as a tracked change: part of a paragraph (p3#a1b2c3d4:10-15, code-point offsets), a whole paragraph (p3#a1b2c3d4) or a span across paragraphs (p3#a1b2c3d4:10..p5#e5f6a7b8:2); empty text deletes it. Get ranges from text.find or para.get. File engine: backed up first, logged for history.undo, dry_run previews, expect.sha256 refuses a changed file. tracked: false writes plainly, on either engine. engine live edits the open app. STALE_ADDRESS if the paragraph changed since read. Use term.rename for a name everywhere, doc.batch for several edits.

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesRange p3#fp:10-15, p3#fp or p3#fp:10..p5#fp:2.
docYesPath to the .docx (live: or the file name of one open in a live app).
tagNoAppended to the author.
textYesNew text; empty deletes the range.
authorNoRevision author.
engineNo`live` edits the document open in Word or LibreOffice (see live.open).
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.
trackedNotrue (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations). engine live: the app's change tracking is off for the edit and put back after; text.replace and para.insert, refused (UNSUPPORTED_CONTENT) next to another unresolved tracked change; the app's undo takes it back. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the generic safety triple, so the description carries real weight and delivers: file engine backs up first, logs for history.undo, dry_run previews, expect.sha256 refuses a changed file, STALE_ADDRESS on stale paragraphs, DOC_CHANGED_ON_DISK, and the full tracked:false accept-as-you-write semantics. Deletion via empty text is disclosed, which is consistent with destructiveHint=false because everything is backed up and undoable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded and nearly every clause carries distinct operational information (guards, errors, engine behavior, alternatives). It is, however, a dense semicolon-chained run-on that packs many independent facts into single sentences, which costs a little scannability despite the high information density.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. For a 9-parameter mutation tool with nested objects, the description still covers engines, guards, error conditions, staleness, and sibling alternatives, so an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter meaning the schema does not: 'empty `text` deletes it', the interaction of tracked:false with engine live, and the alternate range syntaxes for `at`. It stops short of fully restating each field, which is fine given the schema already documents them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('Replace one range with new text, as a tracked change') and enumerates the addressable range forms (sub-paragraph offsets, whole paragraph, cross-paragraph span). It also names the sibling tools it is not (term.rename, doc.batch), so an agent can differentiate it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'Get ranges from text.find or para.get' for obtaining inputs, and 'Use term.rename for a name everywhere, doc.batch for several edits' as alternatives. When-to-use and when-to-use-something-else are both stated, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

toc_insertA

Insert a table of contents (a TOC field) after a body paragraph after (p1#a1b2c3d4), as tracked insertions: a title (default "Contents", "" for none), the field listing heading levels levels (default "1-3") with a placeholder result, and a closing paragraph. Run field.update next to fill in the entries and page numbers (until then field.list shows it stale). Backed up and undoable (history.undo); dry_run previews. Returns the field paragraph's address.

ParametersJSON Schema
NameRequiredDescriptionDefault
docYesPath to the .docx.
tagNoAppended to the author.
afterYesAddress of the body paragraph it goes after.
titleNoTitle paragraph above it (default "Contents"); "" for none.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
levelsNoHeading levels it lists, e.g. "1-3" (default) or "2".
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial context beyond annotations: the insertion is tracked as revisions, the operation is backed up and reversible via history.undo, dry_run previews, and the field is left with a placeholder result until refreshed. These are exactly the behavioral traits an agent needs for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and position, and every clause carries real information, though the heavy parenthetical nesting makes it denser than ideal. No wasted sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutation tool with an output schema, the description covers purpose, ordering dependency with field.update, safety (backup/undo/dry_run), and the return value's meaning. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameters are already documented in the schema; the description restates defaults for `title` and `levels` and gives an example address format for `after`, which is only marginally additive. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Insert a table of contents (a TOC field)') plus the exact position anchor ('after a body paragraph `after`'). This clearly distinguishes it from siblings like index_insert or field_update.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear workflow instruction ('Run field.update next to fill in the entries and page numbers') and notes that field.list shows the result as stale until then, so the agent knows the follow-up step. It does not explicitly contrast with index_insert, but the context of use is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

xref_addA

Insert a cross-reference field at an insertion point (at: p14#a1b2c3d4:20-20, or a paragraph address for its end), pointing to a caption or another body paragraph. show number (default: "Table 3" for a caption), page (a PAGEREF) or text. The target gets a hidden bookmark when it has none; run field.update afterwards to fill in the shown value. A tracked insertion; backed up and undoable (history.undo); dry_run previews. Add captions with caption.add first.

ParametersJSON Schema
NameRequiredDescriptionDefault
atYesInsertion point: p<n>#<fp>:<k>-<k>, or a paragraph address for its end.
toYesAddress of the caption or heading it points at.
docYesPath to the .docx.
tagNoAppended to the author.
showNonumber (default): a caption's label and number, or a paragraph's number; page: the page it is on; text: the caption or paragraph text.
authorNoRevision author.
expectNoWrite guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {"sha256": "9f86d081…"}; a file changed since is DOC_CHANGED_ON_DISK.
dry_runNoPreview only; write nothing.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesAlways true on success.
opYesThe operation that ran.
apiYesAPI version (1.0).
docNoThe document read or written: path, sha256 and paragraph count.
nextYesCursor for the next page (pass as cursor), or null.
resultYesWhat the operation returns.
warningsYesThings to know about the result.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false, destructiveHint=false, openWorldHint=false. The description adds substantive side effects the annotations cannot convey: a tracked insertion, backup plus undoability via history.undo, and that the target gets a hidden bookmark when it has none. That is exactly the kind of hidden-state mutation an agent must know before calling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the primary action and followed by side effects and sequencing. Parentheticals carry real detail rather than filler, though the address-format clause makes the first sentence heavy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not explain returns; instead it covers the prerequisites (caption first), follow-up (field.update), mutation semantics (tracked, undoable, hidden bookmark), write guard via `expect`, and dry_run. Nothing an agent needs to invoke this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline would be 3. The description goes beyond it by giving a concrete address example (`p14#a1b2c3d4:20-20`) and clarifying that `show` defaults to a caption's label and number ('Table 3') versus page (PAGEREF) or text, which helps an agent construct valid arguments.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource: 'Insert a cross-reference field at an insertion point... pointing `to` a caption or another body paragraph.' It names the exact `at`/`to` model, so an agent can distinguish it from caption_add (which creates the target) and field_update (which fills the value).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Routes the agent explicitly: 'Add captions with caption.add first' and 'run field.update afterwards to fill in the shown value,' which gives both prerequisite and follow-up. It also notes dry_run previews. There is no explicit when-not-to-use, but the sequencing guidance is clear enough for confident selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 67 tool updatesv0.7.2
    • Changedanchor_create1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "anchor": {
        +          "description": "The anchor: pass it whole to anchor.resolve later.",
        +          "properties": {
        +            "at": {
        +              "description": "Range address, p<n>#<fp>:<start>-<end> (code points).",
        +              "type": "string"
        +            },
        +            "exact": {
        +              "description": "The quoted text.",
        +              "type": "string"
        +            },
        +            "fingerprint": {
        +              "description": "That paragraph's fingerprint then.",
        +              "type": "string"
        +            },
        +            "hint": {
        +              "description": "Paragraph number then, as p<n>.",
        +              "type": "string"
        +            },
        +            "prefix": {
        +              "description": "Text just before it.",
        +              "type": "string"
        +            },
        +            "sentence": {
        +              "description": "Sentence address when the range was a sentence.",
        +              "type": "string"
        +            },
        +            "suffix": {
        +              "description": "Text just after it.",
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "exact",
        +            "prefix",
        +            "suffix"
        +          ],
        +          "type": "object"
        +        }
        +      },
        +      "required": [
        +        "anchor"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedanchor_resolve1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "at": {
        +          "description": "Range address, p<n>#<fp>:<start>-<end> (code points).",
        +          "type": "string"
        +        },
        +        "match": {
        +          "description": "exact, normalized or fuzzy.",
        +          "type": "string"
        +        },
        +        "match_level": {
        +          "description": "Strictest fold level at which the quote equals the matched text.",
        +          "type": "string"
        +        },
        +        "matched_text": {
        +          "description": "The text matched, when not character for character.",
        +          "type": "string"
        +        },
        +        "score": {
        +          "description": "Match score, 0-1.",
        +          "type": "number"
        +        },
        +        "sentence": {
        +          "description": "Sentence address, for a sentence anchor.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "at",
        +        "score",
        +        "match"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedcaption_add2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "at": {
        +          "description": "Address of the caption paragraph.",
        +          "type": "string"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "bookmark": {
        +          "description": "Hidden bookmark around label and number (xref.add points at it).",
        +          "type": "string"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "label": {
        +          "description": "Table, Figure or Equation.",
        +          "type": "string"
        +        },
        +        "number": {
        +          "description": "The number its SEQ field shows now.",
        +          "type": "integer"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "position": {
        +          "description": "above or below.",
        +          "type": "string"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "label",
        +        "position",
        +        "number",
        +        "bookmark",
        +        "at",
        +        "revision_ids"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedcomment_add2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (1).",
        +          "type": "integer"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "comment_ids": {
        +          "description": "Ids of the comments added.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "engine": {
        +          "description": "live: edited in the open app; nothing backed up or verified.",
        +          "type": "string"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "op_ids": {
        +          "description": "Live: one log entry per edit, in request order.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "False for a plain (untracked) write.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedcomment_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "comments": {
        +          "description": "This page of comments, each root then its replies.",
        +          "items": {
        +            "description": "A comment.",
        +            "properties": {
        +              "at": {
        +                "description": "Address of the paragraph where its range starts.",
        +                "type": "string"
        +              },
        +              "author": {
        +                "description": "Author.",
        +                "type": "string"
        +              },
        +              "date": {
        +                "description": "Date (ISO 8601).",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "id": {
        +                "description": "Comment id.",
        +                "type": "string"
        +              },
        +              "reply_to": {
        +                "description": "Id of the comment it answers.",
        +                "type": "string"
        +              },
        +              "resolved": {
        +                "description": "Marked done.",
        +                "type": "boolean"
        +              },
        +              "story": {
        +                "description": "footnote, endnote, header or footer when not in the body.",
        +                "type": "string"
        +              },
        +              "text": {
        +                "description": "Text, clipped at 1,000 characters.",
        +                "type": "string"
        +              },
        +              "truncated": {
        +                "description": "True when text was clipped.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "total": {
        +          "description": "Items in the whole list, across pages.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "total",
        +        "comments"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changeddoc_batch3 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedInput schema / properties / tracked / description
        Previous value: -"true (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations); file engine only for now. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too."New value: +"true (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations). engine live: the app's change tracking is off for the edit and put back after; text.replace and para.insert, refused (UNSUPPORTED_CONTENT) next to another unresolved tracked change; the app's undo takes it back. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "accepted": {
        +          "description": "Revisions accepted.",
        +          "type": "integer"
        +        },
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (a count), or for style kinds one entry per style op.",
        +          "type": [
        +            "integer",
        +            "array"
        +          ]
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changed_parts": {
        +          "description": "Package parts rewritten.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "comment_ids": {
        +          "description": "Ids of the comments added.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "engine": {
        +          "description": "live: edited in the open app; nothing backed up or verified.",
        +          "type": "string"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "merged_paragraphs": {
        +          "description": "Paragraphs joined by resolving paragraph marks.",
        +          "type": "integer"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "op_ids": {
        +          "description": "Live: one log entry per edit, in request order.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "paragraphs_changed": {
        +          "description": "Paragraphs whose style reference was rewritten.",
        +          "type": "integer"
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "references_rewritten": {
        +          "description": "Style references rewritten (renames, merges).",
        +          "type": "integer"
        +        },
        +        "rejected": {
        +          "description": "Revisions rejected.",
        +          "type": "integer"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "revisions": {
        +          "description": "The revisions resolved (capped; see revisions_omitted).",
        +          "items": {
        +            "description": "A resolved revision.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Paragraph address.",
        +                "type": "string"
        +              },
        +              "author": {
        +                "description": "Its author.",
        +                "type": "string"
        +              },
        +              "id": {
        +                "description": "Revision id.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Revision type (insert, delete, mark_insert, format...).",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revisions_omitted": {
        +          "description": "Resolved revisions left out of the list.",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "False for a plain (untracked) write.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changeddoc_compare1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "new": {
        +          "description": "The later version.",
        +          "properties": {
        +            "characters": {
        +              "description": "text.normalize of a text string: its length.",
        +              "type": "integer"
        +            },
        +            "paragraphs": {
        +              "description": "Body paragraphs.",
        +              "type": "integer"
        +            },
        +            "path": {
        +              "description": "Path of the document.",
        +              "type": "string"
        +            },
        +            "sha256": {
        +              "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +              "type": "string"
        +            },
        +            "source": {
        +              "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +              "type": [
        +                "object",
        +                "string"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "old": {
        +          "description": "The earlier version.",
        +          "properties": {
        +            "characters": {
        +              "description": "text.normalize of a text string: its length.",
        +              "type": "integer"
        +            },
        +            "paragraphs": {
        +              "description": "Body paragraphs.",
        +              "type": "integer"
        +            },
        +            "path": {
        +              "description": "Path of the document.",
        +              "type": "string"
        +            },
        +            "sha256": {
        +              "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +              "type": "string"
        +            },
        +            "source": {
        +              "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +              "type": [
        +                "object",
        +                "string"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "output": {
        +          "description": "The redline written.",
        +          "properties": {
        +            "path": {
        +              "description": "Its path.",
        +              "type": "string"
        +            },
        +            "sha256": {
        +              "description": "Its sha256.",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "revisions": {
        +          "description": "Tracked changes in the redline.",
        +          "type": "integer"
        +        },
        +        "summary": {
        +          "description": "Paragraphs per alignment kind.",
        +          "properties": {
        +            "deleted": {
        +              "description": "Deleted.",
        +              "type": "integer"
        +            },
        +            "inserted": {
        +              "description": "Inserted.",
        +              "type": "integer"
        +            },
        +            "merged": {
        +              "description": "Joined.",
        +              "type": "integer"
        +            },
        +            "modified": {
        +              "description": "Edited in place.",
        +              "type": "integer"
        +            },
        +            "moved": {
        +              "description": "Moved.",
        +              "type": "integer"
        +            },
        +            "split": {
        +              "description": "Split in two or more.",
        +              "type": "integer"
        +            },
        +            "unchanged": {
        +              "description": "Unchanged.",
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      },
        +      "required": [
        +        "old",
        +        "new",
        +        "output",
        +        "summary",
        +        "revisions",
        +        "author",
        +        "date"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changeddoc_diff1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address (null if deleted) for this page.",
        +          "type": "object"
        +        },
        +        "changes": {
        +          "description": "This page of change records (unchanged paragraphs that kept their address are left out).",
        +          "items": {
        +            "description": "One aligned change.",
        +            "properties": {
        +              "count": {
        +                "description": "With collapse_runs: unchanged paragraphs this record stands for.",
        +                "type": "integer"
        +              },
        +              "kind": {
        +                "description": "unchanged, modified, inserted, deleted, moved, split or merged.",
        +                "type": "string"
        +              },
        +              "moved": {
        +                "description": "True when it also moved.",
        +                "type": "boolean"
        +              },
        +              "new": {
        +                "description": "New addresses involved.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "old": {
        +                "description": "Old addresses involved.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "similarity": {
        +                "description": "Text similarity, 0-1, for a modified paragraph.",
        +                "type": "number"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "new": {
        +          "description": "The later version.",
        +          "properties": {
        +            "characters": {
        +              "description": "text.normalize of a text string: its length.",
        +              "type": "integer"
        +            },
        +            "paragraphs": {
        +              "description": "Body paragraphs.",
        +              "type": "integer"
        +            },
        +            "path": {
        +              "description": "Path of the document.",
        +              "type": "string"
        +            },
        +            "sha256": {
        +              "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +              "type": "string"
        +            },
        +            "source": {
        +              "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +              "type": [
        +                "object",
        +                "string"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "old": {
        +          "description": "The earlier version.",
        +          "properties": {
        +            "characters": {
        +              "description": "text.normalize of a text string: its length.",
        +              "type": "integer"
        +            },
        +            "paragraphs": {
        +              "description": "Body paragraphs.",
        +              "type": "integer"
        +            },
        +            "path": {
        +              "description": "Path of the document.",
        +              "type": "string"
        +            },
        +            "sha256": {
        +              "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +              "type": "string"
        +            },
        +            "source": {
        +              "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +              "type": [
        +                "object",
        +                "string"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "summary": {
        +          "description": "Paragraphs per alignment kind.",
        +          "properties": {
        +            "deleted": {
        +              "description": "Deleted.",
        +              "type": "integer"
        +            },
        +            "inserted": {
        +              "description": "Inserted.",
        +              "type": "integer"
        +            },
        +            "merged": {
        +              "description": "Joined.",
        +              "type": "integer"
        +            },
        +            "modified": {
        +              "description": "Edited in place.",
        +              "type": "integer"
        +            },
        +            "moved": {
        +              "description": "Moved.",
        +              "type": "integer"
        +            },
        +            "split": {
        +              "description": "Split in two or more.",
        +              "type": "integer"
        +            },
        +            "unchanged": {
        +              "description": "Unchanged.",
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "total": {
        +          "description": "Change records in all pages.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "old",
        +        "new",
        +        "summary",
        +        "total",
        +        "changes",
        +        "address_map"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changeddoc_info1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "application": {
        +          "description": "Application properties present (docProps/app.xml).",
        +          "properties": {
        +            "application": {
        +              "description": "Program that wrote it.",
        +              "type": "string"
        +            },
        +            "pages": {
        +              "description": "Page count Word saved.",
        +              "type": [
        +                "integer",
        +                "string"
        +              ]
        +            },
        +            "words": {
        +              "description": "Word count Word saved.",
        +              "type": [
        +                "integer",
        +                "string"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "has": {
        +          "description": "Which parts exist.",
        +          "properties": {
        +            "comments": {
        +              "description": "A comments part.",
        +              "type": "boolean"
        +            },
        +            "endnotes": {
        +              "description": "An endnotes part.",
        +              "type": "boolean"
        +            },
        +            "footers": {
        +              "description": "Footer parts.",
        +              "type": "integer"
        +            },
        +            "footnotes": {
        +              "description": "A footnotes part.",
        +              "type": "boolean"
        +            },
        +            "headers": {
        +              "description": "Header parts.",
        +              "type": "integer"
        +            },
        +            "styles": {
        +              "description": "A styles part.",
        +              "type": "boolean"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "parts": {
        +          "description": "Parts in the package.",
        +          "type": "integer"
        +        },
        +        "properties": {
        +          "description": "Core properties present (docProps/core.xml).",
        +          "properties": {
        +            "created": {
        +              "description": "Created (ISO 8601).",
        +              "type": "string"
        +            },
        +            "creator": {
        +              "description": "Author.",
        +              "type": "string"
        +            },
        +            "last_modified_by": {
        +              "description": "Last modified by.",
        +              "type": "string"
        +            },
        +            "modified": {
        +              "description": "Modified (ISO 8601).",
        +              "type": "string"
        +            },
        +            "revision": {
        +              "description": "Revision number.",
        +              "type": [
        +                "integer",
        +                "string"
        +              ]
        +            },
        +            "subject": {
        +              "description": "Subject.",
        +              "type": "string"
        +            },
        +            "title": {
        +              "description": "Title.",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "size_bytes": {
        +          "description": "File size in bytes.",
        +          "type": "integer"
        +        },
        +        "tracked_changes_on": {
        +          "description": "Whether Track Changes is switched on in the document.",
        +          "type": "boolean"
        +        },
        +        "word_lock": {
        +          "description": "Whether a Word lock file (~$name) is next to it: open in Word.",
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "size_bytes",
        +        "parts",
        +        "properties",
        +        "application",
        +        "tracked_changes_on",
        +        "word_lock",
        +        "has"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changeddoc_open1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "adoptable": {
        +          "description": "Orphan stores whose history this document could take back (history.adopt).",
        +          "items": {
        +            "description": "An orphan store.",
        +            "properties": {
        +              "doc": {
        +                "description": "Path of the document it last recorded.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "doc_id": {
        +                "description": "Id of that document's history, null when unknown.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "entries": {
        +                "description": "Log entries.",
        +                "type": "integer"
        +              },
        +              "last_time": {
        +                "description": "Time of the last entry (ISO 8601).",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "sha_matched": {
        +                "description": "Its last recorded state is this file.",
        +                "type": "boolean"
        +              },
        +              "store": {
        +                "description": "Store folder.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "backup": {
        +          "description": "Path of the backup just taken.",
        +          "type": "string"
        +        },
        +        "hint": {
        +          "description": "What to do with adoptable.",
        +          "type": "string"
        +        },
        +        "op_id": {
        +          "description": "Log entry noting the open, or null if the file is as last logged.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "store": {
        +          "description": "The document's store folder (backups and log).",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "backup",
        +        "op_id",
        +        "store"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changeddoc_outline1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "headings": {
        +          "description": "This page of headings, in document order.",
        +          "items": {
        +            "additionalProperties": true,
        +            "description": "A heading (layout facts may add keys).",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "blank_before": {
        +                "description": "Empty paragraphs right before it.",
        +                "type": "integer"
        +              },
        +              "centred": {
        +                "description": "Whether it is centred.",
        +                "type": "boolean"
        +              },
        +              "kind": {
        +                "description": "Header/footer kind: default, first or even.",
        +                "type": "string"
        +              },
        +              "level": {
        +                "description": "Heading level, 1-9.",
        +                "type": "integer"
        +              },
        +              "note": {
        +                "description": "A note's id, displayed number and the body paragraph holding its mark.",
        +                "properties": {
        +                  "id": {
        +                    "description": "Note id.",
        +                    "type": "integer"
        +                  },
        +                  "number": {
        +                    "description": "Displayed number.",
        +                    "type": "string"
        +                  },
        +                  "of": {
        +                    "description": "Address of the paragraph holding the mark.",
        +                    "type": "string"
        +                  }
        +                },
        +                "type": [
        +                  "object",
        +                  "null"
        +                ]
        +              },
        +              "page_break_before": {
        +                "description": "Whether it starts a page.",
        +                "type": "boolean"
        +              },
        +              "section": {
        +                "description": "Section (1-based) whose header or footer this is.",
        +                "type": "integer"
        +              },
        +              "story": {
        +                "description": "Story kind outside the body: footnote, endnote, header or footer.",
        +                "type": "string"
        +              },
        +              "style": {
        +                "description": "Paragraph style id.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "style_name": {
        +                "description": "Paragraph style display name.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "text": {
        +                "description": "Heading text, whitespace collapsed, clipped at 160 characters.",
        +                "type": "string"
        +              },
        +              "truncated": {
        +                "description": "True when text was clipped.",
        +                "type": "boolean"
        +              },
        +              "used_by_sections": {
        +                "description": "Sections that show this header or footer.",
        +                "items": {
        +                  "type": "integer"
        +                },
        +                "type": "array"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "total": {
        +          "description": "Items in the whole list, across pages.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "total",
        +        "headings"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changeddoc_segment1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "chapters": {
        +          "description": "unit chapters: this page of chapters.",
        +          "items": {
        +            "description": "A chapter.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "first": {
        +                "description": "First paragraph number.",
        +                "type": "integer"
        +              },
        +              "heading_last": {
        +                "description": "Last paragraph number of its heading.",
        +                "type": [
        +                  "integer",
        +                  "null"
        +                ]
        +              },
        +              "id": {
        +                "description": "Stable id (ch-…, sc-…, pt-…), usable as `range`.",
        +                "type": "string"
        +              },
        +              "kind": {
        +                "description": "How its heading reads: chapter, numeral, ...",
        +                "type": "string"
        +              },
        +              "last": {
        +                "description": "Last paragraph number.",
        +                "type": "integer"
        +              },
        +              "number": {
        +                "description": "Its number, when the heading has one.",
        +                "type": [
        +                  "integer",
        +                  "null"
        +                ]
        +              },
        +              "part": {
        +                "description": "Id of the part holding it.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "scenes": {
        +                "description": "Scenes in it.",
        +                "type": "integer"
        +              },
        +              "signals": {
        +                "description": "What detected it (heading_style, numeral, centred, scene_marker...).",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "text": {
        +                "description": "Heading text (clipped).",
        +                "type": "string"
        +              },
        +              "words": {
        +                "description": "Words in it.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "dialogue": {
        +          "description": "unit dialogue: this page of dialogue lines.",
        +          "items": {
        +            "description": "A dialogue line.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "end": {
        +                "description": "End offset.",
        +                "type": "integer"
        +              },
        +              "parts": {
        +                "description": "Its speech and narration pieces.",
        +                "items": {
        +                  "description": "A piece.",
        +                  "properties": {
        +                    "end": {
        +                      "description": "End offset.",
        +                      "type": "integer"
        +                    },
        +                    "kind": {
        +                      "description": "speech or narration.",
        +                      "type": "string"
        +                    },
        +                    "start": {
        +                      "description": "Start offset.",
        +                      "type": "integer"
        +                    }
        +                  },
        +                  "type": "object"
        +                },
        +                "type": "array"
        +              },
        +              "start": {
        +                "description": "Start offset.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "front": {
        +          "description": "chapters/parts: front matter before the first one (at, first, last, words).",
        +          "type": [
        +            "object",
        +            "null"
        +          ]
        +        },
        +        "parts": {
        +          "description": "unit parts: this page of parts.",
        +          "items": {
        +            "description": "A part.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "chapters": {
        +                "description": "Chapters in it.",
        +                "type": "integer"
        +              },
        +              "first": {
        +                "description": "First paragraph number.",
        +                "type": "integer"
        +              },
        +              "heading_last": {
        +                "description": "Last paragraph number of its heading.",
        +                "type": [
        +                  "integer",
        +                  "null"
        +                ]
        +              },
        +              "id": {
        +                "description": "Stable id (ch-…, sc-…, pt-…), usable as `range`.",
        +                "type": "string"
        +              },
        +              "kind": {
        +                "description": "How its heading reads: chapter, numeral, ...",
        +                "type": "string"
        +              },
        +              "last": {
        +                "description": "Last paragraph number.",
        +                "type": "integer"
        +              },
        +              "number": {
        +                "description": "Its number, when the heading has one.",
        +                "type": [
        +                  "integer",
        +                  "null"
        +                ]
        +              },
        +              "signals": {
        +                "description": "What detected it (heading_style, numeral, centred, scene_marker...).",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "text": {
        +                "description": "Heading text (clipped).",
        +                "type": "string"
        +              },
        +              "words": {
        +                "description": "Words in it.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "scenes": {
        +          "description": "unit scenes: this page of scenes.",
        +          "items": {
        +            "description": "A scene.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "chapter": {
        +                "description": "Id of its chapter.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "first": {
        +                "description": "First paragraph number.",
        +                "type": "integer"
        +              },
        +              "id": {
        +                "description": "Stable id (ch-…, sc-…, pt-…), usable as `range`.",
        +                "type": "string"
        +              },
        +              "last": {
        +                "description": "Last paragraph number.",
        +                "type": "integer"
        +              },
        +              "signals": {
        +                "description": "What detected it (heading_style, numeral, centred, scene_marker...).",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "words": {
        +                "description": "Words in it.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "sentences": {
        +          "description": "unit sentences: this page of sentences.",
        +          "items": {
        +            "description": "A sentence.",
        +            "properties": {
        +              "at": {
        +                "description": "Sentence address, p<n>#<fp>.s<k>.",
        +                "type": "string"
        +              },
        +              "end": {
        +                "description": "End offset.",
        +                "type": "integer"
        +              },
        +              "start": {
        +                "description": "Start offset.",
        +                "type": "integer"
        +              },
        +              "text": {
        +                "description": "Its text (clipped).",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "suppressed": {
        +          "description": "Suppressed breaks (capped).",
        +          "items": {
        +            "description": "A suppressed break.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "kind": {
        +                "description": "chapter or scene.",
        +                "type": "string"
        +              },
        +              "reason": {
        +                "description": "Why.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "suppressed_total": {
        +          "description": "Breaks suppressed (by an override or rule).",
        +          "type": "integer"
        +        },
        +        "total": {
        +          "description": "Items in the whole list, across pages.",
        +          "type": "integer"
        +        },
        +        "unit": {
        +          "description": "chapters, parts or scenes.",
        +          "type": "string"
        +        },
        +        "unmatched_overrides": {
        +          "description": "Overrides that matched no paragraph.",
        +          "items": {
        +            "description": "An override.",
        +            "properties": {
        +              "action": {
        +                "description": "force or suppress.",
        +                "type": "string"
        +              },
        +              "fp": {
        +                "description": "Fingerprint.",
        +                "type": "string"
        +              },
        +              "kind": {
        +                "description": "chapter or scene.",
        +                "type": "string"
        +              },
        +              "nth": {
        +                "description": "Which occurrence.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "total"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changeddoc_stats1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "characters": {
        +          "description": "Characters in the body.",
        +          "type": "integer"
        +        },
        +        "comments": {
        +          "description": "Comments.",
        +          "type": "integer"
        +        },
        +        "empty_paragraphs": {
        +          "description": "Body paragraphs with no visible text.",
        +          "type": "integer"
        +        },
        +        "fonts": {
        +          "description": "Fonts named in the body and styles, most used first (top 20).",
        +          "items": {
        +            "description": "A font.",
        +            "properties": {
        +              "font": {
        +                "description": "Font name.",
        +                "type": "string"
        +              },
        +              "uses": {
        +                "description": "References.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "footnotes": {
        +          "description": "Footnotes.",
        +          "type": "integer"
        +        },
        +        "headings": {
        +          "description": "Heading paragraphs.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "revisions": {
        +          "description": "Tracked changes in the body.",
        +          "properties": {
        +            "by_type": {
        +              "description": "Revision type -> count.",
        +              "type": "object"
        +            },
        +            "total": {
        +              "description": "All of them.",
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "stories": {
        +          "description": "With stories: the same counts for notes and for headers/footers.",
        +          "properties": {
        +            "headers": {
        +              "description": "Counts for one story kind.",
        +              "properties": {
        +                "characters": {
        +                  "description": "Characters.",
        +                  "type": "integer"
        +                },
        +                "paragraphs": {
        +                  "description": "Paragraphs.",
        +                  "type": "integer"
        +                },
        +                "stories": {
        +                  "description": "Stories (notes, or header/footer parts).",
        +                  "type": "integer"
        +                },
        +                "words": {
        +                  "description": "Words.",
        +                  "type": "integer"
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "notes": {
        +              "description": "Counts for one story kind.",
        +              "properties": {
        +                "characters": {
        +                  "description": "Characters.",
        +                  "type": "integer"
        +                },
        +                "paragraphs": {
        +                  "description": "Paragraphs.",
        +                  "type": "integer"
        +                },
        +                "stories": {
        +                  "description": "Stories (notes, or header/footer parts).",
        +                  "type": "integer"
        +                },
        +                "words": {
        +                  "description": "Words.",
        +                  "type": "integer"
        +                }
        +              },
        +              "type": "object"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "styles_in_use": {
        +          "description": "Distinct styles used.",
        +          "type": "integer"
        +        },
        +        "tables": {
        +          "description": "Tables (w:tbl), nested included.",
        +          "type": "integer"
        +        },
        +        "words": {
        +          "description": "Words in the body (whitespace-separated).",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "paragraphs",
        +        "empty_paragraphs",
        +        "words",
        +        "characters",
        +        "headings",
        +        "tables",
        +        "comments",
        +        "revisions",
        +        "footnotes",
        +        "styles_in_use",
        +        "fonts"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedfield_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "count": {
        +          "description": "Fields listed.",
        +          "type": "integer"
        +        },
        +        "fields": {
        +          "description": "Every field, story by story, in document order.",
        +          "items": {
        +            "description": "A field.",
        +            "properties": {
        +              "at": {
        +                "description": "Address of its paragraph (comment:<id> in a comment).",
        +                "type": "string"
        +              },
        +              "citation": {
        +                "description": "A reference-manager citation (never changed by field.update).",
        +                "type": "boolean"
        +              },
        +              "code": {
        +                "description": "Instruction code.",
        +                "type": "string"
        +              },
        +              "in": {
        +                "description": "textbox when inside a text box.",
        +                "type": "string"
        +              },
        +              "result": {
        +                "description": "Result text shown.",
        +                "type": "string"
        +              },
        +              "stale": {
        +                "description": "Marked dirty, or a placeholder result: needs updating.",
        +                "type": "boolean"
        +              },
        +              "story": {
        +                "description": "body, comments, or the story key (fn3, hdr1.default...).",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Field type (PAGE, TOC, REF, ADDIN ZOTERO_ITEM, CITATION...).",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "fields",
        +        "count"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedfield_update2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changed": {
        +          "description": "set_update_on_open: whether the setting changed.",
        +          "type": "boolean"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "set_update_on_open": {
        +          "description": "True when w:updateFields was set instead.",
        +          "type": "boolean"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "skipped": {
        +          "description": "Fields left as they are, with why: SECTIONPAGES, SECTION and NOTEREF (LibreOffice keeps their cached results), every INDEX (rebuild it in Word, F9), a REF that resolves to an error or to nothing, and fields not paired with LibreOffice's.",
        +          "items": {
        +            "description": "A skipped field.",
        +            "properties": {
        +              "at": {
        +                "description": "Its address.",
        +                "type": "string"
        +              },
        +              "reason": {
        +                "description": "Why it was not recomputed.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Field type.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "unchanged": {
        +          "description": "Fields whose result was already right.",
        +          "type": "integer"
        +        },
        +        "updated": {
        +          "description": "Fields whose result changed.",
        +          "items": {
        +            "description": "An updated field.",
        +            "properties": {
        +              "after": {
        +                "description": "Result paragraphs after.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Result paragraphs before.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "code": {
        +                "description": "Field code.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Field type (TOC, PAGE, REF...).",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "written": {
        +          "description": "Whether the document was written.",
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "updated",
        +        "skipped",
        +        "footprint"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedhistory_adopt1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "adopted": {
        +          "description": "Whether the store was moved to the document.",
        +          "type": "boolean"
        +        },
        +        "candidates": {
        +          "description": "When several stores match: pass one as `store`; nothing moved.",
        +          "items": {
        +            "description": "An orphan store.",
        +            "properties": {
        +              "doc": {
        +                "description": "Path of the document it last recorded.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "doc_id": {
        +                "description": "Id of that document's history, null when unknown.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "entries": {
        +                "description": "Log entries.",
        +                "type": "integer"
        +              },
        +              "last_time": {
        +                "description": "Time of the last entry (ISO 8601).",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "sha_matched": {
        +                "description": "Its last recorded state is this file.",
        +                "type": "boolean"
        +              },
        +              "store": {
        +                "description": "Store folder.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "entries": {
        +          "description": "Log entries it holds.",
        +          "type": "integer"
        +        },
        +        "from": {
        +          "description": "The orphan store adopted.",
        +          "type": "string"
        +        },
        +        "op_id": {
        +          "description": "Log entry noting the adoption.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "sha_matched": {
        +          "description": "The file is the store's last recorded state.",
        +          "type": "boolean"
        +        },
        +        "store": {
        +          "description": "Where the store lives now (or would).",
        +          "type": "string"
        +        },
        +        "would_move": {
        +          "description": "dry_run: the store that would move.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "adopted"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedhistory_list3 fields changed
      • addedInput schema / properties / kind / description
        Added value: +"Only entries of this kind (batch: every logged edit)."
      • addedInput schema / properties / limit / description
        Added value: +"Most entries per page (default 20)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "entries": {
        +          "description": "This page of log entries, newest first.",
        +          "items": {
        +            "description": "A logged write.",
        +            "properties": {
        +              "adopted_from": {
        +                "description": "adopt: the store and document it came from.",
        +                "type": "object"
        +              },
        +              "author": {
        +                "description": "Revision author.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "backup": {
        +                "description": "Backup taken before it.",
        +                "type": "string"
        +              },
        +              "deleted": {
        +                "description": "Paragraphs it deleted that history.restore can bring back (first 5).",
        +                "items": {
        +                  "description": "A deleted paragraph.",
        +                  "properties": {
        +                    "change": {
        +                      "description": "Change number.",
        +                      "type": "integer"
        +                    },
        +                    "text": {
        +                      "description": "Text (clipped).",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "type": "object"
        +                },
        +                "type": "array"
        +              },
        +              "engine": {
        +                "description": "live for a live-engine edit.",
        +                "type": "string"
        +              },
        +              "kind": {
        +                "description": "batch, restore, style, undo, open, purge or adopt.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "op_id": {
        +                "description": "Op id (history.undo / history.restore).",
        +                "type": "string"
        +              },
        +              "ops": {
        +                "description": "Operation kinds in the request.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "paragraphs": {
        +                "description": "Paragraphs it changed.",
        +                "type": "integer"
        +              },
        +              "removed": {
        +                "description": "purge: entries removed.",
        +                "type": [
        +                  "integer",
        +                  "null"
        +                ]
        +              },
        +              "restores": {
        +                "description": "Op id it restored from.",
        +                "type": "string"
        +              },
        +              "scope": {
        +                "description": "purge: what was removed.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "sha256_after": {
        +                "description": "File hash after it.",
        +                "type": "string"
        +              },
        +              "tag": {
        +                "description": "Author tag.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "time": {
        +                "description": "When (ISO 8601).",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "tracked": {
        +                "description": "False for a plain write.",
        +                "type": "boolean"
        +              },
        +              "undoes": {
        +                "description": "Op id it undid.",
        +                "type": "string"
        +              },
        +              "undone": {
        +                "description": "Whether it was taken back.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "total": {
        +          "description": "Entries in the log (after the kind filter).",
        +          "type": "integer"
        +        },
        +        "unreadable_lines": {
        +          "description": "Log lines that could not be read.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "entries",
        +        "total"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedhistory_orphans1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "orphans": {
        +          "description": "Stores whose document is gone.",
        +          "items": {
        +            "description": "A store.",
        +            "properties": {
        +              "doc": {
        +                "description": "Path of the document it last recorded.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "doc_id": {
        +                "description": "Id of that document's history, null when unknown.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "entries": {
        +                "description": "Log entries.",
        +                "type": "integer"
        +              },
        +              "last_time": {
        +                "description": "Time of the last entry (ISO 8601).",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "store": {
        +                "description": "Store folder.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "total": {
        +          "description": "Orphans found.",
        +          "type": "integer"
        +        },
        +        "unknown": {
        +          "description": "Stores that name no document.",
        +          "items": {
        +            "description": "A store.",
        +            "properties": {
        +              "doc": {
        +                "description": "Path of the document it last recorded.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "doc_id": {
        +                "description": "Id of that document's history, null when unknown.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "entries": {
        +                "description": "Log entries.",
        +                "type": "integer"
        +              },
        +              "last_time": {
        +                "description": "Time of the last entry (ISO 8601).",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "store": {
        +                "description": "Store folder.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "orphans",
        +        "unknown",
        +        "total"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedhistory_purge1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "confirm": {
        +          "description": "Token to pass as confirm to really purge.",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "first_op_id": {
        +          "description": "Oldest entry removed.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "last_op_id": {
        +          "description": "Newest entry removed.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "removed": {
        +          "description": "Entries removed (0 on a dry run).",
        +          "type": "integer"
        +        },
        +        "scope": {
        +          "description": "What is removed: all, or before <time>.",
        +          "type": "string"
        +        },
        +        "tombstone": {
        +          "description": "Op id of the purge entry left in the log.",
        +          "type": "string"
        +        },
        +        "would_remove": {
        +          "description": "Entries the scope covers.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "scope",
        +        "removed",
        +        "would_remove",
        +        "confirm"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedhistory_restore2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (a count), or for style kinds one entry per style op.",
        +          "type": [
        +            "integer",
        +            "array"
        +          ]
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "comment_ids": {
        +          "description": "Ids of the comments added.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "from": {
        +          "description": "The logged op restored from.",
        +          "type": "string"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "restored": {
        +          "description": "The paragraphs brought back.",
        +          "items": {
        +            "description": "A restored paragraph.",
        +            "properties": {
        +              "after": {
        +                "description": "Address it was inserted after.",
        +                "type": "string"
        +              },
        +              "change": {
        +                "description": "Change number in the logged op.",
        +                "type": "integer"
        +              },
        +              "text": {
        +                "description": "Its text (clipped).",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "False for a plain (untracked) write.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "restored",
        +        "from"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedhistory_search4 fields changed
      • addedInput schema / properties / ignore_accents / description
        Added value: +"Ignore accents: `maria` finds `María`."
      • addedInput schema / properties / ignore_case / description
        Added value: +"Ignore case."
      • addedInput schema / properties / limit / description
        Added value: +"Most hits to return (default 20); `total` counts them all."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "matches": {
        +          "description": "Hits, newest entry first (up to limit).",
        +          "items": {
        +            "description": "A hit.",
        +            "properties": {
        +              "end": {
        +                "description": "With match_level: end of the hit.",
        +                "type": "integer"
        +              },
        +              "in": {
        +                "description": "Where: request, or change <n> before/after.",
        +                "type": "string"
        +              },
        +              "match_level": {
        +                "description": "With match_level: the level it matched at.",
        +                "type": "string"
        +              },
        +              "op_id": {
        +                "description": "The logged op it is in.",
        +                "type": "string"
        +              },
        +              "start": {
        +                "description": "With match_level: start of the hit in the text.",
        +                "type": "integer"
        +              },
        +              "text": {
        +                "description": "The text around the hit.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "matches_by_level": {
        +          "description": "With match_level: hits per level.",
        +          "type": "object"
        +        },
        +        "total": {
        +          "description": "Hits in the whole log.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "matches",
        +        "total"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedhistory_undo2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "paragraphs": {
        +          "description": "Paragraphs returned to their prior state.",
        +          "type": "integer"
        +        },
        +        "parts": {
        +          "description": "Whole parts put back (comments, styles); absent if none.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "undid": {
        +          "description": "Op id taken back.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "undid",
        +        "dry_run",
        +        "paragraphs"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedindex_insert2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "after": {
        +          "description": "Address of the paragraph it went after.",
        +          "type": "string"
        +        },
        +        "at": {
        +          "description": "Address of the field's paragraph.",
        +          "type": "string"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "code": {
        +          "description": "The field code.",
        +          "type": "string"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "title": {
        +          "description": "The title paragraph's text, or null for none.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "at",
        +        "after",
        +        "code",
        +        "title",
        +        "revision_ids"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedindex_mark2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "at": {
        +          "description": "Address of the paragraph that holds the mark.",
        +          "type": "string"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "code": {
        +          "description": "The XE field code, e.g. XE \"Term:Sub\".",
        +          "type": "string"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "entry": {
        +          "description": "The entry, levels joined with a colon.",
        +          "type": "string"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "at",
        +        "entry",
        +        "code",
        +        "revision_ids"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlayout_apply3 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedInput schema / properties / plan / description
        Previous value: -"The page plan: version 1 and sections, each with a from address."New value: +"The page plan, as layout.get returns it: version 1, two_sided, mirror_margins and sections, each with a `from` address; keys left out stay as they are, and numbering.shown is checked, not set. Every section already in the document must be kept. A header/footer text a section already prints changes nothing; a shared part is rewritten only when every section using it asks the same text, else the section gets a new part. Changing a header or footer that a later section inherits is refused. A split-off section keeps the number format of the one it came from unless the plan states one."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changes": {
        +          "description": "What changed (or would): section properties, breaks, header/footer text, settings.",
        +          "items": {
        +            "additionalProperties": true,
        +            "description": "A change.",
        +            "properties": {
        +              "at": {
        +                "description": "Where: section <n> or a paragraph address.",
        +                "type": "string"
        +              },
        +              "kind": {
        +                "description": "section.props, section.break, settings, header/footer text...",
        +                "type": "string"
        +              },
        +              "revision_ids": {
        +                "description": "w:id of every revision this write created.",
        +                "items": {
        +                  "type": [
        +                    "integer",
        +                    "string"
        +                  ]
        +                },
        +                "type": "array"
        +              },
        +              "tracked": {
        +                "description": "Whether it is a tracked change.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "plan": {
        +          "description": "The page plan after the write (as layout.get returns it).",
        +          "properties": {
        +            "mirror_margins": {
        +              "description": "Mirrored margins.",
        +              "type": "boolean"
        +            },
        +            "sections": {
        +              "description": "Each section, in order.",
        +              "items": {
        +                "description": "A section of the plan.",
        +                "properties": {
        +                  "break": {
        +                    "description": "nextPage, oddPage, evenPage or continuous.",
        +                    "type": "string"
        +                  },
        +                  "first_page_different": {
        +                    "description": "Different first page.",
        +                    "type": "boolean"
        +                  },
        +                  "footer": {
        +                    "description": "Text per kind; {PAGE}, {NUMPAGES} and {chapter} stand for fields; null: inherited.",
        +                    "properties": {
        +                      "default": {
        +                        "description": "Default (odd) pages.",
        +                        "type": [
        +                          "string",
        +                          "null"
        +                        ]
        +                      },
        +                      "even": {
        +                        "description": "Even pages.",
        +                        "type": [
        +                          "string",
        +                          "null"
        +                        ]
        +                      },
        +                      "first": {
        +                        "description": "First page.",
        +                        "type": [
        +                          "string",
        +                          "null"
        +                        ]
        +                      }
        +                    },
        +                    "type": "object"
        +                  },
        +                  "from": {
        +                    "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                    "type": "string"
        +                  },
        +                  "header": {
        +                    "description": "Text per kind; {PAGE}, {NUMPAGES} and {chapter} stand for fields; null: inherited.",
        +                    "properties": {
        +                      "default": {
        +                        "description": "Default (odd) pages.",
        +                        "type": [
        +                          "string",
        +                          "null"
        +                        ]
        +                      },
        +                      "even": {
        +                        "description": "Even pages.",
        +                        "type": [
        +                          "string",
        +                          "null"
        +                        ]
        +                      },
        +                      "first": {
        +                        "description": "First page.",
        +                        "type": [
        +                          "string",
        +                          "null"
        +                        ]
        +                      }
        +                    },
        +                    "type": "object"
        +                  },
        +                  "numbering": {
        +                    "description": "Page numbering.",
        +                    "properties": {
        +                      "format": {
        +                        "description": "decimal, lowerRoman, upperRoman, lowerLetter, upperLetter...",
        +                        "type": "string"
        +                      },
        +                      "shown": {
        +                        "description": "A page number is printed (checked, not set).",
        +                        "type": "boolean"
        +                      },
        +                      "start": {
        +                        "description": "Restart value, or null to continue.",
        +                        "type": [
        +                          "integer",
        +                          "null"
        +                        ]
        +                      }
        +                    },
        +                    "type": "object"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "two_sided": {
        +              "description": "Different even and odd headers.",
        +              "type": "boolean"
        +            },
        +            "version": {
        +              "description": "Plan format version (1).",
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "changes",
        +        "plan"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlayout_get1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "mirror_margins": {
        +          "description": "Mirrored margins.",
        +          "type": "boolean"
        +        },
        +        "sections": {
        +          "description": "Each section, in order.",
        +          "items": {
        +            "description": "A section of the plan.",
        +            "properties": {
        +              "break": {
        +                "description": "nextPage, oddPage, evenPage or continuous.",
        +                "type": "string"
        +              },
        +              "first_page_different": {
        +                "description": "Different first page.",
        +                "type": "boolean"
        +              },
        +              "footer": {
        +                "description": "Text per kind; {PAGE}, {NUMPAGES} and {chapter} stand for fields; null: inherited.",
        +                "properties": {
        +                  "default": {
        +                    "description": "Default (odd) pages.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "even": {
        +                    "description": "Even pages.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "first": {
        +                    "description": "First page.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "from": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "header": {
        +                "description": "Text per kind; {PAGE}, {NUMPAGES} and {chapter} stand for fields; null: inherited.",
        +                "properties": {
        +                  "default": {
        +                    "description": "Default (odd) pages.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "even": {
        +                    "description": "Even pages.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "first": {
        +                    "description": "First page.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "numbering": {
        +                "description": "Page numbering.",
        +                "properties": {
        +                  "format": {
        +                    "description": "decimal, lowerRoman, upperRoman, lowerLetter, upperLetter...",
        +                    "type": "string"
        +                  },
        +                  "shown": {
        +                    "description": "A page number is printed (checked, not set).",
        +                    "type": "boolean"
        +                  },
        +                  "start": {
        +                    "description": "Restart value, or null to continue.",
        +                    "type": [
        +                      "integer",
        +                      "null"
        +                    ]
        +                  }
        +                },
        +                "type": "object"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "two_sided": {
        +          "description": "Different even and odd headers.",
        +          "type": "boolean"
        +        },
        +        "version": {
        +          "description": "Plan format version (1).",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "version",
        +        "two_sided",
        +        "mirror_margins",
        +        "sections"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlive_close1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "closed": {
        +          "description": "Always true.",
        +          "type": "boolean"
        +        },
        +        "saved": {
        +          "description": "Whether it was saved first.",
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "closed",
        +        "saved"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlive_get_selection1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "paragraph": {
        +          "description": "The paragraph the selection starts in.",
        +          "properties": {
        +            "at": {
        +              "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +              "type": "string"
        +            },
        +            "text": {
        +              "description": "Its text.",
        +              "type": "string"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "text": {
        +          "description": "The selected text (empty for a bare cursor).",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "text",
        +        "paragraph"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlive_open1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "app": {
        +          "description": "The app now attached (word or libreoffice).",
        +          "type": "string"
        +        },
        +        "dirty": {
        +          "description": "It has unsaved changes.",
        +          "type": "boolean"
        +        },
        +        "front": {
        +          "description": "With front: whether its window was brought to the front.",
        +          "type": "boolean"
        +        },
        +        "path": {
        +          "description": "Full path of the document.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "app",
        +        "path",
        +        "dirty"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlive_places1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "doc": {
        +          "description": "The document, as given.",
        +          "type": "string"
        +        },
        +        "mode": {
        +          "description": "cursor or select: what a click does.",
        +          "type": "string"
        +        },
        +        "places": {
        +          "description": "The places, as given.",
        +          "items": {
        +            "description": "A place.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "find_phrase": {
        +                "description": "Find phrase from para.locate.",
        +                "type": "string"
        +              },
        +              "find_phrase_across": {
        +                "description": "previous or next, from para.locate.",
        +                "type": "string"
        +              },
        +              "label": {
        +                "description": "Button label.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "doc",
        +        "mode",
        +        "places"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlive_save1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "saved": {
        +          "description": "Always true: the app saved the file.",
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "saved"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlive_select1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "at": {
        +          "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +          "type": "string"
        +        },
        +        "front": {
        +          "description": "With front: whether the window was brought to the front.",
        +          "type": "boolean"
        +        },
        +        "match_level": {
        +          "description": "By find_phrase: the level it matched at.",
        +          "type": "string"
        +        },
        +        "matched_text": {
        +          "description": "By find_phrase: the text matched, when not exact.",
        +          "type": "string"
        +        },
        +        "text": {
        +          "description": "Text of the paragraph selected.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "text",
        +        "at"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedlive_status1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "apps": {
        +          "description": "Every live app, running or not.",
        +          "items": {
        +            "description": "A live app.",
        +            "properties": {
        +              "app": {
        +                "description": "word, libreoffice (or a test adapter).",
        +                "type": "string"
        +              },
        +              "available": {
        +                "description": "Installed on this machine.",
        +                "type": "boolean"
        +              },
        +              "listening": {
        +                "description": "LibreOffice: its UNO listener is up.",
        +                "type": "boolean"
        +              },
        +              "reachable": {
        +                "description": "Can be driven now.",
        +                "type": "boolean"
        +              },
        +              "reason": {
        +                "description": "Why it is not available or reachable.",
        +                "type": "string"
        +              },
        +              "version": {
        +                "description": "App version, when known.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "dirty": {
        +          "description": "With doc: it has unsaved changes.",
        +          "type": "boolean"
        +        },
        +        "documents": {
        +          "description": "Without doc: the documents the apps have open.",
        +          "items": {
        +            "description": "An open document.",
        +            "properties": {
        +              "app": {
        +                "description": "App.",
        +                "type": "string"
        +              },
        +              "name": {
        +                "description": "File name.",
        +                "type": "string"
        +              },
        +              "path": {
        +                "description": "Full path.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "open_in": {
        +          "description": "With doc: the app holding it {app, controlled, stale}; controlled false means only a lock file says so. Null when no app has it open.",
        +          "type": [
        +            "object",
        +            "null"
        +          ]
        +        },
        +        "path": {
        +          "description": "With doc: its full path.",
        +          "type": "string"
        +        },
        +        "update": {
        +          "description": "Opt-in update notice (DOC_CONTROL_UPDATE_CHECK): the newest release.",
        +          "properties": {
        +            "checked_at": {
        +              "description": "When it was checked (UTC).",
        +              "type": "string"
        +            },
        +            "current": {
        +              "description": "This version.",
        +              "type": "string"
        +            },
        +            "error": {
        +              "description": "Why the check failed.",
        +              "type": "string"
        +            },
        +            "latest": {
        +              "description": "Newest release.",
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "mcpb_url": {
        +              "description": "Download of the newest .mcpb bundle.",
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        }
        +      },
        +      "required": [
        +        "apps",
        +        "open_in",
        +        "dirty"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changednote_add3 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • addedInput schema / properties / kind / description
        Added value: +"footnote (bottom of the page) or endnote (end of the document)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "created_part": {
        +          "description": "Whether the footnotes/endnotes part was created.",
        +          "type": "boolean"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "mark_at": {
        +          "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +          "type": "string"
        +        },
        +        "note": {
        +          "description": "The new note.",
        +          "properties": {
        +            "at": {
        +              "description": "Address of its paragraph, e.g. fn5/p1#9447b777.",
        +              "type": "string"
        +            },
        +            "id": {
        +              "description": "Note id (w:id).",
        +              "type": "integer"
        +            },
        +            "number": {
        +              "description": "Displayed number (null on a dry run).",
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "note",
        +        "mark_at",
        +        "created_part",
        +        "revision_ids"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedpage_estimate1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "at": {
        +          "description": "With at: the paragraph.",
        +          "type": "string"
        +        },
        +        "basis": {
        +          "description": "model, or rendered+model when Word's page marks are used.",
        +          "type": "string"
        +        },
        +        "end_page": {
        +          "description": "Page it ends on, when it runs onto another page.",
        +          "type": "integer"
        +        },
        +        "end_page_label": {
        +          "description": "Page number as printed.",
        +          "type": [
        +            "integer",
        +            "string"
        +          ]
        +        },
        +        "estimated": {
        +          "description": "Always true: pages are estimates.",
        +          "type": "boolean"
        +        },
        +        "model": {
        +          "description": "The model's constants.",
        +          "type": "object"
        +        },
        +        "notes": {
        +          "description": "Caveats about the estimate.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "page": {
        +          "description": "Estimated page (1-based).",
        +          "type": "integer"
        +        },
        +        "page_count": {
        +          "description": "Estimated page count.",
        +          "type": "integer"
        +        },
        +        "page_label": {
        +          "description": "Page number as printed.",
        +          "type": [
        +            "integer",
        +            "string"
        +          ]
        +        },
        +        "pages": {
        +          "description": "by page: this page of rows.",
        +          "items": {
        +            "description": "A page.",
        +            "properties": {
        +              "from": {
        +                "description": "First paragraph number on it.",
        +                "type": "integer"
        +              },
        +              "page": {
        +                "description": "Page.",
        +                "type": "integer"
        +              },
        +              "page_label": {
        +                "description": "Page number as printed.",
        +                "type": [
        +                  "integer",
        +                  "string"
        +                ]
        +              },
        +              "paragraphs": {
        +                "description": "Paragraphs starting on it.",
        +                "type": "integer"
        +              },
        +              "to": {
        +                "description": "Last paragraph number on it.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "paragraphs": {
        +          "description": "by paragraph: this page of rows.",
        +          "items": {
        +            "description": "A paragraph.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "end_page": {
        +                "description": "Page it ends on, when it runs onto another page.",
        +                "type": "integer"
        +              },
        +              "end_page_label": {
        +                "description": "Page number as printed.",
        +                "type": [
        +                  "integer",
        +                  "string"
        +                ]
        +              },
        +              "page": {
        +                "description": "Estimated page (1-based).",
        +                "type": "integer"
        +              },
        +              "page_label": {
        +                "description": "Page number as printed.",
        +                "type": [
        +                  "integer",
        +                  "string"
        +                ]
        +              },
        +              "source": {
        +                "description": "rendered (Word's page marks), break (explicit break) or model.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "rendered_marks": {
        +          "description": "Rendered page-break marks found.",
        +          "type": "integer"
        +        },
        +        "source": {
        +          "description": "rendered (Word's page marks), break (explicit break) or model.",
        +          "type": "string"
        +        },
        +        "total": {
        +          "description": "Items in the whole list, across pages.",
        +          "type": "integer"
        +        },
        +        "words_per_page": {
        +          "description": "Words per page the model assumes.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "estimated",
        +        "page_count",
        +        "basis",
        +        "words_per_page",
        +        "rendered_marks",
        +        "model",
        +        "notes"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedpara_delete3 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedInput schema / properties / tracked / description
        Previous value: -"true (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations); file engine only for now. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too."New value: +"true (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations). engine live: the app's change tracking is off for the edit and put back after; text.replace and para.insert, refused (UNSUPPORTED_CONTENT) next to another unresolved tracked change; the app's undo takes it back. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (1).",
        +          "type": "integer"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "False for a plain (untracked) write.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedpara_get1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "additionalProperties": true,
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "at": {
        +          "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +          "type": "string"
        +        },
        +        "blank_before": {
        +          "description": "Empty paragraphs right before it.",
        +          "type": "integer"
        +        },
        +        "centred": {
        +          "description": "Whether it is centred.",
        +          "type": "boolean"
        +        },
        +        "empty": {
        +          "description": "No visible text.",
        +          "type": "boolean"
        +        },
        +        "format": {
        +          "description": "Direct paragraph formatting (alignment, indent, spacing...).",
        +          "type": "object"
        +        },
        +        "heading_level": {
        +          "description": "1-9 for a heading, null for a body paragraph.",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "kind": {
        +          "description": "Header/footer kind: default, first or even.",
        +          "type": "string"
        +        },
        +        "length": {
        +          "description": "Length of the whole text, in code points.",
        +          "type": "integer"
        +        },
        +        "note": {
        +          "description": "A note's id, displayed number and the body paragraph holding its mark.",
        +          "properties": {
        +            "id": {
        +              "description": "Note id.",
        +              "type": "integer"
        +            },
        +            "number": {
        +              "description": "Displayed number.",
        +              "type": "string"
        +            },
        +            "of": {
        +              "description": "Address of the paragraph holding the mark.",
        +              "type": "string"
        +            }
        +          },
        +          "type": [
        +            "object",
        +            "null"
        +          ]
        +        },
        +        "number": {
        +          "description": "Paragraph number (1-based) in its story.",
        +          "type": "integer"
        +        },
        +        "offset": {
        +          "description": "Where this page of text starts in the paragraph.",
        +          "type": "integer"
        +        },
        +        "page_break_before": {
        +          "description": "Whether it starts a page.",
        +          "type": "boolean"
        +        },
        +        "runs": {
        +          "description": "Spans of the text with direct character formatting.",
        +          "items": {
        +            "additionalProperties": true,
        +            "description": "A span: start/end offsets plus its formatting (bold, italic, font...).",
        +            "properties": {
        +              "end": {
        +                "description": "End offset.",
        +                "type": "integer"
        +              },
        +              "start": {
        +                "description": "Start offset.",
        +                "type": "integer"
        +              }
        +            },
        +            "required": [
        +              "start",
        +              "end"
        +            ],
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "section": {
        +          "description": "Section (1-based) whose header or footer this is.",
        +          "type": "integer"
        +        },
        +        "story": {
        +          "description": "Story kind outside the body: footnote, endnote, header or footer.",
        +          "type": "string"
        +        },
        +        "style": {
        +          "description": "Paragraph style id.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "style_name": {
        +          "description": "Paragraph style display name.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "text": {
        +          "description": "This page of the text.",
        +          "type": "string"
        +        },
        +        "used_by_sections": {
        +          "description": "Sections that show this header or footer.",
        +          "items": {
        +            "type": "integer"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "at",
        +        "number",
        +        "length",
        +        "style",
        +        "style_name",
        +        "format",
        +        "offset",
        +        "text",
        +        "runs"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedpara_insert4 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • addedInput schema / properties / text / description
        Added value: +"Text of the new paragraph."
      • changedInput schema / properties / tracked / description
        Previous value: -"true (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations); file engine only for now. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too."New value: +"true (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations). engine live: the app's change tracking is off for the edit and put back after; text.replace and para.insert, refused (UNSUPPORTED_CONTENT) next to another unresolved tracked change; the app's undo takes it back. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (1).",
        +          "type": "integer"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "engine": {
        +          "description": "live: edited in the open app; nothing backed up or verified.",
        +          "type": "string"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "op_ids": {
        +          "description": "Live: one log entry per edit, in request order.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "False for a plain (untracked) write.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedpara_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "page_basis": {
        +          "description": "With pages: model, or rendered+model when Word's page marks are used.",
        +          "type": "string"
        +        },
        +        "page_count": {
        +          "description": "With pages: estimated page count.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "This page of paragraphs, in document order.",
        +          "items": {
        +            "description": "A paragraph.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "blank_before": {
        +                "description": "Empty paragraphs right before it.",
        +                "type": "integer"
        +              },
        +              "cell": {
        +                "description": "Inside a table: where.",
        +                "properties": {
        +                  "col": {
        +                    "description": "Grid column (0-based).",
        +                    "type": "integer"
        +                  },
        +                  "row": {
        +                    "description": "Row (0-based).",
        +                    "type": "integer"
        +                  },
        +                  "table": {
        +                    "description": "Table number.",
        +                    "type": "integer"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "centred": {
        +                "description": "Whether it is centred.",
        +                "type": "boolean"
        +              },
        +              "empty": {
        +                "description": "No visible text.",
        +                "type": "boolean"
        +              },
        +              "heading_level": {
        +                "description": "1-9 for a heading, null for a body paragraph.",
        +                "type": [
        +                  "integer",
        +                  "null"
        +                ]
        +              },
        +              "kind": {
        +                "description": "Header/footer kind: default, first or even.",
        +                "type": "string"
        +              },
        +              "normalized": {
        +                "description": "With normalized: the text as text.normalize gives it.",
        +                "type": "string"
        +              },
        +              "note": {
        +                "description": "A note's id, displayed number and the body paragraph holding its mark.",
        +                "properties": {
        +                  "id": {
        +                    "description": "Note id.",
        +                    "type": "integer"
        +                  },
        +                  "number": {
        +                    "description": "Displayed number.",
        +                    "type": "string"
        +                  },
        +                  "of": {
        +                    "description": "Address of the paragraph holding the mark.",
        +                    "type": "string"
        +                  }
        +                },
        +                "type": [
        +                  "object",
        +                  "null"
        +                ]
        +              },
        +              "number": {
        +                "description": "Paragraph number (1-based) in its story.",
        +                "type": "integer"
        +              },
        +              "page": {
        +                "description": "With pages: estimated page (body paragraphs).",
        +                "type": "integer"
        +              },
        +              "page_break_before": {
        +                "description": "Whether it starts a page.",
        +                "type": "boolean"
        +              },
        +              "page_label": {
        +                "description": "Page number as printed.",
        +                "type": [
        +                  "integer",
        +                  "string"
        +                ]
        +              },
        +              "section": {
        +                "description": "Section (1-based) whose header or footer this is.",
        +                "type": "integer"
        +              },
        +              "story": {
        +                "description": "Story kind outside the body: footnote, endnote, header or footer.",
        +                "type": "string"
        +              },
        +              "style": {
        +                "description": "Paragraph style id.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "style_name": {
        +                "description": "Paragraph style display name.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "text": {
        +                "description": "Full text.",
        +                "type": "string"
        +              },
        +              "used_by_sections": {
        +                "description": "Sections that show this header or footer.",
        +                "items": {
        +                  "type": "integer"
        +                },
        +                "type": "array"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "rendered_marks": {
        +          "description": "With pages: rendered page-break marks found.",
        +          "type": "integer"
        +        },
        +        "total": {
        +          "description": "Items in the whole list, across pages.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "total",
        +        "paragraphs"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedpara_locate1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "basis": {
        +          "description": "Page basis: model or rendered+model.",
        +          "type": "string"
        +        },
        +        "estimated": {
        +          "description": "Always true: pages are estimates.",
        +          "type": "boolean"
        +        },
        +        "page_count": {
        +          "description": "Estimated page count.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "This page of paragraphs.",
        +          "items": {
        +            "description": "Where one paragraph is.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                "type": "string"
        +              },
        +              "chapter": {
        +                "description": "Its chapter: id, title, number, kind; null if none.",
        +                "type": [
        +                  "object",
        +                  "null"
        +                ]
        +              },
        +              "complete": {
        +                "description": "True when the phrase is the whole paragraph.",
        +                "type": "boolean"
        +              },
        +              "context": {
        +                "description": "When find_phrase is null: the nearest earlier paragraph with one.",
        +                "properties": {
        +                  "after": {
        +                    "description": "Its find phrase.",
        +                    "type": "string"
        +                  },
        +                  "after_word": {
        +                    "description": "As typed in Word's Find box.",
        +                    "type": "string"
        +                  },
        +                  "at": {
        +                    "description": "Paragraph address, p<n>#<fingerprint> (story-prefixed in notes/headers).",
        +                    "type": "string"
        +                  },
        +                  "paragraphs_after": {
        +                    "description": "Paragraphs from there to this one.",
        +                    "type": "integer"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "find_phrase": {
        +                "description": "Text Word's Find meets exactly once, or null.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "find_phrase_across": {
        +                "description": "previous or next: the phrase spans a paragraph break.",
        +                "type": "string"
        +              },
        +              "find_phrase_reason": {
        +                "description": "Why find_phrase is null.",
        +                "type": "string"
        +              },
        +              "find_phrase_unique": {
        +                "description": "Whether find_phrase is non-null.",
        +                "type": "boolean"
        +              },
        +              "find_phrase_word": {
        +                "description": "find_phrase as typed in Word's Find box (^p, ^t...).",
        +                "type": "string"
        +              },
        +              "find_phrase_words": {
        +                "description": "Words in find_phrase.",
        +                "type": "integer"
        +              },
        +              "head_words": {
        +                "description": "Words of the phrase's head.",
        +                "type": "integer"
        +              },
        +              "kind": {
        +                "description": "Header/footer kind: default, first or even.",
        +                "type": "string"
        +              },
        +              "mark": {
        +                "description": "A note paragraph: where its mark is (a row like this one).",
        +                "type": [
        +                  "object",
        +                  "null"
        +                ]
        +              },
        +              "note": {
        +                "description": "A note's id, displayed number and the body paragraph holding its mark.",
        +                "properties": {
        +                  "id": {
        +                    "description": "Note id.",
        +                    "type": "integer"
        +                  },
        +                  "number": {
        +                    "description": "Displayed number.",
        +                    "type": "string"
        +                  },
        +                  "of": {
        +                    "description": "Address of the paragraph holding the mark.",
        +                    "type": "string"
        +                  }
        +                },
        +                "type": [
        +                  "object",
        +                  "null"
        +                ]
        +              },
        +              "page": {
        +                "description": "Estimated page.",
        +                "type": "integer"
        +              },
        +              "page_label": {
        +                "description": "Page number as printed.",
        +                "type": [
        +                  "integer",
        +                  "string"
        +                ]
        +              },
        +              "part": {
        +                "description": "Its part: id, title, number; null if none.",
        +                "type": [
        +                  "object",
        +                  "null"
        +                ]
        +              },
        +              "phrase": {
        +                "description": "Shortest unique first … last words phrase, or null.",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "reason": {
        +                "description": "Why phrase is null (empty, duplicate...).",
        +                "type": "string"
        +              },
        +              "scene": {
        +                "description": "Its scene: id and ordinal within the chapter; null if none.",
        +                "type": [
        +                  "object",
        +                  "null"
        +                ]
        +              },
        +              "section": {
        +                "description": "Section (1-based) whose header or footer this is.",
        +                "type": "integer"
        +              },
        +              "story": {
        +                "description": "Story kind outside the body: footnote, endnote, header or footer.",
        +                "type": "string"
        +              },
        +              "tail_words": {
        +                "description": "Words of the phrase's tail.",
        +                "type": "integer"
        +              },
        +              "used_by_sections": {
        +                "description": "Sections that show this header or footer.",
        +                "items": {
        +                  "type": "integer"
        +                },
        +                "type": "array"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "total": {
        +          "description": "Items in the whole list, across pages.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "estimated",
        +        "paragraphs"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedrecipe_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "invalid": {
        +          "description": "Recipe files that could not be loaded.",
        +          "items": {
        +            "description": "An invalid file.",
        +            "properties": {
        +              "error": {
        +                "description": "Why it is invalid.",
        +                "type": "string"
        +              },
        +              "file": {
        +                "description": "File name.",
        +                "type": "string"
        +              },
        +              "source": {
        +                "description": "bundled or user.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "recipes": {
        +          "description": "Every usable recipe, by name.",
        +          "items": {
        +            "description": "A recipe.",
        +            "properties": {
        +              "description": {
        +                "description": "What it fixes.",
        +                "type": "string"
        +              },
        +              "name": {
        +                "description": "Name to pass to recipe.run.",
        +                "type": "string"
        +              },
        +              "source": {
        +                "description": "bundled or user.",
        +                "type": "string"
        +              },
        +              "version": {
        +                "description": "Recipe format version.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "recipes",
        +        "invalid"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedrecipe_run1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "applied": {
        +          "description": "Always false: nothing is written.",
        +          "type": "boolean"
        +        },
        +        "batch": {
        +          "description": "The doc.batch request to apply: pass it as is.",
        +          "properties": {
        +            "doc": {
        +              "description": "The document.",
        +              "type": "string"
        +            },
        +            "expect": {
        +              "description": "Guards the batch.",
        +              "properties": {
        +                "sha256": {
        +                  "description": "The file hash read.",
        +                  "type": "string"
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "ops": {
        +              "description": "The proposed edits.",
        +              "items": {
        +                "type": "object"
        +              },
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "matches": {
        +          "description": "Matches found.",
        +          "type": "integer"
        +        },
        +        "passes": {
        +          "description": "Passes run until the text stopped changing.",
        +          "type": "integer"
        +        },
        +        "recipe": {
        +          "description": "The recipe's name.",
        +          "type": "string"
        +        },
        +        "skipped": {
        +          "description": "Proposed edits left out, with why.",
        +          "items": {
        +            "description": "A skipped edit.",
        +            "properties": {
        +              "at": {
        +                "description": "Its address.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Its kind.",
        +                "type": "string"
        +              },
        +              "reason": {
        +                "description": "Why.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "stable": {
        +          "description": "Whether it reached a fixed point.",
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "recipe",
        +        "applied",
        +        "matches",
        +        "passes",
        +        "stable",
        +        "skipped",
        +        "batch"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedrevision_accept2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "accepted": {
        +          "description": "Revisions accepted.",
        +          "type": "integer"
        +        },
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (a count), or for style kinds one entry per style op.",
        +          "type": [
        +            "integer",
        +            "array"
        +          ]
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "merged_paragraphs": {
        +          "description": "Paragraphs joined by resolving paragraph marks.",
        +          "type": "integer"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "rejected": {
        +          "description": "Revisions rejected.",
        +          "type": "integer"
        +        },
        +        "revisions": {
        +          "description": "The revisions resolved (capped; see revisions_omitted).",
        +          "items": {
        +            "description": "A resolved revision.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Paragraph address.",
        +                "type": "string"
        +              },
        +              "author": {
        +                "description": "Its author.",
        +                "type": "string"
        +              },
        +              "id": {
        +                "description": "Revision id.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Revision type (insert, delete, mark_insert, format...).",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revisions_omitted": {
        +          "description": "Resolved revisions left out of the list.",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedrevision_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "revisions": {
        +          "description": "This page of tracked changes, in document order.",
        +          "items": {
        +            "description": "A tracked change.",
        +            "properties": {
        +              "at": {
        +                "description": "Address of its paragraph.",
        +                "type": "string"
        +              },
        +              "author": {
        +                "description": "Author.",
        +                "type": "string"
        +              },
        +              "date": {
        +                "description": "Date (ISO 8601).",
        +                "type": [
        +                  "string",
        +                  "null"
        +                ]
        +              },
        +              "id": {
        +                "description": "Revision id (for revision.accept / revision.reject).",
        +                "type": "string"
        +              },
        +              "story": {
        +                "description": "footnote, endnote, header or footer when not in the body.",
        +                "type": "string"
        +              },
        +              "text": {
        +                "description": "Text it inserts or deletes, clipped at 200 characters.",
        +                "type": "string"
        +              },
        +              "truncated": {
        +                "description": "True when text was clipped.",
        +                "type": "boolean"
        +              },
        +              "type": {
        +                "description": "insert, delete, move_from, move_to, format, row_insert...",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "total": {
        +          "description": "Items in the whole list, across pages.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "total",
        +        "revisions"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedrevision_reject2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "accepted": {
        +          "description": "Revisions accepted.",
        +          "type": "integer"
        +        },
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (a count), or for style kinds one entry per style op.",
        +          "type": [
        +            "integer",
        +            "array"
        +          ]
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "merged_paragraphs": {
        +          "description": "Paragraphs joined by resolving paragraph marks.",
        +          "type": "integer"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "rejected": {
        +          "description": "Revisions rejected.",
        +          "type": "integer"
        +        },
        +        "revisions": {
        +          "description": "The revisions resolved (capped; see revisions_omitted).",
        +          "items": {
        +            "description": "A resolved revision.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Paragraph address.",
        +                "type": "string"
        +              },
        +              "author": {
        +                "description": "Its author.",
        +                "type": "string"
        +              },
        +              "id": {
        +                "description": "Revision id.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Revision type (insert, delete, mark_insert, format...).",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revisions_omitted": {
        +          "description": "Resolved revisions left out of the list.",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedsection_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "sections": {
        +          "description": "Each section, in order.",
        +          "items": {
        +            "description": "A section's page setup.",
        +            "properties": {
        +              "break": {
        +                "description": "Section break: nextPage, oddPage, evenPage or continuous.",
        +                "type": "string"
        +              },
        +              "even_and_odd": {
        +                "description": "Different even and odd headers (document-wide).",
        +                "type": "boolean"
        +              },
        +              "footers": {
        +                "description": "Header or footer story per kind (null: inherited from the previous section).",
        +                "properties": {
        +                  "default": {
        +                    "description": "Story key of the default one, e.g. hdr1.default.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "even": {
        +                    "description": "Story key of the even-page one.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "first": {
        +                    "description": "Story key of the first-page one.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "headers": {
        +                "description": "Header or footer story per kind (null: inherited from the previous section).",
        +                "properties": {
        +                  "default": {
        +                    "description": "Story key of the default one, e.g. hdr1.default.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "even": {
        +                    "description": "Story key of the even-page one.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "first": {
        +                    "description": "Story key of the first-page one.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "page_numbers": {
        +                "description": "Page numbering.",
        +                "properties": {
        +                  "format": {
        +                    "description": "Number format (decimal, lowerRoman...).",
        +                    "type": "string"
        +                  },
        +                  "start": {
        +                    "description": "Restart value, or null to continue.",
        +                    "type": [
        +                      "integer",
        +                      "null"
        +                    ]
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "section": {
        +                "description": "Section number (1-based).",
        +                "type": "integer"
        +              },
        +              "title_page": {
        +                "description": "Different first page.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "sections"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedserver_capabilities1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "api": {
        +          "description": "API version of the envelope.",
        +          "type": "string"
        +        },
        +        "build": {
        +          "description": "How this copy was built.",
        +          "properties": {
        +            "freezer": {
        +              "description": "Its freezer (pyinstaller).",
        +              "type": "string"
        +            },
        +            "frozen": {
        +              "description": "A frozen binary.",
        +              "type": "boolean"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "engines": {
        +          "description": "Engines: file, live.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "errors": {
        +          "description": "Every error code.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "features": {
        +          "description": "Feature support per engine.",
        +          "properties": {
        +            "plain_writes": {
        +              "description": "tracked: false writes.",
        +              "properties": {
        +                "file": {
        +                  "description": "File engine.",
        +                  "type": "boolean"
        +                },
        +                "live": {
        +                  "description": "Live.",
        +                  "type": "boolean"
        +                }
        +              },
        +              "type": "object"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "live": {
        +          "description": "The live engine.",
        +          "properties": {
        +            "apps": {
        +              "description": "Every live app.",
        +              "items": {
        +                "description": "A live app.",
        +                "properties": {
        +                  "app": {
        +                    "description": "word, libreoffice (or a test adapter).",
        +                    "type": "string"
        +                  },
        +                  "available": {
        +                    "description": "Installed on this machine.",
        +                    "type": "boolean"
        +                  },
        +                  "listening": {
        +                    "description": "LibreOffice: its UNO listener is up.",
        +                    "type": "boolean"
        +                  },
        +                  "reachable": {
        +                    "description": "Can be driven now.",
        +                    "type": "boolean"
        +                  },
        +                  "reason": {
        +                    "description": "Why it is not available or reachable.",
        +                    "type": "string"
        +                  },
        +                  "version": {
        +                    "description": "App version, when known.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "type": "array"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "operations": {
        +          "description": "Every operation.",
        +          "items": {
        +            "description": "An operation.",
        +            "properties": {
        +              "kind": {
        +                "description": "read or write.",
        +                "type": "string"
        +              },
        +              "name": {
        +                "description": "Its name (MCP tool: dots as underscores).",
        +                "type": "string"
        +              },
        +              "summary": {
        +                "description": "What it does.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "update": {
        +          "description": "Opt-in update notice (DOC_CONTROL_UPDATE_CHECK): the newest release.",
        +          "properties": {
        +            "checked_at": {
        +              "description": "When it was checked (UTC).",
        +              "type": "string"
        +            },
        +            "current": {
        +              "description": "This version.",
        +              "type": "string"
        +            },
        +            "error": {
        +              "description": "Why the check failed.",
        +              "type": "string"
        +            },
        +            "latest": {
        +              "description": "Newest release.",
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            },
        +            "mcpb_url": {
        +              "description": "Download of the newest .mcpb bundle.",
        +              "type": [
        +                "string",
        +                "null"
        +              ]
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "version": {
        +          "description": "doc-control version.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "api",
        +        "version",
        +        "engines",
        +        "live",
        +        "features",
        +        "operations",
        +        "errors",
        +        "build"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedserver_help1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "batch_operations": {
        +          "description": "doc.batch kind -> {kind, summary, schema}.",
        +          "type": "object"
        +        },
        +        "operations": {
        +          "description": "Name -> {kind, summary, schema (JSON Schema of the request), and output_schema (of the result) when one operation is asked}.",
        +          "type": "object"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyle_create2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "applied": {
        +          "description": "One entry per style operation.",
        +          "items": {
        +            "description": "What one style operation did.",
        +            "properties": {
        +              "merged": {
        +                "description": "Ids merged into this style.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "name": {
        +                "description": "Display name.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "style.create, style.update, style.rename or style.merge.",
        +                "type": "string"
        +              },
        +              "style": {
        +                "description": "Style id.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Style type.",
        +                "type": "string"
        +              },
        +              "was": {
        +                "description": "Id and name before a rename.",
        +                "properties": {
        +                  "id": {
        +                    "description": "Old id.",
        +                    "type": "string"
        +                  },
        +                  "name": {
        +                    "description": "Old name.",
        +                    "type": "string"
        +                  }
        +                },
        +                "type": "object"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changed_parts": {
        +          "description": "Package parts rewritten.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "paragraphs_changed": {
        +          "description": "Paragraphs whose style reference was rewritten.",
        +          "type": "integer"
        +        },
        +        "references_rewritten": {
        +          "description": "Style references rewritten (renames, merges).",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "Always false: style definitions are not tracked changes.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "tracked",
        +        "changed_parts"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyle_get1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "based_on": {
        +          "description": "Parent style id.",
        +          "type": "string"
        +        },
        +        "chain": {
        +          "description": "The style and its ancestors, nearest first.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "custom": {
        +          "description": "True for a user-defined style.",
        +          "type": "boolean"
        +        },
        +        "default": {
        +          "description": "True for the default style of its type.",
        +          "type": "boolean"
        +        },
        +        "effective": {
        +          "description": "Formatting after inheritance.",
        +          "properties": {
        +            "paragraph": {
        +              "description": "Paragraph properties.",
        +              "type": "object"
        +            },
        +            "run": {
        +              "description": "Run (character) properties.",
        +              "type": "object"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "heading_level": {
        +          "description": "1-9 for a heading style, else null.",
        +          "type": [
        +            "integer",
        +            "null"
        +          ]
        +        },
        +        "id": {
        +          "description": "Style id (w:styleId).",
        +          "type": "string"
        +        },
        +        "link": {
        +          "description": "Linked paragraph/character style.",
        +          "type": "string"
        +        },
        +        "name": {
        +          "description": "Display name.",
        +          "type": "string"
        +        },
        +        "next": {
        +          "description": "Style of the paragraph after this one.",
        +          "type": "string"
        +        },
        +        "own": {
        +          "description": "Formatting the style sets itself.",
        +          "properties": {
        +            "paragraph": {
        +              "description": "Paragraph properties.",
        +              "type": "object"
        +            },
        +            "run": {
        +              "description": "Run (character) properties.",
        +              "type": "object"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "quick": {
        +          "description": "Shown in the quick style gallery.",
        +          "type": "boolean"
        +        },
        +        "type": {
        +          "description": "paragraph, character, table or numbering.",
        +          "type": "string"
        +        },
        +        "used": {
        +          "description": "Uses in the body.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "id",
        +        "name",
        +        "type",
        +        "used",
        +        "quick",
        +        "heading_level",
        +        "chain",
        +        "own",
        +        "effective"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyle_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "styles": {
        +          "description": "This page of styles.",
        +          "items": {
        +            "description": "A style.",
        +            "properties": {
        +              "based_on": {
        +                "description": "Parent style id.",
        +                "type": "string"
        +              },
        +              "custom": {
        +                "description": "True for a user-defined style.",
        +                "type": "boolean"
        +              },
        +              "default": {
        +                "description": "True for the default style of its type.",
        +                "type": "boolean"
        +              },
        +              "id": {
        +                "description": "Style id (w:styleId).",
        +                "type": "string"
        +              },
        +              "name": {
        +                "description": "Display name.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "paragraph, character, table or numbering.",
        +                "type": "string"
        +              },
        +              "used": {
        +                "description": "Uses in the body.",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "total": {
        +          "description": "Items in the whole list, across pages.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "total",
        +        "styles"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyle_merge2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "applied": {
        +          "description": "One entry per style operation.",
        +          "items": {
        +            "description": "What one style operation did.",
        +            "properties": {
        +              "merged": {
        +                "description": "Ids merged into this style.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "name": {
        +                "description": "Display name.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "style.create, style.update, style.rename or style.merge.",
        +                "type": "string"
        +              },
        +              "style": {
        +                "description": "Style id.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Style type.",
        +                "type": "string"
        +              },
        +              "was": {
        +                "description": "Id and name before a rename.",
        +                "properties": {
        +                  "id": {
        +                    "description": "Old id.",
        +                    "type": "string"
        +                  },
        +                  "name": {
        +                    "description": "Old name.",
        +                    "type": "string"
        +                  }
        +                },
        +                "type": "object"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changed_parts": {
        +          "description": "Package parts rewritten.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "paragraphs_changed": {
        +          "description": "Paragraphs whose style reference was rewritten.",
        +          "type": "integer"
        +        },
        +        "references_rewritten": {
        +          "description": "Style references rewritten (renames, merges).",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "Always false: style definitions are not tracked changes.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "tracked",
        +        "changed_parts"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyle_rename2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "applied": {
        +          "description": "One entry per style operation.",
        +          "items": {
        +            "description": "What one style operation did.",
        +            "properties": {
        +              "merged": {
        +                "description": "Ids merged into this style.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "name": {
        +                "description": "Display name.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "style.create, style.update, style.rename or style.merge.",
        +                "type": "string"
        +              },
        +              "style": {
        +                "description": "Style id.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Style type.",
        +                "type": "string"
        +              },
        +              "was": {
        +                "description": "Id and name before a rename.",
        +                "properties": {
        +                  "id": {
        +                    "description": "Old id.",
        +                    "type": "string"
        +                  },
        +                  "name": {
        +                    "description": "Old name.",
        +                    "type": "string"
        +                  }
        +                },
        +                "type": "object"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changed_parts": {
        +          "description": "Package parts rewritten.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "paragraphs_changed": {
        +          "description": "Paragraphs whose style reference was rewritten.",
        +          "type": "integer"
        +        },
        +        "references_rewritten": {
        +          "description": "Style references rewritten (renames, merges).",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "Always false: style definitions are not tracked changes.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "tracked",
        +        "changed_parts"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyle_update2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "applied": {
        +          "description": "One entry per style operation.",
        +          "items": {
        +            "description": "What one style operation did.",
        +            "properties": {
        +              "merged": {
        +                "description": "Ids merged into this style.",
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              "name": {
        +                "description": "Display name.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "style.create, style.update, style.rename or style.merge.",
        +                "type": "string"
        +              },
        +              "style": {
        +                "description": "Style id.",
        +                "type": "string"
        +              },
        +              "type": {
        +                "description": "Style type.",
        +                "type": "string"
        +              },
        +              "was": {
        +                "description": "Id and name before a rename.",
        +                "properties": {
        +                  "id": {
        +                    "description": "Old id.",
        +                    "type": "string"
        +                  },
        +                  "name": {
        +                    "description": "Old name.",
        +                    "type": "string"
        +                  }
        +                },
        +                "type": "object"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changed_parts": {
        +          "description": "Package parts rewritten.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "paragraphs_changed": {
        +          "description": "Paragraphs whose style reference was rewritten.",
        +          "type": "integer"
        +        },
        +        "references_rewritten": {
        +          "description": "Style references rewritten (renames, merges).",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "Always false: style definitions are not tracked changes.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "tracked",
        +        "changed_parts"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyleset_export1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "count": {
        +          "description": "Styles exported.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "With out: the file written.",
        +          "type": "string"
        +        },
        +        "styleset": {
        +          "description": "The style set (styleset.install takes it as is).",
        +          "properties": {
        +            "styles": {
        +              "description": "The styles.",
        +              "items": {
        +                "description": "A style.",
        +                "properties": {
        +                  "based_on": {
        +                    "description": "Parent style id.",
        +                    "type": "string"
        +                  },
        +                  "custom": {
        +                    "description": "User-defined.",
        +                    "type": "boolean"
        +                  },
        +                  "default": {
        +                    "description": "Default style of its type.",
        +                    "type": "boolean"
        +                  },
        +                  "id": {
        +                    "description": "Style id.",
        +                    "type": "string"
        +                  },
        +                  "link": {
        +                    "description": "Linked style.",
        +                    "type": "string"
        +                  },
        +                  "name": {
        +                    "description": "Display name.",
        +                    "type": "string"
        +                  },
        +                  "next": {
        +                    "description": "Style of the next paragraph.",
        +                    "type": "string"
        +                  },
        +                  "paragraph": {
        +                    "description": "Paragraph properties.",
        +                    "type": "object"
        +                  },
        +                  "quick": {
        +                    "description": "In the quick gallery.",
        +                    "type": "boolean"
        +                  },
        +                  "run": {
        +                    "description": "Run properties.",
        +                    "type": "object"
        +                  },
        +                  "type": {
        +                    "description": "paragraph, character, table or numbering.",
        +                    "type": "string"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "type": "array"
        +            },
        +            "styleset": {
        +              "description": "Its name.",
        +              "type": "string"
        +            },
        +            "version": {
        +              "description": "Format version.",
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        }
        +      },
        +      "required": [
        +        "styleset",
        +        "count"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyleset_export_dotx1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "bytes": {
        +          "description": "Its size.",
        +          "type": "integer"
        +        },
        +        "count": {
        +          "description": "Styles in it.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "The template written.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "path",
        +        "count",
        +        "bytes"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyleset_import_dotx2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "applied": {
        +          "description": "One entry per style in the template.",
        +          "items": {
        +            "description": "What happened to a style.",
        +            "properties": {
        +              "action": {
        +                "description": "created, replaced or skipped.",
        +                "type": "string"
        +              },
        +              "style": {
        +                "description": "Style id.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changed_parts": {
        +          "description": "Package parts rewritten.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "paragraphs_changed": {
        +          "description": "Paragraphs whose style reference was rewritten.",
        +          "type": "integer"
        +        },
        +        "references_rewritten": {
        +          "description": "Style references rewritten (renames, merges).",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "Always false: style definitions are not tracked changes.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "tracked",
        +        "changed_parts"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedstyleset_install2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "applied": {
        +          "description": "One entry per style in the set.",
        +          "items": {
        +            "description": "What happened to a style.",
        +            "properties": {
        +              "action": {
        +                "description": "created, replaced or skipped.",
        +                "type": "string"
        +              },
        +              "style": {
        +                "description": "Style id.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "changed_parts": {
        +          "description": "Package parts rewritten.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "paragraphs_changed": {
        +          "description": "Paragraphs whose style reference was rewritten.",
        +          "type": "integer"
        +        },
        +        "references_rewritten": {
        +          "description": "Style references rewritten (renames, merges).",
        +          "type": "integer"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "Always false: style definitions are not tracked changes.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "tracked",
        +        "changed_parts"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedtable_get1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "rows": {
        +          "description": "Rows, each a list of cells.",
        +          "items": {
        +            "description": "A row.",
        +            "items": {
        +              "description": "A cell.",
        +              "properties": {
        +                "col": {
        +                  "description": "First grid column (0-based).",
        +                  "type": "integer"
        +                },
        +                "paragraphs": {
        +                  "description": "Addresses of its own paragraphs.",
        +                  "items": {
        +                    "type": "string"
        +                  },
        +                  "type": "array"
        +                },
        +                "span": {
        +                  "description": "Grid columns it spans (w:gridSpan).",
        +                  "type": "integer"
        +                },
        +                "vmerge": {
        +                  "description": "Vertical merge: restart, continue or null.",
        +                  "type": [
        +                    "string",
        +                    "null"
        +                  ]
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "type": "array"
        +          },
        +          "type": "array"
        +        },
        +        "table": {
        +          "description": "Table number (in its story).",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "table",
        +        "rows"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedtable_row_delete2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (a count), or for style kinds one entry per style op.",
        +          "type": [
        +            "integer",
        +            "array"
        +          ]
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "preview",
        +        "address_map",
        +        "footprint",
        +        "revision_ids"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedtable_row_insert2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (a count), or for style kinds one entry per style op.",
        +          "type": [
        +            "integer",
        +            "array"
        +          ]
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied",
        +        "dry_run",
        +        "preview",
        +        "address_map",
        +        "footprint",
        +        "revision_ids"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedterm_rename2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "counts": {
        +          "description": "Counts.",
        +          "properties": {
        +            "matches": {
        +              "description": "Matches found.",
        +              "type": "integer"
        +            },
        +            "paragraphs": {
        +              "description": "Paragraphs changed.",
        +              "type": "integer"
        +            },
        +            "replaced": {
        +              "description": "Replaced (or would be).",
        +              "type": "integer"
        +            },
        +            "skipped_boundary": {
        +              "description": "Left alone: would split a character from its marks.",
        +              "type": "integer"
        +            },
        +            "skipped_unsupported": {
        +              "description": "Left alone inside a field, link or other structure.",
        +              "type": "integer"
        +            },
        +            "unchanged": {
        +              "description": "Matches already right.",
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "from": {
        +          "description": "The name replaced.",
        +          "type": "string"
        +        },
        +        "matches_by_level": {
        +          "description": "With match_level: matches per level.",
        +          "type": "object"
        +        },
        +        "preview": {
        +          "description": "The changes (capped).",
        +          "items": {
        +            "description": "A change.",
        +            "properties": {
        +              "after": {
        +                "description": "Text after (case kept).",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Range address, p<n>#<fp>:<start>-<end> (code points).",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "context": {
        +                "description": "The text around it.",
        +                "type": "string"
        +              },
        +              "match_level": {
        +                "description": "Level it matched at.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "skipped": {
        +          "description": "Matches left alone (capped).",
        +          "items": {
        +            "description": "A skipped match.",
        +            "properties": {
        +              "at": {
        +                "description": "Range address, p<n>#<fp>:<start>-<end> (code points).",
        +                "type": "string"
        +              },
        +              "match_level": {
        +                "description": "Level it matched at.",
        +                "type": "string"
        +              },
        +              "reason": {
        +                "description": "Why.",
        +                "type": "string"
        +              },
        +              "text": {
        +                "description": "The text.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "to": {
        +          "description": "The new name.",
        +          "type": "string"
        +        },
        +        "tracked": {
        +          "description": "False for a plain (untracked) write.",
        +          "type": "boolean"
        +        }
        +      },
        +      "required": [
        +        "from",
        +        "to",
        +        "dry_run",
        +        "counts",
        +        "skipped",
        +        "preview"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedtext_find1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "matches": {
        +          "description": "This page of matches, in document order.",
        +          "items": {
        +            "description": "A match.",
        +            "properties": {
        +              "at": {
        +                "description": "Range address, p<n>#<fp>:<start>-<end> (code points).",
        +                "type": "string"
        +              },
        +              "context": {
        +                "description": "The match with some text around it (… marks a cut).",
        +                "type": "string"
        +              },
        +              "match_level": {
        +                "description": "With match_level: the level it matched at.",
        +                "type": "string"
        +              },
        +              "text": {
        +                "description": "The matched text (clipped when very long).",
        +                "type": "string"
        +              },
        +              "text_truncated": {
        +                "description": "True when text was clipped.",
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "more": {
        +          "description": "First page, time budget hit: true (more matches may follow).",
        +          "type": "boolean"
        +        },
        +        "query_word": {
        +          "description": "The query as typed in Word's Find box (^p, ^l, ^t, ^s, ^^ codes); null past 255 characters, with ignore_accents, with a soft or no-break hyphen, or at a folded match_level. Absent for a regex.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "query_word_options": {
        +          "description": "Find options to tick in Word for the same matches.",
        +          "properties": {
        +            "match_case": {
        +              "description": "Match case.",
        +              "type": "boolean"
        +            },
        +            "whole_words": {
        +              "description": "Find whole words only.",
        +              "type": "boolean"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "total": {
        +          "description": "First page only: matches in the whole document.",
        +          "type": "integer"
        +        },
        +        "total_at_least": {
        +          "description": "First page, time budget hit: matches counted so far.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "matches"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedtext_normalize1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "paragraphs": {
        +          "description": "This page of entries.",
        +          "items": {
        +            "description": "One paragraph, or one part of a very long one.",
        +            "properties": {
        +              "at": {
        +                "description": "Paragraph address (absent for `text`).",
        +                "type": "string"
        +              },
        +              "from": {
        +                "description": "Normalised offset where this entry's text begins.",
        +                "type": "integer"
        +              },
        +              "offset_map": {
        +                "description": "Two-way offset map, as runs [index, value, count] or [index, value, count, 0].",
        +                "properties": {
        +                  "to_normalized": {
        +                    "description": "Original -> normalised offsets.",
        +                    "items": {
        +                      "type": "array"
        +                    },
        +                    "type": "array"
        +                  },
        +                  "to_original": {
        +                    "description": "Normalised -> original offsets.",
        +                    "items": {
        +                      "type": "array"
        +                    },
        +                    "type": "array"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              "part": {
        +                "description": "Part k of a split paragraph.",
        +                "type": "integer"
        +              },
        +              "parts": {
        +                "description": "Parts the paragraph was split into.",
        +                "type": "integer"
        +              },
        +              "start": {
        +                "description": "Where the entry's text begins in the paragraph's visible text.",
        +                "type": "integer"
        +              },
        +              "text": {
        +                "description": "Normalised text.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "total": {
        +          "description": "Paragraphs (or text strings) in the selection.",
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "total",
        +        "paragraphs"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedtext_replace3 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedInput schema / properties / tracked / description
        Previous value: -"true (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations); file engine only for now. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too."New value: +"true (default): edits are tracked changes. false: a plain write, for a change the writer already approved: built as the tracked edit, then this call's own revisions are accepted in the same verified write (no revision marks; the log has it, and undo takes it back from the backup, only while the document is exactly as the write left it: no out-of-order undo). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change. Text, paragraph and style/format edits only (refused with revision, row and comment operations). engine live: the app's change tracking is off for the edit and put back after; text.replace and para.insert, refused (UNSUPPORTED_CONTENT) next to another unresolved tracked change; the app's undo takes it back. A plain edit inside a tracked-inserted table row is allowed: rejecting that row later removes the plain text too."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "address_map": {
        +          "description": "Old address -> new address of every paragraph whose address changed.",
        +          "type": "object"
        +        },
        +        "applied": {
        +          "description": "Edits applied (1).",
        +          "type": "integer"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "engine": {
        +          "description": "live: edited in the open app; nothing backed up or verified.",
        +          "type": "string"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "op_ids": {
        +          "description": "Live: one log entry per edit, in request order.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "preview": {
        +          "description": "One entry per edit: what changes where.",
        +          "items": {
        +            "description": "A previewed edit.",
        +            "properties": {
        +              "action": {
        +                "description": "accept or reject (revision kinds).",
        +                "type": "string"
        +              },
        +              "after": {
        +                "description": "Text after.",
        +                "type": "string"
        +              },
        +              "at": {
        +                "description": "Where it applies.",
        +                "type": "string"
        +              },
        +              "before": {
        +                "description": "Text before.",
        +                "type": "string"
        +              },
        +              "op": {
        +                "description": "Index of the edit in ops.",
        +                "type": "integer"
        +              },
        +              "revisions": {
        +                "description": "Revisions it resolves (revision kinds).",
        +                "type": "integer"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "tracked": {
        +          "description": "False for a plain (untracked) write.",
        +          "type": "boolean"
        +        },
        +        "warnings": {
        +          "description": "Notes on what the write could not do as asked.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "applied"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedtoc_insert2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "after": {
        +          "description": "Address of the paragraph it went after.",
        +          "type": "string"
        +        },
        +        "at": {
        +          "description": "Address of the field's paragraph.",
        +          "type": "string"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "code": {
        +          "description": "The field code.",
        +          "type": "string"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "title": {
        +          "description": "The title paragraph's text, or null for none.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "at",
        +        "after",
        +        "code",
        +        "title",
        +        "revision_ids"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
    • Changedxref_add2 fields changed
      • addedInput schema / properties / expect / description
        Added value: +"Write guard: the sha256 read earlier (doc.info, or a reply's doc.sha256), e.g. {\"sha256\": \"9f86d081…\"}; a file changed since is DOC_CHANGED_ON_DISK."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "api": {
        +      "description": "API version (1.0).",
        +      "type": "string"
        +    },
        +    "doc": {
        +      "description": "The document read or written: path, sha256 and paragraph count.",
        +      "properties": {
        +        "characters": {
        +          "description": "text.normalize of a text string: its length.",
        +          "type": "integer"
        +        },
        +        "paragraphs": {
        +          "description": "Body paragraphs.",
        +          "type": "integer"
        +        },
        +        "path": {
        +          "description": "Path of the document.",
        +          "type": "string"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file (pass as expect.sha256 to a write).",
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "A .txt/.md/.odt source's format, encoding and split mode; \"text\" for a text string (text.normalize).",
        +          "type": [
        +            "object",
        +            "string"
        +          ]
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "next": {
        +      "description": "Cursor for the next page (pass as cursor), or null.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "ok": {
        +      "description": "Always true on success.",
        +      "type": "boolean"
        +    },
        +    "op": {
        +      "description": "The operation that ran.",
        +      "type": "string"
        +    },
        +    "result": {
        +      "description": "What the operation returns.",
        +      "properties": {
        +        "at": {
        +          "description": "Address of the paragraph that holds the field.",
        +          "type": "string"
        +        },
        +        "author": {
        +          "description": "Revision author stamped on the changes.",
        +          "type": "string"
        +        },
        +        "backup": {
        +          "description": "Path of the backup taken before the write.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "bookmark": {
        +          "description": "The target's bookmark.",
        +          "type": "string"
        +        },
        +        "code": {
        +          "description": "The field code, e.g. REF _Ref100000001 \\h.",
        +          "type": "string"
        +        },
        +        "date": {
        +          "description": "Revision date (UTC, ISO 8601).",
        +          "type": "string"
        +        },
        +        "dry_run": {
        +          "description": "True when nothing was written (a preview).",
        +          "type": "boolean"
        +        },
        +        "footprint": {
        +          "description": "Part name -> the paragraphs or items it touched in that part.",
        +          "type": "object"
        +        },
        +        "op_id": {
        +          "description": "Undo-log id of this write (history.undo / history.restore).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "revision_ids": {
        +          "description": "w:id of every revision this write created.",
        +          "items": {
        +            "type": [
        +              "integer",
        +              "string"
        +            ]
        +          },
        +          "type": "array"
        +        },
        +        "sha256": {
        +          "description": "sha256 of the file after the write (pass as expect.sha256 next).",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "show": {
        +          "description": "number, page or text.",
        +          "type": "string"
        +        },
        +        "to": {
        +          "description": "Address of the target paragraph.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "dry_run",
        +        "at",
        +        "to",
        +        "show",
        +        "code",
        +        "bookmark",
        +        "revision_ids"
        +      ],
        +      "type": "object"
        +    },
        +    "warnings": {
        +      "description": "Things to know about the result.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "api",
        +    "ok",
        +    "op",
        +    "result",
        +    "warnings",
        +    "next"
        +  ],
        +  "type": "object"
        +}
  2. 63 tool updatesv0.1.3
    • Changedanchor_resolve1 field changed
      • changedInput schema / properties / mode / description
        Previous value: -"best: verbatim matches first, then fuzzy ones (match says which). exact: only places holding the quote verbatim or, when none does, in the normalised text (soft hyphens and zero-width characters ignored, whitespace collapsed, as text.normalized) or at a fold level of match_level; anything else is ANCHOR_NOT_FOUND."New value: +"best: verbatim matches first, then fuzzy ones (match says which). exact: only places holding the quote verbatim or, when none does, in the normalised text (soft hyphens and zero-width characters ignored, whitespace collapsed, as text.normalize) or at a fold level of match_level; anything else is ANCHOR_NOT_FOUND."
    • Removedbatch
    • Removedcapabilities
    • Addedcomment_add
    • Addedcomment_list
    • Removedcomments_list
    • Removedcompare
    • Removeddiff
    • Addeddoc_batch
    • Addeddoc_compare
    • Addeddoc_diff
    • Addeddoc_info
    • Addeddoc_open
    • Addeddoc_outline
    • Addeddoc_segment
    • Addeddoc_stats
    • Addedfield_list
    • Addedfield_update
    • Removedfields_list
    • Removedfields_update
    • Removedfind
    • Removedhelp
    • Addedhistory_adopt
    • Changedhistory_list1 field changed
      • changedInput schema / properties / kind / enum
        Previous value: -[
        -  "batch",
        -  "restore",
        -  "undo",
        -  "open",
        -  "purge"
        -]New value: +[
        +  "batch",
        +  "restore",
        +  "undo",
        +  "open",
        +  "purge",
        +  "adopt"
        +]
    • Addedhistory_restore
    • Changedhistory_search1 field changed
      • changedInput schema / properties / match_level / description
        Previous value: -"Fold the search as `find` does: `default` ignores case, accents and punctuation (symbols such as `$` still count), `loose` drops symbols too; `exact` keeps the flags. When passed, Word's Find codes in `query` are read as their characters, every hit in a text is returned (not only the first, `exact` included), each with `start` and `end` (its offsets in that text: the request's JSON or the paragraph before or after the write, as `in` names it; not offsets into the cut `text`), `match_level` (the strictest level it meets) and `text` cut around it, and the reply gains `matches_by_level`, adding up to `total`. Without it, the first hit per text, with no `start`, `end` or level. Not with `ignore_case` or `ignore_accents` false at a folded level."New value: +"Fold the search as `text.find` does: `default` ignores case, accents and punctuation (symbols such as `$` still count), `loose` drops symbols too; `exact` keeps the flags. When passed, Word's Find codes in `query` are read as their characters, every hit in a text is returned (not only the first, `exact` included), each with `start` and `end` (its offsets in that text: the request's JSON or the paragraph before or after the write, as `in` names it; not offsets into the cut `text`), `match_level` (the strictest level it meets) and `text` cut around it, and the reply gains `matches_by_level`, adding up to `total`. Without it, the first hit per text, with no `start`, `end` or level. Not with `ignore_case` or `ignore_accents` false at a folded level."
    • Addedhistory_undo
    • Removedinfo
    • Addedlive_get_selection
    • Changedlive_places1 field changed
      • changedInput schema / properties / places / items / properties / find_phrase / description
        Previous value: -"A `locate` find phrase; used when `at` is missing or stale."New value: +"A `para.locate` find phrase; used when `at` is missing or stale."
    • Changedlive_select3 fields changed
      • changedInput schema / properties / find_phrase / description
        Previous value: -"A phrase that occurs once in the document (`\\r` for a paragraph mark), as `locate` gives it."New value: +"A phrase that occurs once in the document (`\\r` for a paragraph mark), as `para.locate` gives it."
      • changedInput schema / properties / find_phrase_across / description
        Previous value: -"`locate`'s `find_phrase_across`, for a phrase spanning a mark."New value: +"`para.locate`'s `find_phrase_across`, for a phrase spanning a mark."
      • changedInput schema / properties / match_level / description
        Previous value: -"How loosely `find_phrase` matches. `default` (the default) ignores case, accents and punctuation; `loose` symbols too. Either tries the levels from verbatim on and takes the first that matches, so one verbatim paragraph beats looser ones. `exact` is `locate`'s rule: case ignored, nothing else, no retry. Two meanings of exact: the request's `exact` allows a case difference, the reply's does not. The reply's `match_level` (`exact` character for character, `case`, `default`, `loose`) names the level that matched, with `matched_text` when it is not `exact`."New value: +"How loosely `find_phrase` matches. `default` (the default) ignores case, accents and punctuation; `loose` symbols too. Either tries the levels from verbatim on and takes the first that matches, so one verbatim paragraph beats looser ones. `exact` is `para.locate`'s rule: case ignored, nothing else, no retry. Two meanings of exact: the request's `exact` allows a case difference, the reply's does not. The reply's `match_level` (`exact` character for character, `case`, `default`, `loose`) names the level that matched, with `matched_text` when it is not `exact`."
    • Removedlive_selection
    • Removedlocate
    • Removedopen
    • Removedoutline
    • Addedpara_delete
    • Addedpara_insert
    • Addedpara_list
    • Addedpara_locate
    • Removedparagraphs_list
    • Removedrestore
    • Addedrevision_accept
    • Addedrevision_list
    • Addedrevision_reject
    • Removedrevisions_list
    • Addedsection_list
    • Removedsections_list
    • Removedsegment
    • Addedserver_capabilities
    • Addedserver_help
    • Removedstats
    • Addedstyle_list
    • Removedstyles_list
    • Addedstyleset_export_dotx
    • Removedstyleset_export-dotx
    • Addedstyleset_import_dotx
    • Removedstyleset_import-dotx
    • Changedterm_rename2 fields changed
      • changedInput schema / properties / match_level / description
        Previous value: -"Fold the search as `find` does: `default` ignores case, accents and punctuation (symbols such as `$` still count), `loose` drops symbols too; `exact` is the rename as without it. When passed, Word's Find codes in `from` are read as their characters, each `preview` change and `skipped` row gains `match_level` (the strictest level it meets) and the reply gains `matches_by_level`, adding up to `counts.matches`. No retry at a looser level. Two meanings of exact: without `match_level` the rename is today's, with ^ codes literal and no levels; `match_level: \"exact\"` keeps that rule but reads the ^ codes and tags each change (`exact` there: character for character). Not with `case_sensitive` or `ignore_accents: false` at a folded level."New value: +"Fold the search as `text.find` does: `default` ignores case, accents and punctuation (symbols such as `$` still count), `loose` drops symbols too; `exact` is the rename as without it. When passed, Word's Find codes in `from` are read as their characters, each `preview` change and `skipped` row gains `match_level` (the strictest level it meets) and the reply gains `matches_by_level`, adding up to `counts.matches`. No retry at a looser level. Two meanings of exact: without `match_level` the rename is today's, with ^ codes literal and no levels; `match_level: \"exact\"` keeps that rule but reads the ^ codes and tags each change (`exact` there: character for character). Not with `case_sensitive` or `ignore_accents: false` at a folded level."
      • addedInput schema / properties / tracked
        Added value: +{
        +  "default": true,
        +  "description": "false: a plain write for a change the writer already approved: the same edits, with this call's own revisions accepted in the same verified write (no revision marks; undo works). Refused (UNSUPPORTED_CONTENT) when a paragraph it rewrites holds another unresolved tracked change.",
        +  "type": "boolean"
        +}
    • Addedtext_find
    • Addedtext_normalize
    • Removedtext_normalized
    • Addedtext_replace
    • Removedundo
  3. 60 tool updatesv0.1.0
    • First observedanchor_create
    • First observedanchor_resolve
    • First observedbatch
    • First observedcapabilities
    • First observedcaption_add
    • First observedcomments_list
    • First observedcompare
    • First observeddiff
    • First observedfields_list
    • First observedfields_update
    • First observedfind
    • First observedhelp
    • First observedhistory_list
    • First observedhistory_orphans
    • First observedhistory_purge
    • First observedhistory_search
    • First observedindex_insert
    • First observedindex_mark
    • First observedinfo
    • First observedlayout_apply
    • First observedlayout_get
    • First observedlive_close
    • First observedlive_open
    • First observedlive_places
    • First observedlive_save
    • First observedlive_select
    • First observedlive_selection
    • First observedlive_status
    • First observedlocate
    • First observednote_add
    • First observedopen
    • First observedoutline
    • First observedpage_estimate
    • First observedpara_get
    • First observedparagraphs_list
    • First observedrecipe_list
    • First observedrecipe_run
    • First observedrestore
    • First observedrevisions_list
    • First observedsections_list
    • First observedsegment
    • First observedstats
    • First observedstyle_create
    • First observedstyle_get
    • First observedstyle_merge
    • First observedstyle_rename
    • First observedstyle_update
    • First observedstyles_list
    • First observedstyleset_export
    • First observedstyleset_export-dotx
    • First observedstyleset_import-dotx
    • First observedstyleset_install
    • First observedtable_get
    • First observedtable_row_delete
    • First observedtable_row_insert
    • First observedterm_rename
    • First observedtext_normalized
    • First observedtoc_insert
    • First observedundo
    • First observedxref_add

TDQS

A4.2/5.0

Scored across 67 tools

Disambiguation4/5

Tools are mostly distinct, with clear domain-specific purposes and descriptions that explicitly cross-reference alternatives (e.g., doc_batch vs individual edits, doc_info vs doc_stats). However, with 67 tools, some read-only tools (para_list, doc_outline, doc_segment) and editing tools (text_replace vs doc_batch) could be confused by an agent under time pressure.

Naming Consistency5/5

Consistent snake_case noun_verb pattern throughout (e.g., text_find, para_get, style_update, revision_accept). Minor deviations like server_capabilities are still readable and domain-prefixed.

Tool Count1/5

67 tools is far beyond the 15-tool guideline and exceeds the 50-tool threshold for extreme mismatch. Many tools are granular and could be consolidated (e.g., individual editing vs doc_batch).

Completeness5/5

Surface covers read, write, style, comment, revision, field, layout, live editing, history, and recipes with lifecycle operations. No obvious gaps for document control.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers