From fad7dc3706c6dbc84b3830354471ec762e336418 Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Fri, 6 Nov 2026 10:55:17 +0000 Subject: [PATCH 1/2] docs(knowledge): route a Word export in the knowledge pack The routing table answered layout and table questions but had no route for exporting to Word, so an agent asking how to write a .docx got the surfaces, which list buildDocx, export and the builder side by side without saying which to use or what each costs. Add the route export.docx: session.buildDocx(path) / writeDocx / toDocxBytes as the one call; a configured DocxSemanticBackend through session.export when the report or stable bytes are wanted; new DocxSemanticBackend() for Stable API only; buildPdf when the page must be read as laid out. It names the @Beta parts and points at the render-docx README's usage. confirmedBy stays null until a maintainer confirms the recommendation. --- CHANGELOG.md | 8 +++++++ knowledge/routing/tasks.json | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14aa05803..b0bd6125f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6275,6 +6275,14 @@ follow semantic versioning; release dates are ISO 8601. ### Documentation +- **The knowledge pack routes a Word export.** `api-query --task export.docx` recommends + `session.buildDocx(path)` — or `writeDocx` / `toDocxBytes` — and says when to export through + another path instead: `DocxSemanticBackend.builder().deterministic(true).reportSink(...)` for + the `DocxExportReport` or the same bytes on every run on one platform (a `{date}` token aside), + `new DocxSemanticBackend()` where only Stable API may be used, and `buildPdf` where the reader + must see the page as laid out rather than edit it. It names what each path costs and which of + these calls are `@Beta`, and points at the `render-docx` README's usage. The route is not yet + confirmed by a maintainer, and `api-query` says so when it prints it. - **`ROADMAP.md` says what 2.5 did for DOCX and what is left.** The strict-mode item said shapes, lines and ellipses are dropped with a warning; they are written where the layout places them, and every loss is named in the `DocxExportReport`. A built-in option that fails the export instead diff --git a/knowledge/routing/tasks.json b/knowledge/routing/tasks.json index d89fa12fd..008635eea 100644 --- a/knowledge/routing/tasks.json +++ b/knowledge/routing/tasks.json @@ -181,6 +181,47 @@ "docs": ["docs/recipes/tables.md#repeated-header-on-page-break"], "verifiedAgainst": "2.2.3-SNAPSHOT", "confirmedBy": "Artem Demchyshyn" + }, + { + "task": "export.docx", + "intent": "Export the document as an editable Word (.docx) file.", + "recommended": "session-build-docx", + "recommendedBecause": "render-docx/README.md#usage makes it one call, as buildPdf(path) is for the PDF: with graph-compose-render-docx on the classpath, session.buildDocx(path), writeDocx(stream) or toDocxBytes() finds the backend and builds a default one for each export. buildDocx makes the bytes first and moves them over the file only on success, so a failed export leaves the old file in place. DocxSessionExportTest opens what each of the three wrote and finds the document's text in it. The three are Experimental (@Beta) in 2.5, under semantic backend discovery in docs/api-stability.md#1-stability-tiers. They hand back no report, and they stamp the export with the date it was made.", + "alternatives": [ + { + "id": "configured-backend-export", + "useWhen": "the caller needs the export report (what Word could not carry as authored, docs/recipes/docx-export.md#finding-out-what-the-export-could-not-carry) or the same bytes on every run, as a byte-level test does", + "tradeoffs": "session.export(DocxSemanticBackend.builder().deterministic(true).reportSink(report -> ...).build(), path) — the builder and DocxExportReport are @Beta; the file is written in place, not replaced on success, and a failure is a plain Exception; the bytes hold on one platform only, and a {date} header or footer token still changes them with the day unless -Dgraphcompose.renderDate pins it (docs/recipes/docx-export.md#byte-identical-output); one backend per thread" + }, + { + "id": "stable-backend-export", + "useWhen": "the code may use Stable API only", + "tradeoffs": "session.export(new DocxSemanticBackend(), path), the path docs/api-stability.md#1-stability-tiers keeps Stable — no report (what is dropped goes to the log only), and the package carries the date of the export" + }, + { + "id": "pdf", + "useWhen": "the recipient must see exactly the page as laid out, not edit it", + "tradeoffs": "session.buildPdf(path) fixes every fragment where the layout placed it, and the file is not meant to be edited; Word paginates and re-flows a DOCX itself" + } + ], + "constraints": [], + "symbols": [ + "DocumentSession.buildDocx", + "DocumentSession.writeDocx", + "DocumentSession.toDocxBytes", + "DocumentSession.export", + "DocxSemanticBackend", + "DocxSemanticBackend.builder", + "DocxSemanticBackend.Builder.deterministic", + "DocxSemanticBackend.Builder.reportSink", + "DocxSemanticBackend.Builder.build", + "DocxExportReport.notes", + "DocumentSession.buildPdf" + ], + "surfaces": ["authoring", "backends"], + "docs": ["render-docx/README.md#usage"], + "verifiedAgainst": "2.5.0-SNAPSHOT", + "confirmedBy": null } ] } From 46e4fc1e102c990ffdeb40e35425daf2cab571db Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Fri, 6 Nov 2026 11:04:45 +0000 Subject: [PATCH 2/2] docs(knowledge): say what a direct DOCX export write costs session.export builds every byte before it writes, so a failed export keeps the old file too; what it lacks against buildDocx is a write that breaks part-way. Cite the byte-identical section for the platform caveat alone, and say the Stable path writes and throws as the configured one. --- knowledge/routing/tasks.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/knowledge/routing/tasks.json b/knowledge/routing/tasks.json index 008635eea..1eed7d858 100644 --- a/knowledge/routing/tasks.json +++ b/knowledge/routing/tasks.json @@ -191,12 +191,12 @@ { "id": "configured-backend-export", "useWhen": "the caller needs the export report (what Word could not carry as authored, docs/recipes/docx-export.md#finding-out-what-the-export-could-not-carry) or the same bytes on every run, as a byte-level test does", - "tradeoffs": "session.export(DocxSemanticBackend.builder().deterministic(true).reportSink(report -> ...).build(), path) — the builder and DocxExportReport are @Beta; the file is written in place, not replaced on success, and a failure is a plain Exception; the bytes hold on one platform only, and a {date} header or footer token still changes them with the day unless -Dgraphcompose.renderDate pins it (docs/recipes/docx-export.md#byte-identical-output); one backend per thread" + "tradeoffs": "session.export(DocxSemanticBackend.builder().deterministic(true).reportSink(report -> ...).build(), path) — the builder and DocxExportReport are @Beta; the bytes go straight over the file, so a write that breaks part-way can truncate it, and a failure is a plain Exception; the bytes hold on one platform only (docs/recipes/docx-export.md#byte-identical-output), and a {date} token changes them daily unless -Dgraphcompose.renderDate pins it; one backend per thread" }, { "id": "stable-backend-export", "useWhen": "the code may use Stable API only", - "tradeoffs": "session.export(new DocxSemanticBackend(), path), the path docs/api-stability.md#1-stability-tiers keeps Stable — no report (what is dropped goes to the log only), and the package carries the date of the export" + "tradeoffs": "session.export(new DocxSemanticBackend(), path), the path docs/api-stability.md#1-stability-tiers keeps Stable — no report (what is dropped goes to the log only), the package carries the date of the export, and it writes and throws as the configured backend does" }, { "id": "pdf",