dsh-office-kit 0.4.2 → 0.4.4

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 (123) hide show
  1. package/assets/skills/excel-live-control/SKILL.md +119 -152
  2. package/assets/skills/excel-live-control/domain_guidance/financial_models.md +42 -58
  3. package/assets/skills/excel-live-control/domain_guidance/healthcare.md +36 -42
  4. package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +33 -34
  5. package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +34 -36
  6. package/assets/skills/excel-live-control/references/office-automation.md +127 -153
  7. package/assets/skills/excel-live-control/references/read_only_qna.md +40 -45
  8. package/assets/skills/excel-live-control/style_guidelines.md +56 -64
  9. package/assets/skills/excel-live-control/workflows/create_workflows.md +40 -47
  10. package/assets/skills/excel-live-control/workflows/edit_workflows.md +37 -45
  11. package/assets/skills/office-documents/SKILL.md +24 -60
  12. package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +5 -5
  13. package/assets/skills/office-documents/ooxml/comments.md +8 -8
  14. package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +10 -10
  15. package/assets/skills/office-documents/ooxml/rels_and_content_types.md +7 -7
  16. package/assets/skills/office-documents/ooxml/tracked_changes.md +12 -12
  17. package/assets/skills/office-documents/references/docx-structure.md +11 -13
  18. package/assets/skills/office-documents/references/template-elicitation.md +11 -13
  19. package/assets/skills/office-documents/references/writing-quality.md +20 -20
  20. package/assets/skills/office-documents/scripts/add_tracked_replacements.py +4 -3
  21. package/assets/skills/office-documents/scripts/docx_kit.py +68 -27
  22. package/assets/skills/office-documents/scripts/heading_audit.py +3 -4
  23. package/assets/skills/office-documents/scripts/internal_nav.py +3 -1
  24. package/assets/skills/office-documents/scripts/merge_docx_append.py +104 -0
  25. package/assets/skills/office-documents/scripts/table_geometry.py +13 -3
  26. package/assets/skills/office-documents/scripts/watermark_add.py +6 -5
  27. package/assets/skills/office-documents/scripts/watermark_audit_remove.py +6 -4
  28. package/assets/skills/office-documents/tasks/accessibility_a11y.md +16 -22
  29. package/assets/skills/office-documents/tasks/captions_crossrefs.md +23 -26
  30. package/assets/skills/office-documents/tasks/clean_tracked_changes.md +17 -22
  31. package/assets/skills/office-documents/tasks/comments_manage.md +9 -11
  32. package/assets/skills/office-documents/tasks/compare_diff.md +10 -16
  33. package/assets/skills/office-documents/tasks/create_edit.md +14 -16
  34. package/assets/skills/office-documents/tasks/equations.md +17 -28
  35. package/assets/skills/office-documents/tasks/fields_update.md +14 -16
  36. package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +19 -33
  37. package/assets/skills/office-documents/tasks/footnotes_endnotes.md +12 -14
  38. package/assets/skills/office-documents/tasks/forms_content_controls.md +16 -20
  39. package/assets/skills/office-documents/tasks/headings_numbering.md +17 -22
  40. package/assets/skills/office-documents/tasks/images_figures.md +15 -25
  41. package/assets/skills/office-documents/tasks/multi_doc_merge.md +13 -23
  42. package/assets/skills/office-documents/tasks/navigation_internal_links.md +18 -21
  43. package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +16 -22
  44. package/assets/skills/office-documents/tasks/protection_restrict_editing.md +19 -21
  45. package/assets/skills/office-documents/tasks/read_review.md +9 -20
  46. package/assets/skills/office-documents/tasks/redaction_anonymization.md +17 -18
  47. package/assets/skills/office-documents/tasks/sections_layout.md +16 -23
  48. package/assets/skills/office-documents/tasks/style_lint_normalize.md +18 -22
  49. package/assets/skills/office-documents/tasks/tables_spreadsheets.md +21 -31
  50. package/assets/skills/office-documents/tasks/templates_style_packs.md +17 -21
  51. package/assets/skills/office-documents/tasks/toc_workflow.md +10 -14
  52. package/assets/skills/office-documents/tasks/verify_render.md +11 -23
  53. package/assets/skills/office-documents/tasks/watermarks_background.md +10 -14
  54. package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +6 -6
  55. package/assets/skills/office-documents/troubleshooting/run_splitting.md +12 -12
  56. package/assets/skills/office-pdf/SKILL.md +36 -51
  57. package/assets/skills/office-pdf/references/form-fields.md +20 -20
  58. package/assets/skills/office-pdf/references/geometry.md +10 -10
  59. package/assets/skills/office-pdf/references/layout-quality.md +13 -13
  60. package/assets/skills/office-pdf/references/limits.md +12 -56
  61. package/assets/skills/office-pdf/tasks/annotations.md +5 -5
  62. package/assets/skills/office-pdf/tasks/create.md +6 -9
  63. package/assets/skills/office-pdf/tasks/edit-pages.md +14 -14
  64. package/assets/skills/office-pdf/tasks/forms.md +15 -15
  65. package/assets/skills/office-pdf/tasks/read.md +9 -9
  66. package/assets/skills/office-pdf/tasks/redact.md +18 -18
  67. package/assets/skills/office-pdf/tasks/stamp.md +10 -10
  68. package/assets/skills/office-presentations/SKILL.md +71 -91
  69. package/assets/skills/office-presentations/container_tools/preview_render.py +4 -1
  70. package/assets/skills/office-presentations/container_tools/render_slides.py +1 -1
  71. package/assets/skills/office-presentations/domain_guidance/finance.md +16 -16
  72. package/assets/skills/office-presentations/recipes/README.md +24 -35
  73. package/assets/skills/office-presentations/recipes/autolayout.md +12 -13
  74. package/assets/skills/office-presentations/recipes/connectors.md +11 -12
  75. package/assets/skills/office-presentations/recipes/images.md +11 -12
  76. package/assets/skills/office-presentations/recipes/master-and-layouts.md +18 -18
  77. package/assets/skills/office-presentations/recipes/native-charts.md +8 -8
  78. package/assets/skills/office-presentations/recipes/rich-text-runs.md +13 -13
  79. package/assets/skills/office-presentations/recipes/speaker-notes.md +7 -7
  80. package/assets/skills/office-presentations/recipes/tables.md +14 -14
  81. package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +9 -9
  82. package/assets/skills/office-presentations/recipes/theme-tokens.md +7 -8
  83. package/assets/skills/office-presentations/references/authoring-workflow.md +38 -43
  84. package/assets/skills/office-presentations/references/finalization.md +10 -12
  85. package/assets/skills/office-presentations/references/native-bullets.md +14 -18
  86. package/assets/skills/office-presentations/references/native-evidence.md +18 -32
  87. package/assets/skills/office-presentations/references/style-guidelines.md +27 -32
  88. package/assets/skills/office-presentations/references/templates.md +31 -60
  89. package/assets/skills/office-presentations/routing/google_slides.md +4 -4
  90. package/assets/skills/office-presentations/tasks/apply-annotations.md +17 -17
  91. package/assets/skills/office-presentations/tasks/charts-tables-notes.md +20 -23
  92. package/assets/skills/office-presentations/tasks/create-deck.md +19 -19
  93. package/assets/skills/office-presentations/tasks/edit-deck.md +14 -16
  94. package/assets/skills/office-presentations/tasks/inspect-and-verify.md +31 -34
  95. package/assets/skills/office-presentations/tasks/template-following.md +23 -28
  96. package/assets/skills/office-spreadsheets/SKILL.md +32 -39
  97. package/assets/skills/office-spreadsheets/recipes/charts.md +8 -26
  98. package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +9 -26
  99. package/assets/skills/office-spreadsheets/recipes/data-tables.md +7 -23
  100. package/assets/skills/office-spreadsheets/recipes/named-ranges.md +8 -21
  101. package/assets/skills/office-spreadsheets/recipes/number-formats.md +7 -23
  102. package/assets/skills/office-spreadsheets/recipes/sparklines.md +7 -20
  103. package/assets/skills/office-spreadsheets/references/charts.md +15 -34
  104. package/assets/skills/office-spreadsheets/references/domain/financial-models.md +10 -25
  105. package/assets/skills/office-spreadsheets/references/domain/healthcare.md +8 -19
  106. package/assets/skills/office-spreadsheets/references/domain/marketing.md +8 -22
  107. package/assets/skills/office-spreadsheets/references/domain/research.md +8 -19
  108. package/assets/skills/office-spreadsheets/references/formula-patterns.md +20 -50
  109. package/assets/skills/office-spreadsheets/references/style-guidelines.md +19 -44
  110. package/assets/skills/office-spreadsheets/references/workbook-structure.md +12 -35
  111. package/assets/skills/office-spreadsheets/routing/google-sheets.md +11 -26
  112. package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +10 -25
  113. package/assets/skills/office-spreadsheets/tasks/annotations.md +12 -30
  114. package/assets/skills/office-spreadsheets/tasks/create-workbook.md +5 -5
  115. package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +2 -2
  116. package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +5 -5
  117. package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +9 -9
  118. package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +10 -30
  119. package/assets/skills/shared/annotation-recipes.md +98 -120
  120. package/assets/skills/shared/common-workflow.md +70 -80
  121. package/dist/index.js +1 -1
  122. package/package.json +1 -1
  123. package/python/office_cli.py +38 -4
@@ -1,36 +1,21 @@
1
1
  # Google Sheets
2
2
 
3
- This runtime works on local files with openpyxl. There are no Google credentials,
4
- no Drive API, and no live link to a browser sheet, so "update my Google Sheet"
5
- cannot be done directly.
3
+ This runtime works on local files with openpyxl. There are no Google credentials, no Drive API, and no live link to a browser sheet, so "update my Google Sheet" cannot be done directly.
6
4
 
7
5
  ## What to do instead
8
6
 
9
- 1. Say plainly what is possible: the work is done on a local `.xlsx` file the user
10
- opens in Sheets, or the user exports the sheet and shares the file.
11
- 2. Ask for an export when the source lives in Sheets: `File > Download >
12
- Microsoft Excel (.xlsx)`. A single-sheet CSV loses formulas and formats, so ask
13
- for `.xlsx` unless the sheet is truly one flat table.
14
- 3. Do the work on the exported file with this skill, then hand back the `.xlsx`.
15
- The user re-uploads or imports it. State that formulas recalculate when Sheets
16
- opens the file.
17
- 4. Do not promise a round trip that keeps Sheets-specific features. Named
18
- functions, Apps Script, and connected sheets do not survive export.
7
+ 1. Say plainly what is possible: the work is done on a local `.xlsx` file the user opens in Sheets, or the user exports the sheet and shares the file.
8
+ 2. Ask for an export when the source lives in Sheets: `File > Download > Microsoft Excel (.xlsx)`. A single-sheet CSV loses formulas and formats, so ask for `.xlsx` unless the sheet is truly one flat table.
9
+ 3. Do the work on the exported file with this skill, then hand back the `.xlsx`. The user re-uploads or imports it. State that formulas recalculate when Sheets opens the file.
10
+ 4. Do not promise a round trip that keeps Sheets-specific features. Named functions, Apps Script, and connected sheets do not survive export.
19
11
 
20
- ## When writing formulas for a file that will go back to Sheets
12
+ ## Formulas for a file that goes back to Sheets
21
13
 
22
- - Keep to functions both engines share: `SUMIFS`, `INDEX/MATCH`, `XLOOKUP`,
23
- `IFERROR`, `EDATE`, `TEXT`.
24
- - Newer functions that Excel stores with an `_xlfn.` prefix are a common source of
25
- `#NAME?` after a round trip. If a function is genuinely new, say so.
26
- - Array formulas and dynamic spills behave differently in the two engines. Avoid
27
- them in shared files.
28
- - Number formats, conditional-formatting rules, and charts mostly survive an
29
- export; images and pivot tables often do not. Check them after the round trip
30
- with `container_tools/inspect_workbook.py`.
14
+ - Keep to functions both engines share: `SUMIFS`, `INDEX/MATCH`, `XLOOKUP`, `IFERROR`, `EDATE`, `TEXT`.
15
+ - Newer functions that Excel stores with an `_xlfn.` prefix are a common source of `#NAME?` after a round trip. If a function is genuinely new, say so.
16
+ - Array formulas and dynamic spills behave differently in the two engines. Avoid them in shared files.
17
+ - Number formats, conditional-formatting rules, and charts mostly survive an export; images and pivot tables often do not. Check them after the round trip with `container_tools/inspect_workbook.py`.
31
18
 
32
19
  ## Links
33
20
 
34
- A sheet shared by URL is not a workbook on this machine. Do not fetch a Google
35
- Sheets URL and pretend it is a file: without a published CSV or an export, there
36
- is nothing to read.
21
+ A sheet shared by URL is not a workbook on this machine. Do not fetch a Google Sheets URL and pretend it is a file: without a published CSV or an export, there is nothing to read.
@@ -1,37 +1,22 @@
1
1
  # Answer questions about an existing workbook
2
2
 
3
- This is a read-only job. Do not "improve" the file, do not recalculate it in
4
- place, and do not save a copy unless the user asked for one.
3
+ This is a read-only job. Do not "improve" the file, do not recalculate it in place, and do not save a copy unless the user asked for one.
5
4
 
6
5
  ## Procedure
7
6
 
8
- 1. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"` —
9
- sheet names, used ranges, and cell contents.
10
- 2. Read **values**, not formulas, when the question is about numbers:
11
- `xlsx read --data-only` returns cached results. If the cache is empty (the
12
- file was last written by a script), say so and quote the formula instead of a
13
- number, or recalculate into a copy first (`tasks/recalc-and-check.md`).
14
- 3. `container_tools/inspect_workbook.py --input "<book.xlsx>" --sample 8` when the
15
- question touches structure: which cells are formulas, merged ranges, totals
16
- rows, conditional formats, defined names, hidden rows, extra sheets.
17
- 4. Answer with the cells you used: "`Pipeline!B4:B13`, the Amount column, sums to
18
- `812,000`" beats "the pipeline is about 800k". Name the sheet, the range, and
19
- the figure.
7
+ 1. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"` — sheet names, used ranges, and cell contents.
8
+ 2. Read **values**, not formulas, when the question is about numbers: `xlsx read --data-only` returns cached results. If the cache is empty (the file was last written by a script), say so and quote the formula instead of a number, or recalculate into a copy first (`tasks/recalc-and-check.md`).
9
+ 3. `container_tools/inspect_workbook.py --input "<book.xlsx>" --sample 8` when the question touches structure: which cells are formulas, merged ranges, totals rows, conditional formats, defined names, hidden rows, extra sheets.
10
+ 4. Answer with the cells you used: "`Pipeline!B4:B13`, the Amount column, sums to `812,000`" beats "the pipeline is about 800k". Name the sheet, the range, and the figure.
20
11
 
21
12
  ## Judgement calls
22
13
 
23
- - A number that disagrees with the user's expectation is usually a real answer,
24
- not an error to fix. Explain the calculation and stop.
25
- - Pre-existing `#REF!`/`#DIV/0!` cells are part of the answer. Point at them, say
26
- what breaks, and wait for instructions.
27
- - Two tabs with the same title and different numbers: report both and ask which
28
- one the user means before averaging or picking.
29
- - Empty cells are not zeros. "Not reported" and "zero" are different answers, and
30
- a missing month in a total usually means a filter, not a zero.
14
+ - A number that disagrees with the user's expectation is usually a real answer, not an error to fix. Explain the calculation and stop.
15
+ - Pre-existing `#REF!`/`#DIV/0!` cells are part of the answer. Point at them, say what breaks, and wait for instructions.
16
+ - Two tabs with the same title and different numbers: report both and ask which one the user means before averaging or picking.
17
+ - Empty cells are not zeros. "Not reported" and "zero" are different answers, and a missing month in a total usually means a filter, not a zero.
31
18
  - If the workbook has a case selector, check it. The answer depends on it.
32
19
 
33
20
  ## Output shape
34
21
 
35
- Short answer first (one line with the figure), then the cells behind it, then any
36
- caveat about missing data or stale cache. No file changes, no new workbook, no
37
- chart unless asked.
22
+ Short answer first (one line with the figure), then the cells behind it, then any caveat about missing data or stale cache. No file changes, no new workbook, no chart unless asked.
@@ -1,7 +1,6 @@
1
1
  # Resolve an `office-annotations` region to cells
2
2
 
3
- The user drags a box on the rendered workbook and types a requirement. The
4
- payload for spreadsheets is:
3
+ The user drags a box on the rendered workbook and types a requirement. The payload for spreadsheets is:
5
4
 
6
5
  ```json
7
6
  {
@@ -15,37 +14,20 @@ payload for spreadsheets is:
15
14
  }
16
15
  ```
17
16
 
18
- There is no `page`, no `sheet`, and no `range`: the preview client cannot turn a
19
- pixel rectangle into a cell address and will not fake one. Read it as "look at
20
- this area of this sheet and do this", not as a cell reference.
17
+ There is no `page`, no `sheet`, and no `range`: the preview client cannot turn a pixel rectangle into a cell address and will not fake one. Read it as "look at this area of this sheet and do this", not as a cell reference.
21
18
 
22
19
  ## Procedure
23
20
 
24
- 1. `read_image` the attachment named `imageName`. It is the screenshot of the
25
- area the user marked: read the visible headers, row labels, and the numbers
26
- around the box.
27
- 2. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"`,
28
- then match the visible values to sheets and A1 addresses. Values repeat across
29
- sheets more often than you expect — match on a combination (a row label plus
30
- two numbers), not on one number.
31
- 3. When the numbers are ambiguous, `container_tools/inspect_workbook.py` adds
32
- formulas, merges, tables, and names; formats often disambiguate ("the only
33
- column with a `%` format").
34
- 4. State what you resolved, in the user's terms: "`Pipeline!D2:D13`, the Amount
35
- column — 12 rows of whole dollars". Ask only if two sheets or two columns
36
- match equally well.
37
- 5. Apply the smallest change that satisfies `requirement` with the mutation tools
38
- (`tasks/edit-workbook.md`), re-render, and confirm the region now looks right.
21
+ 1. `read_image` the attachment named `imageName`. It is the screenshot of the area the user marked: read the visible headers, row labels, and the numbers around the box.
22
+ 2. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"`, then match the visible values to sheets and A1 addresses. Values repeat across sheets more often than you expect — match on a combination (a row label plus two numbers), not on one number.
23
+ 3. When the numbers are ambiguous, `container_tools/inspect_workbook.py` adds formulas, merges, tables, and names; formats often disambiguate ("the only column with a `%` format").
24
+ 4. State what you resolved, in the user's terms: "`Pipeline!D2:D13`, the Amount column — 12 rows of whole dollars". Ask only if two sheets or two columns match equally well.
25
+ 5. Apply the smallest change that satisfies `requirement` with the mutation tools (`tasks/edit-workbook.md`), re-render, and confirm the region now looks right.
39
26
 
40
27
  ## What not to do
41
28
 
42
- - Do not compute a cell from the rectangle's coordinates. Header width, frozen
43
- panes, hidden columns, and zoom all move cells under the same pixel.
44
- - Do not edit the first sheet because it was the default. The visible page may be
45
- the fourth sheet.
46
- - Do not re-style the whole sheet to make the marked area consistent. Match the
47
- surrounding convention and change the cells the requirement names.
48
- - If the region covers a chart or a picture, the change is to the object, not the
49
- cells behind it — check `charts`/`images` in the inspect output first.
50
- - If nothing on the page carries the values in the screenshot, say which image
51
- you looked at and what you could not locate. Do not guess a sheet.
29
+ - Do not compute a cell from the rectangle's coordinates. Header width, frozen panes, hidden columns, and zoom all move cells under the same pixel.
30
+ - Do not edit the first sheet because it was the default. The visible page may be the fourth sheet.
31
+ - Do not re-style the whole sheet to make the marked area consistent. Match the surrounding convention and change the cells the requirement names.
32
+ - If the region covers a chart or a picture, the change is to the object, not the cells behind it — check `charts`/`images` in the inspect output first.
33
+ - If nothing on the page carries the values in the screenshot, say which image you looked at and what you could not locate. Do not guess a sheet.
@@ -40,9 +40,9 @@
40
40
 
41
41
  ## Order of work
42
42
 
43
- 1. Sketch the sheets as roles, not tabs: inputs, calculations, outputs, checks. A five-line model belongs on one sheet with labelled blocks.
44
- 2. Put the number formats on the cells, not on a copy of the values. `#,##0` for currency-ish amounts, `0.0%` for percentages, `yyyy-mm-dd` for real dates.
45
- 3. Write the calculation as visible steps (quantity × rate, opening + movements = closing) and link the output to the build rather than repeating the arithmetic.
43
+ 1. Sketch sheets as roles, not tabs: inputs, calculations, outputs, checks. A five-line model belongs on one sheet with labelled blocks.
44
+ 2. Put number formats on the cells, not on a copy of the values. `#,##0` for currency-ish amounts, `0.0%` for percentages, `yyyy-mm-dd` for real dates.
45
+ 3. Write calculations as visible steps (quantity × rate, opening + movements = closing) and link the output to the build rather than repeating the arithmetic.
46
46
  4. Add a chart only when it answers a comparison question the numbers alone answer slowly; see `references/charts.md`.
47
47
  5. Render and read the PNG, then recalc if formulas exist.
48
48
 
@@ -60,7 +60,7 @@
60
60
  ## Pitfalls
61
61
 
62
62
  - Values written through the CLI keep their type: `1840000` is a number, `"1,840,000"` is text and will not sum. Format numbers, never pre-format them as strings.
63
- - A chart whose `max_row` is larger than the data plots empty points as zero, which reads as a collapse to the floor. Match the range to the data.
64
- - `anchor` is where the chart's top-left corner sits; a chart outside the print area gets cut off by `xlsx render`. Put it below or beside the data inside the printed range.
63
+ - A chart whose `max_row` exceeds the data plots empty points as zero, which reads as a collapse to the floor. Match the range to the data.
64
+ - `anchor` is where the chart's top-left corner sits; a chart outside the print area gets cut off by `xlsx render`. Put it below or beside the data, inside the printed range.
65
65
  - Dates must be real dates (`date(2026, 1, 31)` via a snippet, or Excel serial numbers), never `"Jan-26"` strings, or period filters fail silently.
66
66
  - Set the font family explicitly if the file will be opened on another machine; a missing Calibri falls back to a serif in some renderers and every column width shifts.
@@ -25,8 +25,8 @@ Exit code `0` means the files match at the requested level, `1` means difference
25
25
 
26
26
  Run it as `--before original --after original-edited` immediately after any edit, and read the "changed" sections as the diff you are about to describe to the user:
27
27
 
28
- 1. Anything under cells that you did not intend to touch is collateral damage — revert and redo with a narrower edit.
29
- 2. A sheet, table, name, or chart in "removed" is a lost object; rebuild it from `recipes/charts.md` / `recipes/named-ranges.md` before presenting.
28
+ 1. Cells you did not intend to touch are collateral damage — revert and redo with a narrower edit.
29
+ 2. A sheet, table, name, or chart under "removed" is a lost object; rebuild it from `recipes/charts.md` / `recipes/named-ranges.md` before presenting.
30
30
  3. Formatting-only differences across many rows usually mean a style object was reapplied to a range instead of a cell.
31
31
 
32
32
  Diffing a file against itself is a useful sanity check that the tool and the file load cleanly: it should return `identical: true`.
@@ -5,7 +5,7 @@ The file is the specification. Read its conventions before writing a cell, then
5
5
  ## Procedure
6
6
 
7
7
  1. `"<python>" "<cli>" xlsx read --input "<book.xlsx>" --json-out "<dump>.json"` — every sheet, its used range, and its formulas.
8
- 2. `"<python>" "<skill>/container_tools/inspect_workbook.py" --input "<book.xlsx>"` — what the read verb does not show: merged ranges, conditional formatting, defined names, Excel Tables, charts and their series, freeze panes, protections. It prints JSON; `--no-values` skips the second load that looks for cached results.
8
+ 2. `"<python>" "<skill>/container_tools/inspect_workbook.py" --input "<book.xlsx>"` — what the read verb hides: merged ranges, conditional formatting, defined names, Excel Tables, charts and their series, freeze panes, protections. It prints JSON; `--no-values` skips the second load that looks for cached results.
9
9
  3. Render the sheets you are about to touch and look at them: `xlsx render`, then `read_image`. Match the surrounding format, not your personal default.
10
10
  4. Apply the edit with the narrowest tool that fits (below), or with an openpyxl snippet when the change is not one of those shapes.
11
11
  5. Read back and re-check structure, recalculate if formulas changed, render again, compare.
@@ -24,11 +24,11 @@ There is no `xlsx edit` verb. Each tool loads the workbook, changes only what yo
24
24
  | Add a native chart | `add_chart.py --input "<book.xlsx>" --sheet Trend --type line --title "Monthly revenue (USD)" --anchor A6 --data-min-col 2 --data-min-row 3 --data-max-col 13 --data-max-row 3 --cat-min-row 2 --cat-max-row 2` |
25
25
  | Embed an image | `add_image.py --input "<book.xlsx>" --sheet Cover --path logo.png --anchor B2 --width 320` |
26
26
 
27
- Each tool writes `<input>-edited.xlsx` unless you pass `--out`, so chain by naming outputs, never by editing the file you just read and forgetting the step in between.
27
+ Each tool writes `<input>-edited.xlsx` unless you pass `--out`, so chain by naming outputs — never edit the file you just read and lose the step in between.
28
28
 
29
29
  `cells.json` is `{"sheet": "Model", "cells": {"B3": 0.07, "D9": "=SUM(D2:D8)"}}` or a list of those. `styles.json` is `{"sheet": "Model", "styles": {"A11:B11": {"bold": true}, "C11:C14": {"number_format": "0.0%"}}}`.
30
30
 
31
- Two tool limits are deliberate: `append_rows.py` does not extend an Excel Table, copy the formula from the row above, or grow a chart — do those with a snippet from `recipes/data-tables.md` and `recipes/charts.md`, or the new rows will sit outside the table and the chart will stop at the old last row. `add_chart.py` treats a one-row data range as one series of many points (which is what a monthly row means) but cannot set axis number formats or series colours; fix those in the same snippet.
31
+ Two tool limits are deliberate: `append_rows.py` does not extend an Excel Table, copy the formula from the row above, or grow a chart — use a snippet from `recipes/data-tables.md` and `recipes/charts.md`, or the new rows sit outside the table and the chart stops at the old last row. `add_chart.py` treats a one-row data range as one series of many points (what a monthly row means) but cannot set axis number formats or series colours; fix those in the same snippet.
32
32
 
33
33
  ## What must survive an edit
34
34
 
@@ -48,7 +48,7 @@ New conditional formatting that covers a whole table must extend to the rows you
48
48
  ## Cells: the smallest change
49
49
 
50
50
  - Write to the sheet and address you resolved; never "the first empty row" of an unnamed sheet.
51
- - A text edit changes run-level text only in a cell; the format stays unless the request names it.
51
+ - A text edit changes run-level text only; the cell format stays unless the request names it.
52
52
  - A number-format change is a format change, not a value change: do not replace `0.0649` with `6.5%` text.
53
53
  - Do not autofit every column or restyle a table to fix one clipped cell. Widen the column, or shrink the font only for that block.
54
54
  - Do not add spacer rows, helper sheets, or "Notes" tabs unless the request needs them.
@@ -66,4 +66,4 @@ If `xlsx read` shows `#REF!`, `#DIV/0!`, or a formula pointing at a sheet that n
66
66
  "<python>" "<cli>" xlsx render --input "<book-edited.xlsx>" --out-dir "<render-dir>"
67
67
  ```
68
68
 
69
- The diff is the closest thing to a guarantee that nothing else moved: it reports changed cells and formulas, changed formatting unless you pass `--no-formats`, and structure changes (sheets, merges, widths, tables, charts, defined names). Exit code `1` means differences — not failure. Use `--sheet` to narrow and `--limit` to cap the per-sheet cell list.
69
+ The diff is the closest thing to a guarantee that nothing else moved: it reports changed cells and formulas, changed formatting unless you pass `--no-formats`, and structure changes (sheets, merges, widths, tables, charts, defined names). Exit code `1` means differences — not failure. Use `--sheet` to narrow and `--limit` to cap the per-sheet cell list. Gate flags and exit codes: `tasks/recalc-and-check.md`.
@@ -2,10 +2,10 @@
2
2
 
3
3
  Two readers, different jobs:
4
4
 
5
- - `"<python>" "<cli>" xlsx read --input "<book.xlsx>" [--data-only]` — the cell values, per sheet, as arrays without coordinates. `--data-only` returns cached results instead of formula text.
6
- - `"<python>" "<skill>/container_tools/inspect_workbook.py" --input "<book.xlsx>"` — the structure around the cells: formats that govern how they read, objects that live beside them, and whether the formulas were ever computed.
5
+ - `"<python>" "<cli>" xlsx read --input "<book.xlsx>" [--data-only]` — cell values per sheet, as arrays without coordinates. `--data-only` returns cached results instead of formula text.
6
+ - `"<python>" "<skill>/container_tools/inspect_workbook.py" --input "<book.xlsx>"` — the structure around the cells: the formats that govern how they read, the objects beside them, and whether the formulas were ever computed.
7
7
 
8
- Run both before editing, and after editing to prove nothing was lost.
8
+ Run both before editing, and again after to prove nothing was lost.
9
9
 
10
10
  ## What the inspector reports
11
11
 
@@ -19,20 +19,20 @@ Run both before editing, and after editing to prove nothing was lost.
19
19
  | `sheets[].print_area`, `freeze_panes`, `gridlines` | Layout choices a render will honour |
20
20
  | `sheets[].merged` | Merged ranges; a value lives in the top-left cell only |
21
21
  | `sheets[].tables` | Excel Table names and refs; rows appended below a `ref` land outside the table |
22
- | `sheets[].charts[].anchor`, `.kind`, `.series` | Where a chart sits and what it plots; `anchor` outside `print_area` means the chart is cut off when printed |
22
+ | `sheets[].charts[].anchor`, `.kind`, `.series` | Where a chart sits and what it plots; an `anchor` outside `print_area` is cut off when printed |
23
23
  | `sheets[].conditional_formats[].rules` | `type` (`cellIs`, `colorScale`, `dataBar`, `expression`), `operator`, `formula`, `priority`. A rule whose range stops short of new rows silently stops applying |
24
24
  | `sheets[].data_validations` | Dropdowns and constraints an edit must preserve |
25
25
  | `sheets[].hidden_rows`, `hidden_columns` | Content the user deliberately folded away |
26
26
  | `sheets[].formulas.shared`, `.array`, `.data_tables` | Non-trivial formula storage; re-saving can materialise or drop these |
27
27
  | `sheets[].values.cached`, `.missing`, `.errors` | How many formula cells carry a cached result, carry none, or carry an error value |
28
28
 
29
- `--no-values` skips the second load that reads cached results (faster on big files, blind to whether formulas were ever computed). `--sample N` sets how many formula samples per sheet are printed (default 5).
29
+ `--no-values` skips the second load that reads cached results (faster on big files, blind to whether formulas ever computed). `--sample N` sets how many formula samples per sheet are printed (default 5).
30
30
 
31
31
  ## How to read it
32
32
 
33
33
  - `values.missing` equal to `formulas.count` means nothing has ever calculated this file. Do not quote any formula result; recalculate first (`tasks/recalc-and-check.md`).
34
- - `values.errors` non-empty is pre-existing damage (or a deliberately `#N/A` sentinel). Report it, do not fix it unasked.
35
- - `container.pivot_tables > 0` or `has_vba_project: true` means a plain openpyxl rewrite is risky: back up, change the fewest cells possible, and re-inspect after saving.
34
+ - `values.errors` non-empty is pre-existing damage (or a deliberate `#N/A` sentinel). Report it; do not fix it unasked.
35
+ - `container.pivot_tables > 0` or `has_vba_project: true` means a plain openpyxl rewrite is risky: back up, change the fewest cells possible, re-inspect after saving.
36
36
  - `formulas.shared > 0` means a spreadsheet app wrote the file; copy an existing formula down rather than inventing a new pattern.
37
- - A sheet with a huge `dimensions` and few real cells is a formatting artefact (fill applied to whole columns). Do not "clean" it; note it if the user asks why the file is slow.
38
- - `print_area` and chart `anchor` are the two fields that explain most render surprises: charts clipped at the page edge, or entire data blocks missing from a PDF because they fall outside the print range.
37
+ - A huge `dimensions` with few real cells is a formatting artefact (fill applied to whole columns). Do not "clean" it; note it if the user asks why the file is slow.
38
+ - `print_area` and chart `anchor` explain most render surprises: charts clipped at the page edge, or whole data blocks missing from a PDF because they fall outside the print range.
@@ -1,25 +1,15 @@
1
1
  # Recalculate and gate consistency
2
2
 
3
- A workbook written by openpyxl or by a script has formula text and no cached
4
- results. Open it in a viewer that does not calculate and every formula cell shows
5
- blank. `xlsx recalc` runs the real engine to fill the cache; the gate then proves
6
- every formula cell got a value and none of them is an error.
3
+ A workbook written by openpyxl or by a script has formula text and no cached results. Open it in a viewer that does not calculate and every formula cell shows blank. `xlsx recalc` runs the real engine to fill the cache; the gate then proves every formula cell got a value and none is an error.
7
4
 
8
5
  ```bash
9
6
  "<python>" "<cli>" xlsx recalc --input "<book.xlsx>" --out "<book-recalculated.xlsx>"
10
7
  "<python>" "<skill>/container_tools/recalc_gate.py" --input "<book-recalculated.xlsx>"
11
8
  ```
12
9
 
13
- - `recalc` needs the DSH LibreOffice kit (the same renderer used for images);
14
- it runs on Windows, macOS and Linux. Without the kit the verb fails with a
15
- plain message and changes nothing.
16
- - `recalc_gate.py` runs `recalc` for you when given `--cli`: it takes
17
- `--input`, writes `<stem>-recalculated.xlsx` unless `--out` is given, then
18
- scans every formula cell.
19
- - It exits `0` clean, `1` with failures, `2` on a usage or file error, and `3`
20
- when recalculation was requested but no engine exists. Exit `3` with
21
- `verdict: unverified` is an honest result — report it as "structure verified,
22
- numbers not recalculated", never as "numbers verified".
10
+ - `recalc` needs the DSH LibreOffice kit (the same renderer used for images) and runs on Windows, macOS and Linux. Without the kit the verb fails with a plain message and changes nothing.
11
+ - `recalc_gate.py --cli` runs `recalc` for you: it takes `--input`, writes `<stem>-recalculated.xlsx` unless `--out` is given, then scans every formula cell.
12
+ - It exits `0` clean, `1` with failures, `2` on a usage or file error, and `3` when recalculation was requested but no engine exists. Exit `3` with `verdict: unverified` is an honest result — report it as "structure verified, numbers not recalculated", never as "numbers verified".
23
13
 
24
14
  ## What the gate flags
25
15
 
@@ -30,28 +20,18 @@ every formula cell got a value and none of them is an error.
30
20
  | `dangling` | Formula references a sheet that does not exist | Renaming a sheet without updating formulas does this; restore the name or repoint the reference |
31
21
  | `ignored` | Cells you passed with `--ignore` | Pre-existing errors the user asked you to leave alone |
32
22
 
33
- `--strict` treats missing values as failures instead of notes, which is what you
34
- want after a successful recalc. `--ignore 'Rates!B7,B9'` keeps a known,
35
- user-accepted error out of the verdict without hiding the rest.
23
+ `--strict` treats missing values as failures instead of notes, which is what you want after a successful recalc. `--ignore 'Rates!B7,B9'` keeps a known, user-accepted error out of the verdict without hiding the rest.
36
24
 
37
25
  ## Consistency checks the gate cannot do
38
26
 
39
27
  Recalculation proves formulas evaluate, not that they are right. Check by hand:
40
28
 
41
- - Totals equal the sum of the rows above them, and detail rows add to the
42
- summary — not just that both computed something.
29
+ - Totals equal the sum of the rows above them, and detail rows add to the summary — not just that both computed something.
43
30
  - Percentages are stored as fractions and formatted, not typed as `6.4`.
44
- - A case selector drives every tab that claims to follow the case. Two tabs
45
- showing different cases is the most expensive defect in a model.
46
- - Hard-coded overrides are visible (a different fill or a comment) and the
47
- formula path still exists. If an override replaced a formula, the workbook can
48
- no longer update.
49
- - Every input the user expects to change is in a cell they can find, not inside a
50
- formula constant.
31
+ - A case selector drives every tab that claims to follow the case. Two tabs showing different cases is the most expensive defect in a model.
32
+ - Hard-coded overrides are visible (a different fill or a comment) and the formula path still exists. If an override replaced a formula, the workbook can no longer update.
33
+ - Every input the user expects to change is in a cell they can find, not inside a formula constant.
51
34
 
52
35
  ## When there is no engine
53
36
 
54
- Report exactly what happened: the file was created and structurally verified, the
55
- numbers are formulas, and they will populate the first time the user opens the
56
- file in Excel, LibreOffice, or Sheets. Offer to render so the user sees the layout
57
- and labels. Do not invent values to make the preview look complete.
37
+ Report exactly what happened: the file was created and structurally verified, the numbers are formulas, and they will populate the first time the user opens the file in Excel, LibreOffice, or Sheets. Offer to render so the user sees the layout and labels. Do not invent values to make the preview look complete.