shippingszn 0.9.3 → 0.9.5

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.
Files changed (3) hide show
  1. package/README.md +30 -21
  2. package/dist/index.js +121 -82
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -12,13 +12,15 @@ pnpm dlx shippingszn@latest
12
12
  ```
13
13
 
14
14
  The CLI **never writes, modifies, or deletes** any files - it only reads.
15
- Normal runs send one anonymous report-card summary with score, severity counts,
16
- files scanned, scanner version, and safe stack tags. It never uploads source
17
- code, paths, filenames, repo URLs, project names, secrets, handles, emails, or
18
- finding-level details. This Wall signal is automatic and not user-configurable.
19
-
20
- Human output starts with a Launch Readiness Score, scope covered, and severity
21
- counts. Run with `--json` to get the same score-and-counts summary in a
15
+ Normal runs create a locked scan handoff for checkout and send one anonymous
16
+ Wall report-card summary with score, severity counts, files scanned, scanner
17
+ version, and safe stack tags. It never uploads source code, repo URLs, project
18
+ names, secrets, handles, or emails. Finding-level detail stays out of public
19
+ CLI/Wall output and opens inside the paid Launch Fix Kit.
20
+
21
+ Human output starts with a Launch Debt Score, severity counts, a short
22
+ plain-English launch-risk explanation, completed checks, and the locked Fix Kit
23
+ handoff. Run with `--json` to get the same score-and-counts summary in a
22
24
  machine-readable shape:
23
25
 
24
26
  ```json
@@ -27,13 +29,20 @@ machine-readable shape:
27
29
  "band": "no_go",
28
30
  "counts": { "critical": 1, "high": 3, "medium": 4, "lower": 2 },
29
31
  "filesScanned": 128,
32
+ "coverage": { "checksCompleted": 19, "checklistAreas": 46 },
30
33
  "detailsLocked": true,
31
- "unlockUrl": "https://shippingszn.com/fix-kit"
34
+ "unlockUrl": "https://shippingszn.com/fix-kit?scanResultId=00000000-0000-4000-8000-000000000123",
35
+ "scanHandoff": {
36
+ "status": "uploaded",
37
+ "resultId": "00000000-0000-4000-8000-000000000123",
38
+ "unlockUrl": "https://shippingszn.com/fix-kit?scanResultId=00000000-0000-4000-8000-000000000123"
39
+ }
32
40
  }
33
41
  ```
34
42
 
35
43
  Finding titles, files, evidence, fix prompts, and verification steps are paid.
36
- They unlock inside the Launch Fix Kit.
44
+ The free CLI explains why the score matters, but the actual fixes unlock inside
45
+ the Launch Fix Kit.
37
46
 
38
47
  ## Aggregate summary
39
48
 
@@ -41,10 +50,10 @@ Plain `npx shippingszn@latest` sends the Wall summary automatically. The stored
41
50
  row is anonymous and intentionally small: score, launch label, files scanned,
42
51
  finding counts by severity, detected stack tags, scanner version, and timestamp.
43
52
 
44
- For a scan-specific paid-report handoff, run `npx shippingszn@latest --proof`.
45
- That uploads the canonical scan result, returns a proof URL plus a
46
- `/fix-kit?scanResultId=...` URL, and gives the paid Launch Fix Kit the evidence
47
- it needs after checkout.
53
+ The same run also creates a scan-specific paid-report handoff. The terminal
54
+ prints a `/fix-kit?scanResultId=...` URL so checkout can carry that scan into
55
+ the Launch Fix Kit after purchase. `--proof` is still accepted for old docs, but
56
+ it is no longer required.
48
57
 
49
58
  ## What gets checked
50
59
 
@@ -123,8 +132,8 @@ shippingszn [path] [options]
123
132
 
124
133
  Options:
125
134
  --json Output a machine-readable JSON summary.
126
- --proof Upload full scan evidence and return a scan-specific
127
- Launch Fix Kit URL.
135
+ --proof Backward-compatible alias. Normal runs already return
136
+ a scan-specific Launch Fix Kit URL.
128
137
  --base-url <url> Base URL used to build checkout and Fix Kit links.
129
138
  --cwd <path> Directory to scan. Default: current working directory.
130
139
  --no-color Disable ANSI colors in the human-readable summary.
@@ -151,12 +160,12 @@ summary as a comment: score, severity counts, and unlock URL.
151
160
  ## Privacy
152
161
 
153
162
  `shippingszn` reads files on your machine. It never uploads source code. By
154
- default it makes one best-effort outbound request to post an anonymous aggregate
155
- summary: score, launch label, files scanned count, finding counts by severity,
156
- detected stack tags, scanner version, and timestamp. It never uploads source
157
- code, file paths, filenames, project names, repo URLs, secrets, emails, handles,
158
- finding titles, evidence, or report contents. The aggregate summary is automatic
159
- and not user-configurable.
163
+ default it creates a locked scan handoff for checkout and makes one best-effort
164
+ outbound request to post anonymous Wall stats: score, launch label, files
165
+ scanned count, finding counts by severity, detected stack tags, scanner version,
166
+ and timestamp. Wall stats never include source code, file paths, filenames,
167
+ project names, repo URLs, secrets, emails, handles, finding titles, evidence, or
168
+ report contents. The Wall summary is automatic and not user-configurable.
160
169
 
161
170
  ## License
162
171
 
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import * as path19 from "node:path";
5
- import * as process2 from "node:process";
4
+ import * as path18 from "node:path";
5
+ import * as process from "node:process";
6
6
  import { createRequire } from "node:module";
7
7
 
8
8
  // src/checks/secrets.ts
@@ -3685,13 +3685,8 @@ async function publishScan(totals, filesScanned, opts) {
3685
3685
  }
3686
3686
 
3687
3687
  // src/proof.ts
3688
- import * as path18 from "node:path";
3689
3688
  var PROOF_TIMEOUT_MS = 5e3;
3690
3689
  var MAX_FINDINGS = 100;
3691
- function shouldUploadProof() {
3692
- const v = process.env["SHIPPINGSZN_PROOF"] ?? "";
3693
- return v === "1" || v.toLowerCase() === "true" || v === "yes";
3694
- }
3695
3690
  function clampText(value, max, fallback = "") {
3696
3691
  const text = value ?? fallback;
3697
3692
  return text.length > max ? text.slice(0, max - 3) + "..." : text;
@@ -3705,8 +3700,8 @@ function buildBadgeMarkdown(baseUrl, id, score) {
3705
3700
  scanResultId: id,
3706
3701
  theme: "dark"
3707
3702
  });
3708
- const proofUrl = `${baseUrl}/proof/${encodeURIComponent(id)}`;
3709
- return `[![shippingszn scan proof: ${score}%](${baseUrl}/api/badge.svg?${params.toString()})](${proofUrl})`;
3703
+ const fixKitUrl = `${baseUrl}/fix-kit?${new URLSearchParams({ scanResultId: id }).toString()}`;
3704
+ return `[![shippingszn scan score: ${score}%](${baseUrl}/api/badge.svg?${params.toString()})](${fixKitUrl})`;
3710
3705
  }
3711
3706
  function buildProofPayload(report, scannerVersion) {
3712
3707
  const counts = {
@@ -3719,7 +3714,7 @@ function buildProofPayload(report, scannerVersion) {
3719
3714
  version: 1,
3720
3715
  source: report.source ?? "cli",
3721
3716
  scanner: "shippingszn",
3722
- targetName: path18.basename(report.cwd) || "CLI scan",
3717
+ targetName: "Anonymous CLI scan",
3723
3718
  score: report.launchReadiness.score,
3724
3719
  label: report.launchReadiness.label,
3725
3720
  decision: report.launchReadiness.decision,
@@ -4376,13 +4371,13 @@ var PKG_VERSION = (() => {
4376
4371
  })();
4377
4372
  function parseArgs(argv2) {
4378
4373
  const opts = {
4379
- cwd: process2.cwd(),
4374
+ cwd: process.cwd(),
4380
4375
  json: false,
4381
- baseUrl: process2.env.SHIPPINGSZN_BASE_URL ?? process2.env.VIBE_LAUNCH_CHECK_BASE_URL ?? DEFAULT_BASE_URL2,
4376
+ baseUrl: process.env.SHIPPINGSZN_BASE_URL ?? process.env.VIBE_LAUNCH_CHECK_BASE_URL ?? DEFAULT_BASE_URL2,
4382
4377
  help: false,
4383
4378
  version: false,
4384
- noColor: !!process2.env.NO_COLOR,
4385
- proof: shouldUploadProof()
4379
+ noColor: !!process.env.NO_COLOR,
4380
+ proof: true
4386
4381
  };
4387
4382
  for (let i = 0; i < argv2.length; i++) {
4388
4383
  const a = argv2[i];
@@ -4394,8 +4389,8 @@ function parseArgs(argv2) {
4394
4389
  else if (a === "--no-publish" || a === "--publish")
4395
4390
  opts.unsupportedWallFlag = a;
4396
4391
  else if (a === "--base-url") opts.baseUrl = argv2[++i] ?? opts.baseUrl;
4397
- else if (a === "--cwd") opts.cwd = path19.resolve(argv2[++i] ?? opts.cwd);
4398
- else if (!a.startsWith("-")) opts.cwd = path19.resolve(a);
4392
+ else if (a === "--cwd") opts.cwd = path18.resolve(argv2[++i] ?? opts.cwd);
4393
+ else if (!a.startsWith("-")) opts.cwd = path18.resolve(a);
4399
4394
  }
4400
4395
  return opts;
4401
4396
  }
@@ -4414,8 +4409,14 @@ function color(enabled) {
4414
4409
  };
4415
4410
  }
4416
4411
  var SEVERITY_ORDER = ["critical", "high", "medium", "lower"];
4412
+ function pluralize(count, singular, plural = `${singular}s`) {
4413
+ return count === 1 ? singular : plural;
4414
+ }
4415
+ function findingVerb(count) {
4416
+ return count === 1 ? "is" : "are";
4417
+ }
4417
4418
  function printHelp() {
4418
- process2.stdout.write(
4419
+ process.stdout.write(
4419
4420
  `shippingszn v${PKG_VERSION}
4420
4421
 
4421
4422
  Read-only scanner that checks the current project against a small set of
@@ -4426,8 +4427,8 @@ Usage:
4426
4427
 
4427
4428
  Options:
4428
4429
  --json Output a machine-readable JSON summary.
4429
- --proof Upload full scan evidence and return a scan-specific
4430
- Launch Fix Kit URL.
4430
+ --proof Backward-compatible alias. Normal runs already return
4431
+ a scan-specific Launch Fix Kit URL.
4431
4432
  --base-url <url> Base URL used to build checkout and Fix Kit links.
4432
4433
  (default: ${DEFAULT_BASE_URL2})
4433
4434
  --cwd <path> Directory to scan. Default: current working directory.
@@ -4438,35 +4439,36 @@ Options:
4438
4439
  This is the FREE preflight. It tells you launch debt exists. It does NOT tell
4439
4440
  you what's broken or how to fix it \u2014 that's gated behind the $49 Launch Fix Kit
4440
4441
  (unlocks full findings + 46-item workbook + paste-ready AI-builder prompts +
4441
- verification steps + red-flag checks). Read-only on disk. Anonymous Wall stats
4442
- (score, severity counts, file count, scanner version \u2014 no project name, no
4443
- paths, no finding-level detail) are sent on every normal run; there is no
4444
- publish opt-in or opt-out flag. Exit code non-zero if any critical findings.
4442
+ verification steps + red-flag checks). Read-only on disk. Normal runs create a
4443
+ locked scan handoff for checkout and send anonymous Wall stats (score, severity
4444
+ counts, file count, scanner version \u2014 no project name, no paths, no
4445
+ finding-level detail); there is no Wall publish opt-in or opt-out flag. Exit
4446
+ code non-zero if any critical findings.
4445
4447
  `
4446
4448
  );
4447
4449
  }
4448
4450
  function scanSource() {
4449
- return process2.env.GITHUB_ACTIONS === "true" ? "github" : "cli";
4451
+ return process.env.GITHUB_ACTIONS === "true" ? "github" : "cli";
4450
4452
  }
4451
4453
  async function run() {
4452
- const opts = parseArgs(process2.argv.slice(2));
4454
+ const opts = parseArgs(process.argv.slice(2));
4453
4455
  if (opts.help) {
4454
4456
  printHelp();
4455
4457
  return 0;
4456
4458
  }
4457
4459
  if (opts.version) {
4458
- process2.stdout.write(`${PKG_VERSION}
4460
+ process.stdout.write(`${PKG_VERSION}
4459
4461
  `);
4460
4462
  return 0;
4461
4463
  }
4462
4464
  if (opts.unsupportedWallFlag) {
4463
- process2.stderr.write(
4465
+ process.stderr.write(
4464
4466
  `${opts.unsupportedWallFlag} is not supported. shippingszn sends anonymous Wall stats on normal runs: score, severity counts, file count, scanner version, and safe stack tags. It never uploads code, file paths, finding-level details, project names, repo URLs, secrets, emails, or handles.
4465
4467
  `
4466
4468
  );
4467
4469
  return 2;
4468
4470
  }
4469
- const c = color(!opts.noColor && process2.stdout.isTTY === true && !opts.json);
4471
+ const c = color(!opts.noColor && process.stdout.isTTY === true && !opts.json);
4470
4472
  const files = await listFiles(opts.cwd);
4471
4473
  const tracked = getTrackedFiles(opts.cwd);
4472
4474
  const ctx = { rootDir: opts.cwd, files };
@@ -4489,7 +4491,7 @@ async function run() {
4489
4491
  const fixKitUrl = `${trimmedBaseUrl}/fix-kit`;
4490
4492
  const reportUrl = fixKitUrl;
4491
4493
  const proofCreatePath = `${trimmedBaseUrl}/scan`;
4492
- const proofUploadHint = "Run `npx shippingszn@latest --proof` to generate a scan-specific Launch Fix Kit URL.";
4494
+ const proofUploadHint = "Normal runs automatically generate a scan-specific Launch Fix Kit URL.";
4493
4495
  const tracked_aware = applyTrackingAwareSeverity(all, tracked);
4494
4496
  const source = scanSource();
4495
4497
  const enriched = tracked_aware.map((f) => {
@@ -4635,9 +4637,6 @@ async function run() {
4635
4637
  const automatedAreas = CHECKLIST.filter(
4636
4638
  (item) => item.cliCoverage === "automated"
4637
4639
  ).length;
4638
- const ownerVerifyAreas = CHECKLIST.filter(
4639
- (item) => item.cliCoverage === "manual_only"
4640
- ).length;
4641
4640
  const SCORE_BAND_LABEL = {
4642
4641
  blocked: "NO-GO",
4643
4642
  fix_first: "FIX FIRST",
@@ -4668,9 +4667,8 @@ async function run() {
4668
4667
  counts: { ...totals },
4669
4668
  filesScanned: files.length,
4670
4669
  coverage: {
4671
- automatedAreas,
4672
- ownerVerifyAreas,
4673
- totalAreas: CHECKLIST.length
4670
+ checksCompleted: automatedAreas,
4671
+ checklistAreas: CHECKLIST.length
4674
4672
  },
4675
4673
  scannerVersion: PKG_VERSION,
4676
4674
  detailsLocked: true,
@@ -4680,112 +4678,153 @@ async function run() {
4680
4678
  ...wallUrl ? { url: wallUrl } : {},
4681
4679
  ...wallError ? { error: wallError } : {}
4682
4680
  },
4683
- proof: {
4681
+ scanHandoff: {
4684
4682
  status: proofResult.status,
4685
4683
  ...proofResult.status === "uploaded" ? {
4686
- url: proofResult.proofUrl,
4687
4684
  resultId: proofResult.id,
4688
- reportUrl: proofResult.reportUrl
4685
+ unlockUrl: proofResult.reportUrl
4689
4686
  } : {},
4690
4687
  ...proofResult.status === "failed" && proofResult.error ? { error: proofResult.error } : {}
4691
4688
  }
4692
4689
  };
4693
- process2.stdout.write(JSON.stringify(scoreSummary, null, 2) + "\n");
4690
+ process.stdout.write(JSON.stringify(scoreSummary, null, 2) + "\n");
4694
4691
  return totals.critical > 0 ? 1 : 0;
4695
4692
  }
4696
4693
  const bandColor = band === "no_go" ? c.red : band === "fix_first" ? c.yellow : band === "verify_before_launch" ? c.blue : c.green;
4697
- process2.stdout.write(
4694
+ process.stdout.write(
4698
4695
  `
4699
4696
  ${c.bold("shippingszn")} ${c.dim(`v${PKG_VERSION}`)}
4700
4697
  `
4701
4698
  );
4702
- process2.stdout.write(c.dim(`Scanned ${files.length} files.
4699
+ process.stdout.write(c.dim(`Scanned ${files.length} files.
4703
4700
 
4704
4701
  `));
4705
- process2.stdout.write(
4702
+ process.stdout.write(
4706
4703
  `${c.bold("Launch Debt Score:")} ${launchReadiness.score}/100 \u2014 ${bandColor(c.bold(bandLabel))}
4707
4704
 
4708
4705
  `
4709
4706
  );
4710
- process2.stdout.write(`${c.bold("Findings detected:")}
4707
+ process.stdout.write(`${c.bold("Findings detected:")}
4711
4708
  `);
4712
- process2.stdout.write(` ${c.red(`${totals.critical} critical`)}
4709
+ process.stdout.write(` ${c.red(`${totals.critical} critical`)}
4713
4710
  `);
4714
- process2.stdout.write(` ${c.yellow(`${totals.high} high`)}
4711
+ process.stdout.write(` ${c.yellow(`${totals.high} high`)}
4715
4712
  `);
4716
- process2.stdout.write(` ${c.blue(`${totals.medium} medium`)}
4713
+ process.stdout.write(` ${c.blue(`${totals.medium} medium`)}
4717
4714
  `);
4718
- process2.stdout.write(` ${c.gray(`${totals.lower} lower`)}
4715
+ process.stdout.write(` ${c.gray(`${totals.lower} lower`)}
4719
4716
 
4720
4717
  `);
4721
- process2.stdout.write(`${c.bold("Coverage:")}
4718
+ const totalFindings = totals.critical + totals.high + totals.medium + totals.lower;
4719
+ if (totalFindings > 0) {
4720
+ if (totals.critical > 0) {
4721
+ process.stdout.write(c.red("Critical launch blocker found.\n"));
4722
+ process.stdout.write(
4723
+ `This scan found ${totalFindings} ${pluralize(totalFindings, "issue")} that should be fixed before launch.
4724
+
4725
+ `
4726
+ );
4727
+ process.stdout.write(`${c.bold("What that means:")}
4722
4728
  `);
4723
- process2.stdout.write(
4724
- c.dim(
4725
- ` ${automatedAreas} of ${CHECKLIST.length} launch-readiness areas checked by the scanner
4729
+ process.stdout.write(
4730
+ c.dim(
4731
+ "Critical launch debt can expose users, break signup or payment paths, or make the launch unsafe until fixed.\n\n"
4732
+ )
4733
+ );
4734
+ } else {
4735
+ process.stdout.write("No critical blockers found.\n");
4736
+ if (totals.high === 0) {
4737
+ process.stdout.write("No high blockers found.\n");
4738
+ }
4739
+ process.stdout.write(
4740
+ `But ${totalFindings} ${pluralize(totalFindings, "issue")} ${findingVerb(totalFindings)} still holding this back from a clean launch.
4741
+
4726
4742
  `
4727
- )
4728
- );
4729
- process2.stdout.write(
4730
- c.dim(` ${ownerVerifyAreas} require owner verification
4743
+ );
4744
+ process.stdout.write(`${c.bold("What that means:")}
4745
+ `);
4746
+ if (totals.high > 0) {
4747
+ process.stdout.write(
4748
+ c.dim(
4749
+ "High and medium launch debt can expose trust gaps, break conversion moments, or make the project feel unfinished.\n\n"
4750
+ )
4751
+ );
4752
+ } else if (totals.medium > 0) {
4753
+ process.stdout.write(
4754
+ c.dim(
4755
+ "Medium launch debt usually will not crash the app, but it can make users hesitate, miss conversion moments, or make the project feel unfinished.\n\n"
4756
+ )
4757
+ );
4758
+ } else {
4759
+ process.stdout.write(
4760
+ c.dim(
4761
+ "Lower launch debt usually is not launch-blocking, but it can still make the project feel rough or unfinished.\n\n"
4762
+ )
4763
+ );
4764
+ }
4765
+ }
4766
+ }
4767
+ process.stdout.write(`${c.bold("Coverage:")}
4768
+ `);
4769
+ process.stdout.write(
4770
+ c.dim(` ${automatedAreas} launch-readiness checks completed
4731
4771
 
4732
4772
  `)
4733
4773
  );
4734
- if (totals.critical + totals.high + totals.medium + totals.lower > 0) {
4774
+ if (totalFindings > 0) {
4735
4775
  if (scanSpecificUnlockUrl) {
4736
- process2.stdout.write(c.bold("Unlock this exact scan:\n"));
4737
- process2.stdout.write(` ${c.cyan(scanSpecificUnlockUrl)}
4776
+ process.stdout.write(c.bold("Unlock this exact scan:\n"));
4777
+ process.stdout.write(` ${c.cyan(scanSpecificUnlockUrl)}
4738
4778
  `);
4739
- process2.stdout.write(
4779
+ process.stdout.write(
4740
4780
  c.dim(
4741
- " Full findings, file evidence, and AI-builder prompts stay locked until purchase.\n\n"
4781
+ ` Includes the ${totalFindings} specific ${pluralize(totalFindings, "finding")}, file evidence, and AI-builder fix prompts.
4782
+
4783
+ `
4742
4784
  )
4743
4785
  );
4744
4786
  } else {
4745
- process2.stdout.write(c.bold("Full findings are locked:\n"));
4746
- process2.stdout.write(` ${c.cyan(fixKitUrl)}
4787
+ process.stdout.write(c.bold("Full findings are locked:\n"));
4788
+ process.stdout.write(` ${c.cyan(fixKitUrl)}
4747
4789
  `);
4748
- process2.stdout.write(
4790
+ process.stdout.write(
4749
4791
  c.dim(
4750
- " For a scan-specific Fix Kit link, rerun: npx shippingszn@latest --proof\n\n"
4792
+ " This run could not attach scan evidence. The full report stays locked until purchase.\n\n"
4751
4793
  )
4752
4794
  );
4753
4795
  }
4754
4796
  } else {
4755
4797
  if (scanSpecificUnlockUrl) {
4756
- process2.stdout.write(
4798
+ process.stdout.write(
4757
4799
  c.green("No automated findings detected for this scan.\n")
4758
4800
  );
4759
- process2.stdout.write(c.bold("Unlock the owner-verification Fix Kit:\n"));
4760
- process2.stdout.write(` ${c.cyan(scanSpecificUnlockUrl)}
4801
+ process.stdout.write(c.bold("Unlock this exact scan:\n"));
4802
+ process.stdout.write(` ${c.cyan(scanSpecificUnlockUrl)}
4761
4803
 
4762
4804
  `);
4763
4805
  } else {
4764
- process2.stdout.write(
4806
+ process.stdout.write(
4765
4807
  c.green(
4766
- "No automated findings detected. The Launch Fix Kit covers the 27 owner-verify areas the scanner can't reach:\n"
4808
+ "No automated findings detected. Unlock the Launch Fix Kit for the full checklist and written launch report:\n"
4767
4809
  )
4768
4810
  );
4769
- process2.stdout.write(` ${c.cyan(fixKitUrl)}
4811
+ process.stdout.write(` ${c.cyan(fixKitUrl)}
4770
4812
  `);
4771
- process2.stdout.write(
4813
+ process.stdout.write(
4772
4814
  c.dim(
4773
- " For a scan-specific Fix Kit link, rerun: npx shippingszn@latest --proof\n\n"
4815
+ " This run could not attach scan evidence. The full report stays locked until purchase.\n\n"
4774
4816
  )
4775
4817
  );
4776
4818
  }
4777
4819
  }
4778
- if (proofResult.status === "uploaded" && proofResult.proofUrl) {
4779
- process2.stdout.write(c.dim(`Share score proof: ${proofResult.proofUrl}
4780
- `));
4781
- } else if (proofResult.status === "failed") {
4782
- process2.stdout.write(
4783
- c.dim(`(Proof upload failed: ${proofResult.error ?? "unknown"})
4820
+ if (proofResult.status === "failed") {
4821
+ process.stdout.write(
4822
+ c.dim(`(Scan handoff failed: ${proofResult.error ?? "unknown"})
4784
4823
  `)
4785
4824
  );
4786
4825
  }
4787
4826
  if (publishResult === "published") {
4788
- process2.stdout.write(
4827
+ process.stdout.write(
4789
4828
  c.dim("(Anonymous Wall stats sent: score + severity counts.)\n")
4790
4829
  );
4791
4830
  }
@@ -4795,12 +4834,12 @@ ${c.bold("shippingszn")} ${c.dim(`v${PKG_VERSION}`)}
4795
4834
  return 0;
4796
4835
  }
4797
4836
  run().then(
4798
- (code) => process2.exit(code),
4837
+ (code) => process.exit(code),
4799
4838
  (err) => {
4800
- process2.stderr.write(
4839
+ process.stderr.write(
4801
4840
  `shippingszn failed: ${err instanceof Error ? err.message : String(err)}
4802
4841
  `
4803
4842
  );
4804
- process2.exit(2);
4843
+ process.exit(2);
4805
4844
  }
4806
4845
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shippingszn",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "Read-only CLI scanner that checks a project for common pre-launch issues from the shippingszn.com launch checklist.",
5
5
  "license": "MIT",
6
6
  "type": "module",