dsh-office-kit 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/CAPABILITY.md +147 -68
  2. package/README.md +3 -1
  3. package/assets/skills/excel-live-control/SKILL.md +234 -0
  4. package/assets/skills/excel-live-control/container_tools/live_excel.py +1589 -0
  5. package/assets/skills/excel-live-control/domain_guidance/financial_models.md +86 -0
  6. package/assets/skills/excel-live-control/domain_guidance/healthcare.md +58 -0
  7. package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +53 -0
  8. package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +53 -0
  9. package/assets/skills/excel-live-control/references/office-automation.md +207 -0
  10. package/assets/skills/excel-live-control/references/read_only_qna.md +59 -0
  11. package/assets/skills/excel-live-control/style_guidelines.md +87 -0
  12. package/assets/skills/excel-live-control/workflows/create_workflows.md +78 -0
  13. package/assets/skills/excel-live-control/workflows/edit_workflows.md +72 -0
  14. package/assets/skills/office-documents/SKILL.md +90 -77
  15. package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +86 -0
  16. package/assets/skills/office-documents/ooxml/comments.md +40 -0
  17. package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +66 -0
  18. package/assets/skills/office-documents/ooxml/rels_and_content_types.md +62 -0
  19. package/assets/skills/office-documents/ooxml/tracked_changes.md +53 -0
  20. package/assets/skills/office-documents/references/docx-structure.md +83 -0
  21. package/assets/skills/office-documents/references/template-elicitation.md +49 -0
  22. package/assets/skills/office-documents/references/writing-quality.md +49 -0
  23. package/assets/skills/office-documents/render_docx.py +99 -0
  24. package/assets/skills/office-documents/scripts/a11y_audit.py +201 -0
  25. package/assets/skills/office-documents/scripts/accept_tracked_changes.py +158 -0
  26. package/assets/skills/office-documents/scripts/add_tracked_replacements.py +155 -0
  27. package/assets/skills/office-documents/scripts/append_blocks.py +115 -0
  28. package/assets/skills/office-documents/scripts/apply_template_styles.py +111 -0
  29. package/assets/skills/office-documents/scripts/captions_and_crossrefs.py +109 -0
  30. package/assets/skills/office-documents/scripts/comments_add.py +143 -0
  31. package/assets/skills/office-documents/scripts/comments_apply_patch.py +121 -0
  32. package/assets/skills/office-documents/scripts/comments_extract.py +92 -0
  33. package/assets/skills/office-documents/scripts/comments_strip.py +81 -0
  34. package/assets/skills/office-documents/scripts/content_controls.py +199 -0
  35. package/assets/skills/office-documents/scripts/core_properties.py +131 -0
  36. package/assets/skills/office-documents/scripts/docx_kit.py +594 -0
  37. package/assets/skills/office-documents/scripts/docx_ooxml_patch.py +232 -0
  38. package/assets/skills/office-documents/scripts/docx_table_to_csv.py +106 -0
  39. package/assets/skills/office-documents/scripts/fields_materialize.py +73 -0
  40. package/assets/skills/office-documents/scripts/fields_report.py +66 -0
  41. package/assets/skills/office-documents/scripts/flatten_ref_fields.py +69 -0
  42. package/assets/skills/office-documents/scripts/footnotes_report.py +84 -0
  43. package/assets/skills/office-documents/scripts/google_docs_title_sanitize.py +103 -0
  44. package/assets/skills/office-documents/scripts/heading_audit.py +88 -0
  45. package/assets/skills/office-documents/scripts/images_audit.py +87 -0
  46. package/assets/skills/office-documents/scripts/insert_note.py +133 -0
  47. package/assets/skills/office-documents/scripts/insert_ref_fields.py +97 -0
  48. package/assets/skills/office-documents/scripts/insert_toc.py +91 -0
  49. package/assets/skills/office-documents/scripts/internal_nav.py +153 -0
  50. package/assets/skills/office-documents/scripts/make_fixtures.py +176 -0
  51. package/assets/skills/office-documents/scripts/merge_docx_append.py +246 -0
  52. package/assets/skills/office-documents/scripts/privacy_scrub.py +138 -0
  53. package/assets/skills/office-documents/scripts/redact_docx.py +120 -0
  54. package/assets/skills/office-documents/scripts/render_and_diff.py +108 -0
  55. package/assets/skills/office-documents/scripts/replace_text.py +161 -0
  56. package/assets/skills/office-documents/scripts/section_audit.py +98 -0
  57. package/assets/skills/office-documents/scripts/set_protection.py +99 -0
  58. package/assets/skills/office-documents/scripts/style_lint.py +118 -0
  59. package/assets/skills/office-documents/scripts/style_normalize.py +110 -0
  60. package/assets/skills/office-documents/scripts/table_geometry.py +174 -0
  61. package/assets/skills/office-documents/scripts/watermark_add.py +55 -0
  62. package/assets/skills/office-documents/scripts/watermark_audit_remove.py +74 -0
  63. package/assets/skills/office-documents/scripts/xlsx_to_docx_table.py +124 -0
  64. package/assets/skills/office-documents/tasks/accessibility_a11y.md +45 -0
  65. package/assets/skills/office-documents/tasks/captions_crossrefs.md +49 -0
  66. package/assets/skills/office-documents/tasks/clean_tracked_changes.md +49 -0
  67. package/assets/skills/office-documents/tasks/comments_manage.md +59 -0
  68. package/assets/skills/office-documents/tasks/compare_diff.md +40 -0
  69. package/assets/skills/office-documents/tasks/create_edit.md +107 -0
  70. package/assets/skills/office-documents/tasks/equations.md +59 -0
  71. package/assets/skills/office-documents/tasks/fields_update.md +44 -0
  72. package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +50 -0
  73. package/assets/skills/office-documents/tasks/footnotes_endnotes.md +38 -0
  74. package/assets/skills/office-documents/tasks/forms_content_controls.md +48 -0
  75. package/assets/skills/office-documents/tasks/headings_numbering.md +55 -0
  76. package/assets/skills/office-documents/tasks/images_figures.md +63 -0
  77. package/assets/skills/office-documents/tasks/multi_doc_merge.md +43 -0
  78. package/assets/skills/office-documents/tasks/navigation_internal_links.md +38 -0
  79. package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +45 -0
  80. package/assets/skills/office-documents/tasks/protection_restrict_editing.md +41 -0
  81. package/assets/skills/office-documents/tasks/read_review.md +50 -0
  82. package/assets/skills/office-documents/tasks/redaction_anonymization.md +42 -0
  83. package/assets/skills/office-documents/tasks/sections_layout.md +54 -0
  84. package/assets/skills/office-documents/tasks/style_lint_normalize.md +44 -0
  85. package/assets/skills/office-documents/tasks/tables_spreadsheets.md +64 -0
  86. package/assets/skills/office-documents/tasks/templates_style_packs.md +53 -0
  87. package/assets/skills/office-documents/tasks/toc_workflow.md +39 -0
  88. package/assets/skills/office-documents/tasks/verify_render.md +50 -0
  89. package/assets/skills/office-documents/tasks/watermarks_background.md +35 -0
  90. package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +47 -0
  91. package/assets/skills/office-documents/troubleshooting/run_splitting.md +36 -0
  92. package/assets/skills/office-pdf/SKILL.md +73 -56
  93. package/assets/skills/office-pdf/references/form-fields.md +56 -0
  94. package/assets/skills/office-pdf/references/geometry.md +44 -0
  95. package/assets/skills/office-pdf/references/layout-quality.md +41 -0
  96. package/assets/skills/office-pdf/references/limits.md +58 -0
  97. package/assets/skills/office-pdf/scripts/extract_text.py +172 -0
  98. package/assets/skills/office-pdf/scripts/forms.py +556 -0
  99. package/assets/skills/office-pdf/scripts/metadata.py +161 -0
  100. package/assets/skills/office-pdf/scripts/page_ops.py +198 -0
  101. package/assets/skills/office-pdf/scripts/redact_region.py +347 -0
  102. package/assets/skills/office-pdf/scripts/render_pages.py +207 -0
  103. package/assets/skills/office-pdf/scripts/split_pages.py +155 -0
  104. package/assets/skills/office-pdf/scripts/stamp_overlay.py +199 -0
  105. package/assets/skills/office-pdf/tasks/annotations.md +98 -0
  106. package/assets/skills/office-pdf/tasks/create.md +75 -0
  107. package/assets/skills/office-pdf/tasks/edit-pages.md +71 -0
  108. package/assets/skills/office-pdf/tasks/forms.md +67 -0
  109. package/assets/skills/office-pdf/tasks/read.md +62 -0
  110. package/assets/skills/office-pdf/tasks/redact.md +72 -0
  111. package/assets/skills/office-pdf/tasks/stamp.md +60 -0
  112. package/assets/skills/office-presentations/SKILL.md +141 -87
  113. package/assets/skills/office-presentations/container_tools/add_slides.py +143 -0
  114. package/assets/skills/office-presentations/container_tools/core_properties.py +127 -0
  115. package/assets/skills/office-presentations/container_tools/create_montage.py +133 -0
  116. package/assets/skills/office-presentations/container_tools/inspect_presentation_layout_geometry.py +292 -0
  117. package/assets/skills/office-presentations/container_tools/inspect_presentation_package_integrity.py +164 -0
  118. package/assets/skills/office-presentations/container_tools/native_chart_title_gate.py +151 -0
  119. package/assets/skills/office-presentations/container_tools/native_quantitative_chart_gate.py +206 -0
  120. package/assets/skills/office-presentations/container_tools/native_table_arithmetic_gate.py +219 -0
  121. package/assets/skills/office-presentations/container_tools/ooxml_helpers.py +352 -0
  122. package/assets/skills/office-presentations/container_tools/preview_render.py +382 -0
  123. package/assets/skills/office-presentations/container_tools/render_slides.py +146 -0
  124. package/assets/skills/office-presentations/container_tools/replace_text.py +175 -0
  125. package/assets/skills/office-presentations/container_tools/template_source_fidelity_gate.py +236 -0
  126. package/assets/skills/office-presentations/domain_guidance/finance.md +66 -0
  127. package/assets/skills/office-presentations/recipes/README.md +71 -0
  128. package/assets/skills/office-presentations/recipes/autolayout.md +88 -0
  129. package/assets/skills/office-presentations/recipes/connectors.md +83 -0
  130. package/assets/skills/office-presentations/recipes/images.md +80 -0
  131. package/assets/skills/office-presentations/recipes/master-and-layouts.md +127 -0
  132. package/assets/skills/office-presentations/recipes/native-charts.md +87 -0
  133. package/assets/skills/office-presentations/recipes/rich-text-runs.md +86 -0
  134. package/assets/skills/office-presentations/recipes/speaker-notes.md +65 -0
  135. package/assets/skills/office-presentations/recipes/tables.md +88 -0
  136. package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +71 -0
  137. package/assets/skills/office-presentations/recipes/theme-tokens.md +87 -0
  138. package/assets/skills/office-presentations/references/authoring-workflow.md +65 -0
  139. package/assets/skills/office-presentations/references/finalization.md +63 -0
  140. package/assets/skills/office-presentations/references/native-bullets.md +78 -0
  141. package/assets/skills/office-presentations/references/native-evidence.md +67 -0
  142. package/assets/skills/office-presentations/references/style-guidelines.md +66 -0
  143. package/assets/skills/office-presentations/references/templates.md +76 -0
  144. package/assets/skills/office-presentations/routing/google_slides.md +45 -0
  145. package/assets/skills/office-presentations/tasks/apply-annotations.md +83 -0
  146. package/assets/skills/office-presentations/tasks/charts-tables-notes.md +79 -0
  147. package/assets/skills/office-presentations/tasks/create-deck.md +106 -0
  148. package/assets/skills/office-presentations/tasks/edit-deck.md +93 -0
  149. package/assets/skills/office-presentations/tasks/inspect-and-verify.md +107 -0
  150. package/assets/skills/office-presentations/tasks/template-following.md +132 -0
  151. package/assets/skills/office-presentations/template_following_scripts/check_template_fidelity.py +183 -0
  152. package/assets/skills/office-presentations/template_following_scripts/inspect_template_deck.py +161 -0
  153. package/assets/skills/office-presentations/template_following_scripts/make_contact_sheet.py +118 -0
  154. package/assets/skills/office-presentations/template_following_scripts/prepare_template_starter_deck.py +246 -0
  155. package/assets/skills/office-presentations/template_following_scripts/validate_template_plan.py +192 -0
  156. package/assets/skills/office-spreadsheets/SKILL.md +105 -101
  157. package/assets/skills/office-spreadsheets/container_tools/add_chart.py +243 -0
  158. package/assets/skills/office-spreadsheets/container_tools/add_image.py +114 -0
  159. package/assets/skills/office-spreadsheets/container_tools/append_rows.py +129 -0
  160. package/assets/skills/office-spreadsheets/container_tools/diff_workbooks.py +313 -0
  161. package/assets/skills/office-spreadsheets/container_tools/inspect_workbook.py +405 -0
  162. package/assets/skills/office-spreadsheets/container_tools/recalc_gate.py +287 -0
  163. package/assets/skills/office-spreadsheets/container_tools/set_cells.py +142 -0
  164. package/assets/skills/office-spreadsheets/container_tools/sheet_ops.py +141 -0
  165. package/assets/skills/office-spreadsheets/container_tools/style_cells.py +140 -0
  166. package/assets/skills/office-spreadsheets/recipes/charts.md +66 -0
  167. package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +69 -0
  168. package/assets/skills/office-spreadsheets/recipes/data-tables.md +58 -0
  169. package/assets/skills/office-spreadsheets/recipes/named-ranges.md +41 -0
  170. package/assets/skills/office-spreadsheets/recipes/number-formats.md +72 -0
  171. package/assets/skills/office-spreadsheets/recipes/sparklines.md +43 -0
  172. package/assets/skills/office-spreadsheets/references/charts.md +63 -0
  173. package/assets/skills/office-spreadsheets/references/domain/financial-models.md +40 -0
  174. package/assets/skills/office-spreadsheets/references/domain/healthcare.md +22 -0
  175. package/assets/skills/office-spreadsheets/references/domain/marketing.md +28 -0
  176. package/assets/skills/office-spreadsheets/references/domain/research.md +22 -0
  177. package/assets/skills/office-spreadsheets/references/formula-patterns.md +78 -0
  178. package/assets/skills/office-spreadsheets/references/style-guidelines.md +69 -0
  179. package/assets/skills/office-spreadsheets/references/workbook-structure.md +60 -0
  180. package/assets/skills/office-spreadsheets/routing/google-sheets.md +36 -0
  181. package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +37 -0
  182. package/assets/skills/office-spreadsheets/tasks/annotations.md +51 -0
  183. package/assets/skills/office-spreadsheets/tasks/create-workbook.md +66 -0
  184. package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +38 -0
  185. package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +69 -0
  186. package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +38 -0
  187. package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +57 -0
  188. package/assets/skills/shared/annotation-recipes.md +252 -0
  189. package/assets/skills/shared/check_runtime.py +260 -0
  190. package/assets/skills/shared/common-workflow.md +139 -0
  191. package/assets/skills/shared/scripts/ensure_raster_image.py +187 -0
  192. package/dist/client.js +4 -4
  193. package/dist/client.js.map +1 -1
  194. package/dist/index.js +246 -89
  195. package/package.json +1 -1
  196. package/postinstall.mjs +92 -82
  197. package/python/office_cli.py +213 -254
@@ -0,0 +1,78 @@
1
+ # Creating content in a live workbook
2
+
3
+ The user is watching, so the order you do things in is visible. Plan on paper first, then
4
+ make a small number of writes.
5
+
6
+ ## 1. Decide what is actually being created
7
+
8
+ Before you write a cell, you should be able to answer:
9
+
10
+ - **Who reads it, and what decision does it support?** A one-page summary for a committee
11
+ and a working model for an analyst are different sheets.
12
+ - **What are the outputs?** Name them. Each output is a number with a label, a period and
13
+ a unit.
14
+ - **What are the inputs?** Name them, with their sources. Inputs nobody will update are
15
+ decoration.
16
+ - **What is calculated in between?** The steps between input and output are what a reviewer
17
+ audits; if you cannot name them, the model is not designed yet.
18
+ - **What would make it wrong?** A check or a reconciliation, even one line: totals tie,
19
+ parts sum to the whole, cash ends at the right balance.
20
+
21
+ If the request leaves two of these open, ask one short question rather than guessing —
22
+ a live edit is expensive to unpick.
23
+
24
+ ## 2. Where it goes
25
+
26
+ - Roles, not a fixed tab count: inputs, assumptions, calculations, outputs. A small sheet
27
+ can carry several roles; a large model separates them.
28
+ - Outputs at the left of the tab strip, workings in the middle, inputs at the right; a
29
+ check/audit tab last if the model warrants one. Do not add a Checks tab to a simple
30
+ sheet — a labelled verification row is enough.
31
+ - Keep inputs next to the calculations they feed when the model is small; move them to a
32
+ dedicated input sheet only when more than one sheet consumes them.
33
+ - Calculate once, link everywhere else. Two cells computing the same number is a future
34
+ disagreement.
35
+ - Insights (a short comment or a highlighted conclusion) go next to the result they
36
+ explain, not in a separate "insights" area.
37
+
38
+ **Adding a tab is not an operation of this skill.** The tool writes into sheets that
39
+ already exist. If the job needs a new sheet, ask the user to insert one (Right-click a tab
40
+ → Insert), or use the file route in `../../office-spreadsheets/SKILL.md` and tell them to
41
+ reopen. Do not repurpose an existing sheet as scratch space.
42
+
43
+ ## 3. Write it
44
+
45
+ ```
46
+ info # confirm workbook, sheet, used range
47
+ write_range --sheet "Inputs" --range B4:C9 --data-file inputs.json
48
+ set_formula --sheet "Inputs" --range D4:D9 --formula "=B4*C4" # fills down with relative rows
49
+ style_range --sheet "Inputs" --range B3:D3 --style '{"bold":true,"border":"outline"}'
50
+ recalc
51
+ read_range --sheet "Inputs" --range B3:D9 --formulas
52
+ ```
53
+
54
+ - One `write_range` per block with its real shape. The array is rows × columns; do not pad
55
+ with empty strings to make it rectangular — use `null` for a genuinely empty cell.
56
+ - Write the labels and the units with the numbers. A block of bare numbers is not done.
57
+ - Default formats in the write step, not afterwards: `number_format` in `style_range`
58
+ applied to the whole block is one call and keeps every cell consistent.
59
+ - Formulas as text starting with `=`, absolute where they must stay put (`$C$4`), relative
60
+ where the fill should walk (`D5`). Test one cell before filling a column.
61
+ - If the sheet already has content, check the used range first and write beside it, not
62
+ over it.
63
+
64
+ ## 4. Check it, then say what you did
65
+
66
+ - `read_range --formulas` over everything you wrote; `errors` must be empty.
67
+ - `recalc`, then read the outputs again — a formula that never calculated proves nothing.
68
+ - `info` if you added tables or charts, to confirm they landed on the sheet you meant.
69
+ - Report the ranges and the state of the document (unsaved, or saved where). See the
70
+ Delivery section of `../SKILL.md`.
71
+
72
+ ## 5. Sizing and layout
73
+
74
+ - Set column widths after the content exists, from the widest formatted value, then
75
+ re-read with `--display` to catch `###`.
76
+ - Wrap long text labels instead of widening a column to half the screen.
77
+ - Helper calculations go in their own block or sheet, labelled, not buried between two
78
+ output rows.
@@ -0,0 +1,72 @@
1
+ # Editing a workbook the user already built
2
+
3
+ The existing workbook is the reference. Its structure, formula style, formats, labels and
4
+ navigation are what the user expects to keep seeing; your job is to make one change that
5
+ looks like it was always there.
6
+
7
+ ## Read the ground first
8
+
9
+ Nothing below works without this step, and it is cheap:
10
+
11
+ 1. `info` — workbook name and path, `saved` flag (unsaved work in progress!), sheets,
12
+ used ranges, tables, charts, pivots, protection.
13
+ 2. `read_range --formulas` over the block you are about to touch **and its neighbours**.
14
+ You need to know the pattern a formula follows before you extend it.
15
+ 3. `read_range --display` when the change is formatting — it tells you the current number
16
+ format's effect, not just the stored value.
17
+ 4. Read the labels around the block: period, unit, actual/forecast. A number is only
18
+ meaningful with its label, and your new row must match the surrounding convention.
19
+
20
+ If the target block holds values you cannot explain from the request, stop and ask. On a
21
+ live document, "I thought it was empty" is how an analyst's afternoon disappears.
22
+
23
+ ## Rules of the edit
24
+
25
+ - **Change the cells the request names, and the formulas those cells feed.** A changed
26
+ input propagates on its own; do not hand-edit downstream totals.
27
+ - **Do not add, remove, rename, reorder or split sheets/tabs** unless the request says so
28
+ or the change genuinely cannot be expressed otherwise (a new output with no home).
29
+ - **Preserve everything you did not create**: other sheets, formulas, named ranges,
30
+ comments, protection, hidden or grouped rows, freeze panes (user-set), native tables and
31
+ their structured references, pivot sources, shared formulas, filters, external links,
32
+ `INDIRECT` routing, calculation settings.
33
+ - **Never flatten formulas to values.** Not to "simplify", not to "fix" a display problem.
34
+ - **Extend, do not replace.** When a row or column is added to a block that has a table,
35
+ conditional format or chart on it, extend the object to cover the new cells instead of
36
+ building a parallel object beside it. `ListObject.Resize` and the chart's
37
+ `SetSourceData` are the tools.
38
+ - **Small visual fixes stay local.** Widen the one column that clips. Do not autofit the
39
+ sheet, do not restyle a header because it is not your default style.
40
+ - **Match the existing formula conventions** — anchoring style, `SUMIFS` vs `SUMPRODUCT`,
41
+ rounding, the workbook's error handling. A locally "better" formula that reads
42
+ differently is a maintenance cost the user did not ask for.
43
+ - **Pre-existing errors are not yours to fix.** Report them with the cell and the formula
44
+ and ask. Silently repairing a `#REF!` can change a number the user relies on.
45
+
46
+ ## Doing it
47
+
48
+ ```
49
+ read_range --sheet "Build" --range D5:F12 --formulas # understand the pattern
50
+ write_range --sheet "Build" --range D13:F13 --data '[...]' # the new row only
51
+ set_formula --sheet "Build" --range G5:G13 --formula "=SUM(D5:F5)"
52
+ style_range --sheet "Build" --range D13:F13 --style '{"number_format":"#,##0"}'
53
+ recalc
54
+ read_range --sheet "Build" --range D5:G13 --formulas # prove it
55
+ ```
56
+
57
+ - Keep writes to the named rectangle; `--clear` only on a range whose previous contents
58
+ you have read and can restore.
59
+ - Style by copying the neighbouring block's codes: read a cell you want to match, mirror
60
+ its `number_format`, and apply it to the new cells. Do not invent a new format for one
61
+ row.
62
+ - If a formula in the new cell must differ from the pattern (a different anchor, a
63
+ one-off), say why in the reply — a reviewer will find it.
64
+
65
+ ## When you are done
66
+
67
+ - `read_range --formulas` over every cell you changed and its immediate neighbours.
68
+ - `recalc` after formulas, then re-read the outputs that depend on them.
69
+ - `info` if tables, charts or pivots were extended, to confirm the objects still exist and
70
+ cover the new cells.
71
+ - Report: sheet, exact ranges, cell counts, and what the document's saved state is. If the
72
+ edit touched a formula graph, say which outputs were affected.
@@ -1,101 +1,114 @@
1
1
  ---
2
- description: Create, inspect, edit, and render Word .docx documents with the bundled Office helper CLI.
2
+ description: Build, inspect, revise, and visually verify Word .docx files using the Office helper CLI and the bundled XML scripts.
3
3
  ---
4
4
 
5
5
  # Documents (.docx)
6
6
 
7
- Create, read, edit, and render local Word documents. This skill produces Office Open XML files; it does not edit Google Docs and does not use the artifact-tool runtime.
7
+ A `.docx` is a zip of XML parts: `word/document.xml` holds the body, and headers, footers, footnotes, comments, styles and numbering live beside it. Two routes reach every part of it:
8
+
9
+ - **Fast path** — the helper CLI inspects, renders and creates: `docx create`, `docx read`, `docx render`. It performs no in-place mutation.
10
+ - **Structural path** — `scripts/*.py` in this skill do all editing: replace text, append blocks, set properties, and everything structural — comments, tracked changes, fields, protection, watermarks.
11
+
12
+ Pick the cheapest route that produces the structure the user asked for, then verify it visually. Never invent content, and never deliver a file you have not looked at.
8
13
 
9
14
  ## Before any file work
10
15
 
11
16
  1. Call the `office_status` tool.
12
- 2. Use the `python` and `cli` values from the `## Office runtime` JSON block at the end of this file. These are verified absolute paths; do not assume `python` or `soffice` is on `PATH`.
13
- 3. If the runtime block says no compatible Python was found, stop and tell the user to run the package install/rebuild step. Do not fabricate a document or claim success.
17
+ 2. Read the `## Office runtime` block at the end of this file for the verified `python`, `cli`, `skill` and `shared` paths.
18
+ 3. If that block says no runtime is available, stop and give the user the `node "..."` remedy command it names, then call `office_status` again. Do not fake a document or claim success.
14
19
 
15
- Quote every path. Windows paths and paths containing spaces, Chinese characters, or `&` are supported.
20
+ Quote every path. Spaces, non-ASCII names and `&` are normal on Windows.
16
21
 
17
- ## Create
22
+ ## Delivery
18
23
 
19
- Write a JSON spec in the user's workspace, then run:
24
+ Always hand the finished file to the user with the `present` tool, then summarise in one sentence what changed. A bare path is not delivery: the chat transcript renders `.docx`/`.pptx`/`.xlsx`/`.pdf` links as "二进制文件,无法显示改动" and the user cannot open them.
20
25
 
21
- ```bash
22
- "<python>" "<cli>" docx create --spec "<spec.json>" --out "<output.docx>"
23
- ```
26
+ - Creating a file: write it into the user's workspace, verify it, then `present`.
27
+ - Editing an existing file: never overwrite the original. Write `<original>-edited.<ext>` (or a name the user asked for), verify it, `present` it, and state both paths.
24
28
 
25
- Minimal spec:
26
-
27
- ```json
28
- {
29
- "title": "Quarterly Report",
30
- "subtitle": "Internal review",
31
- "author": "Prepared by DSH Office Suite",
32
- "header": "Confidential",
33
- "footer": "Page 1",
34
- "page_size": "A4",
35
- "orientation": "portrait",
36
- "blocks": [
37
- { "type": "heading", "level": 1, "text": "Executive summary" },
38
- { "type": "paragraph", "text": "Revenue grew 18.4% year over year." },
39
- { "type": "bullets", "items": ["Renewal rate 92%", "42 new customers"] },
40
- { "type": "table", "headers": ["Metric", "Q3"], "rows": [["Revenue", "12,480,000"], ["Gross margin", "71.2%"]] },
41
- { "type": "equation", "latex": "\\frac{a^2+b^2}{c^2}" },
42
- { "type": "page_break" }
43
- ]
44
- }
45
- ```
29
+ ## Annotations
46
30
 
47
- Supported block types: `heading` (`level` 0–9), `paragraph` (`bold`, `italic`, `size`, `color`, `align`, `style`), `bullets`, `numbered`, `table` (`headers`, `rows`, optional `style`, default `Table Grid`), `image` (`path`, optional `width` in inches), `equation` (`latex`), `quote`, `page_break`, `spacer`. Page fields: `page_size` (`Letter` or `A4`), `orientation`, margins in inches (`top_margin`, `bottom_margin`, `left_margin`, `right_margin`).
31
+ The user may reply with an `office-annotations` block: `[{ page, text, requirement, region: { left, top, width, height } }]`. `region` is normalised 0–1 against the rendered preview page the user drew on; `requirement` is free-form natural language. Treat it as a change request, not as editor state: locate what the region covers, apply the smallest edit that satisfies `requirement`, re-render, and confirm the region now looks right.
48
32
 
49
- LaTeX equations are converted to native OMML. Simple fractions, superscripts, subscripts, roots, and Greek symbols work; unsupported LaTeX silently falls back to italic text and increments `equation_fallbacks`. Check that counter when the equation matters.
33
+ When the payload cannot be mapped to a concrete object (the region is empty or the file has no geometry), do not guess silently — say what you could not locate.
50
34
 
51
- ## Read
35
+ For `.docx`, `page` is the page of the *rendered PDF preview*, not a Word page. Use `text` (and the paragraph text near it) to locate the target; the region is a hint for near-misses only. A region that lands on a table row, a caption or a header is ambiguous — state which object you picked before editing.
52
36
 
53
- ```bash
54
- "<python>" "<cli>" docx read --input "<file.docx>"
55
- ```
56
-
57
- Returns title, author, paragraphs with styles, headings, tables, image count, equation count, and page dimensions. Use it to verify a file you did not create.
58
-
59
- ## Edit
37
+ ## Verify
60
38
 
61
- Copy-then-edit: the CLI never modifies the input in place.
62
-
63
- ```bash
64
- "<python>" "<cli>" docx edit --input "<file.docx>" --spec "<edit.json>" --out "<file-edited.docx>"
65
- ```
66
-
67
- ```json
68
- {
69
- "replace": [{ "find": "37 customers", "replace": "42 customers" }],
70
- "blocks": [{ "type": "heading", "level": 1, "text": "Appendix" }],
71
- "core": { "title": "Quarterly Report (final)", "author": "Finance" }
72
- }
73
- ```
74
-
75
- `replace` works on runs and falls back to rebuilding a paragraph when the text spans runs. It cannot reliably edit headers/footers, comments, tracked changes, content controls, or fields; those are unsupported (see below). Adding blocks appends them at the end of the body.
76
-
77
- ## Render and verify
39
+ Rendering is the only proof that a document looks right.
78
40
 
79
41
  ```bash
80
42
  "<python>" "<cli>" docx render --input "<file.docx>" --out-dir "<render-dir>"
81
43
  ```
82
44
 
83
- The renderer prefers Microsoft Word COM on Windows and LibreOffice otherwise. It writes a PDF and one PNG per page. Open the PNGs with your image-viewing tool and inspect: title/heading hierarchy, table geometry, page breaks, missing glyphs, overflowing text, header/footer, and equation rendering.
84
-
85
- If no renderer is available, report "not visually verified" and offer the file. Do not claim layout quality you did not see.
86
-
87
- ## Quality rules
88
-
89
- - Write real content from the user's request; never invent metrics, citations, or names.
90
- - Use one consistent heading hierarchy. Do not skip levels.
91
- - Keep tables narrow enough for the page; abbreviate long headers.
92
- - Verify a non-Latin script renders in the chosen fonts before delivering.
93
- - Prefer native Word structures (headings, tables, lists) over hand-positioned text.
94
-
95
- ## Not supported
96
-
97
- - Google Docs / Google Drive import or native online editing.
98
- - Comments, tracked changes, redlining, accept/reject workflows.
99
- - Existing headers/footers, footnotes, TOC fields, cross-references, content controls, protection, watermarks, redaction.
100
- - In-place editing, macros, encrypted documents, `.doc` input.
101
- - Word-perfect pagination or template cloning. `render` is a fidelity check, not a guarantee that Word and LibreOffice paginate identically.
45
+ The command writes a PDF plus one PNG per page and prints the paths. Open each PNG with `read_image` and check: heading hierarchy, table width and cell wrapping, page breaks, header/footer, clipped or overflowing text, missing glyphs (dashes, CJK, symbols), equation rendering, and caption placement.
46
+
47
+ - Iterate until the pages look correct, then deliver. "It parses" is not verification.
48
+ - If the runtime reports no renderer (none of Microsoft Word, WPS Writer, or LibreOffice), ask the user to install one, or fall back to `docx read` plus the audit scripts. Say plainly that layout was not visually verified — do not describe a page you did not see.
49
+ - After a script edits XML, re-render. A package can stay valid while the page it produces is broken.
50
+
51
+ ## Choosing a route
52
+
53
+ | Job | Fast path | Structural path |
54
+ |---|---|---|
55
+ | New document from scratch | `docx create --spec` | `python-docx` snippet in `tasks/create_edit.md` |
56
+ | Replace or append text and blocks | — | `scripts/replace_text.py`, `scripts/append_blocks.py` |
57
+ | Document properties | — | `scripts/core_properties.py` |
58
+ | Read structure | `docx read` | `scripts/docx_kit.py text`, `style_lint`, audits |
59
+ | Comments, tracked changes | — | `scripts/comments_*.py`, `scripts/*tracked*.py` |
60
+ | Fields, TOC, cross-references | — | `scripts/insert_toc.py`, `insert_ref_fields.py`, `fields_*.py` |
61
+ | Footnotes, endnotes | — | `scripts/insert_note.py`, `footnotes_report.py` |
62
+ | Tables, layout geometry | `docx create` table block | `scripts/table_geometry.py`, `docx_table_to_csv.py` |
63
+ | Styles, templates | — | `scripts/style_*.py`, `apply_template_styles.py` |
64
+ | Protection, watermarks, privacy | — | `scripts/set_protection.py`, `watermark_*.py`, `privacy_scrub.py`, `redact_docx.py` |
65
+
66
+ Where no verb exists, the fallback is the listed script or a short `python-docx`/`lxml` snippet. Both are runnable with the runtime `python`; neither needs a new dependency.
67
+
68
+ ## Task index
69
+
70
+ | Task | Read | Main tool |
71
+ |---|---|---|
72
+ | Create or edit a document | `tasks/create_edit.md` | CLI create, `replace_text.py`, `append_blocks.py`, `core_properties.py` |
73
+ | Read and review a file | `tasks/read_review.md` | CLI read, `docx_kit.py text` |
74
+ | Comments | `tasks/comments_manage.md` | `comments_add/extract/apply_patch/strip.py` |
75
+ | Tracked changes | `tasks/clean_tracked_changes.md` | `accept_tracked_changes.py`, `add_tracked_replacements.py` |
76
+ | Fields and updates | `tasks/fields_update.md` | `fields_report.py`, `fields_materialize.py` |
77
+ | Table of contents | `tasks/toc_workflow.md` | `insert_toc.py`, `fields_*.py` |
78
+ | Captions and cross-references | `tasks/captions_crossrefs.md` | `captions_and_crossrefs.py`, `insert_ref_fields.py` |
79
+ | Navigation links | `tasks/navigation_internal_links.md` | `internal_nav.py` |
80
+ | Footnotes and endnotes | `tasks/footnotes_endnotes.md` | `insert_note.py`, `footnotes_report.py` |
81
+ | Headings and numbering | `tasks/headings_numbering.md` | `heading_audit.py` |
82
+ | Tables | `tasks/tables_spreadsheets.md` | `table_geometry.py`, `docx_table_to_csv.py`, `xlsx_to_docx_table.py` |
83
+ | Images and figures | `tasks/images_figures.md` | `images_audit.py` |
84
+ | Sections and page setup | `tasks/sections_layout.md` | `section_audit.py` |
85
+ | Styles | `tasks/style_lint_normalize.md` | `style_lint.py`, `style_normalize.py` |
86
+ | Templates | `tasks/templates_style_packs.md` | `apply_template_styles.py`, `references/template-elicitation.md` |
87
+ | Accessibility | `tasks/accessibility_a11y.md` | `a11y_audit.py` |
88
+ | Content controls | `tasks/forms_content_controls.md` | `content_controls.py` |
89
+ | Editing protection | `tasks/protection_restrict_editing.md` | `set_protection.py` |
90
+ | Watermarks | `tasks/watermarks_background.md` | `watermark_add.py`, `watermark_audit_remove.py` |
91
+ | Privacy and metadata | `tasks/privacy_scrub_metadata.md` | `privacy_scrub.py` |
92
+ | Redaction | `tasks/redaction_anonymization.md` | `redact_docx.py` |
93
+ | Merging documents | `tasks/multi_doc_merge.md` | `merge_docx_append.py` |
94
+ | Comparing versions | `tasks/compare_diff.md` | `render_and_diff.py` |
95
+ | Equations | `tasks/equations.md` | CLI `equation` block |
96
+ | Visual verification | `tasks/verify_render.md` | `render_docx.py` (skill root) |
97
+ | Fixtures and edge cases | `tasks/fixtures_edge_cases.md` | `make_fixtures.py` |
98
+
99
+ ## Document defaults
100
+
101
+ - Letter 8.5×11 portrait (A4 when the user or template says so), 1in margins, body 11–12pt, single column.
102
+ - Black headings and body text; colour only for deliberate emphasis, links and chart series.
103
+ - Tables: light grey `#D9D9D9` borders, a bold header row, `w:tblHeader` so the header repeats across pages, no vertical merges in wide tables.
104
+ - No decorative callout boxes, drop shadows or coloured sidebars. Structure comes from headings, lists and tables.
105
+ - Captions sit under figures and above tables, in the `Caption` style, and stay with their object.
106
+ - Prefer native structures — heading styles, real lists, real tables, OMML equations — over hand-positioned runs, because the next edit depends on that structure.
107
+
108
+ ## Writing quality
109
+
110
+ Write the content the user asked for, in plain sentences, without filler. `references/writing-quality.md` holds the checklist; `references/docx-structure.md` explains which package part each feature lives in before you touch XML.
111
+
112
+ ## Shared workflow
113
+
114
+ Cross-format habits, the review loop and how to read annotation payloads live in `"<shared>/common-workflow.md"` and `"<shared>/annotation-recipes.md"`; read them when the job spans more than one Office format.
@@ -0,0 +1,86 @@
1
+ # End-to-end smoke test
2
+
3
+ A short job that touches creation, inspection, structural changes and verification. Run it once after a runtime change, or as a template for "is this environment healthy".
4
+
5
+ ```bash
6
+ PY="<python>"; CLI="<cli>"; S="<skill>/scripts"; R="<skill>"; W="/tmp/docx-smoke"
7
+ mkdir -p "$W"
8
+ ```
9
+
10
+ ## 1. Create a document
11
+
12
+ ```bash
13
+ cat > "$W/spec.json" <<'JSON'
14
+ {
15
+ "title": "Smoke Test",
16
+ "author": "Runtime Check",
17
+ "page_size": "Letter",
18
+ "header": "Smoke test",
19
+ "blocks": [
20
+ { "type": "paragraph", "text": "This file exercises the DOCX path end to end." },
21
+ { "type": "paragraph", "text": "[[TOC]]" },
22
+ { "type": "heading", "level": 1, "text": "Findings" },
23
+ { "type": "paragraph", "text": "Revenue grew 18% year over year." },
24
+ { "type": "bullets", "items": ["Hardware flat", "Services up"] },
25
+ { "type": "table", "headers": ["Region", "Q1", "Q2"], "rows": [["North", "10", "12"], ["South", "8", "9"]], "style": "Table Grid" },
26
+ { "type": "equation", "latex": "E = mc^2" }
27
+ ]
28
+ }
29
+ JSON
30
+ "$PY" "$CLI" docx create --spec "$W/spec.json" --out "$W/base.docx"
31
+ ```
32
+
33
+ Expect `ok: true` and non-zero `headings`, `tables`, `equations`.
34
+
35
+ ## 2. Inspect
36
+
37
+ ```bash
38
+ "$PY" "$CLI" docx read --input "$W/base.docx"
39
+ "$PY" "$S/docx_kit.py" parts "$W/base.docx"
40
+ "$PY" "$S/section_audit.py" "$W/base.docx"
41
+ "$PY" "$S/style_lint.py" "$W/base.docx"
42
+ ```
43
+
44
+ Expect the sections, the parts list to include `word/document.xml`, Letter 8.5×11 portrait, and an empty style-lint `counts`.
45
+
46
+ ## 3. Change it structurally
47
+
48
+ ```bash
49
+ "$PY" "$S/replace_text.py" --input "$W/base.docx" --out "$W/replaced.docx" \
50
+ --find "Revenue grew 18%" --replace "Revenue climbed 21%" --require-all
51
+ "$PY" "$S/captions_and_crossrefs.py" "$W/replaced.docx" "$W/captioned.docx" --tables --figures --bookmarks
52
+ "$PY" "$S/insert_toc.py" "$W/captioned.docx" --placeholder "[[TOC]]" --out "$W/with-toc.docx"
53
+ ```
54
+
55
+ `replace_text.py` prints `misses: []`; captions report one table caption; the TOC step reports whether the placeholder was found.
56
+
57
+ ## 4. Audit
58
+
59
+ ```bash
60
+ "$PY" "$S/heading_audit.py" "$W/with-toc.docx"
61
+ "$PY" "$S/a11y_audit.py" "$W/with-toc.docx" --out_json "$W/a11y.json"
62
+ "$PY" "$S/fields_report.py" "$W/with-toc.docx"
63
+ "$PY" "$S/table_geometry.py" "$W/with-toc.docx"
64
+ ```
65
+
66
+ Audits may exit 1 with findings — that is a report, not a failure of the environment. Every finding should be explainable.
67
+
68
+ ## 5. Verify visually
69
+
70
+ ```bash
71
+ "$PY" "$R/render_docx.py" "$W/with-toc.docx" --output_dir "$W/render" --dpi 150
72
+ ```
73
+
74
+ Then open each PNG with `read_image`. Without a renderer the command exits 3 with `no_renderer`; that is the expected result on a machine with neither LibreOffice nor Word, and the rest of the test still stands.
75
+
76
+ ## 6. Deliver
77
+
78
+ Copy the final file into the user's workspace, `present` it, and state what changed in one sentence. Never present a temp path.
79
+
80
+ ## Teardown
81
+
82
+ ```bash
83
+ rm -rf "$W"
84
+ ```
85
+
86
+ Nothing under the workspace should be left behind from a smoke test.
@@ -0,0 +1,40 @@
1
+ # Comments in the package
2
+
3
+ A comment is three pieces that must agree: `word/comments.xml` holds the content, `word/document.xml` holds a range marking which text is discussed, and the relationship plus content-type override make the part exist at all.
4
+
5
+ ## The markup
6
+
7
+ ```xml
8
+ <w:commentRangeStart w:id="1"/>
9
+ <w:r><w:t>the sentence under discussion</w:t></w:r>
10
+ <w:commentRangeEnd w:id="1"/>
11
+ <w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr>
12
+ <w:commentReference w:id="1"/></w:r>
13
+ ```
14
+
15
+ ```xml
16
+ <w:comment w:id="1" w:author="Reviewer" w:date="2026-10-21T00:00:00Z" w:initials="R">
17
+ <w:p><w:r><w:t>Please double-check this number.</w:t></w:r></w:p>
18
+ </w:comment>
19
+ ```
20
+
21
+ Rules that matter in practice:
22
+
23
+ - `w:id` must be unique across comments **and** match in all three places. A range start without an end leaves Word showing a comment with no anchor; an end without a start can make the file refuse to open.
24
+ - The comment reference run belongs at the end of the range, not somewhere else in the paragraph.
25
+ - `word/comments.xml` needs an override in `[Content_Types].xml` and a relationship from `word/document.xml`; without both, the part is ignored or the file is corrupt.
26
+ - The file's root has `mc:Ignorable` listing `w14`/`w15` etc.; a `w15:done` attribute (the "resolved" flag) is only legal when those namespaces are declared.
27
+
28
+ ## Resolved versus deleted
29
+
30
+ `w15:done="1"` on the `w:comment` keeps the comment in the file and shows it as resolved. Removing the comment is a different operation: delete the `w:comment`, both range markers and the reference run. Resolving hides it from the default pane; it does not remove the text from the file.
31
+
32
+ ## Where comments hide
33
+
34
+ - Replies are comments too, linked by `w15:paraIdParent`; a strip that removes the parent leaves an orphan.
35
+ - Anchors can sit in headers, footnotes and text boxes as well as the body.
36
+ - A comment deleted in Word leaves no trace; a comment whose range was deleted may remain in `comments.xml` with nothing anchoring it. That is why extraction reports anchors: a comment with empty anchored text is evidence of drift.
37
+
38
+ ## Working from the scripts
39
+
40
+ `comments_extract.py` reads the pairing and prints anchored text per comment; `comments_add.py` writes all three pieces; `comments_apply_patch.py` edits content and the resolved flag; `comments_strip.py` removes every trace and the part itself. Use `docx_kit.py xml '<file.docx>' word/comments.xml` when you need to see the raw part.
@@ -0,0 +1,66 @@
1
+ # Hyperlinks and fields
2
+
3
+ A hyperlink and a field are both "a run that looks like text but is a pointer", and both break in the same way: the visible result is cached, so editing the text does not update anything.
4
+
5
+ ## Hyperlinks
6
+
7
+ ```xml
8
+ <w:hyperlink r:id="rId7">
9
+ <w:r><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t>the report</w:t></w:r>
10
+ </w:hyperlink>
11
+ ```
12
+
13
+ - The target is a relationship in `word/_rels/document.xml.rels` with `TargetMode="External"` for a URL, or a bare relative path for a file inside the package.
14
+ - An internal link uses `w:anchor="bookmarkName"` and no relationship at all.
15
+ - `w:hyperlink` is a wrapper around runs; a link that spans paragraphs is not legal — put one link per paragraph.
16
+
17
+ A link whose relationship is missing renders as blue underlined text that goes nowhere. That is also what a copy-paste between documents produces.
18
+
19
+ ## Simple fields
20
+
21
+ ```xml
22
+ <w:fldSimple w:instr=" REF tbl1 \h ">
23
+ <w:r><w:t>Table 1</w:t></w:r>
24
+ </w:fldSimple>
25
+ ```
26
+
27
+ The `w:t` inside is a cache, not the truth. Change the text and the next field update overwrites it.
28
+
29
+ ## Complex fields
30
+
31
+ ```xml
32
+ <w:r><w:fldChar w:fldCharType="begin"/></w:r>
33
+ <w:r><w:instrText xml:space="preserve"> TOC \o "1-3" \h \z \u </w:instrText></w:r>
34
+ <w:r><w:fldChar w:fldCharType="separate"/></w:r>
35
+ <w:r><w:t>Cached entries go here</w:t></w:r>
36
+ <w:r><w:fldChar w:fldCharType="end"/></w:r>
37
+ ```
38
+
39
+ The begin/instrText/separate/result/end sequence must stay in that order inside one paragraph. Word shows the result between `separate` and `end`, or recomputes on open when `w:updateFields` is set in `settings.xml`:
40
+
41
+ ```xml
42
+ <w:updateFields w:val="true"/>
43
+ ```
44
+
45
+ Setting it makes Word prompt or update on open. A viewer that ignores it (a PDF export, some libraries) keeps showing the cache — which is why a document delivered as PDF can show "1" for every page number.
46
+
47
+ ## Which field for which job
48
+
49
+ | Need | Instruction |
50
+ |---|---|
51
+ | Page number | `PAGE` / `NUMPAGES` |
52
+ | Table or figure number | `SEQ Table \* ARABIC` |
53
+ | Reference to a number | `REF tbl1 \h` |
54
+ | Table of contents | `TOC \o "1-3" \h \z \u` |
55
+ | Document title from properties | `TITLE` / `AUTHOR` |
56
+
57
+ ## Editing fields safely
58
+
59
+ - To freeze a result, replace the whole field span with a plain run (`fields_materialize.py`, `flatten_ref_fields.py`).
60
+ - To renumber, update the cached result and leave the instruction alone; do not delete the begin/end markers.
61
+ - `w:instrText` is where the instruction lives — a search-and-replace over `w:t` will not find `TOC`.
62
+ - Bookmarks referenced by `REF` must exist (`w:bookmarkStart`/`w:bookmarkEnd` with matching `w:id`); a missing bookmark shows "Error! Reference source not found."
63
+
64
+ ## See also
65
+
66
+ `tasks/fields_update.md`, `tasks/toc_workflow.md`, `tasks/captions_crossrefs.md`, and `ooxml/rels_and_content_types.md` for the relationship side.
@@ -0,0 +1,62 @@
1
+ # Relationships and content types
2
+
3
+ A `.docx` is a zip of parts, and every relationship between parts is declared twice: once as a relationship entry, once as a content type. Miss either and the file either loses the feature or refuses to open.
4
+
5
+ ## The two registries
6
+
7
+ ```
8
+ [Content_Types].xml # what kind of file each part is
9
+ _rels/.rels # package -> document, core props
10
+ word/_rels/document.xml.rels # document -> styles, numbering, media, header, footer, comments, hyperlinks
11
+ ```
12
+
13
+ `[Content_Types].xml` has `<Default Extension="xml" ContentType="..."/>` for extension defaults and `<Override PartName="/word/comments.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"/>` for parts that do not follow an extension rule.
14
+
15
+ A relationship:
16
+
17
+ ```xml
18
+ <Relationship Id="rId5"
19
+ Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
20
+ Target="comments.xml"/>
21
+ ```
22
+
23
+ `Id` is scoped to the part that owns the `.rels` file, so `rId5` in the document and `rId5` in a header are unrelated. `Target` is relative to the owner directory unless it is absolute (`/word/media/image1.png`) or external (`TargetMode="External"`, used for hyperlinks).
24
+
25
+ ## What breaks
26
+
27
+ | Symptom | Cause |
28
+ |---|---|
29
+ | Word: "unreadable content" | A part exists but has no content-type override |
30
+ | Feature silently ignored | Part and override exist, but no relationship points at it |
31
+ | Duplicate header text | Two header relationships, only one referenced by `sectPr` |
32
+ | Broken link | Relationship removed but `r:id` left in the body |
33
+ | Lost image | Media copied without a new relationship id |
34
+
35
+ Ids must be unique within a `.rels` part. When adding one, read the existing ids and take `max+1`; reusing an id silently rewires an unrelated reference.
36
+
37
+ ## The parts that exist only when used
38
+
39
+ `word/comments.xml`, `word/footnotes.xml`, `word/endnotes.xml`, `word/headerN.xml`, `word/footerN.xml`, `word/numbering.xml`, `docProps/custom.xml` — none are required, and each needs three pieces when added: the part, the override, the relationship. Removing one means removing all three (or Word reports corruption).
40
+
41
+ Headers and footers are referenced from the section properties, not from the document root:
42
+
43
+ ```xml
44
+ <w:sectPr>
45
+ <w:headerReference w:type="default" r:id="rId8"/>
46
+ <w:footerReference w:type="default" r:id="rId9"/>
47
+ </w:sectPr>
48
+ ```
49
+
50
+ ## Inspecting
51
+
52
+ ```bash
53
+ "<python>" "<skill>/scripts/docx_kit.py" parts '<file.docx>'
54
+ "<python>" "<skill>/scripts/docx_kit.py" xml '<file.docx>' word/_rels/document.xml.rels
55
+ "<python>" "<skill>/scripts/docx_kit.py" xml '<file.docx>' '[Content_Types].xml'
56
+ ```
57
+
58
+ `parts` lists what is actually in the package — the fastest way to see whether a feature exists at all. Read the `.rels` part before editing relationships by hand.
59
+
60
+ ## Rebuild rather than regenerate
61
+
62
+ When a package is broken, unzipping it, fixing the two registries and rezipping with `[Content_Types].xml` first (stored, not deflated) usually recovers it. The kit writes that order on save for this reason.