shopify-image-audit 0.3.0__tar.gz
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.
- shopify_image_audit-0.3.0/PKG-INFO +231 -0
- shopify_image_audit-0.3.0/README.md +196 -0
- shopify_image_audit-0.3.0/pyproject.toml +78 -0
- shopify_image_audit-0.3.0/setup.cfg +4 -0
- shopify_image_audit-0.3.0/src/audit/__init__.py +0 -0
- shopify_image_audit-0.3.0/src/audit/models.py +262 -0
- shopify_image_audit-0.3.0/src/audit/parser.py +136 -0
- shopify_image_audit-0.3.0/src/audit/ranker_heuristic.py +108 -0
- shopify_image_audit-0.3.0/src/audit/ranker_ml.py +246 -0
- shopify_image_audit-0.3.0/src/audit/report.py +908 -0
- shopify_image_audit-0.3.0/src/core/__init__.py +2 -0
- shopify_image_audit-0.3.0/src/core/baseline_manager.py +549 -0
- shopify_image_audit-0.3.0/src/core/image_extractor.py +225 -0
- shopify_image_audit-0.3.0/src/core/image_signals.py +79 -0
- shopify_image_audit-0.3.0/src/engine/__init__.py +0 -0
- shopify_image_audit-0.3.0/src/engine/audit_orchestrator.py +198 -0
- shopify_image_audit-0.3.0/src/engine/cli.py +808 -0
- shopify_image_audit-0.3.0/src/engine/cli_helpers/__init__.py +1 -0
- shopify_image_audit-0.3.0/src/engine/cli_helpers/_dispatchers.py +55 -0
- shopify_image_audit-0.3.0/src/engine/cli_helpers/_errors.py +108 -0
- shopify_image_audit-0.3.0/src/engine/cli_helpers/_table.py +103 -0
- shopify_image_audit-0.3.0/src/engine/cli_helpers/_validators.py +133 -0
- shopify_image_audit-0.3.0/src/engine/history.py +449 -0
- shopify_image_audit-0.3.0/src/integrations/__init__.py +25 -0
- shopify_image_audit-0.3.0/src/integrations/pagespeed_api.py +446 -0
- shopify_image_audit-0.3.0/src/integrations/shopify_admin.py +343 -0
- shopify_image_audit-0.3.0/src/shopify_image_audit.egg-info/PKG-INFO +231 -0
- shopify_image_audit-0.3.0/src/shopify_image_audit.egg-info/SOURCES.txt +48 -0
- shopify_image_audit-0.3.0/src/shopify_image_audit.egg-info/dependency_links.txt +1 -0
- shopify_image_audit-0.3.0/src/shopify_image_audit.egg-info/entry_points.txt +2 -0
- shopify_image_audit-0.3.0/src/shopify_image_audit.egg-info/requires.txt +14 -0
- shopify_image_audit-0.3.0/src/shopify_image_audit.egg-info/top_level.txt +4 -0
- shopify_image_audit-0.3.0/tests/test_baseline_manager.py +645 -0
- shopify_image_audit-0.3.0/tests/test_branded_report.py +245 -0
- shopify_image_audit-0.3.0/tests/test_cli.py +582 -0
- shopify_image_audit-0.3.0/tests/test_cli_helpers_errors.py +198 -0
- shopify_image_audit-0.3.0/tests/test_cli_helpers_validators.py +188 -0
- shopify_image_audit-0.3.0/tests/test_core.py +103 -0
- shopify_image_audit-0.3.0/tests/test_extract_vitals.py +91 -0
- shopify_image_audit-0.3.0/tests/test_history.py +437 -0
- shopify_image_audit-0.3.0/tests/test_models.py +108 -0
- shopify_image_audit-0.3.0/tests/test_pagespeed_api.py +489 -0
- shopify_image_audit-0.3.0/tests/test_per_image_deltas.py +240 -0
- shopify_image_audit-0.3.0/tests/test_pipeline.py +213 -0
- shopify_image_audit-0.3.0/tests/test_ranker_heuristic.py +332 -0
- shopify_image_audit-0.3.0/tests/test_ranker_ml.py +335 -0
- shopify_image_audit-0.3.0/tests/test_report.py +410 -0
- shopify_image_audit-0.3.0/tests/test_report_pdf.py +295 -0
- shopify_image_audit-0.3.0/tests/test_schema_validation.py +84 -0
- shopify_image_audit-0.3.0/tests/test_shopify_admin.py +446 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shopify-image-audit
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Shopify store image audit - Lighthouse-based analysis with heuristic and ML scoring
|
|
5
|
+
Author: xopsio
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/xopsio/shopify-image-audit
|
|
8
|
+
Project-URL: Repository, https://github.com/xopsio/shopify-image-audit
|
|
9
|
+
Project-URL: Issues, https://github.com/xopsio/shopify-image-audit/issues
|
|
10
|
+
Keywords: shopify,lighthouse,image-audit,performance,pagespeed,audit,cli
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: jsonschema>=4.20
|
|
23
|
+
Requires-Dist: pydantic>=2.6
|
|
24
|
+
Requires-Dist: typer>=0.12
|
|
25
|
+
Requires-Dist: rich>=13.7
|
|
26
|
+
Requires-Dist: requests>=2.31
|
|
27
|
+
Requires-Dist: weasyprint<70,>=69.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
31
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
32
|
+
Requires-Dist: responses>=0.25; extra == "dev"
|
|
33
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
34
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
35
|
+
|
|
36
|
+
# Shopify Image Audit
|
|
37
|
+
|
|
38
|
+
[](https://github.com/xopsio/shopify-image-audit/actions)
|
|
39
|
+
[](https://www.python.org/)
|
|
40
|
+
[](https://docs.astral.sh/ruff/)
|
|
41
|
+
[](#testing)
|
|
42
|
+
|
|
43
|
+
A Lighthouse-based image audit tool for Shopify stores. Produces per-image
|
|
44
|
+
scores, role assignments, optimisation recommendations, and a **before/after
|
|
45
|
+
comparison** workflow that proves image-optimisation ROI to paying customers.
|
|
46
|
+
|
|
47
|
+
Designed for the 99–199 € audit-on-demand business model: run the audit,
|
|
48
|
+
deliver a customer-ready HTML report, optionally compare live metrics after
|
|
49
|
+
the customer implements the recommendations.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Quickstart
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/xopsio/shopify-image-audit.git
|
|
57
|
+
cd shopify-image-audit
|
|
58
|
+
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
59
|
+
pip install -e ".[dev]"
|
|
60
|
+
|
|
61
|
+
# Verify the install
|
|
62
|
+
audit version
|
|
63
|
+
pytest -q # 390 tests
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## CLI commands
|
|
69
|
+
|
|
70
|
+
The tool ships with a single Typer app. Run `audit --help` for the full list;
|
|
71
|
+
below are the high-value entry points.
|
|
72
|
+
|
|
73
|
+
### `audit run <url>` — full Lighthouse + audit pipeline
|
|
74
|
+
```bash
|
|
75
|
+
audit run https://kauppa.myshopify.com --device mobile --runs 3 \
|
|
76
|
+
--out-dir artifacts
|
|
77
|
+
# -> artifacts/lhr_run1.json, audit_result.json (schema-compliant)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### `audit baseline <lhr.json> --save baseline.json` — capture baseline
|
|
81
|
+
```bash
|
|
82
|
+
audit baseline fixtures/before_after/before_lcp.json \
|
|
83
|
+
--save baseline.json \
|
|
84
|
+
--url https://demo.myshopify.com
|
|
85
|
+
# -> Baseline saved to baseline.json
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### `audit compare <baseline> <current>` — before/after (file or URL)
|
|
89
|
+
```bash
|
|
90
|
+
# File vs file (offline)
|
|
91
|
+
audit compare baseline.json fixtures/before_after/after_lcp.json \
|
|
92
|
+
-o comparison.html --json comparison.json
|
|
93
|
+
|
|
94
|
+
# File vs live URL (fetches via PageSpeed Insights API)
|
|
95
|
+
audit compare baseline.json https://demo.myshopify.com \
|
|
96
|
+
--strategy mobile --api-key YOUR_KEY \
|
|
97
|
+
-o comparison.html
|
|
98
|
+
|
|
99
|
+
# HTML report includes a per-image delta table (bytes, score, status per image).
|
|
100
|
+
# PDF export via --pdf flag.
|
|
101
|
+
```
|
|
102
|
+
Exit codes: `0` success, `2` invalid args, `10` backend failure.
|
|
103
|
+
|
|
104
|
+
### `audit report <audit_result.json>` — HTML or PDF report
|
|
105
|
+
```bash
|
|
106
|
+
audit report baseline.json -o report.html # HTML
|
|
107
|
+
audit report baseline.json -o report.pdf --pdf # PDF (WeasyPrint)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `audit measure <url>` — live PageSpeed metrics only
|
|
111
|
+
```bash
|
|
112
|
+
audit measure https://demo.myshopify.com --strategy mobile
|
|
113
|
+
# -> JSON metrics to stdout (or --output metrics.json)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `audit shopify <auth|inventory> <store>` — Shopify Admin API
|
|
117
|
+
```bash
|
|
118
|
+
# Verify a token
|
|
119
|
+
audit shopify auth mystore.myshopify.com --access-token shpat_xxx
|
|
120
|
+
# -> Token valid, prints shop info
|
|
121
|
+
|
|
122
|
+
# List all image URLs (products + theme assets)
|
|
123
|
+
audit shopify inventory mystore.myshopify.com --access-token shpat_xxx -o inventory.json
|
|
124
|
+
```
|
|
125
|
+
Read-only scopes required (`read_products`, `read_themes`, `read_shop`).
|
|
126
|
+
See `docs/integrations/SHOPIFY_ADMIN.md` for token-acquisition steps.
|
|
127
|
+
|
|
128
|
+
### `audit score <audit_input.json> --ranker {heuristic|ml}`
|
|
129
|
+
```bash
|
|
130
|
+
audit score extracted.json # default: heuristic
|
|
131
|
+
audit score extracted.json --ranker ml # weighted feature ensemble
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Full reference: [`docs/spec/cli_v0_1.md`](docs/spec/cli_v0_1.md).
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Scoring algorithms
|
|
139
|
+
|
|
140
|
+
The pipeline assigns each image a `role`, a `score` (0–100), and a
|
|
141
|
+
`recommendation`. Two rankers ship, switchable via `--ranker ml`:
|
|
142
|
+
|
|
143
|
+
| Ranker | Formula | Use case |
|
|
144
|
+
|--------|---------|----------|
|
|
145
|
+
| `heuristic` (default) | bytes per displayed pixel (bpp) + LCP penalty | fast, predictable baseline |
|
|
146
|
+
| `ml` | weighted ensemble: f_size, f_density, f_format, f_dim_match + LCP strictness | richer signal, more honest scoring |
|
|
147
|
+
|
|
148
|
+
Both produce the same output contract (role + score + recommendation). The ML
|
|
149
|
+
ranker is a hand-coded feature ensemble, not a statistical model — see
|
|
150
|
+
[`src/audit/ranker_ml.py`](src/audit/ranker_ml.py) for the design rationale
|
|
151
|
+
(no model deps, deterministic, fully explainable via `ml_features()`).
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Architecture
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
src/
|
|
159
|
+
├── audit/ # scoring + reporting
|
|
160
|
+
│ ├── models.py # Pydantic v2 schemas (AuditResult, ComparisonResult, ImageDelta)
|
|
161
|
+
│ ├── parser.py # Lighthouse / fixture JSON parser
|
|
162
|
+
│ ├── ranker_heuristic.py # default ranker (bpp-based)
|
|
163
|
+
│ ├── ranker_ml.py # opt-in ML-style ranker (weighted ensemble)
|
|
164
|
+
│ └── report.py # HTML/PDF report renderer (split into _render_* funcs)
|
|
165
|
+
├── core/ # core algorithms
|
|
166
|
+
│ ├── image_extractor.py # LHR image audit extraction
|
|
167
|
+
│ ├── image_signals.py # shared displayed_area, assign_role, _safe_int
|
|
168
|
+
│ └── baseline_manager.py # save/load baselines + compare() + per-image matching
|
|
169
|
+
├── engine/ # orchestration + CLI
|
|
170
|
+
│ ├── cli.py # Typer app (run, measure, baseline, compare, shopify, ...)
|
|
171
|
+
│ ├── cli_helpers/ # extracted CLI helpers (validators, dispatchers, table, errors)
|
|
172
|
+
│ └── audit_orchestrator.py # run_audit() pipeline
|
|
173
|
+
└── integrations/ # external APIs
|
|
174
|
+
├── pagespeed_api.py # PageSpeed Insights (measure + fetch_lighthouse_json)
|
|
175
|
+
└── shopify_admin.py # Shopify Admin API (auth, products, theme_assets)
|
|
176
|
+
|
|
177
|
+
schemas/audit_result.schema.json # JSON Schema contract (validated by tests)
|
|
178
|
+
tests/ # 390 tests, single-writer (ZCode)
|
|
179
|
+
docs/examples/ # live demo report + comparison JSON
|
|
180
|
+
docs/integrations/ # Shopify Admin API token guide
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The codebase is governed by **a single ZCode agent** (see
|
|
184
|
+
[`docs/governance.md`](docs/governance.md) v1.3).
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Testing
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
pytest -q # 489 tests, single-writer discipline
|
|
192
|
+
pytest --cov=src --cov-report=term # ~87% coverage
|
|
193
|
+
ruff check src/ tests/ # 0 violations
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The CI workflow runs `pytest -q` + `ruff check` on Python 3.11 and 3.12 for
|
|
197
|
+
every PR. Branch protection on `main` requires both checks to pass before
|
|
198
|
+
merge. See [`.github/workflows/ci.yml`](.github/workflows/ci.yml).
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Customer deliverables (Phase 1)
|
|
203
|
+
|
|
204
|
+
- **Customer report template** — [`docs/CUSTOMER_REPORT_TEMPLATE.md`](docs/CUSTOMER_REPORT_TEMPLATE.md)
|
|
205
|
+
- **Onboarding workflow** — [`docs/CUSTOMER_ONBOARDING.md`](docs/CUSTOMER_ONBOARDING.md)
|
|
206
|
+
- **Example audit report** (Nordic Lifestyle demo store, LCP 4200ms → 1800ms) — [`docs/examples/demo_audit_report.html`](docs/examples/demo_audit_report.html)
|
|
207
|
+
- **Example comparison data** — [`docs/examples/demo_comparison.json`](docs/examples/demo_comparison.json)
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Roadmap
|
|
212
|
+
|
|
213
|
+
- ✅ Sprint 1 — v0.1.0 baseline (parser, ranker, orchestrator, CLI, HTML report, 103 tests)
|
|
214
|
+
- ✅ Sprint 2 — before/after workflow, customer docs, ML ranker, live URL compare, CI, governance cleanup (276 tests)
|
|
215
|
+
- ✅ Sprint 3 — PDF export, per-image deltas, Shopify Admin API, v0.2.0 release prep (390 tests)
|
|
216
|
+
- ✅ Sprint 4 — Branded reports, ROI-ranked recs, audit history, v0.3.0 (489 tests)
|
|
217
|
+
- Branded report templates (--brand-logo, --brand-color)
|
|
218
|
+
- ROI-ranked recommendations (ComparisonRecommendation model)
|
|
219
|
+
- Audit history + trend view (HistoryStore, `audit history list/show`)
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Further reading
|
|
224
|
+
|
|
225
|
+
- [`docs/spec/cli_v0_1.md`](docs/spec/cli_v0_1.md) — full CLI specification
|
|
226
|
+
- [`docs/governance.md`](docs/governance.md) — ownership + workflow
|
|
227
|
+
- [`docs/runbook/measurement_protocol.md`](docs/runbook/measurement_protocol.md) — how LCP/CLS/INP are measured deterministically
|
|
228
|
+
- [`docs/SPRINT_1_COMPLETE.md`](docs/SPRINT_1_COMPLETE.md) — what shipped in Sprint 1
|
|
229
|
+
- [`docs/SPRINT_3_PLAN.md`](docs/SPRINT_3_PLAN.md) — Sprint 3 breakdown (all done)
|
|
230
|
+
- [`docs/SPRINT_4_PLAN.md`](docs/SPRINT_4_PLAN.md) — Sprint 4 breakdown (all done)
|
|
231
|
+
- [`QA_CHECKLIST.md`](QA_CHECKLIST.md) — quality gates
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Shopify Image Audit
|
|
2
|
+
|
|
3
|
+
[](https://github.com/xopsio/shopify-image-audit/actions)
|
|
4
|
+
[](https://www.python.org/)
|
|
5
|
+
[](https://docs.astral.sh/ruff/)
|
|
6
|
+
[](#testing)
|
|
7
|
+
|
|
8
|
+
A Lighthouse-based image audit tool for Shopify stores. Produces per-image
|
|
9
|
+
scores, role assignments, optimisation recommendations, and a **before/after
|
|
10
|
+
comparison** workflow that proves image-optimisation ROI to paying customers.
|
|
11
|
+
|
|
12
|
+
Designed for the 99–199 € audit-on-demand business model: run the audit,
|
|
13
|
+
deliver a customer-ready HTML report, optionally compare live metrics after
|
|
14
|
+
the customer implements the recommendations.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Quickstart
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/xopsio/shopify-image-audit.git
|
|
22
|
+
cd shopify-image-audit
|
|
23
|
+
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
24
|
+
pip install -e ".[dev]"
|
|
25
|
+
|
|
26
|
+
# Verify the install
|
|
27
|
+
audit version
|
|
28
|
+
pytest -q # 390 tests
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## CLI commands
|
|
34
|
+
|
|
35
|
+
The tool ships with a single Typer app. Run `audit --help` for the full list;
|
|
36
|
+
below are the high-value entry points.
|
|
37
|
+
|
|
38
|
+
### `audit run <url>` — full Lighthouse + audit pipeline
|
|
39
|
+
```bash
|
|
40
|
+
audit run https://kauppa.myshopify.com --device mobile --runs 3 \
|
|
41
|
+
--out-dir artifacts
|
|
42
|
+
# -> artifacts/lhr_run1.json, audit_result.json (schema-compliant)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### `audit baseline <lhr.json> --save baseline.json` — capture baseline
|
|
46
|
+
```bash
|
|
47
|
+
audit baseline fixtures/before_after/before_lcp.json \
|
|
48
|
+
--save baseline.json \
|
|
49
|
+
--url https://demo.myshopify.com
|
|
50
|
+
# -> Baseline saved to baseline.json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### `audit compare <baseline> <current>` — before/after (file or URL)
|
|
54
|
+
```bash
|
|
55
|
+
# File vs file (offline)
|
|
56
|
+
audit compare baseline.json fixtures/before_after/after_lcp.json \
|
|
57
|
+
-o comparison.html --json comparison.json
|
|
58
|
+
|
|
59
|
+
# File vs live URL (fetches via PageSpeed Insights API)
|
|
60
|
+
audit compare baseline.json https://demo.myshopify.com \
|
|
61
|
+
--strategy mobile --api-key YOUR_KEY \
|
|
62
|
+
-o comparison.html
|
|
63
|
+
|
|
64
|
+
# HTML report includes a per-image delta table (bytes, score, status per image).
|
|
65
|
+
# PDF export via --pdf flag.
|
|
66
|
+
```
|
|
67
|
+
Exit codes: `0` success, `2` invalid args, `10` backend failure.
|
|
68
|
+
|
|
69
|
+
### `audit report <audit_result.json>` — HTML or PDF report
|
|
70
|
+
```bash
|
|
71
|
+
audit report baseline.json -o report.html # HTML
|
|
72
|
+
audit report baseline.json -o report.pdf --pdf # PDF (WeasyPrint)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### `audit measure <url>` — live PageSpeed metrics only
|
|
76
|
+
```bash
|
|
77
|
+
audit measure https://demo.myshopify.com --strategy mobile
|
|
78
|
+
# -> JSON metrics to stdout (or --output metrics.json)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### `audit shopify <auth|inventory> <store>` — Shopify Admin API
|
|
82
|
+
```bash
|
|
83
|
+
# Verify a token
|
|
84
|
+
audit shopify auth mystore.myshopify.com --access-token shpat_xxx
|
|
85
|
+
# -> Token valid, prints shop info
|
|
86
|
+
|
|
87
|
+
# List all image URLs (products + theme assets)
|
|
88
|
+
audit shopify inventory mystore.myshopify.com --access-token shpat_xxx -o inventory.json
|
|
89
|
+
```
|
|
90
|
+
Read-only scopes required (`read_products`, `read_themes`, `read_shop`).
|
|
91
|
+
See `docs/integrations/SHOPIFY_ADMIN.md` for token-acquisition steps.
|
|
92
|
+
|
|
93
|
+
### `audit score <audit_input.json> --ranker {heuristic|ml}`
|
|
94
|
+
```bash
|
|
95
|
+
audit score extracted.json # default: heuristic
|
|
96
|
+
audit score extracted.json --ranker ml # weighted feature ensemble
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Full reference: [`docs/spec/cli_v0_1.md`](docs/spec/cli_v0_1.md).
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Scoring algorithms
|
|
104
|
+
|
|
105
|
+
The pipeline assigns each image a `role`, a `score` (0–100), and a
|
|
106
|
+
`recommendation`. Two rankers ship, switchable via `--ranker ml`:
|
|
107
|
+
|
|
108
|
+
| Ranker | Formula | Use case |
|
|
109
|
+
|--------|---------|----------|
|
|
110
|
+
| `heuristic` (default) | bytes per displayed pixel (bpp) + LCP penalty | fast, predictable baseline |
|
|
111
|
+
| `ml` | weighted ensemble: f_size, f_density, f_format, f_dim_match + LCP strictness | richer signal, more honest scoring |
|
|
112
|
+
|
|
113
|
+
Both produce the same output contract (role + score + recommendation). The ML
|
|
114
|
+
ranker is a hand-coded feature ensemble, not a statistical model — see
|
|
115
|
+
[`src/audit/ranker_ml.py`](src/audit/ranker_ml.py) for the design rationale
|
|
116
|
+
(no model deps, deterministic, fully explainable via `ml_features()`).
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Architecture
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
src/
|
|
124
|
+
├── audit/ # scoring + reporting
|
|
125
|
+
│ ├── models.py # Pydantic v2 schemas (AuditResult, ComparisonResult, ImageDelta)
|
|
126
|
+
│ ├── parser.py # Lighthouse / fixture JSON parser
|
|
127
|
+
│ ├── ranker_heuristic.py # default ranker (bpp-based)
|
|
128
|
+
│ ├── ranker_ml.py # opt-in ML-style ranker (weighted ensemble)
|
|
129
|
+
│ └── report.py # HTML/PDF report renderer (split into _render_* funcs)
|
|
130
|
+
├── core/ # core algorithms
|
|
131
|
+
│ ├── image_extractor.py # LHR image audit extraction
|
|
132
|
+
│ ├── image_signals.py # shared displayed_area, assign_role, _safe_int
|
|
133
|
+
│ └── baseline_manager.py # save/load baselines + compare() + per-image matching
|
|
134
|
+
├── engine/ # orchestration + CLI
|
|
135
|
+
│ ├── cli.py # Typer app (run, measure, baseline, compare, shopify, ...)
|
|
136
|
+
│ ├── cli_helpers/ # extracted CLI helpers (validators, dispatchers, table, errors)
|
|
137
|
+
│ └── audit_orchestrator.py # run_audit() pipeline
|
|
138
|
+
└── integrations/ # external APIs
|
|
139
|
+
├── pagespeed_api.py # PageSpeed Insights (measure + fetch_lighthouse_json)
|
|
140
|
+
└── shopify_admin.py # Shopify Admin API (auth, products, theme_assets)
|
|
141
|
+
|
|
142
|
+
schemas/audit_result.schema.json # JSON Schema contract (validated by tests)
|
|
143
|
+
tests/ # 390 tests, single-writer (ZCode)
|
|
144
|
+
docs/examples/ # live demo report + comparison JSON
|
|
145
|
+
docs/integrations/ # Shopify Admin API token guide
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The codebase is governed by **a single ZCode agent** (see
|
|
149
|
+
[`docs/governance.md`](docs/governance.md) v1.3).
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Testing
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
pytest -q # 489 tests, single-writer discipline
|
|
157
|
+
pytest --cov=src --cov-report=term # ~87% coverage
|
|
158
|
+
ruff check src/ tests/ # 0 violations
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The CI workflow runs `pytest -q` + `ruff check` on Python 3.11 and 3.12 for
|
|
162
|
+
every PR. Branch protection on `main` requires both checks to pass before
|
|
163
|
+
merge. See [`.github/workflows/ci.yml`](.github/workflows/ci.yml).
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Customer deliverables (Phase 1)
|
|
168
|
+
|
|
169
|
+
- **Customer report template** — [`docs/CUSTOMER_REPORT_TEMPLATE.md`](docs/CUSTOMER_REPORT_TEMPLATE.md)
|
|
170
|
+
- **Onboarding workflow** — [`docs/CUSTOMER_ONBOARDING.md`](docs/CUSTOMER_ONBOARDING.md)
|
|
171
|
+
- **Example audit report** (Nordic Lifestyle demo store, LCP 4200ms → 1800ms) — [`docs/examples/demo_audit_report.html`](docs/examples/demo_audit_report.html)
|
|
172
|
+
- **Example comparison data** — [`docs/examples/demo_comparison.json`](docs/examples/demo_comparison.json)
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Roadmap
|
|
177
|
+
|
|
178
|
+
- ✅ Sprint 1 — v0.1.0 baseline (parser, ranker, orchestrator, CLI, HTML report, 103 tests)
|
|
179
|
+
- ✅ Sprint 2 — before/after workflow, customer docs, ML ranker, live URL compare, CI, governance cleanup (276 tests)
|
|
180
|
+
- ✅ Sprint 3 — PDF export, per-image deltas, Shopify Admin API, v0.2.0 release prep (390 tests)
|
|
181
|
+
- ✅ Sprint 4 — Branded reports, ROI-ranked recs, audit history, v0.3.0 (489 tests)
|
|
182
|
+
- Branded report templates (--brand-logo, --brand-color)
|
|
183
|
+
- ROI-ranked recommendations (ComparisonRecommendation model)
|
|
184
|
+
- Audit history + trend view (HistoryStore, `audit history list/show`)
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Further reading
|
|
189
|
+
|
|
190
|
+
- [`docs/spec/cli_v0_1.md`](docs/spec/cli_v0_1.md) — full CLI specification
|
|
191
|
+
- [`docs/governance.md`](docs/governance.md) — ownership + workflow
|
|
192
|
+
- [`docs/runbook/measurement_protocol.md`](docs/runbook/measurement_protocol.md) — how LCP/CLS/INP are measured deterministically
|
|
193
|
+
- [`docs/SPRINT_1_COMPLETE.md`](docs/SPRINT_1_COMPLETE.md) — what shipped in Sprint 1
|
|
194
|
+
- [`docs/SPRINT_3_PLAN.md`](docs/SPRINT_3_PLAN.md) — Sprint 3 breakdown (all done)
|
|
195
|
+
- [`docs/SPRINT_4_PLAN.md`](docs/SPRINT_4_PLAN.md) — Sprint 4 breakdown (all done)
|
|
196
|
+
- [`QA_CHECKLIST.md`](QA_CHECKLIST.md) — quality gates
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "shopify-image-audit"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Shopify store image audit - Lighthouse-based analysis with heuristic and ML scoring"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "xopsio"},
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"shopify",
|
|
17
|
+
"lighthouse",
|
|
18
|
+
"image-audit",
|
|
19
|
+
"performance",
|
|
20
|
+
"pagespeed",
|
|
21
|
+
"audit",
|
|
22
|
+
"cli",
|
|
23
|
+
]
|
|
24
|
+
classifiers = [
|
|
25
|
+
"Development Status :: 4 - Beta",
|
|
26
|
+
"Environment :: Console",
|
|
27
|
+
"Intended Audience :: Developers",
|
|
28
|
+
"Operating System :: OS Independent",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3.11",
|
|
31
|
+
"Programming Language :: Python :: 3.12",
|
|
32
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
33
|
+
"Typing :: Typed",
|
|
34
|
+
]
|
|
35
|
+
dependencies = [
|
|
36
|
+
"jsonschema>=4.20",
|
|
37
|
+
"pydantic>=2.6",
|
|
38
|
+
"typer>=0.12",
|
|
39
|
+
"rich>=13.7",
|
|
40
|
+
"requests>=2.31",
|
|
41
|
+
"weasyprint>=69.0,<70",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
Homepage = "https://github.com/xopsio/shopify-image-audit"
|
|
46
|
+
Repository = "https://github.com/xopsio/shopify-image-audit"
|
|
47
|
+
Issues = "https://github.com/xopsio/shopify-image-audit/issues"
|
|
48
|
+
|
|
49
|
+
[project.optional-dependencies]
|
|
50
|
+
dev = [
|
|
51
|
+
"pytest>=8.0",
|
|
52
|
+
"pytest-cov>=5.0",
|
|
53
|
+
"ruff>=0.4",
|
|
54
|
+
"responses>=0.25",
|
|
55
|
+
"build>=1.0",
|
|
56
|
+
"twine>=5.0",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[project.scripts]
|
|
60
|
+
audit = "engine.cli:main"
|
|
61
|
+
|
|
62
|
+
[tool.setuptools.packages.find]
|
|
63
|
+
where = ["src"]
|
|
64
|
+
|
|
65
|
+
[tool.pytest.ini_options]
|
|
66
|
+
testpaths = ["tests"]
|
|
67
|
+
pythonpath = ["src"]
|
|
68
|
+
|
|
69
|
+
[tool.ruff]
|
|
70
|
+
target-version = "py311"
|
|
71
|
+
line-length = 120
|
|
72
|
+
|
|
73
|
+
[tool.ruff.lint]
|
|
74
|
+
select = ["E", "F", "W", "I", "UP", "B"]
|
|
75
|
+
# B008: Typer's official pattern is typer.Option()/typer.Argument() in default
|
|
76
|
+
# arguments — this is how Typer documents CLI definition, so the lint is a
|
|
77
|
+
# false positive for this framework.
|
|
78
|
+
ignore = ["B008"]
|
|
File without changes
|