@decocms/parity 0.11.10 → 0.11.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [0.11.11](https://github.com/decocms/parity/compare/v0.11.10...v0.11.11) (2026-06-17)
9
+
10
+ ### Fixed
11
+
12
+ * **Runtime auto-install was incomplete in 0.11.10.** The 0.11.10 install path ran `npx --yes playwright install chromium` and reported success, but Playwright 1.49+ launches `chromium-headless-shell` for `headless: true` — that's a *separate* binary download. The retry still failed with `Executable doesn't exist at .../chrome-headless-shell` and the user saw the friendly fallback message even though we tried to fix it. Live-reproduced against bagaggio.
13
+ * **Now installs both `chromium` AND `chromium-headless-shell`** so `parity run` works headless without manual intervention.
14
+ * **Uses the bundled Playwright CLI, not `npx --yes playwright`.** `npx --yes` may fetch a *different* Playwright version into its cache, and the binaries it downloads may not match the version `parity` actually launches — so even a successful install can leave the retry failing. We now resolve `playwright/cli.js` via `createRequire` against the local `node_modules` and spawn `node <local-cli> install chromium chromium-headless-shell` — guaranteed version-matched. Falls back to `npx` only if the local resolution fails.
15
+ * **Validated locally end-to-end**: cleared `~/Library/Caches/ms-playwright`, ran `parity audit`, both binaries downloaded (`chromium-1217` + `chromium_headless_shell-1217`), audit completed successfully — no manual `npx playwright install` needed.
16
+
8
17
  ## [0.11.10](https://github.com/decocms/parity/compare/v0.11.9...v0.11.10) (2026-06-17)
9
18
 
10
19
  ### Fixed
package/dist/cli.js CHANGED
@@ -1619,6 +1619,8 @@ function countBy(arr, pick) {
1619
1619
 
1620
1620
  // src/engine/browser.ts
1621
1621
  import { spawnSync } from "node:child_process";
1622
+ import { createRequire as createRequire2 } from "node:module";
1623
+ import { dirname, resolve as resolvePath } from "node:path";
1622
1624
  import { chromium, devices } from "playwright";
1623
1625
 
1624
1626
  // src/engine/carousel-stabilizer.ts
@@ -1822,18 +1824,33 @@ async function launchBrowser(opts = {}) {
1822
1824
  }
1823
1825
  }
1824
1826
  function installChromiumSync() {
1825
- const result = spawnSync("npx", ["--yes", "playwright", "install", "chromium"], {
1827
+ const localCli = resolveLocalPlaywrightCli();
1828
+ const cmd = localCli ? { command: process.execPath, args: [localCli, "install", "chromium", "chromium-headless-shell"] } : { command: "npx", args: ["--yes", "playwright", "install", "chromium", "chromium-headless-shell"] };
1829
+ const result = spawnSync(cmd.command, cmd.args, {
1826
1830
  stdio: "inherit",
1827
1831
  env: process.env
1828
1832
  });
1829
1833
  return result.status ?? 1;
1830
1834
  }
1835
+ function resolveLocalPlaywrightCli() {
1836
+ try {
1837
+ const req = createRequire2(import.meta.url);
1838
+ const pkgJsonPath = req.resolve("playwright/package.json");
1839
+ const pkg = req("playwright/package.json");
1840
+ const binEntry = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.playwright;
1841
+ if (!binEntry)
1842
+ return null;
1843
+ return resolvePath(dirname(pkgJsonPath), binEntry);
1844
+ } catch {
1845
+ return null;
1846
+ }
1847
+ }
1831
1848
  function missingBrowserError(cause) {
1832
1849
  const original = cause instanceof Error ? cause.message : String(cause);
1833
1850
  return new Error([
1834
1851
  "Playwright's Chromium binary is not installed.",
1835
- "Run: npx playwright install chromium",
1836
- "Or set PARITY_SKIP_PLAYWRIGHT_INSTALL=0 and rerun `parity` to auto-install.",
1852
+ "Run: npx playwright install chromium chromium-headless-shell",
1853
+ "Or unset PARITY_SKIP_PLAYWRIGHT_INSTALL and rerun `parity` to auto-install.",
1837
1854
  "",
1838
1855
  `Original error: ${original}`
1839
1856
  ].join(`
@@ -10267,7 +10284,7 @@ async function visualSemanticDiff(input) {
10267
10284
  // src/checks/lib/parity-cache.ts
10268
10285
  import { createHash } from "node:crypto";
10269
10286
  import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
10270
- import { dirname, join as join6 } from "node:path";
10287
+ import { dirname as dirname2, join as join6 } from "node:path";
10271
10288
  function hashScreenshotPair(prodPath, candPath, promptVersion) {
10272
10289
  const h = createHash("sha256");
10273
10290
  h.update(readFileSync6(prodPath));
@@ -10296,7 +10313,7 @@ function readCache(cacheDir) {
10296
10313
  }
10297
10314
  function writeCache(cacheDir, cache) {
10298
10315
  const file = cacheFilePath(cacheDir);
10299
- mkdirSync3(dirname(file), { recursive: true });
10316
+ mkdirSync3(dirname2(file), { recursive: true });
10300
10317
  writeFileSync6(file, JSON.stringify(cache, null, 2));
10301
10318
  }
10302
10319
  function getCacheEntry(cache, hash2, currentPromptVersion) {
@@ -12058,7 +12075,7 @@ async function resolveSearchTerms(url, html, opts = {}) {
12058
12075
 
12059
12076
  // src/learned/repo.ts
12060
12077
  import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync10, renameSync, writeFileSync as writeFileSync9 } from "node:fs";
12061
- import { dirname as dirname2 } from "node:path";
12078
+ import { dirname as dirname3 } from "node:path";
12062
12079
  import { z as z2 } from "zod";
12063
12080
  var SelectorKey = z2.enum([
12064
12081
  "categoryLink",
@@ -12123,7 +12140,7 @@ function loadLearned(path = DEFAULT_PATH) {
12123
12140
  }
12124
12141
  }
12125
12142
  function saveLearned(lib, path = DEFAULT_PATH) {
12126
- const dir = dirname2(path);
12143
+ const dir = dirname3(path);
12127
12144
  if (dir && dir !== "." && !existsSync10(dir))
12128
12145
  mkdirSync7(dir, { recursive: true });
12129
12146
  const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
@@ -15767,7 +15784,7 @@ function analyzeHeatmapBuffer(data, width, height, opts = {}) {
15767
15784
 
15768
15785
  // src/diff/section-bundle.ts
15769
15786
  import { writeFileSync as writeFileSync11 } from "node:fs";
15770
- import { basename as basename2, dirname as dirname3, join as join13, relative as relative3 } from "node:path";
15787
+ import { basename as basename2, dirname as dirname4, join as join13, relative as relative3 } from "node:path";
15771
15788
 
15772
15789
  // src/engine/computed-styles.ts
15773
15790
  var SECTION_STYLE_KEYS = [
@@ -16045,7 +16062,7 @@ function renderMarkdownBundle(input, deltas) {
16045
16062
  }
16046
16063
  function relativeOrAbs(outDir, absPath) {
16047
16064
  try {
16048
- if (dirname3(absPath) === outDir)
16065
+ if (dirname4(absPath) === outDir)
16049
16066
  return basename2(absPath);
16050
16067
  return relative3(outDir, absPath);
16051
16068
  } catch {
@@ -20005,11 +20022,11 @@ function printSummary6(vitals, cache) {
20005
20022
 
20006
20023
  // src/util/version.ts
20007
20024
  import { readFileSync as readFileSync18 } from "node:fs";
20008
- import { dirname as dirname4, resolve as resolve3 } from "node:path";
20025
+ import { dirname as dirname5, resolve as resolve3 } from "node:path";
20009
20026
  import { fileURLToPath } from "node:url";
20010
20027
  function getPackageVersion() {
20011
20028
  try {
20012
- const here = dirname4(fileURLToPath(import.meta.url));
20029
+ const here = dirname5(fileURLToPath(import.meta.url));
20013
20030
  for (const up of ["..", "../..", "../../.."]) {
20014
20031
  try {
20015
20032
  const pkgPath = resolve3(here, up, "package.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/parity",
3
- "version": "0.11.10",
3
+ "version": "0.11.11",
4
4
  "description": "E2E parity validator for site migrations. Compares prod vs cand and reports UI, functional, SEO, visual, and Web Vitals deltas with an LLM-ranked HTML report.",
5
5
  "type": "module",
6
6
  "license": "MIT",