# What still stands when the client sends version two

*A worked example of carrying PDF accessibility review evidence across a revision, with one case where most of it carries and one where reuse is refused.*

**Disclosure.** This article was prepared by the PDFCarry product team at RYOX Sales Pty Ltd, with AI assistance. Claude (Fable) wrote it. An OpenAI Codex agent (Astra) generated the sample files and ran the engine that produced the evidence. PDFCarry is our product. The documents are synthetic, no accessibility specialist reviewed them, and every review record in the files is automated setup labelled as such. Nothing here is a customer result, a measured time saving, or a PDF/UA or WCAG certification. These results were prepared on 7 September 2026. The current Windows release has a 14-day trial and paid subscriptions; this educational example and its files remain free to inspect.

All files, page previews and checksums referenced below are in the same folder as this article. The counts come from `results.json`.

## The situation

A tagged, reviewed PDF comes back from the client re-exported. One sentence changed, one paragraph was added, and the export tagged every heading as a paragraph. The new file carries none of the tags or checks recorded against the previous version, so without some way to carry them the review would begin again from the new export. This walkthrough uses exactly that hypothetical, built from synthetic files, to show what carries, what reopens and what is refused.

Compare page 2 of the two files (`previews/guide-baseline-2.png` and `previews/guide-revision-2.png`):

- Baseline: four paragraphs under "Before visitors arrive". The orientation sentence reads "10 am on Monday". Headings tagged H1 and H2. Every check on this version has a review record, all of them automated synthetic setup rather than a specialist's review.
- Revision: five paragraphs. The orientation sentence reads "11 am on Tuesday", and a new final paragraph reads "Bring the updated shift checklist to orientation." The headings keep their appearance, but the export tagged every one of them as a paragraph.

After the revision was imported, the guide case has 58 scopes on 20 items: 35 kept, 17 reopened (all of them reading order) and 6 with nothing to carry. 19 of the 20 items still need a reviewer; only the document properties item is fully covered. Six heading roles were restored. The exported PDF renders identical to the incoming revision on all three pages, both originals are unchanged, and veraPDF 1.30.2 passed the PDF/UA-1 profile, which covers machine-checkable rules only.

In a second file, a one-page table, the revision changed one number inside the table and arrived untagged. PDFCarry refused to reuse the table and carried its cells as loose items. That export also failed machine validation on three rules, not all of them about the table. That case is under "The refusal" below.

Two words have fixed meanings here. An **item** is one piece of content, or the document properties. A **scope** is one check on one item: structure, reading order, language, alternative text for a graphic, or metadata for the document. Evidence is recorded and carried per scope, never per item, so item counts and scope counts are different numbers and are never added together.

Fixing the source and re-exporting is often the sensible route. A well-structured Word or InDesign file that exports correct tags removes the problem at its origin, and nothing here argues against that where it is available. This walkthrough is for the situation where tagging and checking happened on the PDF, the client has sent a new export, and that PDF-side work would otherwise be lost. The first project costs real work: someone has to review the baseline and record what they actually checked before there is anything to carry. Value appears from the second revision onward, and only when the revision stays within what the engine can match.

## 1. The baseline

A fictional three-page volunteer guide for a fictional library, generated with ReportLab and pikepdf so its structure is known exactly (`guide-baseline.pdf`, previews `previews/guide-baseline-1.png` to `-3.png`). Each page has an H1, an H2 and four paragraphs, tagged as such. The header strip, footer and page number are artifacts. The document declares a title, English language and PDF/UA-1 identification.

After import:

| Fact | Value |
|---|---|
| Pages | 3 |
| Items | 19: document properties plus 18 text elements |
| Scopes | 55, all in the state `imported-baseline` |
| Review events | 0 |

Importing a tagged file creates no review records. Tags are not evidence.

## 2. Record what was checked

PDFCarry stores a review event when a reviewer marks a scope on an item as checked. In a real project you record only what you actually verified, and you can leave things unchecked. For this example a script recorded all 55 scopes at once so the next step has something to carry.

That shortcut is visible in the files. Every event names its reviewer as `SYNTHETIC fixture setup - not a professional reviewer` and carries the note "Automated synthetic records solely to demonstrate evidence carryover; no human accessibility review occurred." Reviewer names in PDFCarry are local labels, not authenticated signatures, which is why the manifest quotes them rather than trusting them.

Result: 55 of 55 scopes recorded, 19 review events, one per item.

## 3. The revision arrives

The revised export (`guide-revision.pdf`, preview `previews/guide-revision-2.png`) changes three things:

- The orientation sentence on page 2 now reads "11 am on Tuesday" instead of "10 am on Monday".
- A fifth paragraph, "Bring the updated shift checklist to orientation.", is added to page 2.
- Every element, headings included, is tagged as a paragraph.

The revision is imported into the same project. The baseline is never altered; both originals are kept and their hashes are checked after the run.

## 4. Inspect what carried

Per item, per scope, after the revision. "kept" means a prior review record carried; "reopened" means it carried and was reopened with a recorded reason; "none" means no carried review.

| Item | Structure | Reading order | Language |
|---|---|---|---|
| Document properties (single scope: metadata) | kept | | |
| **Page 1** | | | |
| Harbour Library volunteer guide (H1 restored) | kept | reopened | kept |
| Welcome to the team (H2 restored) | kept | reopened | kept |
| This fictional guide explains a small library volunteer shift. | kept | reopened | kept |
| A coordinator welcomes each volunteer at the front desk. | kept | reopened | kept |
| Read the shift notes before helping visitors find their books. | kept | reopened | kept |
| Ask the coordinator whenever a request is outside your role. | kept | reopened | kept |
| **Page 2, where the content changed** | | | |
| Preparing for a shift (H1 restored) | kept | reopened | kept |
| Before visitors arrive (H2 restored) | kept | reopened | kept |
| Leave the entrance and the reading area clear of boxes. | kept | reopened | kept |
| The weekly orientation begins at 11 am on Tuesday. (changed) | none | none | none |
| Keep the large-print catalogue beside the information desk. | kept | reopened | kept |
| Tell the coordinator if any visitor information has changed. | kept | reopened | kept |
| Bring the updated shift checklist to orientation. (new) | none | none | none |
| **Page 3** | | | |
| Closing the reading room (H1 restored) | kept | reopened | kept |
| A consistent handover (H2 restored) | kept | reopened | kept |
| Return reference copies to their labelled shelves. | kept | reopened | kept |
| Record unresolved questions in the handover notebook. | kept | reopened | kept |
| Leave the next shift a clear account of unfinished tasks. | kept | reopened | kept |
| Thank you for helping make the reading room welcoming. | kept | reopened | kept |

Totals: 58 scopes, of which 35 kept, 17 reopened and 6 with no carried review. 20 items, of which 19 need some review and only the document properties item is fully covered. Review events: 19 before the revision, 19 after. Importing a revision creates no new review records.

**Headings came back.** All six heading elements in the output carry their baseline roles, H1 and H2 on each page, even though the incoming file tagged them P. The engine restored a justified baseline role where the text and position matched. It did not guess new headings.

**Reading order reopened on every carried item, not only page 2.** All 17 carried text items show reading order as reopened, with the recorded reason "A dependency changed between document versions." Adding a paragraph changes the sequence, and in this run the engine did not attempt to localise that to one page. This is deliberately conservative. The accurate summary is therefore not "two sentences need checking". It is: structure and language carried on 17 items, reading order needs a fresh pass everywhere, and two items start from nothing.

**Changed and new text carried nothing.** The altered orientation sentence and the new checklist sentence have no carried evidence on any scope.

The output renders pixel-identical to the incoming revision on all three pages (`guide-output-for-review.pdf`, previews `previews/guide-output-for-review-1.png` to `-3.png`).

## 5. Export with evidence

The export produces a PDF and a manifest (`guide-evidence.json`). The manifest records the SHA-256 of that exact PDF, the purpose of the export, the machine validation result, and every carried, reopened or missing scope with its reviewer label, note and date. It applies to that file only. Edit the PDF anywhere else and the hash no longer matches.

| Fact | Value |
|---|---|
| PDF SHA-256 in manifest | `13c636341f7dd1ebbbf41e94ec8edef46f1fad8b5a57f3810cb1d68bd444b467` |
| Export purpose | `further-review` (human checks are incomplete) |
| Machine validation | veraPDF 1.30.2, PDF/UA-1: passed, 106 rules, 2,663 checks, 0 failures |
| Validation scope, quoted | Machine-checkable PDF/UA-1 requirements only; not full accessibility approval. |

A passing validator and a nineteen-item review backlog sit side by side in the same manifest. That is the normal state of a revised document.

## The refusal: a changed table

The second case is a one-page synthetic Word document from the repository's test fixtures. The baseline (`table-baseline.pdf`) is tagged and its header row was explicitly promoted to header cells with column scope. The revision (`table-revision.pdf`) is an untagged Word export of the same page in which the amount for the Review row changes from 100 to 900.

The engine refused to reuse the table. The recorded warning is: "Complete group text, boundaries or geometry could not be uniquely established." Role: Table. The output (`table-output-for-review.pdf`) contains no Table structure at all. The cells are present as individual items, the number 900 is preserved, and the page renders identically, but the table as a table has to be rebuilt by a person, in PDFCarry if it can be uniquely reconstructed, or in an external editor.

| Item | Structure | Reading order | Language | Alt text |
|---|---|---|---|---|
| Document properties (single scope: metadata) | kept | | | |
| A guide to accessible revisions (H1 carried) | kept | reopened | kept | n/a |
| This introduction stays the same between revisions. | kept | reopened | kept | n/a |
| **Table refused for reuse** | | | | |
| Service | none | none | none | n/a |
| Amount | none | none | none | n/a |
| Graphic without text | none | none | none | none |
| Review | none | none | none | n/a |
| 900 (changed; baseline said 100) | none | none | none | n/a |
| Graphic without text | none | none | none | none |
| Export | none | none | none | n/a |
| 200 | none | none | none | n/a |
| Graphic without text | none | none | none | none |
| **After the table** | | | | |
| A stable closing note completes the document. | kept | reopened | kept | n/a |

Totals: 40 scopes, of which 7 kept, 3 reopened and 30 with no carried review. 13 items, 12 needing review. Review events: 11 before, 11 after.

Some unrelated text did carry. The heading, the introduction and the closing note kept structure and language and reopened reading order, exactly as in the guide case. The refusal is scoped to the group that could not be matched, not the whole page.

**What machine validation reported.** The output fails PDF/UA-1 on 3 rules and 5 checks. The report lists a missing PDF/UA identification, a missing document title, and three Figure elements without alternative text. Those three figures are drawings with no text; whether they are table rules or something else is not something the validator determines, and this article does not attribute them. What the report cannot show is the table's missing semantics. In this run, the validator reported no missing-table-structure failure. That does not establish that the table is accessible. The refusal record and a person are what tell you the table needs rebuilding.

| Rule | Failed checks | Validator message |
|---|---|---|
| ISO 14289-1 clause 5, test 1 | 1 | The document metadata stream doesn't contain PDF/UA Identification Schema |
| ISO 14289-1 clause 7.3, test 1 | 3 | Figure structure element neither has an alternate description nor a replacement text |
| ISO 14289-1 clause 7.1, test 9 | 1 | Metadata stream does not contain dc:title |

Manifest: `table-evidence.json`. PDF SHA-256: `48d110dfd819db7d4af25beae1f83b08a0f2e3124a42af48aadd40e3857ff258`. Export purpose `further-review`. veraPDF 1.30.2: 103 rules passed, 3 failed; 920 checks passed, 5 failed.

What a specialist does next is ordinary work: set the title and PDF/UA identification, describe or mark the three graphics, rebuild the table with its header cells, then record those checks. The engine's contribution was to refuse quietly and say why, rather than carrying a header-cell review onto a table whose numbers had changed.

## What this example does not show

- No human review. All 30 review events across both cases are automated setup.
- No timing. Setup, review and export durations were not measured, and no time saving is claimed or implied.
- Controlled producers. The guide was generated so its structure is exact; the table is a small Word fixture. Real exports from Acrobat, InDesign, CommonLook or other tools were not tested in this run.
- Small documents. Three pages and one page. The supported envelope is born-digital PDF 1.x up to 50 MB, 200 pages and 20,000 structure elements.
- Out of scope by design: scanned pages, encrypted or signed files, interactive forms and XFA, PDF 2.0, complex or changed tables, mixed or stream-scoped structure, and untagged grouped graphics containing text.
- Not certification. A veraPDF pass covers machine-checkable PDF/UA-1 rules. Reading order, meaningful alternative text, heading logic and table relationships still need a person.
- Not a release. The run used the installed local PDFCarry 0.2.2 Python engine at source commit `f33848a`, not a signed public installer. Windows only.

## Files

Checksums are copied from `SHA256SUMS.txt` in this folder.

| File | Role | SHA-256 |
|---|---|---|
| `guide-baseline.pdf` | Guide case, tagged baseline | `1a6ff2915faaa9b5b190749d0556c51d9a3a3a6f64706d1a8893fb19c8f06683` |
| `guide-revision.pdf` | Guide case, revision with headings tagged P | `fc1e621742db299b94f6c1fdc337571818ed3ee3f4d6b06beb7f3268449f1852` |
| `guide-output-for-review.pdf` | Guide case, exported output | `13c636341f7dd1ebbbf41e94ec8edef46f1fad8b5a57f3810cb1d68bd444b467` |
| `guide-evidence.json` | Guide case, evidence manifest | `2fbde60298a18673f8c517d0893d18876d23e24524a7957ed753ae11a8f8f681` |
| `table-baseline.pdf` | Table case, tagged baseline with header cells | `394f8479914052f5538a95bfa848f28ac3a76b9de0dad6e818a7f60ca712a129` |
| `table-revision.pdf` | Table case, untagged revision, 100 changed to 900 | `8e241ec3e0e2f7d323e715ff9029c73d04baf9509a4c28b00e90685cba98954a` |
| `table-output-for-review.pdf` | Table case, exported output | `48d110dfd819db7d4af25beae1f83b08a0f2e3124a42af48aadd40e3857ff258` |
| `table-evidence.json` | Table case, evidence manifest | `741dd87123a131db7a3f30c68ced1406ad57bad8063f46b74bf7ec6d2c108eed` |
| `results.json` | Run summary, the source of every count above | `524ed6a47af1507abdb1701cc8fc91ef4d37cad498dee3faa89c629b79ed7383` |

Page previews are in `previews/`. `README.md` records the engine, source commit, fixture provenance and the command that regenerates the pack. `index.html` is the same walkthrough with the page comparison and scope totals first, then the ledgers and previews laid out for reading and printing.

The public customer guide at https://pdfcarry.com/guide describes the current application. Questions about these files: support@pdfcarry.com.
