# Humanise DOCX Report

> Humanise a finished .docx report end to end - strip machine-generated fingerprints from prose, tables, figures and the OOXML container, then apply the user's house style for headings, tables and captions. Use when asked to humanise, de-AI, clean up or restyle a Word report, dissertation, technical results document or similar deliverable, or when a .docx needs its headings and tables brought into house style. Covers what the generic prose humanizer does not: DOCX container metadata, PNG generator tags, table and figure overflow, blank pages from manual page breaks, and rigorous number-preservation checks.

- Skill: `faaz17/humanise-docx-report` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add faaz17/humanise-docx-report`
- Raw SKILL.md: https://api.skillmd.com/api/skills/faaz17/humanise-docx-report/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: Faaz17 (https://skillmd.com/u/faaz17)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/faaz17/humanise-docx-report

---


# Humanise a DOCX report

Turn a machine-generated report into one that reads and inspects as human-written, without changing a single fact.

Three layers, in order. Do not skip the audit; the audit is what tells you which layers are actually needed.

1. **Audit** - measure before touching anything
2. **Content** - prose, tables, captions
3. **Container and layout** - metadata, embedded media, page geometry

Then verify. The verification step is not optional: a rewrite that silently drops a number is worse than no rewrite.

## 0. Always do this first

Copy the input to a scratch backup before any write. Work on a copy named `*_humanised.docx` unless the user asks for in-place. Never overwrite the user's original.

```bash
python scripts/audit_docx.py INPUT.docx
```

This reports character-level tells, phrase-level tics, sentence rhythm, container fingerprints and layout defects. Read it before deciding what to change.

## 1. Layer A - deterministic character cleanup

Verifiable, so state the counts honestly.

| Tell | Fix | Why it matters |
| --- | --- | --- |
| U+2212 MINUS SIGN | `-` (hyphen-minus) | A person typing in Word produces a hyphen. A typesetting engine produces U+2212. Usually the loudest signal in the file. |
| Em dash `—` | period, comma, colon or parentheses | Highest-profile AI tell. Target zero in body prose. |
| En dash `–` | `to` in numeric ranges, `-` in proper-name compounds | Keep in reference-list page ranges, where it is correct style. |
| Invisible / zero-width Unicode | strip | Run `clean-user-facing-text/scripts/inspect_text.py`. Often already clean. |
| NBSP, soft hyphen, U+2010 | normalise | Layout artefacts from generators. |

Proper-name compounds (`Shapiro–Wilk`, `Kuhn–Munkres`, `Mann–Whitney`) become hyphens: that is what a person types.

## 2. Layer B - prose

Load the `humanizer` skill for the pattern catalogue. This skill adds what that one does not cover.

**A well-built generated report has already dodged the obvious tells.** Expect zero hits on *delve*, *tapestry*, *crucial*, *showcase*, `-ing` analysis tails. The tells that survive are structural:

- **One dominant crutch phrase.** Measure frequency per 1,000 words. In the reference job `rather than` appeared 57 times in 11,000 words, once per 193 words. Anything above roughly one per 400 words is a tic.
- **Enumerated triples**: `First, ... Second, ... Third, ...` repeated across sections.
- **The "worth noting" family**: *worth noting / worth naming / worth labouring / deserves comment*.
- **Signposting**: *the table below gives*, *is given below*.
- **Even sentence rhythm.** Compare mean and standard deviation before and after.

**The trap that matters most:** you will replace one crutch with another of your own. After rewriting, re-run the audit and count *your* phrases. In the reference job `and not` went 1 -> 17 and `instead of` 2 -> 14 on the first pass, which needed a second pass to redistribute. Always do this second pass.

**Do not drive a tic to zero.** Going from 57 to 0 is its own signal. Land on a natural residue, roughly 5 to 10 per 13,000 words.

Preserve exactly: every number, statistic, parameter, equation, equation number, cross-reference, citation, proper noun and technical term. Keep the document's spelling convention (British or US) and its register. Technical prose stays neutral: do not inject personality.

## 3. Tables

- Abbreviations expanded (`Cent.` -> `Central`).
- Em-dash placeholders -> `n/a` for missing data, empty for a genuinely empty column such as an unused Symbol column.
- En-dash ranges -> `1.78 to 2.34`.
- Every table scaled to fit the text column; see layout below.

## 4. Container and media

These are the fingerprints nobody looks at and every forensic check finds.

| Part | Fingerprint | Fix |
| --- | --- | --- |
| `docProps/app.xml` | **empty stub** | Real Word always writes `Application`, `Pages`, `Words`, `Template`, `AppVersion`, `TotalTime`. An empty stub means a library wrote the file. Populate with values measured from the finished document. |
| `docProps/core.xml` | `lastModifiedBy` = `Un-named` | The `docx` JS library default. Set to the author. |
| `docProps/core.xml` | `revision` 1, `created` == `modified` to the microsecond | A human-authored file has a revision count and an authoring window. |
| `word/media/*.png` | `tEXt Software: Matplotlib version ...` | Strip `tEXt`/`iTXt`/`zTXt`/`eXIf`/`tIME` chunks. |
| `word/media/*` | SHA-1 hash filenames | Rename `image1.png`, `image2.png`, ... and update `word/_rels/document.xml.rels`. |
| `w:tblPr` | no `tblLook` | Word always writes it. |

Populating `app.xml` beats stripping it. A stripped-empty `app.xml` is the same fingerprint you started with.

## 5. Layout defects

Generated reports carry these consistently. Check all four.

- **Manual page-break spacers.** An empty paragraph whose only content is `<w:br w:type="page"/>` emits a blank page whenever the previous section happens to end near a page bottom. Convert every one to `pageBreakBefore` on the following heading: same break points, structurally cannot produce a blank page.
- **Tables wider than the text column.** Scale total width and every `gridCol` and `tcW` proportionally to the column width. In the reference job 12 of 14 tables overflowed.
- **Figures wider than the text column.** Scale, preserving aspect ratio.
- **Blank and near-empty pages.** Render and check. A title page and a figure page are legitimately sparse; nothing else is.

## 6. House style

Apply `references/house-style.md`. The headings and tables spec there is the finished, human-tuned convention: Cambria headings, Calibri body, the `Grid Table Light` table style rather than direct cell formatting, italic grey captions.

The single most important item: **tables must use a named Word table style, not direct formatting on every run.** Direct formatting everywhere with no style reference is a generator signature, and it is also what makes tables painful to edit by hand.

## 7. Verify - not optional

```bash
python scripts/verify_docx.py ORIGINAL.docx HUMANISED.docx
```

Must all pass:

- **Numeric reconciliation**: zero numbers dropped, zero added. Normalise trailing punctuation before comparing or you will chase phantom diffs.
- **Cross-references**: every `Section N.N`, `Table N.N`, `Equation N.N`, `Figure N.N` count unchanged.
- **Structure**: paragraph count, table count, table row/column shapes, heading text.
- **Alignment**: if you rewrite by paragraph index, confirm no rewrite landed on a heading. Index drift is the most likely bug in this whole workflow and the numeric check alone will not catch it when the paragraph has no numbers. Check style names and content overlap.

Then render to PDF through Word and inspect every page for blank pages, clipping, overlap and table borders.

```powershell
$w = New-Object -ComObject Word.Application; $w.Visible = $false
$d = $w.Documents.Open($path, $false, $true); $d.Repaginate()
$d.SaveAs([ref]$pdf, [ref]17); $d.Close($false); $w.Quit()
```

## Reporting

Separate the three honestly, every time:

- **Verifiable**: Unicode counts, metadata removed, media chunks stripped, layout defects fixed.
- **Best-effort**: the prose rewrite reduces stylistic signal.
- **Not established**: that it defeats any detector, or proves human authorship. Statistical token-sampling watermarks cannot be confirmed removed without vendor detectors.

If you fabricate metadata such as timestamps or revision counts, say so explicitly and offer to reset it.

Flag, do not silently fix, anything the user wrote themselves. Their edits can introduce heading styles on body paragraphs, spelling drift, autocorrect damage to technical terms, and factual inversions. Report these with locations and let them decide.

