@decocms/parity 0.1.0

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/AGENTS.md ADDED
@@ -0,0 +1,112 @@
1
+ # AGENTS.md
2
+
3
+ Guidance for AI coding agents (Claude Code, Cursor, Aider, etc.) using `parity` to validate or fix a site migration.
4
+
5
+ ## When to run parity
6
+
7
+ Use `parity run` (or `parity journey` in CI) when the user:
8
+
9
+ - finished migrating a section / page / route and wants to verify nothing regressed
10
+ - mentions "is this still working in cand?" / "compare prod and cand"
11
+ - wants a baseline before starting a refactor
12
+ - asks for a visual diff or "what's missing in the migration"
13
+ - needs a structured artifact (`report.json`) to drive other automation
14
+
15
+ Do **not** run parity for:
16
+
17
+ - linting / type errors — that's `tsc`
18
+ - single-component unit tests — use vitest
19
+ - performance profiling of just one page — use Lighthouse or Chrome DevTools directly
20
+
21
+ ## Picking the command
22
+
23
+ | User intent | Command |
24
+ | -------------------------------------------- | ----------------------------------------------- |
25
+ | "is everything still working?" | `parity run --preset smoke` then `--preset full` if smoke is clean |
26
+ | "compare these two URLs in CI" | `parity journey --prod ... --cand ... --junit ... --github` |
27
+ | "find sections missing in the migration" | `parity run --visual-pages 5` then read `report.json` `.visualDiff` |
28
+ | "did web vitals regress?" | `parity vitals --prod ... --cand ... --limit 20` |
29
+ | "is the new site missing cache?" | `parity cache --cand ... --pages 30` |
30
+ | "I want an LLM prompt with all the issues" | `parity prompt <runId>` (writes Markdown to stdout) |
31
+ | "explain this specific issue" | `parity explain <runId> <issueId>` (needs `ANTHROPIC_API_KEY`) |
32
+
33
+ ## Reading the JSON output
34
+
35
+ `./parity-output/runs/<runId>/report.json` is the source of truth. Key fields:
36
+
37
+ ```ts
38
+ {
39
+ verdict: { status: "pass"|"warn"|"fail", score: 0..100, critical, high, medium, low },
40
+ topIssues: Issue[], // LLM-ranked, deduplicated; usually 5-10 items
41
+ issues: Issue[], // all raw issues from every check
42
+ checks: CheckResult[], // one per check; .data has structured details
43
+ visualDiff: {
44
+ pagesChecked, pagesWithDiffs, pagesPassed,
45
+ results: VisualDiffPage[] // per page: prod/cand screenshots, sections, LLM diffs
46
+ },
47
+ flowCaptures: FlowCapture[] // per-flow page captures with vitals + network
48
+ }
49
+ ```
50
+
51
+ To programmatically decide if a migration is ready:
52
+
53
+ ```ts
54
+ const run = JSON.parse(fs.readFileSync(`${runDir}/report.json`));
55
+ if (run.verdict.critical === 0 && run.verdict.high === 0) {
56
+ // ship it
57
+ }
58
+ ```
59
+
60
+ ## Driving fixes from the output
61
+
62
+ The most useful flow for an AI agent is:
63
+
64
+ 1. Run `parity run --preset full` → wait → read `report.json`
65
+ 2. For each `topIssue` with severity ≥ high, open the file(s) referenced in `suggestedFix`
66
+ 3. For visual diffs: read `visualDiff.results[].sectionsOnlyInProd` — these are Deco sections present in prod's DOM but missing in cand. Most likely cause: not registered in `src/setup.ts → registerSections()`.
67
+ 4. For console errors: read `issues[].evidence[]` for HAR paths; the failed request is usually the root cause.
68
+ 5. Re-run `parity journey` (cheaper) after each fix to confirm.
69
+
70
+ **Important:** prod is the source of truth. Never modify prod-side code to make tests pass — always fix cand.
71
+
72
+ ## When LLM features are unavailable
73
+
74
+ If neither `ANTHROPIC_API_KEY` nor `OPENROUTER_API_KEY` is set:
75
+
76
+ - `topIssues` will fall back to deterministic severity-sorted merge (still useful)
77
+ - `visualDiff.results[].differences` will be empty (only pixelmatch heatmap survives)
78
+ - `sectionsOnlyInProd` is still populated (uses DOM, not vision)
79
+ - Selector discovery is skipped; defaults from `.parityrc.json` or platform heuristics kick in
80
+
81
+ The CLI never fails just because the LLM is unavailable. Issues will still be reported, just less polished.
82
+
83
+ ## Cost-conscious usage
84
+
85
+ A `--preset full` run with visual diff ≈ 6-12 Claude calls × ~$0.01-0.02 each. Cheap, but in tight loops:
86
+
87
+ - Use `--preset smoke` first (no LLM, ~30s) to validate the URLs respond
88
+ - Use `--no-visual-diff` if you only care about functional checks
89
+ - Use `parity journey` (no aggregation step) for the tightest CI loop
90
+
91
+ Hard caps already in place:
92
+
93
+ - 12 max Claude Vision calls per `run` (visual diff)
94
+ - 8 max selector recovery calls per run
95
+ - 120s timeout per Vision call, 60s per text call
96
+
97
+ ## Gotchas
98
+
99
+ - **First run is slower** — Playwright downloads Chromium (~150MB). After that, ~30s for smoke, ~5min for full.
100
+ - **Sites with X-Frame-Options block the side-by-side iframe tab.** Use `parity serve <runId>` which proxies through.
101
+ - **Cookies are isolated per run** — no shared session between prod and cand. If a flow needs auth, you'll need to handle that in `.parityrc.json` or extend the flow.
102
+ - **Visual diff catches missing sections** mostly via DOM (`data-section`); if the migrated site doesn't emit that attribute, the LLM still sees the screenshots but loses the section-name context.
103
+ - **`parity run` doesn't apply schema changes from old runs** — if you change `src/types/schema.ts`, old `report.json` files won't parse. Delete `parity-output/` or re-run.
104
+
105
+ ## Files agents should and should not write
106
+
107
+ - ✅ `.parityrc.json` (selectors, CEP) — gitignored, per-user
108
+ - ✅ `.parityignore` (noise filters) — gitignored
109
+ - ✅ Code changes in `src/` of the candidate site
110
+ - ❌ Don't commit `learned-selectors.json` (gitignored) — it contains host names
111
+ - ❌ Don't commit `parity-output/` — gitignored, can be GB-sized
112
+ - ❌ Don't modify `parity-baselines/<name>.json` by hand — use `parity baseline set`
package/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] — 2026-05-12
11
+
12
+ First public release.
13
+
14
+ ### Added
15
+
16
+ - `parity run` — full comparison between two URLs with 12 built-in checks
17
+ - `parity journey` — CI-friendly purchase journey runner with JUnit + GitHub annotations
18
+ - `parity vitals` — multi-page Web Vitals comparison
19
+ - `parity cache` — CDN cache analysis with opportunities
20
+ - `parity serve` — local HTTP proxy server so side-by-side iframes work for any site
21
+ - `parity baseline` / `parity compare` — track regressions over time
22
+ - `parity prompt` — export prioritized issues as LLM-ready Markdown
23
+ - `parity explain` — LLM root-cause analysis on a specific issue
24
+ - **Visual Diff tab** in the HTML report — galleries of prod / cand / pixelmatch heatmap with per-page Claude Vision analysis, missing-section detection from DOM, and dedicated export prompt
25
+ - **CLI presets** (`--preset smoke|full|ci`) bundling common flag combinations
26
+ - **Pre-flight check** — pings both URLs before the heavy capture phase, fails fast on dead URLs
27
+ - **Hard timeouts everywhere**: 120s per LLM Vision call, 60s per text call, 60s per page capture, 5s per response body read, 5s for the response flush. No more infinite hangs on streaming endpoints.
28
+ - Learned-selectors library with platform detection (VTEX, Shopify, Nuvemshop, Wake, Deco)
29
+ - LLM-driven selector discovery and step recovery
30
+ - Cross-site PDP matching via Claude (fingerprint comparison)
31
+
32
+ ### Security
33
+
34
+ - `learned-selectors.json` is now gitignored and `.npmignored`. It may contain host names of sites you've tested.
35
+ - `.parityrc.json` and `.parityignore` are gitignored — they're per-user config that may reference private URLs.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 deco CMS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # @decocms/parity
2
+
3
+ E2E parity validator for site migrations. CLI that runs comparative tests between two URLs — `prod` (source of truth) and `cand` (migrated version) — and produces a single HTML report flagging UI, functional, SEO, and Web Vitals regressions.
4
+
5
+ Built originally for Fresh → TanStack Start migrations of Deco storefronts, but the checks are generic enough for any side-by-side migration.
6
+
7
+ > **Status:** alpha. APIs and report layout may still change.
8
+
9
+ ## What it checks
10
+
11
+ | Check | What it catches |
12
+ | ----------------------------- | ---------------------------------------------------------------------- |
13
+ | HTTP status parity | Routes that 404 / 500 in cand but worked in prod |
14
+ | Console errors | New hydration mismatches, failed fetches, JS exceptions |
15
+ | HTML structural diff | Section / element counts drifting beyond tolerance |
16
+ | Meta / SEO parity | `<title>`, `<meta description>`, canonical, og:\*, twitter:\*, JSON-LD |
17
+ | **Visual diff (LLM Vision)** | Sections missing, wrong hero, broken shelf, layout shifts |
18
+ | Purchase journey | Home → PLP → PDP → CEP → cart → checkout completes in both |
19
+ | Network summary | Request count / bytes / cache hit rate |
20
+ | Web Vitals | LCP, FCP, TTFB, INP, CLS — mobile |
21
+ | Image loading health | Missing alt text, no srcset, broken `<img>` |
22
+ | Lazy section presence | Deco `/deco/render` and `/_loader/*` routes responding |
23
+ | SEO deep audit | robots.txt, sitemap, noindex regressions |
24
+ | Cache coverage | Cache hit rate, opportunities to cache |
25
+
26
+ All results are aggregated (optionally via Claude) and ranked by severity. Each issue includes screenshots, reproduction, and a suggested fix.
27
+
28
+ ## Quickstart
29
+
30
+ ```bash
31
+ # Install
32
+ npm install -g @decocms/parity
33
+ # or run without install
34
+ npx @decocms/parity run --prod ... --cand ...
35
+
36
+ # First-time smoke run (~30s, no LLM needed)
37
+ parity run \
38
+ --prod https://oldsite.com \
39
+ --cand https://newsite.example.dev \
40
+ --preset smoke --open
41
+
42
+ # Full audit with visual diff (set ANTHROPIC_API_KEY for the LLM bits)
43
+ ANTHROPIC_API_KEY=sk-... parity run \
44
+ --prod https://oldsite.com \
45
+ --cand https://newsite.example.dev \
46
+ --preset full --open
47
+ ```
48
+
49
+ ## Presets
50
+
51
+ `--preset smoke` — homepage only, mobile only, no LLM, no extra crawl. Use to validate the pipeline runs at all (~30s).
52
+
53
+ `--preset full` — purchase journey, mobile + desktop, 5 visual diff pages, 10 vitals pages, LLM enabled if API key is set. Use for releases.
54
+
55
+ `--preset ci` — purchase journey on mobile, smaller crawls (3 visual + 5 vitals). Tuned for CI runtime.
56
+
57
+ Individual flags always override the preset.
58
+
59
+ ## Commands
60
+
61
+ | Command | What it does |
62
+ | ------------------ | ----------------------------------------------------------------------------- |
63
+ | `parity run` | Full comparison run between two URLs |
64
+ | `parity journey` | CI-friendly: only the purchase journey, with JUnit / GitHub annotations |
65
+ | `parity vitals` | Crawl N pages, compare Web Vitals prod vs cand |
66
+ | `parity cache` | CDN cache analysis, opportunities, request categorization |
67
+ | `parity serve` | Local HTTP server with iframe proxy so side-by-side tab works for any site |
68
+ | `parity report` | Reopen an existing run's HTML report |
69
+ | `parity compare` | Compare a run against a baseline |
70
+ | `parity baseline` | Manage baselines (`set`, `list`, `unset`) |
71
+ | `parity list` | List saved runs |
72
+ | `parity prompt` | Export issues as a Markdown prompt for any LLM |
73
+ | `parity explain` | LLM deep-dive on a specific issue (needs `ANTHROPIC_API_KEY`) |
74
+ | `parity learned` | Inspect the learned-selectors library |
75
+
76
+ Run any command with `--help` for the full flag list.
77
+
78
+ ## Output
79
+
80
+ ```
81
+ ./parity-output/runs/<runId>/
82
+ ├── report.html # standalone, open in any browser
83
+ ├── report.json # structured output for CI / tooling
84
+ ├── screenshots/ # per-page, per-viewport, per-side; includes pixelmatch heatmaps
85
+ ├── har/ # Playwright HARs (one per viewport/side)
86
+ ├── traces/ # Playwright traces — drag into trace.playwright.dev
87
+ └── console/ # console messages captured per page
88
+ ```
89
+
90
+ Plus `./parity-baselines/<name>.json` for git-trackable baseline manifests.
91
+
92
+ ## Visual Diff tab
93
+
94
+ When `--visual-pages > 0` and an LLM key is set, the report's **Visual Diff** tab shows, per page:
95
+
96
+ - prod screenshot · cand screenshot · pixelmatch heatmap, side-by-side
97
+ - list of Deco sections present in prod but missing in cand (auto-detected from `data-section`)
98
+ - semantic differences identified by Claude Vision (region, type, severity, description)
99
+ - one-click "Export visual prompt" — Markdown ready to paste into Claude / ChatGPT to generate the fix
100
+
101
+ The visual prompt focuses *only* on visual diffs, references the screenshot paths, and includes migration-specific guidance (register section in `setup.ts`, loader shape drift, useDevice hydration, etc).
102
+
103
+ ## Configuration (optional)
104
+
105
+ `.parityrc.json` at the project root — selector overrides and run defaults:
106
+
107
+ ```json
108
+ {
109
+ "cep": "01310-100",
110
+ "selectors": {
111
+ "categoryLink": "header a[href*='/c/']",
112
+ "productCard": "[data-product-card] a",
113
+ "buyButton": "button:has-text('Comprar')",
114
+ "minicartTrigger": "[data-minicart-trigger]",
115
+ "cepInputPdp": "input[name='shipping-zipcode']",
116
+ "cepInputCart": "input[name='cart-zipcode']",
117
+ "checkoutButton": "a:has-text('Finalizar compra')"
118
+ }
119
+ }
120
+ ```
121
+
122
+ `.parityignore` — noise suppression:
123
+
124
+ ```json
125
+ {
126
+ "ignoreSelectorsVisual": [".banner-rotativo", "#trustvox-trustbar"],
127
+ "ignoreRequestPatterns": ["*.gif?t=*", "**/pixel*"],
128
+ "ignoreConsolePatterns": ["ERR_BLOCKED_BY_CLIENT"]
129
+ }
130
+ ```
131
+
132
+ Both files are gitignored by default — they're per-user, not per-repo.
133
+
134
+ ## LLM (optional)
135
+
136
+ Set **one** environment variable to unlock LLM-driven features:
137
+
138
+ - `ANTHROPIC_API_KEY` — direct Anthropic API (Claude Sonnet 4.6 with prompt caching). Preferred.
139
+ - `OPENROUTER_API_KEY` — OpenRouter (default model `anthropic/claude-sonnet-4.5`; override with `PARITY_OPENROUTER_MODEL`).
140
+
141
+ What LLM enables:
142
+
143
+ - **Issue aggregation** — flat raw issues become ranked, deduplicated top issues
144
+ - **Selector discovery** — infers `categoryLink` / `productCard` / `buyButton` etc. from HTML
145
+ - **Step recovery** — when a flow step fails, suggest a working selector
146
+ - **Visual semantic diff** — Claude Vision interprets pixel diffs as missing sections / wrong layout / etc.
147
+ - **PLP picker / PDP matcher** — cross-site disambiguation
148
+ - **`parity explain <issue>`** — root-cause analysis on demand
149
+
150
+ Without any key, the CLI still runs and outputs raw check results — only the smart bits are skipped. Deterministic fallbacks always apply.
151
+
152
+ **Cost** — A `--preset full` run with visual diff uses ~6-12 Claude calls (each with 2 screenshots). Roughly $0.05–$0.20 per run on Sonnet 4.6 with prompt caching.
153
+
154
+ ## CI usage
155
+
156
+ ```yaml
157
+ - name: Parity check
158
+ env:
159
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
160
+ run: |
161
+ npx @decocms/parity journey \
162
+ --prod ${{ vars.PROD_URL }} \
163
+ --cand ${{ env.PR_PREVIEW_URL }} \
164
+ --junit parity.junit.xml \
165
+ --github
166
+ ```
167
+
168
+ `parity journey` emits GitHub Actions `::error` and `::warning` annotations for each failed step and writes JUnit XML.
169
+
170
+ ## Development
171
+
172
+ ```bash
173
+ git clone git@github.com:decocms/parity.git
174
+ cd parity
175
+ bun install
176
+ bunx playwright install chromium
177
+ bun run dev run --prod ... --cand ...
178
+ ```
179
+
180
+ Tests: `bun run test` (vitest). Typecheck: `bun run check`. Build: `bun run build`.
181
+
182
+ ## License
183
+
184
+ MIT