Index

An MX Audit, Read by an Engineer

An MX audit is rendered through a pipeline that places every fact into a skeleton, rewrites the skeleton into prose, gates the prose against a battery of deterministic checks, and ships a tagged PDF along with a provenance sidecar pair. We walk through the artefact from an engineer's perspective: the scorecard, the page composition, the sidecar layout, the regression tests, and the contract that makes the PDF MX Compatible.

One vocabulary in the Balanced Scorecard

The Balanced Scorecard at the top of every audit report grades each dimension on a four-band scale (Excellent, Good, Could Be Better, Needs Improvement) with a letter grade alongside (A through D). The vs Peers column speaks the same vocabulary, never raw numbers. Each cell reads as A (median), B (median), C (median), or D (median).

The helper that maps a raw score to a band lives in scoreBandFromValue() at mx-reginald/audit/bin/infill-report.js. The peer-comparison formatter (formatPeerComparison()) routes the peer median through the same helper before emitting the cell, so the row's own grade and its peer comparison can never speak different languages. The boundaries (76, 51, 26) and band names also live as a single source of truth in mx-reginald/audit/lib/scoring-methodology.json for any tooling that wants to read the same enum.

Contents lands on its own page

A cover doctype's PDF flow is: title plus MX Compatible badge on page one, contents on page two, body from page three onward. The cover-to-contents break comes from break-after: page on section.mx-compatible-zone. The contents-to-body break comes from a dedicated rule in scripts/templates/pdf/_base.css:

nav#TOC {
  break-before: page;
  page-break-before: always;
  break-after: page;
  page-break-after: always;
}

Both the modern (break-*) and legacy (page-break-*) properties are set because the rendering engine pairs CSS Paged Media with Chrome's print path. Doctypes that hide the TOC entirely (letter, blog-post, briefing-2col) set display: none on nav#TOC, so the break rule is a no-op there.

Findings ride in a sibling sidecar

Every audit goes through deterministic gates that catch scope mis-statements, exaggeration in prose, unverified numeric claims, voice drift, and similar reviewer-only signals. The gates record every finding to audit_errors.json and the pipeline continues; nothing fails the run. This is the always-produce-PDF contract: a failing gate becomes a recorded warning, not an exit code.

The findings travel with the report as a sibling sidecar named after it:

mx-outputs/audit/<date>/<host>/
├── <basename>-report.md
├── <basename>-report.pdf
├── <basename>-report-findings.md
├── <basename>-report-fierce-critic.json
└── <basename>-report.provenance.ai.json

The findings sidecar is a complete markdown document with its own MX frontmatter (contentType: audit-findings, companion: <report>.md). It carries the gate name, the category, the timestamp, and the supporting evidence for every finding, by severity. The reviewer reads the sidecar before sign-off; the client reads the report.

The renderer at mx-reginald/audit/lib/render-error-section.js exposes renderFindingsMarkdownDoc() for the sidecar; a legacy renderErrorReportSection() survives as an empty no-op so older skeletons that still carry [ERROR_REPORT_SECTION] resolve to invisible sentinels. The post-gates regenerator script writes the sidecar and strips any residual block out of the report markdown. Templates and contracts no longer reference the placeholder.

Tests that hold the contract

Two regression tests live under mx-reginald/audit/test/ and exercise the path from canned fixtures to a rendered skeleton. infill-golden.test.js renders the canonical web-audit-suite template against a synthetic example.com fixture and asserts byte-identical output against golden-skeleton.md; the fixture writes through a stable host-slug subfolder so the rendered mx.generate.output line is deterministic. audit-gates.test.js covers every gate's exit-code contract, including the deterministic verifier's always-continue behaviour: on the unsupported-numeric fixture the verifier exits zero and stdout names unverified claim(s) - logged as warnings, so the test asserts both the exit code and the message.

An MX Compatible regression test

The phrase "MX Compatible" names a specific set of signals an inspector can verify on the rendered PDF: provenance sidecar pair on disk, the pdfuaid:Part=1 Level 2 declaration, MX-namespaced XMP fields populated from frontmatter, pointer fields naming the sidecars, and the full AI evidence chain embedded inline under XMP-mx:ProvenanceAiPayload.

tests/test-pdf-mx-compatible.js at the hub root writes a fixture markdown to a tmp dir with the full mx frontmatter and a declared x-mx-provenance block, renders it through scripts/bin/mx.pdf.sh, then makes eleven assertions: the two sidecars on disk, the PDF/UA declaration, five identity fields, two pointer fields, and one byte-for-byte match between the embedded XMP payload and the adjacent .ai.json after JSON normalisation. The test is wired into npm test and exposed as npm run test:pdf-mx-compatible.

An engineer who wants to sanity-check the contract from outside the repository can run the same probes by hand. The interactive inspector at /tools/pdf-inspector.html accepts any MX PDF and walks the chain in the browser; the explainer at /learn/mx-for-pdfs.html maps each signal to the standard it cites.

How the pieces fit

One scoring vocabulary across every row of the scorecard. One contents page on its own page. One sibling sidecar carrying every reviewer signal so the report markdown stays client-facing. A regression-tested PDF contract that an inspector can verify in a browser or from the command line.

The shared property across all of those is the same: each part of the deliverable does one job, and the part that does it is the part the reader expects to look at. The report carries the argument. The sidecar carries the reviewer's working. The XMP packet carries the evidence chain. The tests catch when any of them stops doing its job.

Back to Top