laxy-verify 1.1.22 → 1.1.24

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/README.md CHANGED
@@ -1,123 +1,156 @@
1
1
  # laxy-verify
2
2
 
3
- A frontend verification CLI that catches build breaks, regressions, and client-visible issues before you ship.
3
+ `laxy-verify` is a deployment blocker gate for frontend apps.
4
4
 
5
- `laxy-verify` runs production build checks, Lighthouse, tiered verify E2E, and plan-gated verification for Free, Pro, and Pro+ accounts.
6
- It is built around three simple questions:
5
+ **Free**: Run verification manually on any project.
6
+ **Pro**: GitHub Actions auto-runs it on every PR + Slack/Discord alerts when things break.
7
7
 
8
- - Free: "Any critical issues right now?"
9
- - Pro: "Ready to show a client?"
10
- - Pro+: "Ready for production?"
8
+ ## Quick start
9
+
10
+ Run it on a frontend app:
11
11
 
12
12
  ```bash
13
- npx laxy-verify --init --run
13
+ cd your-project
14
14
  npx laxy-verify .
15
- npx laxy-verify . --plan-override pro
15
+ ```
16
+
17
+ Generate config plus GitHub Actions workflow:
18
+
19
+ ```bash
20
+ npx laxy-verify --init
21
+ ```
22
+
23
+ That creates:
24
+
25
+ - `.laxy.yml`
26
+ - `.github/workflows/laxy-verify.yml`
27
+
28
+ Log in to unlock Pro features:
29
+
30
+ ```bash
16
31
  npx laxy-verify login
17
32
  npx laxy-verify whoami
18
- npx laxy-verify --help
19
33
  ```
20
34
 
21
- What you get from one run:
35
+ For CI, set `LAXY_TOKEN` instead of interactive login:
36
+
37
+ ```yaml
38
+ env:
39
+ LAXY_TOKEN: ${{ secrets.LAXY_TOKEN }}
40
+ ```
41
+
42
+ ## Why laxy-verify?
43
+
44
+ Most teams already have some mix of:
45
+
46
+ - `npm run build`
47
+ - Lighthouse
48
+ - Playwright or smoke checks
49
+ - CI status rules
50
+
51
+ The gap is not "can these tools exist together?" The gap is "who turns that pile of output into a safe merge or release decision?"
52
+
53
+ `laxy-verify` gives you:
54
+
55
+ - one command instead of a custom build plus audit plus smoke-check script stack
56
+ - one result file instead of scattered logs
57
+ - one blocker-first decision instead of "build passed, but do we actually trust this release?"
58
+ - **Pro**: GitHub Actions auto-run + Slack/Discord alerts so you never miss a failure
59
+
60
+ This is most useful if you ship frontend apps and want a practical gate before:
61
+
62
+ - merge
63
+ - client review
64
+ - QA handoff
65
+ - production release
66
+
67
+ ## The failures it is meant to catch
68
+
69
+ Use `laxy-verify` when you want to catch things like:
22
70
 
71
+ - the production build passes locally but fails in CI
72
+ - the app opens, but a key button or form flow is broken
73
+ - desktop looks fine, but a mobile CTA is pushed out of view
74
+ - Lighthouse looks acceptable, but the user-visible path is still not safe to ship
75
+ - a PR needs a clear hold reason instead of a vague "something failed"
76
+
77
+ ## What it actually checks
78
+
79
+ A standard run includes:
80
+
81
+ - production build success
82
+ - Lighthouse thresholds (3 runs for stable evidence)
83
+ - E2E scenarios for user-visible flows
84
+ - multi-viewport checks (desktop, tablet, mobile)
85
+ - blocker-aware reporting and release decisions
86
+
87
+ With a logged-in account, additional checks run:
88
+
89
+ - security audit
90
+ - visual diff evidence
91
+ - stability pass (second E2E run)
92
+
93
+ ## What you get from one run
94
+
95
+ - a release decision such as `quick-pass`, `client-ready`, `release-ready`, `hold`, or `investigate`
23
96
  - a verification grade: `Gold`, `Silver`, `Bronze`, or `Unverified`
24
- - a decision-oriented verdict such as `client-ready`, `release-ready`, `hold`, or `investigate`
25
- - `.laxy-result.json` for automation
26
- - `laxy-verify-report.md` on paid plans for human review and AI handoff
97
+ - `.laxy-result.json` for CI and automation
98
+ - `laxy-verify-report.md` for human review and AI handoff
27
99
 
28
- ## Quick Start
100
+ Grades still exist, but they are not the main point. The main point is whether the run found blockers you should stop on.
29
101
 
30
- ### 1. Run it on a frontend app
102
+ ## Quick start
103
+
104
+ Run it on a frontend app:
31
105
 
32
106
  ```bash
33
107
  cd your-project
34
108
  npx laxy-verify .
35
109
  ```
36
110
 
37
- This runs the default verification flow in the current app directory.
38
-
39
- ### 2. Generate config and CI workflow
111
+ Generate config plus CI workflow:
40
112
 
41
113
  ```bash
42
114
  npx laxy-verify --init
43
115
  ```
44
116
 
45
- This creates:
117
+ That creates:
46
118
 
47
119
  - `.laxy.yml`
48
120
  - `.github/workflows/laxy-verify.yml`
49
121
 
50
- ### 3. Commit the workflow
51
-
52
- Once committed, each PR gets a verification run, grade output, and optional GitHub reporting.
53
-
54
- ### 4. Unlock paid plan features
122
+ Log in to unlock paid plan features:
55
123
 
56
124
  ```bash
57
125
  npx laxy-verify login
58
126
  npx laxy-verify whoami
59
127
  ```
60
128
 
61
- For CI, set `LAXY_TOKEN` instead of using interactive login.
129
+ For CI, set `LAXY_TOKEN` instead of interactive login:
62
130
 
63
131
  ```yaml
64
132
  env:
65
133
  LAXY_TOKEN: ${{ secrets.LAXY_TOKEN }}
66
134
  ```
67
135
 
68
- ## What It Checks
69
-
70
- - production build success
71
- - Lighthouse thresholds
72
- - verify E2E scenarios for real user flows
73
- - Pro+ viewport and visual regression evidence
74
- - plan-aware verdicts for local runs and CI
75
-
76
- ## Verification Tiers
77
-
78
- | Plan | Question it answers |
79
- |------|---------------------|
80
- | Free | Any critical issues right now? |
81
- | Pro | Ready to show a client? |
82
- | Pro+ | Ready for production? |
83
-
84
- ## Grades
85
-
86
- | Grade | Meaning |
87
- |-------|---------|
88
- | Gold | Build passed + E2E passed + Lighthouse passed + Pro+ viewport evidence passed |
89
- | Silver | Build passed + E2E passed |
90
- | Bronze | Build passed |
91
- | Unverified | Build failed |
92
-
93
- ## Plan Differences
94
-
95
- | Feature | Free | Pro | Pro+ |
96
- |---------|------|-----|------|
97
- | Build verification | Yes | Yes | Yes |
98
- | Lighthouse | 1 run | 3 runs | 3 runs |
99
- | Verify E2E | Smoke checks | Client-facing flow checks | Client-facing flow checks + release evidence |
100
- | Detailed report view | No | Yes | Yes |
101
- | `laxy-verify-report.md` export | No | Yes | Yes |
102
- | Multi-viewport verification | No | No | Yes |
103
- | Visual diff | No | No | Yes |
104
- | Failure analysis signals | No | No | Yes |
136
+ ## Example workflow
105
137
 
106
- Free tells you whether the app is basically standing.
107
- Pro tells you whether the app is strong enough to call client-ready.
108
- Pro+ adds the extra evidence needed for a real release-ready call.
138
+ 1. Run `npx laxy-verify .` locally before opening or merging a PR.
139
+ 2. Fix broken builds, broken flows, and visible regressions.
140
+ 3. Commit `.laxy.yml`.
141
+ 4. Run `npx laxy-verify --init`.
142
+ 5. Let the GitHub Action apply the same gate on every PR.
109
143
 
110
- ## Sample Output
144
+ ## Example output
111
145
 
112
146
  ```text
113
- Plan: Pro+
147
+ Decision: release-ready
114
148
  Grade: Gold
115
- Verdict: release-ready
116
149
 
117
150
  Passed:
118
151
  - production build
119
152
  - Lighthouse thresholds
120
- - core E2E flows
153
+ - core user flows
121
154
  - desktop, tablet, and mobile viewport checks
122
155
 
123
156
  Artifacts:
@@ -125,19 +158,46 @@ Artifacts:
125
158
  - laxy-verify-report.md
126
159
  ```
127
160
 
128
- ## Configuration
161
+ ## The decision it helps you make
129
162
 
130
- All fields are optional in `.laxy.yml`.
163
+ `laxy-verify` answers a delivery decision, not just a score:
164
+
165
+ - Would this break for real users right now?
166
+ - What would block a client demo or QA handoff?
167
+ - Is there enough evidence to merge or release with confidence?
168
+
169
+ Log in to unlock deeper checks (security audit, visual diff, stability pass).
170
+
171
+ ## Grades
172
+
173
+ | Grade | Meaning |
174
+ |---|---|
175
+ | Gold | Build passed, E2E passed, Lighthouse passed, and release-level evidence passed |
176
+ | Silver | Build passed and E2E passed |
177
+ | Bronze | Build passed |
178
+ | Unverified | Build failed |
179
+
180
+ Default Lighthouse thresholds:
181
+
182
+ - Performance `>= 70`
183
+ - Accessibility `>= 85`
184
+ - SEO `>= 80`
185
+ - Best Practices `>= 80`
186
+
187
+ ## Config
188
+
189
+ All fields in `.laxy.yml` are optional.
131
190
 
132
191
  ```yaml
133
- framework: "auto"
192
+ framework: auto
134
193
  build_command: ""
135
194
  dev_command: ""
136
- package_manager: "auto"
195
+ package_manager: auto
137
196
  port: 3000
138
197
  build_timeout: 300
139
198
  dev_timeout: 60
140
199
  lighthouse_runs: 1
200
+ fail_on: bronze
141
201
 
142
202
  thresholds:
143
203
  performance: 70
@@ -145,16 +205,21 @@ thresholds:
145
205
  seo: 80
146
206
  best_practices: 80
147
207
 
148
- fail_on: "bronze"
208
+ crawl: false
209
+ max_crawl_depth: 3
210
+ max_crawl_pages: 10
211
+ browsers:
212
+ - chromium
149
213
  ```
150
214
 
151
- Typical cases:
215
+ Useful adjustments:
152
216
 
153
- - raise `fail_on` to `silver` or `gold` in CI when you want stricter gates
154
- - set `framework`, `build_command`, or `dev_command` if auto-detection is not enough
155
- - increase `lighthouse_runs` when you want more stable performance evidence
217
+ - raise `fail_on` in CI when you want stricter gates
218
+ - set `build_command` or `dev_command` if auto-detection is not enough
219
+ - increase `lighthouse_runs` for more stable performance evidence
220
+ - point the CLI at the actual app directory in a monorepo
156
221
 
157
- ## CLI Options
222
+ ## CLI
158
223
 
159
224
  ```text
160
225
  npx laxy-verify [project-dir]
@@ -165,7 +230,7 @@ Options:
165
230
  --config <path>
166
231
  --fail-on unverified|bronze|silver|gold
167
232
  --skip-lighthouse
168
- --plan-override free|pro|pro_plus
233
+ --plan-override free|pro|team
169
234
  --badge
170
235
  --init
171
236
  --multi-viewport
@@ -177,87 +242,64 @@ Subcommands:
177
242
  whoami
178
243
  ```
179
244
 
180
- `--plan-override` is for downgrade testing only.
181
- Example: if your account is Pro+, you can run `--plan-override pro` or `--plan-override free` to verify the lower-tier behavior without changing your subscription.
182
- It will reject upgrades above your real entitlement.
183
-
184
- ## Result Files
185
-
186
- Each run writes `.laxy-result.json`.
187
-
188
- Paid plans also write a readable markdown summary to `laxy-verify-report.md`.
189
-
190
- - `Pro`: client-ready delivery report
191
- - `Pro+`: release-readiness report with viewport and visual evidence
192
-
193
- Exit behavior follows the verification verdict, not just the legacy grade.
194
-
195
- - `build-failed` -> exit 1
196
- - `hold` -> exit 1
197
- - `Pro+ investigate` -> exit 1
198
- - plain lower-tier pass states can still exit 0
199
-
200
- ```json
201
- {
202
- "grade": "Gold",
203
- "timestamp": "2026-04-09T09:00:00Z",
204
- "build": { "success": true, "durationMs": 12000, "errors": [] },
205
- "e2e": { "passed": 5, "failed": 0, "total": 5, "results": [] },
206
- "lighthouse": { "performance": 82, "accessibility": 94, "seo": 90, "bestPractices": 92, "runs": 3 },
207
- "multiViewport": {
208
- "allPassed": true,
209
- "summary": "Desktop, tablet, and mobile checks passed."
210
- },
211
- "visualDiff": {
212
- "verdict": "pass",
213
- "differencePercentage": 0
214
- },
215
- "verification": {
216
- "tier": "pro_plus",
217
- "report": { "verdict": "release-ready" }
218
- },
219
- "exitCode": 0,
220
- "_plan": "pro_plus"
221
- }
222
- ```
245
+ `--plan-override` is for downgrade testing only. It can simulate lower tiers, but it will not let you exceed your real entitlement.
246
+
247
+ ## Result files
248
+
249
+ Every run writes `.laxy-result.json`.
223
250
 
224
- ### `laxy-verify-report.md`
251
+ When the run finds something worth reviewing, it also writes `laxy-verify-report.md`.
225
252
 
226
- For Pro and Pro+ runs, the markdown report is designed to be easy to read and easy to paste into an AI coding tool.
253
+ Typical use:
254
+
255
+ - `.laxy-result.json` for CI parsing and machine decisions
256
+ - `laxy-verify-report.md` for human review, PR discussion, or AI-assisted fixes
257
+
258
+ The markdown report is designed to be readable and easy to paste into coding tools.
227
259
 
228
260
  It includes:
229
261
 
230
- - the main decision in plain English
262
+ - the main stop-or-ship decision in plain English
231
263
  - what passed
232
264
  - blockers and warnings
233
265
  - exact verification evidence
234
- - failed E2E scenarios
235
- - a `Copy For AI` section you can paste directly into Codex, Cursor, Claude, or ChatGPT
266
+ - failed scenarios
267
+ - a `Copy For AI` section
268
+
269
+ ## What this is good at
270
+
271
+ Use `laxy-verify` when you want:
272
+
273
+ - a merge or release gate for frontend apps
274
+ - one repeatable command for build plus audit plus visible-flow verification
275
+ - a decision that non-authors can understand
276
+ - JSON output for automation without building your own wrapper
236
277
 
237
- ## Environment Notes
278
+ ## What this is not
238
279
 
239
- - Best on current LTS Node releases. `Node 20.18+` is recommended.
240
- - Monorepos should point `laxy-verify` at the actual app directory.
241
- - `playwright` is optional. The CLI can run without it.
242
- - Pro+ viewport and visual checks increase runtime.
280
+ `laxy-verify` is not trying to replace:
243
281
 
244
- ## Regression Fixtures
282
+ - your full Playwright suite
283
+ - deep visual QA by designers
284
+ - production observability
285
+ - manual exploratory testing
245
286
 
246
- The repo also includes dedicated regression fixtures under `.qa-regression-fixtures/`.
247
- They intentionally break build, navigation, coverage, performance, viewport behavior, and visual stability so the verifier can be tested against known failure modes.
287
+ It is a pre-merge and pre-release verification layer, not your entire quality system.
248
288
 
249
289
  ## Limitations
250
290
 
251
- - Monorepos require targeting the app subdirectory explicitly.
252
- - Dev-server-based Lighthouse can differ from production hosting.
253
- - Pro+ visual diff and viewport checks increase runtime.
254
- - Local verification is most stable on current LTS Node releases.
291
+ - monorepos should target the real app subdirectory
292
+ - dev-server-based Lighthouse is not identical to production hosting
293
+ - visual diff and viewport checks increase runtime
294
+ - best stability is on current LTS Node releases
295
+
296
+ ## Requirements
297
+
298
+ - Node `>=20.18.0 <25`
299
+ - a frontend app with a runnable build flow
300
+ - optional: `playwright` if your project already uses it
255
301
 
256
302
  ## Links
257
303
 
258
304
  - GitHub: https://github.com/SUNgm24/Laxy/tree/main/laxy-verify
259
305
  - Issues: https://github.com/SUNgm24/Laxy/issues
260
-
261
- ## License
262
-
263
- MIT
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Broken-links audit.
3
+ * Uses the crawl result to find all internal links, then validates each
4
+ * with an HTTP HEAD/GET request. Links that return 4xx/5xx or timeout are
5
+ * reported as blockers.
6
+ */
7
+ import { type CrawlResult } from "../crawler.js";
8
+ export interface BrokenLink {
9
+ url: string;
10
+ path: string;
11
+ status: number;
12
+ statusText: string;
13
+ severity: "critical" | "high";
14
+ }
15
+ export interface BrokenLinksResult {
16
+ brokenLinks: BrokenLink[];
17
+ checkedCount: number;
18
+ hasBrokenLinks: boolean;
19
+ summary: string;
20
+ }
21
+ export declare function auditBrokenLinks(crawlResult: CrawlResult, baseUrl: string, abortSignal?: AbortSignal): Promise<BrokenLinksResult>;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.auditBrokenLinks = auditBrokenLinks;
4
+ const TIMEOUT_MS = 5000;
5
+ const VALID_OK_STATUS = [200, 201, 202, 203, 204, 301, 302, 303, 307, 308];
6
+ function isSuccessStatus(n) {
7
+ return VALID_OK_STATUS.includes(n);
8
+ }
9
+ async function auditBrokenLinks(crawlResult, baseUrl, abortSignal) {
10
+ const origin = new URL(baseUrl).origin;
11
+ const allUrls = [];
12
+ for (const page of crawlResult.pages) {
13
+ for (const href of page.internalLinks) {
14
+ try {
15
+ const url = new URL(href, baseUrl).href;
16
+ if (!allUrls.includes(url))
17
+ allUrls.push(url);
18
+ }
19
+ catch {
20
+ // skip malformed URLs
21
+ }
22
+ }
23
+ }
24
+ const uniqueUrls = allUrls;
25
+ const brokenLinks = [];
26
+ await Promise.all(uniqueUrls.map(async (url) => {
27
+ if (abortSignal?.aborted)
28
+ return;
29
+ try {
30
+ const controller = new AbortController();
31
+ const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
32
+ let status = 0;
33
+ let statusText = "";
34
+ try {
35
+ const res = await fetch(url, {
36
+ method: "HEAD",
37
+ redirect: "follow",
38
+ signal: controller.signal,
39
+ });
40
+ status = res.status;
41
+ statusText = res.statusText;
42
+ }
43
+ catch {
44
+ // Fall back to GET if HEAD is not allowed
45
+ const controller2 = new AbortController();
46
+ const timer2 = setTimeout(() => controller2.abort(), TIMEOUT_MS);
47
+ try {
48
+ const res = await fetch(url, {
49
+ method: "GET",
50
+ redirect: "follow",
51
+ signal: controller2.signal,
52
+ });
53
+ status = res.status;
54
+ statusText = res.statusText;
55
+ }
56
+ catch {
57
+ status = 0;
58
+ statusText = "timeout or network error";
59
+ }
60
+ clearTimeout(timer2);
61
+ }
62
+ clearTimeout(timer);
63
+ if (!isSuccessStatus(status)) {
64
+ const severity = status >= 500 ? "critical" : "high";
65
+ let path = url;
66
+ try {
67
+ path = new URL(url).pathname;
68
+ }
69
+ catch { }
70
+ brokenLinks.push({ url, path, status, statusText, severity });
71
+ }
72
+ }
73
+ catch {
74
+ // skip
75
+ }
76
+ }));
77
+ const summary = brokenLinks.length === 0
78
+ ? `All ${uniqueUrls.length} links OK`
79
+ : `${brokenLinks.length} broken link(s) found`;
80
+ return {
81
+ brokenLinks,
82
+ checkedCount: uniqueUrls.length,
83
+ hasBrokenLinks: brokenLinks.length > 0,
84
+ summary,
85
+ };
86
+ }