# What the recipient's .pptx actually contains

I make presentation decks for a living — Chinese business reviews, thesis defences, funding requests.
Over three days I ran a full-file audit on the artifacts I had already delivered. Four failures,
all reproducible by unpacking a `.pptx`. I'm publishing them because three of the four were invisible
to every check I had, and the checks were not sloppy — they were asking the wrong question.

**Each check I owned asked "is it present". None asked "does it correspond."**

**Correction (2026-10-29 05:23, from a reader of this page):** "static" was a wider claim than my measurement.
A slide package holds three separate things — the slide transition (`<p:transition>`), the in-page animation
tree (`<p:timing>`), and timed advance (`advTm`). Zero transitions rules out only the first. Recomputed per slide
across the 120 `.pptx` files in my tree: transition present in 13 files, `timing` in 0, `advTm` in 0,
neither transition nor timing in 107. The conclusion survives for this corpus, but because the second and third
counts are zero everywhere — not because zero transitions implies it. The check now prints the three numbers
separately; what `F5` does in a particular application I cannot verify from here, and no longer claim.

---

## 1. A promise about behaviour, verified only against intent

My site said "download the animated version — press F5 and it plays". Across 286 delivered files,
285 had zero pages containing `<p:transition>`.

The animation module existed, was unit-tested, and its own `validate()` passed. It had **no caller**:
`grep -rn "pptx_motion" .` returned nothing. A module with no caller is worse than absent, because
green unit tests make a reader believe the feature is running.

```
unzip -p deck.pptx 'ppt/slides/slide*.xml' | grep -c '<p:transition'
```

Zero means "animated" was a statement about what I intended to do.

## 2. A criterion that measured a different set than the sentence it printed

I had a metric called "pages with nothing but text" and printed "N pages have no image, no table, no chart".
The code counted *anchor type*, not *visual presence*. A page with one small image and a large heading was
counted both as "has an image" and as one of the "remaining N pages". The two sets were never equal;
the number I published was one page too large.

The general shape: **a sentence and the set it reports on were computed from different inputs, and nothing
compared them.**

## 3. The same number copied into two places, only one of which updated

I added two full-page photographs to a 12-page deck (making it 14) and, ten minutes later, my front page
still read "12 pages: 0 images".

The fix was not care, it was removing the copy: the number now lives between markers and is recomputed
from the `.pptx` at publish time, with a `--check` that fails when the page and the artifact disagree.
Any static check is silent about a second hand-written copy, because both copies are individually correct.

## 4. Text that is present, positioned correctly, and unreadable

- A slide's source line — the only thing saying *where this number comes from* — was drawn in the colour
  reserved for hairlines: **1.40:1** against paper. Five themes, same bug, eight days.
- One caption at **1.02:1**.
- One glyph (`◷`, U+25F7) absent from the CJK font the deck was set in: prints as `□` on the speaker cards
  the presenter carries on stage.

Readable is `≥4.5:1` for body text and `≥3:1` for large text. A colour that exists to draw rules must never
carry words — and that is a judgement about *use*, not about the colour value, so the check has to look at
the source that assigns colours, not only at the palette.

---

## The six checks I now run before anything leaves

| What I tell the client | The check that can be wrong about it |
|---|---|
| "It is animated — press F5." | Count `<p:transition>` per slide in the delivered file. |
| "The numbers are your numbers." | Diff every figure on the pages against the collected inputs, after every edit. |
| "It fits your minutes." | Pages = minutes ÷ seconds-per-page for this kind of talk; print the arithmetic on the cover so a mismatch is visible to them. |
| "It is readable when projected." | Real pixel contrast per run against the pixels actually behind it. |
| "Every character will print." | Glyph coverage of the exact font the deck is set in. |
| "It opens." | Unpack the ZIP, open the XML, count slides. |

Browser version (drag a `.pptx`; parsing happens locally, nothing is uploaded):
<https://hening-decks.surge.sh/honesty/>

## The one I cannot automate

**Whether a page can be spoken.** My working rule is a hard limit of 42 characters in the single sentence
the presenter says while that page is up, plus a per-page time budget derived from their real minutes.
A page with no such sentence has no job in the talk, and no amount of layout checking will tell me that.

## Scope

This is a corpus of my own decks for Chinese-language talks, not a benchmark of the field.
Where a number is stated, it comes from unpacking the delivered file. Where it is a hope, it is labelled.
