@productmakersro/fidelity-engine
v0.1.0
Published
Thin CLI wrapper around the vendored fidelity-machine engine: pixel/geometry/content verification for design-locked screens, plus a Chromium build-pin guard.
Readme
@productmakersro/fidelity-engine
Thin CLI wrapper around the vendored fidelity-machine engine — a machine-verified ship
gate for design-locked screens (render, geometry, pixel-diff, content/microcopy lint). See
PROVENANCE.md for exactly what is vendored, what is deliberately excluded, and why.
This package does not modify the engine. vendor/ is a byte-for-byte copy; bin/ and lib/
are thin wrappers this package adds on top.
Install
npm install @productmakersro/fidelity-engineInstalling playwright triggers its own postinstall step that downloads the pinned Chromium
build. If you need to skip that (e.g. scripted/offline installs, CI dependency-resolution
steps that don't need to render), set PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 before npm
install, then run npx playwright install chromium yourself when you're ready to render.
Check readiness any time with:
npx pm-setup-checkBinaries
pm-setup-check
Readiness diagnostic. Checks Node version, that pixelmatch/pngjs/playwright/esbuild
resolve from this package's own node_modules, and that a Chromium executable exists on disk
— reporting everything it finds, never installing anything itself. Thin passthrough to the
vendored vendor/scripts/setup-check.mjs; this wrapper adds no logic of its own.
npx pm-setup-check [--expect-build <chromium-build-id>] [--help]Pass --expect-build chromium-1228 (the build this package pins — see vendor/engine.config.json)
to also get a build-mismatch warning in the report. A mismatch here is reported, not
enforced — see "Why pm-setup-check has no hard pin guard" below.
pm-verify
Runs the full three-gate pipeline (content/compliance lint → geometry → pixel diff) against a
design-lock.json you supply. Thin passthrough to the vendored vendor/scripts/verify.mjs,
plus a hard pre-flight Chromium build-pin guard this package adds (see below) that runs
before the vendored script is even started.
npx pm-verify --lock <path/to/design-lock.json> [--screen <id>] [--calibrate] [--src <dir>]pm-verify --check-vendor is a separate mode, recognized only when it is the sole
argument: it verifies vendor/ against vendor/CHECKSUMS.sha256 (a sha256 manifest of the 22
files this package vendors — see PROVENANCE.md) and exits without touching Chromium,
Playwright, or the vendored verify.mjs — no network, no browser needed. Equivalent to
npm run check-vendor inside a checkout of this package.
npx pm-verify --check-vendorpm-verify --lock x.json --check-vendor (or any other combination) is not this mode —
--check-vendor there passes through verbatim as just another argument to verify.mjs, which
does not recognize it and exits 2, same as any other unknown argument would.
pm-export
Renders a canvas HTML file to a PNG at its true pixel size. Adapted (not vendored — see
PROVENANCE.md) from ProductMakersStudio's repo-root scripts/pm-export.mjs, plus the same
pre-flight Chromium build-pin guard pm-verify uses.
npx pm-export --in <canvas.html> [--out <file.png>] [--width 1080] [--height 1350] [--scale 1]Waits for document.fonts.ready and [data-render-ready] before shooting, so the PNG never
captures a fallback font face. Relative --in/--out paths resolve against the current
working directory.
Also tracks every subresource request the page makes (stylesheet, images, fonts) and fails
(exit 1, listing each URL) if any failed to load — a canvas can visually "settle" and produce
some PNG even with its stylesheet/logo/watermark all 404ing (e.g. copied away from the
assets/ directory it ships next to), and this refuses to ship that PNG under exit 0. A
clean render's stdout always states the count (0 failed subresource requests) so callers have
something positive to assert on.
Why pm-export has its own exit-code scheme
Unlike pm-verify (which delegates to the vendored verify.mjs and preserves its 0-5 table
verbatim), pm-export is original code with no vendored script underneath it — there is no
verify-table meaning to inherit. It keeps the exit scheme its ProductMakersStudio original
already used: 0 pass, 1 render failure, 2 usage/setup error. Its pre-flight chromium-pin
guard reuses 2/4 from the shared guard table below, same as pm-verify's.
Exit codes
pm-verify preserves the delegated vendored script's exit code exactly once delegation
happens — this package never rewrites or reinterprets a code the vendored engine produced.
The full engine exit-code table (from vendor/CONTRACT.md) — this table does NOT apply to
pm-export, which has no vendored script underneath it and keeps its own small scheme (see
"Why pm-export has its own exit-code scheme" above):
| Code | Meaning | Actionable by |
|---|---|---|
| 0 | pass | — |
| 1 | fidelity/lint failure — real finding, feed evidence back to the model | model fix round |
| 2 | setup/usage error (missing dep, bad args, unparseable lock) | human/setup |
| 3 | DIMENSION_MISMATCH — render dims ≠ reference dims. Config error, not a fix target. | lock config |
| 4 | FONT_PARITY — a required document.fonts.check() failed. | fonts/bundling |
| 5 | render failure/timeout | environment |
pm-verify AND pm-export's shared pre-flight chromium-pin guard (runs before either
binary does its real work, so it can never collide with a code the delegated/rendered work
itself would have returned) reuses two of the same numbers, with a narrower, guard-specific
meaning — both binaries call the exact same lib/chromium-pin.mjs function, so a build
mismatch is diagnosed identically either way:
| Code | Guard meaning | Fix |
|---|---|---|
| 2 | playwright package not installed/loadable at all | npm install |
| 4 | Pinned Chromium build (chromium-1228) not confirmed — missing executable, unrecognized layout, or a different build present (often from a stale/foreign PLAYWRIGHT_BROWSERS_PATH) | unset PLAYWRIGHT_BROWSERS_PATH if set, then npx playwright install chromium; or npm install to reinstall the pinned [email protected] |
--help/-h always bypasses the guard on both binaries, so pm-verify --help/pm-export
--help work even with a broken Playwright/Chromium environment.
pm-verify --check-vendor short-circuits before the chromium-pin guard too — it exits 0 on a
match or 2 on any mismatch (a changed, missing, or extra file relative to
vendor/CHECKSUMS.sha256), reusing exit code 2's existing "setup/usage error" meaning from
the table above.
The Chromium pin
vendor/engine.config.json pins chromiumBuild: "chromium-1228" — every reference image this
engine's noise-floor calibration and pixel-diff gate depend on was captured against exactly
that Chromium build. This package pins its playwright dependency to the exact version
whose bundled Chromium is that build: "playwright": "1.61.1" (no ^/~ — verified against
[email protected]'s browsers.json, which lists {"name": "chromium", "revision":
"1228", ...}). A different Playwright version bundles a different Chromium build, which
silently invalidates every stored reference (CONTRACT.md determinism invariant 1) — a render
would still "succeed" but the diff would be meaningless.
Why pm-setup-check has no hard pin guard
vendor/scripts/setup-check.mjs already resolves and reports the Chromium build, and already
accepts a repeatable --expect-build flag for this exact comparison — by design, as a
warning, never a failure (its own comment: "still exit 0 — a build mismatch is a
determinism risk, not a missing dependency"). pm-setup-check is a passthrough with no added
logic; turning that documented warning into a hard exit-4 here would both contradict the
vendored script's own stated design and violate this package's "preserve exit codes exactly"
rule for the delegated script. The hard guard belongs where a wrong build could otherwise
produce a silent, wrong render: pm-verify.
Development
This package's own original code — bin/ and lib/ (vendor/ is untouched upstream) — has
an automated test suite under test/ (not shipped in the published tarball). It never installs
or downloads a Chromium build; the pin-confirmed case runs only when this machine already has
one cached, and skips itself otherwise.
npm testApache attribution
This package's LICENSE and NOTICE are copied verbatim from the standalone
fidelity-machine project (Apache-2.0, Copyright Tudor Juravlea) — see PROVENANCE.md for
why, and for the correction this required from the original build brief.
