@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 +112 -0
- package/CHANGELOG.md +35 -0
- package/LICENSE +21 -0
- package/README.md +184 -0
- package/dist/cli.js +9783 -0
- package/package.json +87 -0
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
|