openpitstop 1.0.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/LICENSE +21 -0
- package/README.md +512 -0
- package/demo-repo/README.md +24 -0
- package/demo-repo/package-lock.json +4483 -0
- package/demo-repo/package.json +17 -0
- package/demo-repo/src/config.js +5 -0
- package/demo-repo/src/db.js +31 -0
- package/demo-repo/src/server.js +13 -0
- package/demo-repo/src/userController.js +22 -0
- package/demo-repo/src/userRepo.js +18 -0
- package/demo-repo/src/userService.js +59 -0
- package/demo-repo/test/user.test.js +12 -0
- package/demo-repo-fintech/README.md +27 -0
- package/demo-repo-fintech/package-lock.json +1023 -0
- package/demo-repo-fintech/package.json +14 -0
- package/demo-repo-fintech/pitstop-repro-ledger-order-ord-conc-1-charged-2.test.mjs +175 -0
- package/demo-repo-fintech/pitstop-repro-ledger-order-ord-retry-2-charged-2.test.mjs +175 -0
- package/demo-repo-fintech/pitstop-repro-ledger-order-ord-webhook-3-charged-2.test.mjs +175 -0
- package/demo-repo-fintech/src/gateway.js +26 -0
- package/demo-repo-fintech/src/server.js +61 -0
- package/demo-repo-generators/package-lock.json +1508 -0
- package/demo-repo-generators/package.json +17 -0
- package/demo-repo-generators/public/index.html +10 -0
- package/demo-repo-generators/scripts/build.js +17 -0
- package/demo-repo-generators/src/counter.js +16 -0
- package/demo-repo-integrity/README.md +49 -0
- package/demo-repo-integrity/package.json +12 -0
- package/demo-repo-integrity/src/money.js +19 -0
- package/demo-repo-integrity/test/money.test.js +17 -0
- package/dist/analyzers/accessibility.d.ts +18 -0
- package/dist/analyzers/accessibility.js +248 -0
- package/dist/analyzers/accessibility.js.map +1 -0
- package/dist/analyzers/dependencyGraph.d.ts +14 -0
- package/dist/analyzers/dependencyGraph.js +206 -0
- package/dist/analyzers/dependencyGraph.js.map +1 -0
- package/dist/analyzers/devex.d.ts +19 -0
- package/dist/analyzers/devex.js +301 -0
- package/dist/analyzers/devex.js.map +1 -0
- package/dist/analyzers/duplication.d.ts +2 -0
- package/dist/analyzers/duplication.js +47 -0
- package/dist/analyzers/duplication.js.map +1 -0
- package/dist/analyzers/index.d.ts +12 -0
- package/dist/analyzers/index.js +38 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/integrity/assertionLiteralTamper.d.ts +2 -0
- package/dist/analyzers/integrity/assertionLiteralTamper.js +164 -0
- package/dist/analyzers/integrity/assertionLiteralTamper.js.map +1 -0
- package/dist/analyzers/integrity/exceptionSwallow.d.ts +2 -0
- package/dist/analyzers/integrity/exceptionSwallow.js +198 -0
- package/dist/analyzers/integrity/exceptionSwallow.js.map +1 -0
- package/dist/analyzers/integrity/exitCheat.d.ts +2 -0
- package/dist/analyzers/integrity/exitCheat.js +31 -0
- package/dist/analyzers/integrity/exitCheat.js.map +1 -0
- package/dist/analyzers/integrity/git.d.ts +10 -0
- package/dist/analyzers/integrity/git.js +181 -0
- package/dist/analyzers/integrity/git.js.map +1 -0
- package/dist/analyzers/integrity/hardcodedMatch.d.ts +2 -0
- package/dist/analyzers/integrity/hardcodedMatch.js +93 -0
- package/dist/analyzers/integrity/hardcodedMatch.js.map +1 -0
- package/dist/analyzers/integrity/helpers.d.ts +21 -0
- package/dist/analyzers/integrity/helpers.js +66 -0
- package/dist/analyzers/integrity/helpers.js.map +1 -0
- package/dist/analyzers/integrity/index.d.ts +10 -0
- package/dist/analyzers/integrity/index.js +27 -0
- package/dist/analyzers/integrity/index.js.map +1 -0
- package/dist/analyzers/integrity/mockOverreach.d.ts +2 -0
- package/dist/analyzers/integrity/mockOverreach.js +72 -0
- package/dist/analyzers/integrity/mockOverreach.js.map +1 -0
- package/dist/analyzers/integrity/suppressionCreep.d.ts +2 -0
- package/dist/analyzers/integrity/suppressionCreep.js +27 -0
- package/dist/analyzers/integrity/suppressionCreep.js.map +1 -0
- package/dist/analyzers/integrity/testTamper.d.ts +2 -0
- package/dist/analyzers/integrity/testTamper.js +153 -0
- package/dist/analyzers/integrity/testTamper.js.map +1 -0
- package/dist/analyzers/integrity/types.d.ts +63 -0
- package/dist/analyzers/integrity/types.js +13 -0
- package/dist/analyzers/integrity/types.js.map +1 -0
- package/dist/analyzers/ledger/attacks.d.ts +17 -0
- package/dist/analyzers/ledger/attacks.js +135 -0
- package/dist/analyzers/ledger/attacks.js.map +1 -0
- package/dist/analyzers/ledger/discover.d.ts +15 -0
- package/dist/analyzers/ledger/discover.js +122 -0
- package/dist/analyzers/ledger/discover.js.map +1 -0
- package/dist/analyzers/ledger/evidence.d.ts +22 -0
- package/dist/analyzers/ledger/evidence.js +127 -0
- package/dist/analyzers/ledger/evidence.js.map +1 -0
- package/dist/analyzers/ledger/harness.d.ts +4 -0
- package/dist/analyzers/ledger/harness.js +270 -0
- package/dist/analyzers/ledger/harness.js.map +1 -0
- package/dist/analyzers/ledger/index.d.ts +14 -0
- package/dist/analyzers/ledger/index.js +116 -0
- package/dist/analyzers/ledger/index.js.map +1 -0
- package/dist/analyzers/ledger/types.d.ts +31 -0
- package/dist/analyzers/ledger/types.js +2 -0
- package/dist/analyzers/ledger/types.js.map +1 -0
- package/dist/analyzers/perf.d.ts +2 -0
- package/dist/analyzers/perf.js +106 -0
- package/dist/analyzers/perf.js.map +1 -0
- package/dist/analyzers/reliability.d.ts +22 -0
- package/dist/analyzers/reliability.js +339 -0
- package/dist/analyzers/reliability.js.map +1 -0
- package/dist/analyzers/routes.d.ts +17 -0
- package/dist/analyzers/routes.js +115 -0
- package/dist/analyzers/routes.js.map +1 -0
- package/dist/analyzers/security.d.ts +2 -0
- package/dist/analyzers/security.js +302 -0
- package/dist/analyzers/security.js.map +1 -0
- package/dist/analyzers/suiteRunner.d.ts +64 -0
- package/dist/analyzers/suiteRunner.js +381 -0
- package/dist/analyzers/suiteRunner.js.map +1 -0
- package/dist/analyzers/tests.d.ts +2 -0
- package/dist/analyzers/tests.js +215 -0
- package/dist/analyzers/tests.js.map +1 -0
- package/dist/analyzers/types.d.ts +203 -0
- package/dist/analyzers/types.js +2 -0
- package/dist/analyzers/types.js.map +1 -0
- package/dist/analyzers/util.d.ts +35 -0
- package/dist/analyzers/util.js +209 -0
- package/dist/analyzers/util.js.map +1 -0
- package/dist/ciCheckA.d.ts +2 -0
- package/dist/ciCheckA.js +5 -0
- package/dist/ciCheckA.js.map +1 -0
- package/dist/ciCheckB.d.ts +2 -0
- package/dist/ciCheckB.js +6 -0
- package/dist/ciCheckB.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +65 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/budget.d.ts +33 -0
- package/dist/commands/budget.js +108 -0
- package/dist/commands/budget.js.map +1 -0
- package/dist/commands/ci.d.ts +14 -0
- package/dist/commands/ci.js +157 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/demo.d.ts +2 -0
- package/dist/commands/demo.js +163 -0
- package/dist/commands/demo.js.map +1 -0
- package/dist/commands/digest.d.ts +8 -0
- package/dist/commands/digest.js +189 -0
- package/dist/commands/digest.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +98 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/drive.d.ts +3 -0
- package/dist/commands/drive.js +170 -0
- package/dist/commands/drive.js.map +1 -0
- package/dist/commands/gate.d.ts +2 -0
- package/dist/commands/gate.js +136 -0
- package/dist/commands/gate.js.map +1 -0
- package/dist/commands/honesty.d.ts +2 -0
- package/dist/commands/honesty.js +182 -0
- package/dist/commands/honesty.js.map +1 -0
- package/dist/commands/inspect.d.ts +2 -0
- package/dist/commands/inspect.js +244 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +81 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/integrity.d.ts +2 -0
- package/dist/commands/integrity.js +74 -0
- package/dist/commands/integrity.js.map +1 -0
- package/dist/commands/memory.d.ts +6 -0
- package/dist/commands/memory.js +90 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/pen.d.ts +17 -0
- package/dist/commands/pen.js +158 -0
- package/dist/commands/pen.js.map +1 -0
- package/dist/commands/prompt.d.ts +2 -0
- package/dist/commands/prompt.js +37 -0
- package/dist/commands/prompt.js.map +1 -0
- package/dist/commands/readyCheck.d.ts +21 -0
- package/dist/commands/readyCheck.js +68 -0
- package/dist/commands/readyCheck.js.map +1 -0
- package/dist/commands/report.d.ts +2 -0
- package/dist/commands/report.js +48 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/repro.d.ts +3 -0
- package/dist/commands/repro.js +61 -0
- package/dist/commands/repro.js.map +1 -0
- package/dist/commands/scan.d.ts +27 -0
- package/dist/commands/scan.js +348 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/share.d.ts +2 -0
- package/dist/commands/share.js +163 -0
- package/dist/commands/share.js.map +1 -0
- package/dist/commands/trends.d.ts +2 -0
- package/dist/commands/trends.js +103 -0
- package/dist/commands/trends.js.map +1 -0
- package/dist/commands/try.d.ts +12 -0
- package/dist/commands/try.js +208 -0
- package/dist/commands/try.js.map +1 -0
- package/dist/commands/verify.d.ts +44 -0
- package/dist/commands/verify.js +381 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/watch.d.ts +10 -0
- package/dist/commands/watch.js +70 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/evidence.d.ts +37 -0
- package/dist/evidence.js +61 -0
- package/dist/evidence.js.map +1 -0
- package/dist/graph/correlate.d.ts +7 -0
- package/dist/graph/correlate.js +246 -0
- package/dist/graph/correlate.js.map +1 -0
- package/dist/graph/integrity.d.ts +22 -0
- package/dist/graph/integrity.js +39 -0
- package/dist/graph/integrity.js.map +1 -0
- package/dist/installer/targets.d.ts +23 -0
- package/dist/installer/targets.js +162 -0
- package/dist/installer/targets.js.map +1 -0
- package/dist/memory/store.d.ts +33 -0
- package/dist/memory/store.js +131 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/pen/dynamic.d.ts +36 -0
- package/dist/pen/dynamic.js +622 -0
- package/dist/pen/dynamic.js.map +1 -0
- package/dist/pen/fix.d.ts +35 -0
- package/dist/pen/fix.js +239 -0
- package/dist/pen/fix.js.map +1 -0
- package/dist/pen/proof.d.ts +46 -0
- package/dist/pen/proof.js +112 -0
- package/dist/pen/proof.js.map +1 -0
- package/dist/pen/report.d.ts +11 -0
- package/dist/pen/report.js +258 -0
- package/dist/pen/report.js.map +1 -0
- package/dist/pen/static.d.ts +17 -0
- package/dist/pen/static.js +565 -0
- package/dist/pen/static.js.map +1 -0
- package/dist/pen/store.d.ts +11 -0
- package/dist/pen/store.js +36 -0
- package/dist/pen/store.js.map +1 -0
- package/dist/pen/types.d.ts +112 -0
- package/dist/pen/types.js +53 -0
- package/dist/pen/types.js.map +1 -0
- package/dist/report/format.d.ts +126 -0
- package/dist/report/format.js +706 -0
- package/dist/report/format.js.map +1 -0
- package/dist/report/score.d.ts +47 -0
- package/dist/report/score.js +164 -0
- package/dist/report/score.js.map +1 -0
- package/dist/repro/framework.d.ts +26 -0
- package/dist/repro/framework.js +224 -0
- package/dist/repro/framework.js.map +1 -0
- package/dist/repro/generate.d.ts +14 -0
- package/dist/repro/generate.js +669 -0
- package/dist/repro/generate.js.map +1 -0
- package/dist/repro/ids.d.ts +32 -0
- package/dist/repro/ids.js +175 -0
- package/dist/repro/ids.js.map +1 -0
- package/dist/repro/index.d.ts +24 -0
- package/dist/repro/index.js +69 -0
- package/dist/repro/index.js.map +1 -0
- package/dist/repro/pen.d.ts +26 -0
- package/dist/repro/pen.js +321 -0
- package/dist/repro/pen.js.map +1 -0
- package/dist/repro/run.d.ts +18 -0
- package/dist/repro/run.js +36 -0
- package/dist/repro/run.js.map +1 -0
- package/dist/sandbox/proxy.d.ts +41 -0
- package/dist/sandbox/proxy.js +231 -0
- package/dist/sandbox/proxy.js.map +1 -0
- package/dist/sandbox/startCmd.d.ts +24 -0
- package/dist/sandbox/startCmd.js +71 -0
- package/dist/sandbox/startCmd.js.map +1 -0
- package/dist/ui/spinner.d.ts +18 -0
- package/dist/ui/spinner.js +26 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/verify/metrics.d.ts +13 -0
- package/dist/verify/metrics.js +72 -0
- package/dist/verify/metrics.js.map +1 -0
- package/package.json +68 -0
- package/scripts/cheat-demo.cjs +102 -0
- package/templates/ledger/preload.cjs +331 -0
- package/templates/pen/preload.cjs +196 -0
- package/templates/pitstop.prompt.md +371 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { exec } from "node:child_process";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { buildModel, escapeHtml, loadHistory, svgTrend } from "../report/format.js";
|
|
7
|
+
import { computeScore, gradeHex, renderBadgeSvg } from "../report/score.js";
|
|
8
|
+
import { checkEvidence } from "../evidence.js";
|
|
9
|
+
import { enumerateFindings } from "../repro/ids.js";
|
|
10
|
+
const SEV_ORDER = { critical: 0, high: 1, medium: 2, low: 3, warning: 4 };
|
|
11
|
+
/**
|
|
12
|
+
* `pitstop share` — the viral artifact: a 1200×630 self-contained HTML card
|
|
13
|
+
* (inline CSS + inline SVG, zero external assets) built to be screenshotted and
|
|
14
|
+
* posted on X/LinkedIn. Opens in the browser with `--open`.
|
|
15
|
+
*/
|
|
16
|
+
function topFindings(latest) {
|
|
17
|
+
if (!latest)
|
|
18
|
+
return [];
|
|
19
|
+
return enumerateFindings(latest)
|
|
20
|
+
.sort((a, b) => (SEV_ORDER[a.severity] ?? 9) - (SEV_ORDER[b.severity] ?? 9) ||
|
|
21
|
+
a.type.localeCompare(b.type))
|
|
22
|
+
.slice(0, 4);
|
|
23
|
+
}
|
|
24
|
+
function chip(hex, text) {
|
|
25
|
+
return `<span style="display:inline-block;background:${hex}1f;color:${hex};border:1px solid ${hex}66;border-radius:999px;padding:3px 12px;font-size:13px;font-weight:600;margin:3px 6px 0 0">${escapeHtml(text)}</span>`;
|
|
26
|
+
}
|
|
27
|
+
function renderShareHtml(args) {
|
|
28
|
+
const sc = args.score;
|
|
29
|
+
const accent = sc ? gradeHex(sc.grade) : "#58a6ff";
|
|
30
|
+
const findingsRows = args.findings.length === 0
|
|
31
|
+
? `<div class="muted" style="font-size:15px">No findings in the latest scan — clean repo.</div>`
|
|
32
|
+
: args.findings
|
|
33
|
+
.map((f) => {
|
|
34
|
+
const dot = f.severity === "critical" || f.severity === "high"
|
|
35
|
+
? "#f85149"
|
|
36
|
+
: f.severity === "medium"
|
|
37
|
+
? "#d29922"
|
|
38
|
+
: "#58a6ff";
|
|
39
|
+
return `<div class="finding"><span class="dot" style="background:${dot}"></span><span class="fsrc">${escapeHtml(f.source)}</span><span class="fdesc">${escapeHtml(f.description)}</span></div>`;
|
|
40
|
+
})
|
|
41
|
+
.join("\n");
|
|
42
|
+
return `<!DOCTYPE html>
|
|
43
|
+
<html lang="en">
|
|
44
|
+
<head>
|
|
45
|
+
<meta charset="utf-8"/>
|
|
46
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
47
|
+
<title>PITSTOP — ${escapeHtml(args.repo)}</title>
|
|
48
|
+
<meta name="twitter:card" content="summary_large_image"/>
|
|
49
|
+
<meta name="og:title" content="OpenPitStop scored ${escapeHtml(args.repo)} — ${sc ? sc.score + "/100 (" + sc.grade + ")" : "no scan yet"}"/>
|
|
50
|
+
<meta name="og:description" content="OpenPitStop scans repos, gates AI agents, and seals every report with a tamper-evident signature. npx openpitstop try"/>
|
|
51
|
+
<style>
|
|
52
|
+
:root{color-scheme:dark}
|
|
53
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
54
|
+
html,body{width:1200px;height:630px;overflow:hidden}
|
|
55
|
+
body{background:#0d1117;color:#e6edf3;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
|
|
56
|
+
.wrap{width:1200px;height:630px;display:flex;flex-direction:column;padding:44px 52px 34px;position:relative;background:radial-gradient(1200px 420px at 88% -8%, ${accent}1c, transparent 60%)}
|
|
57
|
+
header{display:flex;align-items:center;gap:20px}
|
|
58
|
+
.mark{font-size:27px;font-weight:800;letter-spacing:0.5px;flex:0 0 auto}
|
|
59
|
+
.mark b{color:${accent}}
|
|
60
|
+
.repo{color:#8b949e;font-size:16px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
61
|
+
.when{color:#8b949e;font-size:13px;flex:0 0 auto}
|
|
62
|
+
main{flex:1;display:flex;gap:64px;align-items:center;margin-top:22px}
|
|
63
|
+
.left{flex:0 0 300px}
|
|
64
|
+
.score{font-size:150px;font-weight:800;line-height:1;color:${accent};font-variant-numeric:tabular-nums}
|
|
65
|
+
.score small{font-size:34px;font-weight:600;color:#8b949e}
|
|
66
|
+
.grd{font-size:40px;font-weight:800;color:${accent};margin-top:8px}
|
|
67
|
+
.sub{color:#8b949e;font-size:15px;margin-top:10px}
|
|
68
|
+
.right{flex:1;min-width:0}
|
|
69
|
+
.chips{display:flex;flex-wrap:wrap}
|
|
70
|
+
.trend{margin-top:16px;background:#161b22;border:1px solid #30363d;border-radius:12px;padding:14px 16px}
|
|
71
|
+
.trend h4{color:#8b949e;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;margin-bottom:6px}
|
|
72
|
+
.findings{background:#161b22;border:1px solid #30363d;border-radius:12px;padding:16px 18px;margin-top:14px}
|
|
73
|
+
.findings h4{color:#8b949e;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;margin-bottom:8px}
|
|
74
|
+
.finding{display:flex;align-items:center;gap:10px;padding:8px 0;font-size:15px}
|
|
75
|
+
.finding + .finding{border-top:1px solid #21262d}
|
|
76
|
+
.dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
|
|
77
|
+
.fsrc{color:#8b949e;font-size:12px;text-transform:uppercase;letter-spacing:0.4px;flex:0 0 72px}
|
|
78
|
+
.fdesc{color:#e6edf3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
79
|
+
footer{margin-top:22px;padding-top:16px;border-top:1px solid #30363d;display:flex;justify-content:space-between;align-items:center;color:#8b949e;font-size:13px}
|
|
80
|
+
footer b{color:${accent}}
|
|
81
|
+
.muted{color:#8b949e}
|
|
82
|
+
</style>
|
|
83
|
+
</head>
|
|
84
|
+
<body><div class="wrap">
|
|
85
|
+
<header>
|
|
86
|
+
<div class="mark">PITSTOP</div>
|
|
87
|
+
<div class="repo" title="${escapeHtml(args.repo)}">${escapeHtml(args.repo)}</div>
|
|
88
|
+
<div class="when">${escapeHtml(args.generatedAt.slice(0, 19).replace("T", " "))}</div>
|
|
89
|
+
</header>
|
|
90
|
+
<main>
|
|
91
|
+
<div class="left">
|
|
92
|
+
${sc ? `<div class="score">${sc.score}<small>/100</small></div><div class="grd">${escapeHtml(sc.grade)}</div>` : `<div class="score" style="font-size:52px">no scan</div><div class="grd">—</div>`}
|
|
93
|
+
<div class="sub">OpenPitStop Score · health of the repo</div>
|
|
94
|
+
</div>
|
|
95
|
+
<div class="right">
|
|
96
|
+
<div class="chips">${args.chips}</div>
|
|
97
|
+
<div class="trend"><h4>Score across ${args.scansCount} scan(s)</h4>${args.sparkline}</div>
|
|
98
|
+
<div class="findings"><h4>Top findings</h4>${findingsRows}</div>
|
|
99
|
+
</div>
|
|
100
|
+
</main>
|
|
101
|
+
<footer>
|
|
102
|
+
<span>npx openpitstop try · scan / verify / gate / digest</span>
|
|
103
|
+
<span>permanent proof: <b>${args.proofCount}</b> committed repro test(s)</span>
|
|
104
|
+
</footer>
|
|
105
|
+
</div></body></html>`;
|
|
106
|
+
}
|
|
107
|
+
export const share = new Command("share")
|
|
108
|
+
.description("Generate a 1200×630 self-contained share card (PITSTOP_CARD.html) with the OpenPitStop Score, " +
|
|
109
|
+
"integrity/evidence status and top findings — built to be screenshotted and posted.")
|
|
110
|
+
.argument("[repo]", "path to the repo (default: current dir)", ".")
|
|
111
|
+
.option("-o, --open", "open the card in the default browser", false)
|
|
112
|
+
.action((repoArg, options) => {
|
|
113
|
+
const repo = path.resolve(repoArg);
|
|
114
|
+
const model = buildModel(repo);
|
|
115
|
+
const hist = loadHistory(repo);
|
|
116
|
+
if (hist.scans.length === 0) {
|
|
117
|
+
console.log(chalk.yellow(`no scan history in ${path.join(repo, ".pitstop")} — run \`pitstop try\` or \`pitstop scan\` first.`));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const sc = model.latestScan ? computeScore(model.latestScan) : null;
|
|
121
|
+
const accent = sc ? gradeHex(sc.grade) : "#58a6ff";
|
|
122
|
+
const scores = hist.scans.map((s) => computeScore(s).score);
|
|
123
|
+
const spark = svgTrend(scores, "#58a6ff");
|
|
124
|
+
const latestEv = model.latestScan ? checkEvidence(model.latestScan) : null;
|
|
125
|
+
const evStatus = latestEv?.status === "verified"
|
|
126
|
+
? `signed ${latestEv.digest.slice(0, 8)}…`
|
|
127
|
+
: latestEv?.status === "tampered"
|
|
128
|
+
? "evidence TAMPERED"
|
|
129
|
+
: "evidence untracked";
|
|
130
|
+
const chips = [];
|
|
131
|
+
chips.push(`${sc?.score ?? 0}/100 ${sc?.grade ?? "?"}`);
|
|
132
|
+
chips.push(model.integrity
|
|
133
|
+
? `integrity ${model.integrity.catches} catch · ${model.integrity.selfCorrected} self-corrected`
|
|
134
|
+
: "integrity not checked");
|
|
135
|
+
chips.push(evStatus);
|
|
136
|
+
const findings = topFindings(model.latestScan);
|
|
137
|
+
const badgeSvg = sc ? renderBadgeSvg(sc) : "";
|
|
138
|
+
const html = renderShareHtml({
|
|
139
|
+
repo,
|
|
140
|
+
generatedAt: model.generatedAt,
|
|
141
|
+
score: sc ? { score: sc.score, grade: sc.grade } : null,
|
|
142
|
+
scansCount: hist.scans.length,
|
|
143
|
+
sparkline: spark,
|
|
144
|
+
chips: chips.map((c) => chip(accent, c)).join(""),
|
|
145
|
+
findings,
|
|
146
|
+
proofCount: model.proofs.length,
|
|
147
|
+
});
|
|
148
|
+
const out = path.join(repo, "PITSTOP_CARD.html");
|
|
149
|
+
fs.writeFileSync(out, html);
|
|
150
|
+
console.log(chalk.cyan(`\nShare card written to ${out}`));
|
|
151
|
+
console.log(chalk.dim(` open it, screenshot at 1200×630, post it. Fully self-contained.\n`) +
|
|
152
|
+
(badgeSvg ? chalk.dim(` README badge also renders: ${chalk.cyan("[OpenPitStop score](PITSTOP_BADGE.svg)")}\n`) : ""));
|
|
153
|
+
if (options.open) {
|
|
154
|
+
const cmd = process.platform === "win32"
|
|
155
|
+
? `start "" "${out}"`
|
|
156
|
+
: process.platform === "darwin"
|
|
157
|
+
? `open "${out}"`
|
|
158
|
+
: `xdg-open "${out}"`;
|
|
159
|
+
exec(cmd);
|
|
160
|
+
console.log(chalk.dim(" opened in your default browser."));
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=share.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/commands/share.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import boxen from "boxen";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { loadHistory } from "../report/format.js";
|
|
6
|
+
import { computeScore, gradeColor } from "../report/score.js";
|
|
7
|
+
/**
|
|
8
|
+
* `pitstop trends` — turn the .pitstop/scan-*.json history into sparklines.
|
|
9
|
+
* Every scan is persisted, so this shows the loop actually improving things.
|
|
10
|
+
*/
|
|
11
|
+
const BLOCKS = "▁▂▃▄▅▆▇█";
|
|
12
|
+
function sparkline(values) {
|
|
13
|
+
const pts = values.filter((v) => v != null);
|
|
14
|
+
if (pts.length === 0)
|
|
15
|
+
return chalk.dim("no data");
|
|
16
|
+
if (pts.length === 1)
|
|
17
|
+
return chalk.dim(String(pts[0]));
|
|
18
|
+
const min = Math.min(...pts);
|
|
19
|
+
const max = Math.max(...pts);
|
|
20
|
+
const span = max - min || 1;
|
|
21
|
+
const chars = values.map((v) => {
|
|
22
|
+
if (v == null)
|
|
23
|
+
return " ";
|
|
24
|
+
const idx = Math.min(7, Math.floor(((v - min) / span) * 7.999));
|
|
25
|
+
return BLOCKS[idx];
|
|
26
|
+
});
|
|
27
|
+
const improving = pts[pts.length - 1] < pts[0];
|
|
28
|
+
const paint = pts.length < 2 ? chalk.dim : improving ? chalk.green : chalk.yellow;
|
|
29
|
+
return paint(chars.join(""));
|
|
30
|
+
}
|
|
31
|
+
function num(v) {
|
|
32
|
+
return v == null ? null : v;
|
|
33
|
+
}
|
|
34
|
+
/** Show the last N values only — keeps the box readable on long histories. */
|
|
35
|
+
const WINDOW = 10;
|
|
36
|
+
function windowed(vals) {
|
|
37
|
+
if (vals.length <= WINDOW)
|
|
38
|
+
return { window: vals, truncated: false };
|
|
39
|
+
return { window: vals.slice(-WINDOW), truncated: true };
|
|
40
|
+
}
|
|
41
|
+
export const trends = new Command("trends")
|
|
42
|
+
.description("Show how key metrics moved across every recorded scan, as sparklines")
|
|
43
|
+
.argument("[repo]", "path to the repo to trend (defaults to cwd)", ".")
|
|
44
|
+
.action((repoArg) => {
|
|
45
|
+
const repo = path.resolve(repoArg);
|
|
46
|
+
const hist = loadHistory(repo);
|
|
47
|
+
const scans = hist.scans;
|
|
48
|
+
if (scans.length === 0) {
|
|
49
|
+
console.log(chalk.yellow(`no scan history found in ${path.join(repo, ".pitstop")} — run \`pitstop scan\` a few times first.`));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const rows = [];
|
|
53
|
+
const sec = scans.map((s) => (s.security.status === "ok" ? num(s.security.issues.length) : null));
|
|
54
|
+
rows.push({ label: "Security issues", values: sec, fmt: (v) => (v > 0 ? chalk.red(String(v)) : chalk.green(String(v))) });
|
|
55
|
+
const circ = scans.map((s) => (s.dependencyGraph.status === "ok" ? num(s.dependencyGraph.circular.length) : null));
|
|
56
|
+
rows.push({ label: "Circular imports", values: circ, fmt: (v) => (v > 0 ? chalk.yellow(String(v)) : chalk.green(String(v))) });
|
|
57
|
+
const clones = scans.map((s) => (s.duplication.status === "ok" ? num(s.duplication.cloneCount) : null));
|
|
58
|
+
rows.push({ label: "Duplication clones", values: clones, fmt: (v) => (v > 0 ? chalk.yellow(String(v)) : chalk.green(String(v))) });
|
|
59
|
+
const failed = scans.map((s) => (s.tests.status === "ok" ? num(s.tests.failed) : null));
|
|
60
|
+
rows.push({ label: "Failed tests", values: failed, fmt: (v) => (v > 0 ? chalk.red(String(v)) : chalk.green(String(v))) });
|
|
61
|
+
const cov = scans.map((s) => (s.tests.status === "ok" ? num(s.tests.coverage) : null));
|
|
62
|
+
rows.push({ label: "Coverage %", values: cov, fmt: (v) => (v >= 80 ? chalk.green(String(v)) : chalk.yellow(String(v))) });
|
|
63
|
+
const flaky = scans.map((s) => (s.reliability.status === "ok" ? num(s.reliability.flakyTests.length) : null));
|
|
64
|
+
rows.push({ label: "Flaky tests", values: flaky, fmt: (v) => (v > 0 ? chalk.yellow(String(v)) : chalk.green(String(v))) });
|
|
65
|
+
const unused = scans.map((s) => (s.devex.status === "ok" ? num(s.devex.unusedExports.length) : null));
|
|
66
|
+
rows.push({ label: "Unused exports", values: unused, fmt: (v) => (v > 0 ? chalk.yellow(String(v)) : chalk.green(String(v))) });
|
|
67
|
+
const scores = scans.map((s) => computeScore(s));
|
|
68
|
+
const last = scores[scores.length - 1];
|
|
69
|
+
const first = scores[0];
|
|
70
|
+
const gradeColorFn = (g) => gradeColor(g) === "green" ? chalk.green : gradeColor(g) === "yellow" ? chalk.yellow : chalk.red;
|
|
71
|
+
const lines = [];
|
|
72
|
+
lines.push(`${chalk.bold("OpenPitStop Score".padEnd(24))}: ${gradeColorFn(last.grade)(chalk.bold(`${last.score}/100 (${last.grade})`))} ${first.score !== last.score ? chalk.dim(`(was ${first.score}/100 ${first.grade})`) : ""}${scores.length > 1 ? " " + sparkline(scores.map((s) => s.score)) : ""}`);
|
|
73
|
+
lines.push("");
|
|
74
|
+
for (const row of rows) {
|
|
75
|
+
const { window, truncated } = windowed(row.values);
|
|
76
|
+
const vals = window.map((v) => (v == null ? "·" : row.fmt(v))).join(" ");
|
|
77
|
+
const prefix = truncated ? chalk.dim("… ") : "";
|
|
78
|
+
lines.push(`${chalk.bold(row.label.padEnd(24))}: ${sparkline(window)} ${prefix}${chalk.dim(vals)}`);
|
|
79
|
+
}
|
|
80
|
+
lines.push("", chalk.dim(`scan history: ${scans.length} scan(s) · oldest ${scans[0].timestamp.slice(0, 19).replace("T", " ")} · newest ${scans[scans.length - 1].timestamp.slice(0, 19).replace("T", " ")}`));
|
|
81
|
+
if (hist.verifies.length > 0) {
|
|
82
|
+
lines.push("", chalk.bold("Verify history:"));
|
|
83
|
+
for (const v of hist.verifies) {
|
|
84
|
+
const risk = v.risk === "High" ? chalk.red(v.risk) : v.risk === "Medium" ? chalk.yellow(v.risk) : chalk.green(v.risk);
|
|
85
|
+
const s = v.score;
|
|
86
|
+
const sc = s
|
|
87
|
+
? ` · ${gradeColorFn(s.grade)(`${s.current}/100 ${s.grade}${s.delta !== 0 ? `, ${s.delta > 0 ? "+" : ""}${s.delta}` : ""}`)}`
|
|
88
|
+
: "";
|
|
89
|
+
const integ = v.integrity
|
|
90
|
+
? ` · integrity ${v.integrity.verdict === "CLEAN" ? chalk.green("CLEAN") : v.integrity.verdict === "SUSPICIOUS" ? chalk.yellow("SUSPICIOUS") : chalk.red("CONFIRMED_CHEAT")}`
|
|
91
|
+
: "";
|
|
92
|
+
lines.push(` ${chalk.dim(v.timestamp.slice(0, 19).replace("T", " "))} ${risk}${sc}${integ}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
console.log(boxen(lines.join("\n"), {
|
|
96
|
+
title: " PITSTOP — Trends ",
|
|
97
|
+
titleAlignment: "center",
|
|
98
|
+
borderStyle: "double",
|
|
99
|
+
padding: 1,
|
|
100
|
+
borderColor: "cyan",
|
|
101
|
+
}));
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=trends.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trends.js","sourceRoot":"","sources":["../../src/commands/trends.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import type { ScanResult } from "../analyzers/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* `pitstop try` — the instant wow. It runs only the cheap analyzers against
|
|
5
|
+
* ANY existing repo (tests/build/flaky detection are intentionally skipped,
|
|
6
|
+
* honest in the note text) so a OpenPitStop Score lands in a couple of seconds
|
|
7
|
+
* with zero setup: no install, no tool config, no curated fixture. The result
|
|
8
|
+
* is persisted as a sealed baseline so `pitstop scan`/`verify`/`gate` pick up
|
|
9
|
+
* where it left off.
|
|
10
|
+
*/
|
|
11
|
+
export declare function tryScan(repo: string): Promise<ScanResult>;
|
|
12
|
+
export declare const try_: Command;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import boxen from "boxen";
|
|
4
|
+
import { performance } from "node:perf_hooks";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { analyzeDependencyGraph } from "../analyzers/dependencyGraph.js";
|
|
7
|
+
import { analyzeSecurity } from "../analyzers/security.js";
|
|
8
|
+
import { analyzeDuplication } from "../analyzers/duplication.js";
|
|
9
|
+
import { analyzeAccessibility } from "../analyzers/accessibility.js";
|
|
10
|
+
import { analyzeDevex } from "../analyzers/devex.js";
|
|
11
|
+
import { detectLanguage } from "../analyzers/util.js";
|
|
12
|
+
import { stampFindings } from "../repro/ids.js";
|
|
13
|
+
import { correlate } from "../graph/correlate.js";
|
|
14
|
+
import { computeScore } from "../report/score.js";
|
|
15
|
+
import { createSpinner } from "../ui/spinner.js";
|
|
16
|
+
import { persistScan } from "./scan.js";
|
|
17
|
+
function rel(repo, p) {
|
|
18
|
+
return p ? path.relative(repo, p) : "";
|
|
19
|
+
}
|
|
20
|
+
function label(text) {
|
|
21
|
+
return chalk.bold(text.padEnd(17));
|
|
22
|
+
}
|
|
23
|
+
function gradePaint(g) {
|
|
24
|
+
switch (g[0]) {
|
|
25
|
+
case "A": return chalk.greenBright;
|
|
26
|
+
case "B":
|
|
27
|
+
case "C": return chalk.yellow;
|
|
28
|
+
default: return chalk.red;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `pitstop try` — the instant wow. It runs only the cheap analyzers against
|
|
33
|
+
* ANY existing repo (tests/build/flaky detection are intentionally skipped,
|
|
34
|
+
* honest in the note text) so a OpenPitStop Score lands in a couple of seconds
|
|
35
|
+
* with zero setup: no install, no tool config, no curated fixture. The result
|
|
36
|
+
* is persisted as a sealed baseline so `pitstop scan`/`verify`/`gate` pick up
|
|
37
|
+
* where it left off.
|
|
38
|
+
*/
|
|
39
|
+
export async function tryScan(repo) {
|
|
40
|
+
const language = detectLanguage(repo);
|
|
41
|
+
const notesFor = {
|
|
42
|
+
tests: "try is the 2-second pass — `pitstop scan` runs the suite, coverage and build",
|
|
43
|
+
perf: "try is the 2-second pass — `pitstop scan` measures build/bundle timing",
|
|
44
|
+
reliability: "try is the 2-second pass — `pitstop scan` runs flaky-test detection",
|
|
45
|
+
};
|
|
46
|
+
// npm audit via analyzeSecurity is the only subprocess; it is cache-backed so
|
|
47
|
+
// repeated `try` runs on the same lockfile are instant.
|
|
48
|
+
const security = await analyzeSecurity(repo);
|
|
49
|
+
return {
|
|
50
|
+
timestamp: new Date().toISOString(),
|
|
51
|
+
repo,
|
|
52
|
+
mode: "try",
|
|
53
|
+
language,
|
|
54
|
+
dependencyGraph: analyzeDependencyGraph(repo),
|
|
55
|
+
security,
|
|
56
|
+
duplication: analyzeDuplication(repo),
|
|
57
|
+
tests: {
|
|
58
|
+
status: "skipped",
|
|
59
|
+
note: notesFor.tests,
|
|
60
|
+
total: 0,
|
|
61
|
+
passed: 0,
|
|
62
|
+
failed: 0,
|
|
63
|
+
durationMs: 0,
|
|
64
|
+
},
|
|
65
|
+
perf: { status: "skipped", note: notesFor.perf },
|
|
66
|
+
accessibility: analyzeAccessibility(repo),
|
|
67
|
+
reliability: {
|
|
68
|
+
status: "skipped",
|
|
69
|
+
note: notesFor.reliability,
|
|
70
|
+
runs: 0,
|
|
71
|
+
durationMs: 0,
|
|
72
|
+
flakyTests: [],
|
|
73
|
+
raceSmells: [],
|
|
74
|
+
},
|
|
75
|
+
devex: analyzeDevex(repo),
|
|
76
|
+
clusters: [],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function categoryLines(r) {
|
|
80
|
+
const lines = [];
|
|
81
|
+
const dg = r.dependencyGraph;
|
|
82
|
+
if (dg.status === "ok") {
|
|
83
|
+
if (dg.circular.length > 0) {
|
|
84
|
+
const cyc = dg.circular[0].map((f) => rel(r.repo, f)).join(" → ");
|
|
85
|
+
lines.push(`${label("Dependency Graph")}: ${chalk.red(`${dg.circular.length} circular`)} — ${cyc}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
lines.push(`${label("Dependency Graph")}: ${chalk.green("0 circular")} — clean`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
lines.push(`${label("Dependency Graph")}: ${chalk.yellow(`skipped — ${dg.note ?? "unavailable"}`)}`);
|
|
93
|
+
}
|
|
94
|
+
const sec = r.security;
|
|
95
|
+
if (sec.status === "ok") {
|
|
96
|
+
if (sec.issues.length > 0) {
|
|
97
|
+
const i = sec.issues[0];
|
|
98
|
+
lines.push(`${label("Security")}: ${chalk.red(`${sec.issues.length} issue(s)`)} — ${i.type}: ${i.description}`);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
lines.push(`${label("Security")}: ${chalk.green("clean")} — ${sec.issues.length} issues`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
lines.push(`${label("Security")}: ${chalk.yellow(`skipped — ${sec.note ?? "unavailable"}`)}`);
|
|
106
|
+
}
|
|
107
|
+
const dup = r.duplication;
|
|
108
|
+
if (dup.status === "ok") {
|
|
109
|
+
lines.push(dup.cloneCount > 0
|
|
110
|
+
? `${label("Duplication")}: ${chalk.yellow(`${dup.cloneCount} clone(s)`)}`
|
|
111
|
+
: `${label("Duplication")}: ${chalk.green("clean")}`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
lines.push(`${label("Duplication")}: ${chalk.yellow(`skipped — ${dup.note ?? "unavailable"}`)}`);
|
|
115
|
+
}
|
|
116
|
+
const a = r.accessibility;
|
|
117
|
+
if (a.status === "ok") {
|
|
118
|
+
lines.push(a.issues.length > 0
|
|
119
|
+
? `${label("Accessibility")}: ${chalk.yellow(`${a.issues.length} issue(s)`)}`
|
|
120
|
+
: `${label("Accessibility")}: ${chalk.green("clean")}`);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
lines.push(`${label("Accessibility")}: ${chalk.yellow(`skipped — ${a.note ?? "unavailable"}`)}`);
|
|
124
|
+
}
|
|
125
|
+
const dx = r.devex;
|
|
126
|
+
if (dx.status === "ok") {
|
|
127
|
+
const parts = [
|
|
128
|
+
dx.unusedExports.length > 0 ? chalk.yellow(`${dx.unusedExports.length} unused export(s)`) : chalk.green("0 unused"),
|
|
129
|
+
dx.duplicateFunctions.length > 0 ? chalk.yellow(`${dx.duplicateFunctions.length} dup fn(s)`) : chalk.green("0 dup fn"),
|
|
130
|
+
];
|
|
131
|
+
lines.push(`${label("DevEx")}: ${parts.join(" · ")}`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
lines.push(`${label("DevEx")}: ${chalk.yellow(`skipped — ${dx.note ?? "unavailable"}`)}`);
|
|
135
|
+
}
|
|
136
|
+
return lines;
|
|
137
|
+
}
|
|
138
|
+
function renderTryBox(r, elapsedMs) {
|
|
139
|
+
const sc = computeScore(r);
|
|
140
|
+
const paint = gradePaint(sc.grade);
|
|
141
|
+
const skipped = sc.total - sc.analyzed;
|
|
142
|
+
const skippedStr = skipped > 0 ? chalk.dim(` · ${skipped} skipped (tests/perf are a scan-detail)`) : "";
|
|
143
|
+
const lines = [];
|
|
144
|
+
lines.push(`${label("OpenPitStop Score")}: ${paint.bold(`${sc.score}/100 (${sc.grade})`)}${skippedStr}`);
|
|
145
|
+
lines.push("");
|
|
146
|
+
lines.push(...categoryLines(r));
|
|
147
|
+
lines.push("");
|
|
148
|
+
lines.push(chalk.dim(`scanned in ${elapsedMs}ms · ${chalk.bold("static pass")} only — `) +
|
|
149
|
+
chalk.dim("no tests/build/flaky yet"));
|
|
150
|
+
lines.push("");
|
|
151
|
+
lines.push(chalk.cyan("next:"));
|
|
152
|
+
lines.push(` pitstop scan full audit (tests, perf, flaky, ledger) — cached 24h audit`);
|
|
153
|
+
lines.push(` pitstop verify gate every future fix against this baseline`);
|
|
154
|
+
lines.push(` pitstop demo the guided fix-loop tour`);
|
|
155
|
+
return boxen(lines.join("\n"), {
|
|
156
|
+
title: " PITSTOP — Try ",
|
|
157
|
+
titleAlignment: "center",
|
|
158
|
+
borderStyle: "single",
|
|
159
|
+
padding: 1,
|
|
160
|
+
borderColor: paint === chalk.greenBright ? "green" : paint === chalk.yellow ? "yellow" : "red",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
export const try_ = new Command("try")
|
|
164
|
+
.description("Zero-setup 2-second check: static-analyze ANY existing repo (no install, no tool config) " +
|
|
165
|
+
"and print its OpenPitStop Score. Persists a real baseline for scan/verify/gate to build on.")
|
|
166
|
+
.argument("[repo]", "path to the repo to try (default: current dir)", ".")
|
|
167
|
+
.option("--json", "print the raw quick-scan result as JSON")
|
|
168
|
+
.action(async (repoArg, options) => {
|
|
169
|
+
const repo = path.resolve(repoArg);
|
|
170
|
+
if (!options.json) {
|
|
171
|
+
console.log(chalk.cyan(`\nTrying ${repo} ...\n`));
|
|
172
|
+
}
|
|
173
|
+
const language = detectLanguage(repo);
|
|
174
|
+
if (language === "unknown") {
|
|
175
|
+
const msg = `couldn't find a supported project in ${repo} — looking for package.json, ` +
|
|
176
|
+
`requirements.txt, pyproject.toml or setup.py`;
|
|
177
|
+
if (options.json) {
|
|
178
|
+
console.log(JSON.stringify({ ok: false, repo, reason: msg }));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
console.log(chalk.red(msg));
|
|
182
|
+
}
|
|
183
|
+
process.exitCode = 1;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const t0 = performance.now();
|
|
187
|
+
const spin = createSpinner("Running static analyzers");
|
|
188
|
+
let result;
|
|
189
|
+
try {
|
|
190
|
+
result = await tryScan(repo);
|
|
191
|
+
spin.succeed("Probe complete");
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
spin.fail("Probe failed");
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
const elapsedMs = Math.max(1, Math.round(performance.now() - t0));
|
|
198
|
+
stampFindings(result);
|
|
199
|
+
result.clusters = correlate(repo, result).clusters;
|
|
200
|
+
persistScan(repo, result);
|
|
201
|
+
if (options.json) {
|
|
202
|
+
console.log(JSON.stringify(result, null, 2));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
console.log(renderTryBox(result, elapsedMs));
|
|
206
|
+
console.log(chalk.dim(`\nBaseline saved to ${path.join(repo, ".pitstop", "scan-latest.json")}\n`));
|
|
207
|
+
});
|
|
208
|
+
//# sourceMappingURL=try.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"try.js","sourceRoot":"","sources":["../../src/commands/try.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import type { VerifyMetrics } from "../report/format.js";
|
|
3
|
+
import { deltasOf } from "../verify/metrics.js";
|
|
4
|
+
import { type ScoreResult } from "../report/score.js";
|
|
5
|
+
import type { IntegrityFinding, Verdict } from "../analyzers/integrity/types.js";
|
|
6
|
+
import { type EvidenceCheck } from "../evidence.js";
|
|
7
|
+
interface IntegrityGate {
|
|
8
|
+
verdict: Verdict;
|
|
9
|
+
findings: IntegrityFinding[];
|
|
10
|
+
summary: {
|
|
11
|
+
confirmed: number;
|
|
12
|
+
suspicious: number;
|
|
13
|
+
total: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
type Risk = "Low" | "Medium" | "High";
|
|
17
|
+
export interface VerifyOutcome {
|
|
18
|
+
repo: string;
|
|
19
|
+
missingBaseline: boolean;
|
|
20
|
+
baselineTimestamp?: string;
|
|
21
|
+
evidence?: EvidenceCheck;
|
|
22
|
+
stale: boolean;
|
|
23
|
+
staleNote?: string;
|
|
24
|
+
risk: Risk;
|
|
25
|
+
integrity: IntegrityGate;
|
|
26
|
+
blocked: boolean;
|
|
27
|
+
current: VerifyMetrics;
|
|
28
|
+
baseline: VerifyMetrics;
|
|
29
|
+
deltas: ReturnType<typeof deltasOf>;
|
|
30
|
+
baselineScore: ScoreResult;
|
|
31
|
+
currentScore: ScoreResult;
|
|
32
|
+
scoreDelta: number;
|
|
33
|
+
exitCode: number;
|
|
34
|
+
file?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The shared verify pipeline (also used by `pitstop gate`): re-measure the
|
|
38
|
+
* fast metrics, diff against the scan baseline, run the integrity gate, check
|
|
39
|
+
* the baseline's evidence signature, and write a sealed verify report. Returns
|
|
40
|
+
* everything a renderer needs plus the exit code to propagate.
|
|
41
|
+
*/
|
|
42
|
+
export declare function runVerify(repo: string): Promise<VerifyOutcome>;
|
|
43
|
+
export declare const verify: Command;
|
|
44
|
+
export {};
|