Aperio Home All Suites
DOCX Skills Evaluation

Word Document Generation & Editing

Ten self-contained Word document tasks that probe how well a model creates and edits .docx files β€” from simple generate_docx memos to advanced docx-js scripts with custom styles, tables of contents, headers/footers, embedded images, and tracked changes via XML editing. Each task has a copy-paste prompt, a verify command, and clear pass criteria.

These tasks test the docx and docx-advanced skills β€” the model's ability to produce well-structured, professional .docx files using the generate_docx MCP tool and the docx-js library. Tasks 1–4 use generate_docx (simple). Tasks 5–10 require docx-js scripting (advanced). Start at Task 1 and work up.

DOCX Technology (Quick Reference)

These tasks use the generate_docx MCP tool and the docx npm package for scripting. Knowing the conventions helps you evaluate whether the model followed the skill correctly.

ConceptRuleWhy
generate_docxUse for simple documents. Sections with heading + paragraphs + tables.Zero scripting β€” fast and reliable
docx-jsUse for images, custom styles, TOC, headers/footers, footnotes.Advanced features not in generate_docx
Page sizeAlways set explicitly (US Letter 12240Γ—15840 DXA)docx-js defaults to A4
ListsNever unicode bullets β€” use LevelFormat.BULLET + numbering configSurvives round-trip in Word / Google Docs
TablesDual widths: columnWidths array + cell width, both WidthType.DXANever use PERCENTAGE (breaks Google Docs)
ShadingUse ShadingType.CLEAR, never SOLIDSOLID makes backgrounds opaque in Word
PageBreakMust be inside a Paragraphdocx-js requires it
ImageRunRequires type field ("png" / "jpeg")Missing type produces corrupt documents
Smart quotesUse XML entities: “ / ”Raw Unicode breaks in some XML parsers
Tracked changes<w:ins> for insertions, <w:del> for deletionsAuthor must be "Claude"

Setup

You need one terminal with the Aperio server running on your preferred AI provider. Paste each task prompt into the chat (web UI or CLI).

Terminal β€” Aperio server
npm run start:local        # or any AI_PROVIDER, port 31337

Paste each task's prompt into the chat. Use a fresh conversation per task when possible. After the model responds, check that the .docx file was created, then run the Verify command.

Tasks 1–4 use the generate_docx MCP tool β€” no scripting needed. Tasks 5–10 require docx-js scripting where the model writes a Node.js script using the docx npm package. The verify commands use Python 3 (stdlib zipfile for XML inspection) and the project's own validate.py script.

Cleanup between runs

If you want to re-run tasks against a different model, clean up the output files first:

rm -f trash/test-*.docx
rm -rf trash/test-unpacked

The Tasks

Ordered by complexity: simple generate_docx first (memos, letters, reports), then docx-js scripting (lists, styles, TOC, headers/footers, images, tracked changes). Each task lists difficulty, what to look for, the prompt to paste, and the verify command.

Task 1 β€” Simple generate_docx

Internal Memorandum β˜…β˜†β˜†β˜†β˜†

Probes: basic generate_docx usage, heading + paragraphs structure

Files:

1 new file  (trash/test-memo.docx)

Paste thisCreate a Word document at trash/test-memo.docx using the generate_docx tool. It should be an internal memorandum with: - A heading "MEMORANDUM" - A block of fields: To, From, Date, Subject (each on its own line, bold labels) - 2–3 body paragraphs about Q4 quarterly results (meeting targets, growth highlights, next steps) - Use Arial font throughout Do NOT write a script β€” use the generate_docx tool directly.
What to evaluate
  • Is the file created at the right path?
  • Does it contain a heading and at least 3 paragraphs?
  • Are the To/From/Date/Subject fields present?
  • Is Arial font used?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-memo.docx'); xml=z.read('word/document.xml').decode(); p=xml.count('=5 and h>=1, 'Need >=5 paragraphs and >=1 styled heading'; print('OK β€” memo structure valid')"
Result:
Task 2 β€” Table in Document

Meeting Minutes β˜…β˜…β˜†β˜†β˜†

Probes: generate_docx with table, structured content

Files:

1 new file  (trash/test-minutes.docx)

Paste thisCreate a Word document at trash/test-minutes.docx using generate_docx. Structure: - Heading 1: "Meeting Minutes β€” Project Alpha Kickoff" - Paragraph: date, location, attendees summary - A table with columns: Agenda Item, Owner, Time Allotted, Notes. Fill with 5 agenda items (Project Overview, Timeline Review, Budget Discussion, Risk Assessment, Next Steps). - Paragraph: "Action Items" heading followed by a brief list of next steps. - Use Arial font. Bold the table header row.
What to evaluate
  • Does the document contain a table?
  • Are there 5 agenda rows + a header row?
  • Is the heading present?
  • Are action items listed?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-minutes.docx'); xml=z.read('word/document.xml').decode(); tbl=xml.count('=1 and rows>=5, 'Need >=1 table and >=5 rows'; print('OK β€” meeting minutes contain table')"
Result:
Task 3 β€” Structured Layout

Business Letter β˜…β˜…β˜†β˜†β˜†

Probes: generate_docx layout control, multi-paragraph structure, spacing

Files:

1 new file  (trash/test-letter.docx)

Paste thisCreate a formal business letter at trash/test-letter.docx using generate_docx. Include: - Sender block: "Aperio Inc., 123 Tech Street, San Francisco, CA 94105" - Date line: current date - Recipient block: "Dr. Sarah Chen, Chief AI Officer, NovaCloud Systems" - Salutation: "Dear Dr. Chen," - Body: 2 paragraphs proposing a partnership for integrating Aperio's memory layer into NovaCloud's agent platform - Closing: "Sincerely,", a blank line, then "Lyuben Kikov, CTO, Aperio Inc." - Use a professional layout with appropriate spacing between sections. Use Arial font, 11pt.
What to evaluate
  • Are all letter components present (sender, date, recipient, salutation, body, closing)?
  • Is there visual spacing between sections?
  • Is Arial 11pt used?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-letter.docx'); xml=z.read('word/document.xml').decode(); p=xml.count('=8 and not missing, f'Missing: {missing}'; print('OK β€” letter structure complete')"
Result:
Task 4 β€” Multi-Section Document

Structured Report β˜…β˜…β˜…β˜†β˜†

Probes: generate_docx with multiple sections, heading hierarchy, varied content

Files:

1 new file  (trash/test-report.docx)

Paste thisCreate a structured report at trash/test-report.docx using generate_docx. It must have exactly 3 sections, each with a heading and content: Section 1 β€” "Executive Summary" - A brief overview paragraph describing Aperio as a personal memory layer for AI agents. - A small table with metrics: Active Users, Stored Memories, API Calls (use realistic numbers). Section 2 β€” "Technical Architecture" - 2 paragraphs describing the modular design: SQLite/Postgres backend, MCP integration, plugin system. - Key features listed as plain text lines (not a real list β€” just separate paragraphs with feature names). Section 3 β€” "Roadmap" - 2 paragraphs covering Q1 and Q2 milestones. - A closing note about community contributions. Use Heading 1 for the document title and section headings. Use Arial font throughout.
What to evaluate
  • Are there 3 distinct sections with headings?
  • Does at least one section contain a table?
  • Are there sufficient paragraphs across all sections?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-report.docx'); xml=z.read('word/document.xml').decode(); p=xml.count('=10 and tbl>=1, 'Need >=10 paragraphs and >=1 table'; # Check headings via style refs; import re; heading_styles=len(re.findall(r'=3, 'Need >=3 heading references'; print('OK β€” report has 3+ sections')"
Result:
Task 5 β€” docx-js Scripting: Lists

Proper Bulleted & Numbered Lists β˜…β˜…β˜…β˜†β˜†

Probes: docx-js numbering config, LevelFormat, no unicode bullets

Files:

1 script + 1 output  (trash/create-lists.js β†’ trash/test-lists.docx)

Paste thisWrite a docx-js script trash/create-lists.js that creates trash/test-lists.docx with: Section 1 β€” Bulleted list of 5 Aperio features (Memory Layer, MCP Integration, Code Graph, Wiki, Multi-Provider). Use proper numbering config with LevelFormat.BULLET β€” do NOT use unicode bullet characters. Section 2 β€” Numbered list of 5 setup steps (Clone Repo, Install Dependencies, Configure .env, Run Migrations, Start Server). Use LevelFormat.DECIMAL. Requirements: - Use import syntax with the docx npm package - Set page size explicitly to US Letter - Arial font, 11pt body text - The script must use writeFileSync to save to trash/test-lists.docx - Print the output path to console when done
What to evaluate
  • Does the script use proper numbering.config with LevelFormat?
  • Does the output contain <w:numPr> elements (no unicode bullets)?
  • Are there 5 bullet items and 5 numbered items?
  • Does the script compile and run without errors?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-lists.docx', 'r'); xml=z.read('word/document.xml').decode(); import re; nums=len(re.findall(r'', xml)); unicode_bullets=len(re.findall(r'[\\u2022\\u2023\\u25E6\\u2043]', xml)); print('numPr references:',nums,'Unicode bullets:',unicode_bullets); assert nums>=8, 'Need >=8 numbering references'; assert unicode_bullets==0, 'Has unicode bullets β€” FAIL'; print('OK β€” proper numbering with zero unicode bullets')"
Result:
Task 6 β€” Custom Heading Styles

Styled Document with Custom Heading Levels β˜…β˜…β˜…β˜†β˜†

Probes: docx-js styles config, heading level overrides, font consistency

Files:

1 script + 1 output  (trash/create-styles.js β†’ trash/test-styles.docx)

Paste thisWrite a docx-js script trash/create-styles.js that creates trash/test-styles.docx with custom heading styles: Custom styles: - Heading 1: 28pt, bold, Arial, color: dark blue (003366), spacing before 240 after 120 - Heading 2: 22pt, bold, Arial, color: dark teal (004d40), spacing before 180 after 80 - Normal: 11pt, Arial Document content: - Heading 1: "Project Charter" - 2 paragraphs of body text - Heading 2: "Scope" - 1 paragraph - Heading 2: "Deliverables" - A table with columns: Deliverable, Owner, Deadline (3 rows) - Heading 2: "Budget" - 1 paragraph Run the script with node trash/create-styles.js to produce the output.
What to evaluate
  • Are custom style definitions present in the document XML (styles.xml)?
  • Do heading IDs match "Heading1", "Heading2" for TOC compatibility?
  • Are colors and sizes correctly applied?
  • Does validate.py pass?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-styles.docx'); sx=z.read('word/styles.xml').decode(); dx=z.read('word/document.xml').decode(); h1=sx.count('Heading1'); h2=sx.count('Heading2'); tbl=dx.count('=2 and h2>=2 and tbl>=1, 'Need Heading1/2 style defs and table'; print('OK β€” custom styles present')"

python3 skills/docx/scripts/office/validate.py trash/test-styles.docx
Result:
Task 7 β€” Table of Contents

Multi-Page Document with TOC β˜…β˜…β˜…β˜…β˜†

Probes: TableOfContents, headingStyleRange, outlineLevel, page breaks

Files:

1 script + 1 output  (trash/create-toc.js β†’ trash/test-toc.docx)

Paste thisWrite a docx-js script trash/create-toc.js that creates trash/test-toc.docx β€” a multi-page document with a Table of Contents: Requirements: - Set page size to US Letter - Title page: centered "Aperio Technical Reference", then a PageBreak - Table of Contents using TableOfContents with headingStyleRange: "1-2" and hyperlinks enabled - Followed by these sections, each starting on a new page (PageBreak before each): - **Heading 1 "Introduction"** β€” 2 paragraphs of text - **Heading 2 "Core Architecture"** β€” 1 paragraph - **Heading 2 "Plugin System"** β€” 1 paragraph - **Heading 1 "Installation Guide"** β€” 2 paragraphs - **Heading 2 "Prerequisites"** β€” 1 paragraph - **Heading 2 "Configuration"** β€” 1 paragraph - **Heading 1 "API Reference"** β€” 2 paragraphs - Headings MUST use HeadingLevel values only (not custom strings) - Include outlineLevel in heading paragraph properties (0 for H1, 1 for H2) - Arial font throughout Run with node trash/create-toc.js.
What to evaluate
  • Does the document contain a TOC field?
  • Are headings using HeadingLevel with outlineLevel?
  • Are there at least 3 Heading 1 and 4 Heading 2 references?
  • Does the script compile and run?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-toc.docx'); dx=z.read('word/document.xml').decode(); import re; h1=len(re.findall(r'Heading1', dx)); h2=len(re.findall(r'Heading2', dx)); toc='TableOfContents' in dx; outline=dx.count('outlineLevel'); print('H1 refs:',h1,'H2 refs:',h2,'TOC:',toc,'outlineLevel:',outline); assert h1>=3 and h2>=4 and toc and outline>=5, 'Need >=3 H1, >=4 H2, TOC, and outlineLevel'; print('OK β€” TOC and heading structure valid')"
Result:
Task 8 β€” Headers and Footers

Document with Running Header & Page Numbers β˜…β˜…β˜…β˜†β˜†

Probes: Header/Footer elements, PageNumber, multi-page layout

Files:

1 script + 1 output  (trash/create-header.js β†’ trash/test-header.docx)

Paste thisWrite a docx-js script trash/create-header.js that creates trash/test-header.docx: Layout: - US Letter page size, 1-inch margins - Header (default): Left-aligned text "Aperio β€” Internal Document" in italic, 9pt - Footer (default): Centered "Page X" using PageNumber.CURRENT - Title: "Employee Handbook" (Heading 1, centered) - Paragraph: brief introduction - PageBreak - Heading 2 "Code of Conduct" + 1 paragraph - PageBreak - Heading 2 "Remote Work Policy" + 1 paragraph The header must appear on all pages. Use Arial font. Run with node trash/create-header.js.
What to evaluate
  • Are header and footer elements present in the document XML?
  • Does the footer reference PageNumber?
  • Are page breaks used between sections?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-header.docx'); import re; files=z.namelist(); header_files=[f for f in files if 'header' in f.lower()]; footer_files=[f for f in files if 'footer' in f.lower()]; dx=z.read('word/document.xml').decode(); has_pagebreak='w:br' in dx and 'type=\"page\"' in dx; print('Header files:',header_files,'Footer files:',footer_files,'PageBreak:',has_pagebreak); assert len(header_files)>=1 and len(footer_files)>=1, 'Need header and footer files'; assert has_pagebreak, 'Need page breaks'; print('OK β€” header, footer, and page breaks present')"
Result:
Task 9 β€” Embedded Images

Document with Image β˜…β˜…β˜…β˜…β˜†

Probes: ImageRun, data loading, alt text, type field

Files:

1 script + 1 output  (trash/create-image.js β†’ trash/test-image.docx)

Paste thisWrite a docx-js script trash/create-image.js that creates trash/test-image.docx with an embedded image: Requirements: - US Letter page, 1-inch margins - Title: "Aperio Logo Reference" (Heading 1, centered) - A paragraph: "The official Aperio logo appears below." - An ImageRun embedding public/assets/aperio-logo.png (or any PNG in public/assets/ β€” use fs.readFileSync to load it) - type must be specified (e.g., "png") - transformation: width 300, height auto-proportional - altText with title and description - Below the image: a caption paragraph in italic - A second paragraph: "The Aperio favicon is also available." followed by a second ImageRun embedding the favicon from public/assets/favicon.ico (may need to skip if format unsupported β€” just load a PNG if .ico fails) - Use Arial font throughout Run with node trash/create-image.js.
What to evaluate
  • Is an image relationship present in word/_rels/document.xml.rels?
  • Is the image file inside word/media/ inside the docx?
  • Is the type field specified on ImageRun?
  • Is alt text provided?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-image.docx'); files=z.namelist(); rels=z.read('word/_rels/document.xml.rels').decode(); media=[f for f in files if 'media' in f]; has_image='Image' in rels or 'image/' in rels; print('Media files:',media,'Image in rels:',has_image); assert len(media)>=1 and has_image, 'Need image in media/ and relationship'; print('OK β€” image embedded with relationship')"
Result:
Task 10 β€” XML Editing: Tracked Changes

Unpack β†’ Edit with Tracked Changes + Comment β†’ Repack β˜…β˜…β˜…β˜…β˜…

Probes: unpack/edit/repack pipeline, tracked changes XML, comments

Files:

1 source file + output  (create trash/test-source.docx first β†’ edit β†’ trash/test-tracked.docx)

Paste thisDemonstrate the full docx editing pipeline. Do the following steps in order: Step 1 β€” Create a source document First, use generate_docx to create trash/test-source.docx. It should be a simple contract clause: heading "Service Agreement β€” Section 4: Payment Terms" followed by 3 paragraphs of legalese about payment schedules, late fees, and invoicing. Step 2 β€” Unpack Unpack the source file using the project's unpack script: python3 skills/docx/scripts/office/unpack.py /abs/path/to/trash/test-source.docx /abs/path/to/trash/test-unpacked Step 3 β€” Add tracked changes Edit trash/test-unpacked/word/document.xml to add tracked changes: - Change the payment period from "30 days" to "45 days" using a tracked deletion (<w:del>) of "30" and tracked insertion (<w:ins>) of "45" - Change the late fee from "1.5%" to "2.0%" using the same pattern - Use author="Claude" and a reasonable date Step 4 β€” Add a comment Run python3 skills/docx/scripts/comment.py /abs/path/to/trash/test-unpacked 0 "Needs legal review before signing." Then add <w:commentRangeStart>, <w:commentRangeEnd>, and <w:commentReference> around the first tracked change. Step 5 β€” Repack python3 skills/docx/scripts/office/pack.py /abs/path/to/trash/test-unpacked /abs/path/to/trash/test-tracked.docx --original /abs/path/to/trash/test-source.docx Verify with: python3 skills/docx/scripts/office/validate.py trash/test-tracked.docx --original trash/test-source.docx
What to evaluate
  • Does the packed document contain tracked changes XML (<w:ins> and <w:del>)?
  • Is the comment present in word/comments.xml?
  • Does validate.py --original detect and report the changes correctly?
  • Are the author attributes set to "Claude"?
Verify:
python3 -c "from zipfile import ZipFile; z=ZipFile('trash/test-tracked.docx'); dx=z.read('word/document.xml').decode(); has_ins='
python3 skills/docx/scripts/office/validate.py trash/test-tracked.docx --original trash/test-source.docx
Result:

Per‑Task Scoring Rubric

Apply these five signals to each task after running the verify command. They measure not just "does the file exist" but also "did the model follow the skill's conventions and verify its own work".

Signal0 = fail1 = pass
File created at correct pathwrong path / wrong formatcorrect trash/test-*.docx
Verify command passesred / missing file / Python errorsgreen, zero warnings
Uses correct tool for the taskwrote a script when generate_docx was enoughgenerate_docx for 1–4, docx-js script for 5–9, pipeline for 10
Follows skill conventionsunicode bullets, no page size, missing ImageRun typeproper numbering, explicit page size, correct XML
Model verified its own workclaimed "looks good" without checkingran validate.py or inspected the output

Scorecard

Results fill in automatically as you click the buttons above.

TestResultNotes
1. Memo (generate_docx)β€”
2. Meeting Minutes (Table)β€”
3. Business Letterβ€”
4. Multi-Section Reportβ€”
5. Proper Bulleted/Numbered Listsβ€”
6. Custom Heading Stylesβ€”
7. Table of Contentsβ€”
8. Header/Footer & Page Numbersβ€”
9. Embedded Imagesβ€”
10. Tracked Changes Pipelineβ€”
TOTAL: ____ / 10 passed
Scoring notes:
  • Pass β€” the file exists at the right path, structure is valid, verify passes.
  • Fail β€” verify fails, wrong tool used (script when generate_docx would work), unicode bullets, missing ImageRun type, or script errors.
  • N/A β€” prerequisite not available (e.g., no PNG in assets for Task 9).
  • Tasks 5–10 require the docx npm package (already a dependency).
  • Task 10 requires Python 3 for the unpack/comment/pack/validate scripts β€” verify these scripts exist before scoring.
  • A model that passes Tasks 1–4 but fails 5–10 can use generate_docx but not docx-js scripting.

What the Results Mean

← Your result
9–10/10
Production-ready document generation. The model handles both the simple generate_docx tool and advanced docx-js scripting. It follows conventions (no unicode bullets, proper page size, correct ImageRun type) and can unpack/edit/repack documents with tracked changes. Trust it for professional document work.
← Your result
7–8/10
Strong document skills. Handles generate_docx and most docx-js scripting. May struggle with TOC, images, or tracked changes. Reliable for reports, letters, and basic styled documents.
← Your result
4–6/10
Moderate ability. Good with generate_docx for simple documents. Struggles with docx-js scripting β€” lists may use unicode bullets, styles may be inconsistent. Double-check output before sending to clients.
← Your result
1–3/10
Limited document ability. May produce a basic memo or letter. Not reliable for tables, lists, or any advanced formatting.
← Your result
0/10
Cannot produce working Word documents. This model cannot reliably create or edit .docx files.

What the progression reveals

The task order traces a curve from shallow to deep document-creation understanding:

generate_docx memos (1) β†’ tables in documents (2) β†’ structured letters (3) β†’ multi-section reports (4) β†’ proper numbered lists (5) β†’ custom heading styles (6) β†’ TOC with heading levels (7) β†’ headers/footers with page numbers (8) β†’ embedded images (9) β†’ tracked changes via XML editing (10)

A model that drops off after Task 4 knows generate_docx but not docx-js. One that drops off after Task 7 can script basic docs but not advanced features. A model that passes all 10 understands the full document-creation stack.