Skip to content

Visual compare emits a Blocks Engine report schema #2399

Description

@chubes4

Follow-up to #732.

The boundary

#732 built the visual-compare primitive with an explicit split: WP Codebox owns the generic evidence substrate, downstream products own policy. Its acceptance criteria state:

No downstream-specific thresholds, Static Site Importer semantics, Data Liberation semantics, or pass/fail policy are encoded in WP Codebox.

What shipped

browser-visual-compare exports blocksEngineVisualParityReportFromVisualCompare(), returning a BlocksEngineVisualParityReport with schema: "blocks-engine/php-transformer/visual-parity-report/v1".

That type carries verdicts, not evidence:

status: "pass" | "warning" | "fail" | "unknown";
severity: "none" | "info" | "warning" | "error" | "critical";

It is also not opt-in. The adapter is called in four places inside browser-visual-compare.js, and each writes two things:

await artifactSession.writeJson("visualDiff", "visual-diff.json", summaryWithBlocksEngineVisualParity);
await artifactSession.writeJson("blocksEngineVisualParity", "blocks-engine-visual-parity-report.json", blocksEngineVisualParity);

So the downstream report is written as its own artifact and embedded inside the generic one. Every consumer of visual-diff.json receives a blocksEngineVisualParity field carrying another product's schema and its pass/fail verdict, whether or not it has anything to do with Blocks Engine.

Why it matters beyond naming

The status mapping is policy. identical → pass, different → fail, partial → warning is one product's threshold decision, made inside the substrate that was specified not to make it.

It also sets a precedent. #732 names wp-site-generator, data-liberation-agent, and static-site-importer as consumers. If one gets a bespoke report shape in the shared artifact, the others have a reasonable claim to theirs, and the generic artifact becomes a union of downstream schemas.

Where it should live

The schema is owned and consumed by blocks-engine's php-transformer — its parity test fixtures are the readers. static-site-importer sees it only transitively through the vendored figma transformer. data-liberation-agent does not reference it at all.

So the mapping belongs next to the schema that defines it, in blocks-engine, consuming Codebox's generic visual-diff.json.

Suggested shape

  • Stop embedding blocksEngineVisualParity in visual-diff.json.
  • Move blocksEngineVisualParityReportFromVisualCompare and BlocksEngineVisualParityReport to the consumer that owns the schema.
  • Keep visual-diff.json as the normalized generic evidence Add generic browser visual-compare evidence primitive #732 specified: mismatch ratio, diff pixels, dimensions, viewport/profile metadata, source/candidate metadata, pairing strategy, explicit missing-capture and decode failures.

The coupling is small — two declaration files, one schema string, one function and its interface — so this is a contained change rather than a redesign.

AI assistance

Claude via OpenCode inspected the shipped runtime-playground visual-compare surface, traced the adapter's call sites and artifact writes, and identified the consuming repositories. Chris Huber directed and reviewed the finding.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions