Skip to content

Write down the route from an extraction to a Word document - #36

Merged
peopleworks merged 1 commit into
peopleworks:mainfrom
MBrekhof:docs/word-recipe
Aug 23, 2026
Merged

Write down the route from an extraction to a Word document#36
peopleworks merged 1 commit into
peopleworks:mainfrom
MBrekhof:docs/word-recipe

Conversation

@MBrekhof

Copy link
Copy Markdown

Finishes #28. PR #29 made the output survive the trip; this writes the trip down.

What it says

A README section beside the HTML explainer — The same knowledge, as a document — with the route: xaflogic extract, hand a section file to mcpOffice's word_create_from_markdown, word_convert it to PDF. No exporter here, for the reason #28 gave, and the section says so.

It answers the one question #28 left open: word_convert reaches PDF (also html, rtf, txt, and Markdown back), so the route ends in a client-ready document. And it says which file to hand over: a section file for a single audience, _Full.md for the whole thing.

What was verified, with the real tools

I ran the route on PharmacyDemo.Module against mcpOffice on Document.Processor 26.1, then inspected the .docx outline and rendered PDF pages:

Markdown In the document
##### headings Heading styles; the full tree is in the outline, the #### Source code of … headings from #29 included
Pipe tables (properties, seed rows) Real tables, bold shaded header row
Fenced csharp Shaded monospace, indentation kept
Lists, nested lists, **bold**, `code` Word lists and runs

15 pages for the sample. 382 tests pass; nothing outside README changed.

Two things found on the way, not in this PR

  • mcpOffice: text after an inline-code span stays in the code font for the rest of the line. That is mine to fix, tracked on mcpOffice's board.
  • Here: - **Base type:** ViewController<DetailView> at MarkdownDocumentationGenerator.cs:602 (and the entity/orphan lines at 499 and 915) emit a generic type unescaped. <DetailView> is an inline HTML tag to every CommonMark parser, so it is dropped — in the Word export, and on github.com as well, where the sanitizer strips the unknown tag. The reader sees ViewController. The Emit a heading where a <details> fold was #29 guard scans only lines that open with <, so this passes it. AGENTS.md is unaffected; it backticks every type. Separate PR if you want it: backticks at the three sites plus an inline case in PortableMarkdownTests.

🤖 Generated with Claude Code

Closes the half of peopleworks#28 that PR peopleworks#29 left open: the recipe. The extraction
already survives the trip through mcpOffice's Markdown converter, and
this says how to make it — extract, hand a section file to
word_create_from_markdown, word_convert it to PDF — and what was verified
on the sample application: headings reach the outline, tables become
tables, fenced C# stays code.

It also answers the question the issue left for later: word_convert
reaches PDF, so the route ends in a client-ready document.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@peopleworks

peopleworks commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Verified against the tools rather than read, since the section teaches a route somebody will follow. Everything in it holds, and the one thing I went looking to disprove turned out to be a documentation bug on your side rather than an error on ours.

What I checked

word_convert reaches PDF. Confirmed — docs/usage.md:117 lists pdf, html, rtf, txt, md, docx, inferred from the output path when the format is omitted. That answers the one question #28 left open, and it is what makes the route end in something a client can be handed.

word_create_from_markdown takes a templatePath. I doubted this one, because both README.md:39 and docs/usage.md document the three-parameter form:

- `word_create_from_markdown(path, markdown, overwrite=false)`

Then I read src/mcpOffice/Tools/WordTools.cs:61:

[Description("Optional absolute path to a .dotx/.docx template whose styles (Heading 1-6, Normal,
tables, headers/footers) the document is built on")] string? templatePath = null)

So you are right and mcpOffice's own documentation is behind its code. Worth fixing there: templatePath is the parameter that turns this from "a Word file" into "a document on our letterhead", and nobody reading the README or the usage guide can find out it exists. word_mail_merge documents its templatePath and this one does not, which makes the omission read as deliberate.

Your finding is real, and it is bigger than the three sites

I probed the generated Markdown across all nine sample projects, in both languages, matching any HTML-looking tag outside a code fence and outside an inline code span:

MD  Xpo/en:          - **Base type:** ViewController<DetailView>
MD  Xpo/es:          - **Tipo base:** ViewController<DetailView>
MD  Demo/en:         - **Base type:** ViewController<DetailView>
MD  Demo/es:         - **Tipo base:** ViewController<DetailView>
MD  Walkthrough/en:  - **Base type:** ViewController<DetailView>
MD  Walkthrough/es:  - **Tipo base:** ViewController<DetailView>

Six lines, one call site — MarkdownDocumentationGenerator.cs:602, the controller base type. The other four <…> hits in the output are inside fenced blocks (ObjectSpace.CreateObject<Customer>()), which are safe, and AGENTS.md produced nothing at all, exactly as you said.

The entity sites at 499 and 915 do not fire in any fixture we have, because no fixture entity derives from a generic base. They will fire on real code, so all three get backticks.

And the guard is mine. PortableMarkdownTests scans lines that open with <, which was the shape of the <details> block it was written for. A generic type mid-line walks straight past it. That is a hole in a test I wrote one release ago and argued was the durable half of #28 — you found it the first time you pointed a real renderer at the output, which is the second time that has been the thing that worked.

I am taking the fix rather than handing it back to you. You found it; the cleanup is not the reward. It is #39: backticks at the three sites, and the guard widened to catch a tag anywhere on a line rather than only at its start.

One thing to settle before this merges

The section says:

Nothing in the generated Markdown is HTML, and a test keeps it that way.

Both halves of that are false today, and your own findings section is what proves it. It is the kind of sentence that is worth getting right rather than softening, because it is the sentence a reader relies on when they decide not to check the output themselves.

So: merge #39 first, and this becomes true as written. Nothing else in the section needs a word changed.

Separately

#22 is still yours if you want it — positional appearance criteria, and AppearanceItemType never read. No pressure at all, and I will say plainly that it is a live dependency of shipped code: until it lands, the word always that 0.15.0 prints is true of every rule whose criteria we extract, and would be wrong about one written [Appearance("id", "criteria")]. If you would rather not, say so and I will pick it up — that is not a bad outcome, it is just information.

And XafTornado — no rush on #27, but it is the interesting one.

@peopleworks
peopleworks merged commit 5f214f5 into peopleworks:main Aug 23, 2026
6 checks passed
MBrekhof pushed a commit to MBrekhof/XAFLogicExplainer that referenced this pull request Aug 23, 2026
Found by @MBrekhof in peopleworks#36, running the extraction through a real Word
converter. `- **Base type:** ViewController<DetailView>` was printed bare, and
`<DetailView>` is an inline HTML tag to every CommonMark parser. An export
drops it; github.com's sanitizer strips the unknown tag. Either way the page
told the reader the base class was `ViewController`, which is a different
answer rather than a missing one.

Backticks at the three sites that print a type name outside code: the entity
base type, the controller base type, and the orphan-entity line.

The guard from peopleworks#28 is mine and it missed this. It scanned only lines that
*opened* with `<`, which was the shape of the `<details>` block it was written
for, so a generic in the middle of a sentence walked straight past. It now
matches a tag anywhere on a line, excluding fenced blocks -- where
`CreateObject<Customer>()` is exactly right -- and inline code spans, which are
the remedy itself and would otherwise make the guard reject its own fix.

Measured before the fix across nine sample projects in both languages: six
offending lines, all from the controller base type. The entity sites do not
fire on any fixture we have, because no fixture entity derives from a generic
base; they will on real code, so all three are fixed. AGENTS.md produced
nothing, which is what he said.

392 tests, zero warnings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W45tzJFX3NoSrk7svtQeKT
@MBrekhof
MBrekhof deleted the docs/word-recipe branch August 23, 2026 06:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants