@vibgrate/cli 1.0.49 → 1.0.51
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/DOCS.md +2 -2
- package/README.md +1 -1
- package/dist/{baseline-M6HQP4E5.js → baseline-FRBISJ66.js} +2 -2
- package/dist/{chunk-4M7MNV6G.js → chunk-TCYJSLL2.js} +1 -1
- package/dist/{chunk-E53FDKZE.js → chunk-TYAGUEXG.js} +140 -2
- package/dist/cli.js +32 -20
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -4
- package/package.json +1 -1
- package/dist/chunk-PTMLMDZU.js +0 -95
package/DOCS.md
CHANGED
|
@@ -162,12 +162,12 @@ Creates:
|
|
|
162
162
|
The primary command. Scans your project for upgrade drift.
|
|
163
163
|
|
|
164
164
|
```bash
|
|
165
|
-
vibgrate scan [path] [--format text|json|sarif] [--out <file>] [--fail-on warn|error] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy] [--baseline <file>] [--drift-budget <score>] [--drift-worsening <percent>] [--changed-only] [--concurrency <n>]
|
|
165
|
+
vibgrate scan [path] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy] [--baseline <file>] [--drift-budget <score>] [--drift-worsening <percent>] [--changed-only] [--concurrency <n>]
|
|
166
166
|
```
|
|
167
167
|
|
|
168
168
|
| Flag | Default | Description |
|
|
169
169
|
|------|---------|-------------|
|
|
170
|
-
| `--format` | `text` | Output format: `text`, `json`, or `
|
|
170
|
+
| `--format` | `text` | Output format: `text`, `json`, `sarif`, or `md` |
|
|
171
171
|
| `--out <file>` | — | Write output to a file |
|
|
172
172
|
| `--fail-on <level>` | — | Exit with code 2 if findings at this level exist |
|
|
173
173
|
| `--baseline <file>` | — | Compare against a previous baseline |
|
package/README.md
CHANGED
|
@@ -176,7 +176,7 @@ When offline mode runs without a package manifest, package freshness is marked a
|
|
|
176
176
|
## Core commands
|
|
177
177
|
|
|
178
178
|
```bash
|
|
179
|
-
vibgrate scan [path] [--format text|json|sarif] [--out <file>] [--fail-on warn|error] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy]
|
|
179
|
+
vibgrate scan [path] [--format text|json|sarif|md] [--out <file>] [--fail-on warn|error] [--offline] [--package-manifest <file>] [--no-local-artifacts] [--max-privacy]
|
|
180
180
|
vibgrate baseline [path]
|
|
181
181
|
vibgrate report [--in <artifact.json>] [--format md|text|json]
|
|
182
182
|
vibgrate push [--dsn <dsn>] [--file <artifact.json>] [--strict]
|
|
@@ -965,6 +965,98 @@ function toSarifResult(finding) {
|
|
|
965
965
|
};
|
|
966
966
|
}
|
|
967
967
|
|
|
968
|
+
// src/formatters/markdown.ts
|
|
969
|
+
function formatMarkdown(artifact) {
|
|
970
|
+
const lines = [];
|
|
971
|
+
lines.push("# Vibgrate Drift Report");
|
|
972
|
+
lines.push("");
|
|
973
|
+
lines.push(`| Metric | Value |`);
|
|
974
|
+
lines.push(`|--------|-------|`);
|
|
975
|
+
lines.push(`| **Drift Score** | ${artifact.drift.score}/100 |`);
|
|
976
|
+
lines.push(`| **Risk Level** | ${artifact.drift.riskLevel.toUpperCase()} |`);
|
|
977
|
+
lines.push(`| **Projects** | ${artifact.projects.length} |`);
|
|
978
|
+
const scannedMeta = [artifact.timestamp];
|
|
979
|
+
if (artifact.durationMs !== void 0) scannedMeta.push(`${(artifact.durationMs / 1e3).toFixed(1)}s`);
|
|
980
|
+
if (artifact.filesScanned !== void 0) scannedMeta.push(`${artifact.filesScanned} files`);
|
|
981
|
+
if (artifact.treeSummary) scannedMeta.push(`${artifact.treeSummary.totalFiles.toLocaleString()} workspace files \xB7 ${artifact.treeSummary.totalDirs.toLocaleString()} dirs`);
|
|
982
|
+
lines.push(`| **Scanned** | ${scannedMeta.join(" \xB7 ")} |`);
|
|
983
|
+
if (artifact.vcs) {
|
|
984
|
+
lines.push(`| **VCS** | ${artifact.vcs.type} |`);
|
|
985
|
+
if (artifact.vcs.branch) lines.push(`| **Branch** | ${artifact.vcs.branch} |`);
|
|
986
|
+
if (artifact.vcs.sha) lines.push(`| **Commit** | \`${artifact.vcs.shortSha}\` |`);
|
|
987
|
+
}
|
|
988
|
+
lines.push("");
|
|
989
|
+
lines.push("## Score Breakdown");
|
|
990
|
+
lines.push("");
|
|
991
|
+
lines.push(`| Component | Score |`);
|
|
992
|
+
lines.push(`|-----------|-------|`);
|
|
993
|
+
lines.push(`| Runtime | ${artifact.drift.components.runtimeScore} |`);
|
|
994
|
+
lines.push(`| Frameworks | ${artifact.drift.components.frameworkScore} |`);
|
|
995
|
+
lines.push(`| Dependencies | ${artifact.drift.components.dependencyScore} |`);
|
|
996
|
+
lines.push(`| EOL Risk | ${artifact.drift.components.eolScore} |`);
|
|
997
|
+
lines.push("");
|
|
998
|
+
lines.push("## Projects");
|
|
999
|
+
lines.push("");
|
|
1000
|
+
for (const project of artifact.projects) {
|
|
1001
|
+
lines.push(`### ${project.name} (${project.type})`);
|
|
1002
|
+
lines.push("");
|
|
1003
|
+
if (project.runtime) {
|
|
1004
|
+
const lag = project.runtimeMajorsBehind !== void 0 && project.runtimeMajorsBehind > 0 ? ` \u2014 ${project.runtimeMajorsBehind} major(s) behind` : " \u2014 current";
|
|
1005
|
+
lines.push(`- **Runtime:** ${project.runtime}${lag}`);
|
|
1006
|
+
}
|
|
1007
|
+
if (project.frameworks.length > 0) {
|
|
1008
|
+
lines.push("- **Frameworks:**");
|
|
1009
|
+
for (const fw of project.frameworks) {
|
|
1010
|
+
const lag = fw.majorsBehind !== null ? fw.majorsBehind === 0 ? "current" : `${fw.majorsBehind} behind` : "unknown";
|
|
1011
|
+
lines.push(` - ${fw.name}: ${fw.currentVersion ?? "?"} \u2192 ${fw.latestVersion ?? "?"} (${lag})`);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
const b = project.dependencyAgeBuckets;
|
|
1015
|
+
const total = b.current + b.oneBehind + b.twoPlusBehind + b.unknown;
|
|
1016
|
+
if (total > 0) {
|
|
1017
|
+
lines.push(`- **Dependencies:** ${b.current} current, ${b.oneBehind} 1-behind, ${b.twoPlusBehind} 2+ behind, ${b.unknown} unknown`);
|
|
1018
|
+
}
|
|
1019
|
+
lines.push("");
|
|
1020
|
+
}
|
|
1021
|
+
if (artifact.extended?.uiPurpose) {
|
|
1022
|
+
const up = artifact.extended.uiPurpose;
|
|
1023
|
+
lines.push("## Product Purpose Signals");
|
|
1024
|
+
lines.push("");
|
|
1025
|
+
lines.push(`- **Frameworks:** ${up.detectedFrameworks.length > 0 ? up.detectedFrameworks.join(", ") : "unknown"}`);
|
|
1026
|
+
lines.push(`- **Evidence Items:** ${up.topEvidence.length}${up.capped ? ` (capped from ${up.evidenceCount})` : ""}`);
|
|
1027
|
+
if (up.topEvidence.length > 0) {
|
|
1028
|
+
lines.push("- **Top Evidence:**");
|
|
1029
|
+
for (const item of up.topEvidence.slice(0, 10)) {
|
|
1030
|
+
lines.push(` - [${item.kind}] ${item.value} (${item.file})`);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
if (up.unknownSignals.length > 0) {
|
|
1034
|
+
lines.push("- **Unknowns:**");
|
|
1035
|
+
for (const u of up.unknownSignals.slice(0, 5)) {
|
|
1036
|
+
lines.push(` - ${u}`);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
lines.push("");
|
|
1040
|
+
}
|
|
1041
|
+
if (artifact.findings.length > 0) {
|
|
1042
|
+
lines.push("## Findings");
|
|
1043
|
+
lines.push("");
|
|
1044
|
+
lines.push(`| Level | Rule | Message | Location |`);
|
|
1045
|
+
lines.push(`|-------|------|---------|----------|`);
|
|
1046
|
+
for (const f of artifact.findings) {
|
|
1047
|
+
const emoji = f.level === "error" ? "\u{1F534}" : f.level === "warning" ? "\u{1F7E1}" : "\u{1F535}";
|
|
1048
|
+
lines.push(`| ${emoji} ${f.level} | ${f.ruleId} | ${f.message} | ${f.location} |`);
|
|
1049
|
+
}
|
|
1050
|
+
lines.push("");
|
|
1051
|
+
}
|
|
1052
|
+
if (artifact.delta !== void 0) {
|
|
1053
|
+
const dir = artifact.delta > 0 ? "\u{1F4C8}" : artifact.delta < 0 ? "\u{1F4C9}" : "\u27A1\uFE0F";
|
|
1054
|
+
lines.push(`## Drift Delta: ${dir} ${artifact.delta > 0 ? "+" : ""}${artifact.delta} vs baseline`);
|
|
1055
|
+
lines.push("");
|
|
1056
|
+
}
|
|
1057
|
+
return lines.join("\n");
|
|
1058
|
+
}
|
|
1059
|
+
|
|
968
1060
|
// src/commands/dsn.ts
|
|
969
1061
|
import * as crypto2 from "crypto";
|
|
970
1062
|
import * as path from "path";
|
|
@@ -1524,6 +1616,22 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
1524
1616
|
});
|
|
1525
1617
|
}
|
|
1526
1618
|
}
|
|
1619
|
+
for (const s of sections) {
|
|
1620
|
+
if (!s.deps) continue;
|
|
1621
|
+
for (const [pkg2, spec] of Object.entries(s.deps)) {
|
|
1622
|
+
if (!spec.trim().startsWith("workspace:")) continue;
|
|
1623
|
+
dependencies.push({
|
|
1624
|
+
package: pkg2,
|
|
1625
|
+
section: s.name,
|
|
1626
|
+
currentSpec: spec,
|
|
1627
|
+
resolvedVersion: null,
|
|
1628
|
+
latestStable: null,
|
|
1629
|
+
majorsBehind: null,
|
|
1630
|
+
drift: "unknown"
|
|
1631
|
+
});
|
|
1632
|
+
buckets.unknown++;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1527
1635
|
dependencies.sort((a, b) => {
|
|
1528
1636
|
const order = { "major-behind": 0, "minor-behind": 1, "current": 2, "unknown": 3 };
|
|
1529
1637
|
const diff = (order[a.drift] ?? 9) - (order[b.drift] ?? 9);
|
|
@@ -7436,7 +7544,30 @@ async function runScan(rootDir, opts) {
|
|
|
7436
7544
|
filesScanned += polyglotProjects.length;
|
|
7437
7545
|
progress.addProjects(polyglotProjects.length);
|
|
7438
7546
|
progress.completeStep("polyglot", `${polyglotProjects.length} project${polyglotProjects.length !== 1 ? "s" : ""}`, polyglotProjects.length);
|
|
7439
|
-
const
|
|
7547
|
+
const rawProjects = [...nodeProjects, ...dotnetProjects, ...pythonProjects, ...javaProjects, ...polyglotProjects];
|
|
7548
|
+
const deduplicatedMap = /* @__PURE__ */ new Map();
|
|
7549
|
+
for (const project of rawProjects) {
|
|
7550
|
+
const existing = deduplicatedMap.get(project.path);
|
|
7551
|
+
if (!existing) {
|
|
7552
|
+
deduplicatedMap.set(project.path, project);
|
|
7553
|
+
} else {
|
|
7554
|
+
const keepNew = project.dependencies.length > existing.dependencies.length;
|
|
7555
|
+
const winner = keepNew ? project : existing;
|
|
7556
|
+
const loser = keepNew ? existing : project;
|
|
7557
|
+
if (loser.projectReferences?.length) {
|
|
7558
|
+
if (!winner.projectReferences) {
|
|
7559
|
+
winner.projectReferences = loser.projectReferences;
|
|
7560
|
+
} else {
|
|
7561
|
+
const existingPaths = new Set(winner.projectReferences.map((r) => r.path));
|
|
7562
|
+
for (const ref of loser.projectReferences) {
|
|
7563
|
+
if (!existingPaths.has(ref.path)) winner.projectReferences.push(ref);
|
|
7564
|
+
}
|
|
7565
|
+
}
|
|
7566
|
+
}
|
|
7567
|
+
deduplicatedMap.set(project.path, winner);
|
|
7568
|
+
}
|
|
7569
|
+
}
|
|
7570
|
+
const allProjects = [...deduplicatedMap.values()];
|
|
7440
7571
|
const dsn = opts.dsn || process.env.VIBGRATE_DSN;
|
|
7441
7572
|
const parsedDsn = dsn ? parseDsn(dsn) : null;
|
|
7442
7573
|
const workspaceId = parsedDsn?.workspaceId;
|
|
@@ -7841,6 +7972,12 @@ async function runScan(rootDir, opts) {
|
|
|
7841
7972
|
} else {
|
|
7842
7973
|
console.log(sarifStr);
|
|
7843
7974
|
}
|
|
7975
|
+
} else if (opts.format === "md") {
|
|
7976
|
+
const markdown = formatMarkdown(artifact);
|
|
7977
|
+
console.log(markdown);
|
|
7978
|
+
if (opts.out) {
|
|
7979
|
+
await writeTextFile(path22.resolve(opts.out), markdown);
|
|
7980
|
+
}
|
|
7844
7981
|
} else {
|
|
7845
7982
|
const text = formatText(artifact);
|
|
7846
7983
|
console.log(text);
|
|
@@ -7943,7 +8080,7 @@ function parseNonNegativeNumber(value, label) {
|
|
|
7943
8080
|
}
|
|
7944
8081
|
return parsed;
|
|
7945
8082
|
}
|
|
7946
|
-
var scanCommand = new Command3("scan").description("Scan a project for upgrade drift").argument("[path]", "Path to scan", ".").option("--out <file>", "Output file path").option("--format <format>", "Output format (text|json|sarif)", "text").option("--fail-on <level>", "Fail on warn or error").option("--baseline <file>", "Compare against baseline").option("--changed-only", "Only scan changed files").option("--concurrency <n>", "Max concurrent npm calls", "8").option("--push", "Auto-push results to Vibgrate API after scan").option("--dsn <dsn>", "DSN token for push (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region for push (us, eu)").option("--strict", "Fail on push errors").option("--install-tools", "Auto-install missing security scanners via Homebrew").option("--ui-purpose", "Enable optional UI purpose evidence extraction (slower)").option("--no-local-artifacts", "Do not write .vibgrate JSON artifacts to disk").option("--max-privacy", "Enable strongest privacy mode (minimal scanners, no local artifacts)").option("--offline", "Run without network calls; do not upload results").option("--package-manifest <file>", "Use local package-version manifest JSON/ZIP (for offline mode)").option("--drift-budget <score>", "Fail if drift score is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").action(async (targetPath, opts) => {
|
|
8083
|
+
var scanCommand = new Command3("scan").description("Scan a project for upgrade drift").argument("[path]", "Path to scan", ".").option("--out <file>", "Output file path").option("--format <format>", "Output format (text|json|sarif|md)", "text").option("--fail-on <level>", "Fail on warn or error").option("--baseline <file>", "Compare against baseline").option("--changed-only", "Only scan changed files").option("--concurrency <n>", "Max concurrent npm calls", "8").option("--push", "Auto-push results to Vibgrate API after scan").option("--dsn <dsn>", "DSN token for push (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region for push (us, eu)").option("--strict", "Fail on push errors").option("--install-tools", "Auto-install missing security scanners via Homebrew").option("--ui-purpose", "Enable optional UI purpose evidence extraction (slower)").option("--no-local-artifacts", "Do not write .vibgrate JSON artifacts to disk").option("--max-privacy", "Enable strongest privacy mode (minimal scanners, no local artifacts)").option("--offline", "Run without network calls; do not upload results").option("--package-manifest <file>", "Use local package-version manifest JSON/ZIP (for offline mode)").option("--drift-budget <score>", "Fail if drift score is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").action(async (targetPath, opts) => {
|
|
7947
8084
|
const rootDir = path22.resolve(targetPath);
|
|
7948
8085
|
if (!await pathExists(rootDir)) {
|
|
7949
8086
|
console.error(chalk6.red(`Path does not exist: ${rootDir}`));
|
|
@@ -8018,6 +8155,7 @@ export {
|
|
|
8018
8155
|
VERSION,
|
|
8019
8156
|
formatText,
|
|
8020
8157
|
formatSarif,
|
|
8158
|
+
formatMarkdown,
|
|
8021
8159
|
dsnCommand,
|
|
8022
8160
|
pushCommand,
|
|
8023
8161
|
runScan,
|
package/dist/cli.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
formatMarkdown
|
|
4
|
-
} from "./chunk-PTMLMDZU.js";
|
|
5
2
|
import {
|
|
6
3
|
baselineCommand
|
|
7
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-TCYJSLL2.js";
|
|
8
5
|
import {
|
|
9
6
|
VERSION,
|
|
10
7
|
dsnCommand,
|
|
8
|
+
formatMarkdown,
|
|
11
9
|
formatText,
|
|
12
10
|
pushCommand,
|
|
13
11
|
scanCommand,
|
|
14
12
|
writeDefaultConfig
|
|
15
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-TYAGUEXG.js";
|
|
16
14
|
import {
|
|
17
15
|
ensureDir,
|
|
18
16
|
pathExists,
|
|
@@ -41,7 +39,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
41
39
|
console.log(chalk.green("\u2714") + ` Created ${chalk.bold("vibgrate.config.ts")}`);
|
|
42
40
|
}
|
|
43
41
|
if (opts.baseline) {
|
|
44
|
-
const { runBaseline } = await import("./baseline-
|
|
42
|
+
const { runBaseline } = await import("./baseline-FRBISJ66.js");
|
|
45
43
|
await runBaseline(rootDir);
|
|
46
44
|
}
|
|
47
45
|
console.log("");
|
|
@@ -104,11 +102,16 @@ async function checkForUpdate() {
|
|
|
104
102
|
}
|
|
105
103
|
const controller = new AbortController();
|
|
106
104
|
const timeout = setTimeout(() => controller.abort(), 5e3);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
timeout.unref?.();
|
|
106
|
+
let response;
|
|
107
|
+
try {
|
|
108
|
+
response = await fetch(REGISTRY_URL, {
|
|
109
|
+
headers: { Accept: "application/json" },
|
|
110
|
+
signal: controller.signal
|
|
111
|
+
});
|
|
112
|
+
} finally {
|
|
113
|
+
clearTimeout(timeout);
|
|
114
|
+
}
|
|
112
115
|
if (!response.ok) return null;
|
|
113
116
|
const data = await response.json();
|
|
114
117
|
const latest = data.version;
|
|
@@ -127,11 +130,16 @@ async function fetchLatestVersion() {
|
|
|
127
130
|
try {
|
|
128
131
|
const controller = new AbortController();
|
|
129
132
|
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
timeout.unref?.();
|
|
134
|
+
let response;
|
|
135
|
+
try {
|
|
136
|
+
response = await fetch(REGISTRY_URL, {
|
|
137
|
+
headers: { Accept: "application/json" },
|
|
138
|
+
signal: controller.signal
|
|
139
|
+
});
|
|
140
|
+
} finally {
|
|
141
|
+
clearTimeout(timeout);
|
|
142
|
+
}
|
|
135
143
|
if (!response.ok) return null;
|
|
136
144
|
const data = await response.json();
|
|
137
145
|
const latest = data.version;
|
|
@@ -412,14 +420,18 @@ program.addCommand(dsnCommand);
|
|
|
412
420
|
program.addCommand(pushCommand);
|
|
413
421
|
program.addCommand(updateCommand);
|
|
414
422
|
program.addCommand(sbomCommand);
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
423
|
+
function notifyIfUpdateAvailable() {
|
|
424
|
+
void checkForUpdate().then((update) => {
|
|
425
|
+
if (!update?.updateAvailable) return;
|
|
418
426
|
console.error("");
|
|
419
427
|
console.error(chalk5.yellow(` Update available: ${update.current} \u2192 ${update.latest}`));
|
|
420
428
|
console.error(chalk5.dim(' Run "vibgrate update" to install the latest version.'));
|
|
421
429
|
console.error("");
|
|
422
|
-
}
|
|
430
|
+
}).catch(() => {
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
program.parseAsync().then(() => {
|
|
434
|
+
notifyIfUpdateAvailable();
|
|
423
435
|
}).catch((err) => {
|
|
424
436
|
console.error(err);
|
|
425
437
|
process.exit(1);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
type DepSection = 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies';
|
|
2
2
|
type RiskLevel = 'low' | 'moderate' | 'high';
|
|
3
3
|
type ProjectType = 'node' | 'dotnet' | 'python' | 'java' | 'go' | 'rust' | 'php' | 'typescript' | 'ruby' | 'swift' | 'kotlin' | 'dart' | 'scala' | 'r' | 'objective-c' | 'elixir' | 'haskell' | 'lua' | 'perl' | 'julia' | 'shell' | 'clojure' | 'groovy' | 'c' | 'cpp' | 'cobol' | 'fortran' | 'visual-basic' | 'pascal' | 'ada' | 'assembly' | 'rpg';
|
|
4
|
-
type OutputFormat = 'text' | 'json' | 'sarif';
|
|
4
|
+
type OutputFormat = 'text' | 'json' | 'sarif' | 'md';
|
|
5
5
|
interface DependencyRow {
|
|
6
6
|
package: string;
|
|
7
7
|
section: DepSection;
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
formatMarkdown
|
|
3
|
-
} from "./chunk-PTMLMDZU.js";
|
|
4
1
|
import {
|
|
5
2
|
computeDriftScore,
|
|
3
|
+
formatMarkdown,
|
|
6
4
|
formatSarif,
|
|
7
5
|
formatText,
|
|
8
6
|
generateFindings,
|
|
9
7
|
runScan
|
|
10
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TYAGUEXG.js";
|
|
11
9
|
import "./chunk-RNVZIZNL.js";
|
|
12
10
|
export {
|
|
13
11
|
computeDriftScore,
|
package/package.json
CHANGED
package/dist/chunk-PTMLMDZU.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// src/formatters/markdown.ts
|
|
2
|
-
function formatMarkdown(artifact) {
|
|
3
|
-
const lines = [];
|
|
4
|
-
lines.push("# Vibgrate Drift Report");
|
|
5
|
-
lines.push("");
|
|
6
|
-
lines.push(`| Metric | Value |`);
|
|
7
|
-
lines.push(`|--------|-------|`);
|
|
8
|
-
lines.push(`| **Drift Score** | ${artifact.drift.score}/100 |`);
|
|
9
|
-
lines.push(`| **Risk Level** | ${artifact.drift.riskLevel.toUpperCase()} |`);
|
|
10
|
-
lines.push(`| **Projects** | ${artifact.projects.length} |`);
|
|
11
|
-
const scannedMeta = [artifact.timestamp];
|
|
12
|
-
if (artifact.durationMs !== void 0) scannedMeta.push(`${(artifact.durationMs / 1e3).toFixed(1)}s`);
|
|
13
|
-
if (artifact.filesScanned !== void 0) scannedMeta.push(`${artifact.filesScanned} files`);
|
|
14
|
-
if (artifact.treeSummary) scannedMeta.push(`${artifact.treeSummary.totalFiles.toLocaleString()} workspace files \xB7 ${artifact.treeSummary.totalDirs.toLocaleString()} dirs`);
|
|
15
|
-
lines.push(`| **Scanned** | ${scannedMeta.join(" \xB7 ")} |`);
|
|
16
|
-
if (artifact.vcs) {
|
|
17
|
-
lines.push(`| **VCS** | ${artifact.vcs.type} |`);
|
|
18
|
-
if (artifact.vcs.branch) lines.push(`| **Branch** | ${artifact.vcs.branch} |`);
|
|
19
|
-
if (artifact.vcs.sha) lines.push(`| **Commit** | \`${artifact.vcs.shortSha}\` |`);
|
|
20
|
-
}
|
|
21
|
-
lines.push("");
|
|
22
|
-
lines.push("## Score Breakdown");
|
|
23
|
-
lines.push("");
|
|
24
|
-
lines.push(`| Component | Score |`);
|
|
25
|
-
lines.push(`|-----------|-------|`);
|
|
26
|
-
lines.push(`| Runtime | ${artifact.drift.components.runtimeScore} |`);
|
|
27
|
-
lines.push(`| Frameworks | ${artifact.drift.components.frameworkScore} |`);
|
|
28
|
-
lines.push(`| Dependencies | ${artifact.drift.components.dependencyScore} |`);
|
|
29
|
-
lines.push(`| EOL Risk | ${artifact.drift.components.eolScore} |`);
|
|
30
|
-
lines.push("");
|
|
31
|
-
lines.push("## Projects");
|
|
32
|
-
lines.push("");
|
|
33
|
-
for (const project of artifact.projects) {
|
|
34
|
-
lines.push(`### ${project.name} (${project.type})`);
|
|
35
|
-
lines.push("");
|
|
36
|
-
if (project.runtime) {
|
|
37
|
-
const lag = project.runtimeMajorsBehind !== void 0 && project.runtimeMajorsBehind > 0 ? ` \u2014 ${project.runtimeMajorsBehind} major(s) behind` : " \u2014 current";
|
|
38
|
-
lines.push(`- **Runtime:** ${project.runtime}${lag}`);
|
|
39
|
-
}
|
|
40
|
-
if (project.frameworks.length > 0) {
|
|
41
|
-
lines.push("- **Frameworks:**");
|
|
42
|
-
for (const fw of project.frameworks) {
|
|
43
|
-
const lag = fw.majorsBehind !== null ? fw.majorsBehind === 0 ? "current" : `${fw.majorsBehind} behind` : "unknown";
|
|
44
|
-
lines.push(` - ${fw.name}: ${fw.currentVersion ?? "?"} \u2192 ${fw.latestVersion ?? "?"} (${lag})`);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const b = project.dependencyAgeBuckets;
|
|
48
|
-
const total = b.current + b.oneBehind + b.twoPlusBehind + b.unknown;
|
|
49
|
-
if (total > 0) {
|
|
50
|
-
lines.push(`- **Dependencies:** ${b.current} current, ${b.oneBehind} 1-behind, ${b.twoPlusBehind} 2+ behind, ${b.unknown} unknown`);
|
|
51
|
-
}
|
|
52
|
-
lines.push("");
|
|
53
|
-
}
|
|
54
|
-
if (artifact.extended?.uiPurpose) {
|
|
55
|
-
const up = artifact.extended.uiPurpose;
|
|
56
|
-
lines.push("## Product Purpose Signals");
|
|
57
|
-
lines.push("");
|
|
58
|
-
lines.push(`- **Frameworks:** ${up.detectedFrameworks.length > 0 ? up.detectedFrameworks.join(", ") : "unknown"}`);
|
|
59
|
-
lines.push(`- **Evidence Items:** ${up.topEvidence.length}${up.capped ? ` (capped from ${up.evidenceCount})` : ""}`);
|
|
60
|
-
if (up.topEvidence.length > 0) {
|
|
61
|
-
lines.push("- **Top Evidence:**");
|
|
62
|
-
for (const item of up.topEvidence.slice(0, 10)) {
|
|
63
|
-
lines.push(` - [${item.kind}] ${item.value} (${item.file})`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (up.unknownSignals.length > 0) {
|
|
67
|
-
lines.push("- **Unknowns:**");
|
|
68
|
-
for (const u of up.unknownSignals.slice(0, 5)) {
|
|
69
|
-
lines.push(` - ${u}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
lines.push("");
|
|
73
|
-
}
|
|
74
|
-
if (artifact.findings.length > 0) {
|
|
75
|
-
lines.push("## Findings");
|
|
76
|
-
lines.push("");
|
|
77
|
-
lines.push(`| Level | Rule | Message | Location |`);
|
|
78
|
-
lines.push(`|-------|------|---------|----------|`);
|
|
79
|
-
for (const f of artifact.findings) {
|
|
80
|
-
const emoji = f.level === "error" ? "\u{1F534}" : f.level === "warning" ? "\u{1F7E1}" : "\u{1F535}";
|
|
81
|
-
lines.push(`| ${emoji} ${f.level} | ${f.ruleId} | ${f.message} | ${f.location} |`);
|
|
82
|
-
}
|
|
83
|
-
lines.push("");
|
|
84
|
-
}
|
|
85
|
-
if (artifact.delta !== void 0) {
|
|
86
|
-
const dir = artifact.delta > 0 ? "\u{1F4C8}" : artifact.delta < 0 ? "\u{1F4C9}" : "\u27A1\uFE0F";
|
|
87
|
-
lines.push(`## Drift Delta: ${dir} ${artifact.delta > 0 ? "+" : ""}${artifact.delta} vs baseline`);
|
|
88
|
-
lines.push("");
|
|
89
|
-
}
|
|
90
|
-
return lines.join("\n");
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export {
|
|
94
|
-
formatMarkdown
|
|
95
|
-
};
|