@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 +9 -0
- package/dist/cli.js +28 -11
- package/package.json +1 -1
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
|
|
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
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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 (
|
|
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
|
|
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 =
|
|
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.
|
|
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",
|