@vibgrate/cli 2026.623.1 → 2026.625.1
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/dist/cli.js +130 -122
- package/dist/hcs-wasm/vibgrate_hcs_wasm.js +56 -0
- package/dist/hcs-wasm/vibgrate_hcs_wasm_bg.wasm +0 -0
- package/package.json +3 -3
- package/HCS-EXTRACT.md +0 -442
package/dist/cli.js
CHANGED
|
@@ -1,158 +1,166 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import'./chunk-YF3NML7I.js';import {d,c,e,f,b as b$1,a as a$1,h}from'./chunk-BHWXSLTQ.js';import {b,pa,ia,sa,ra,qa,ua,oa}from'./chunk-I65B3ZRL.js';import {a}from'./chunk-MKDRULJ6.js';import {p,b as b$3}from'./chunk-XTHPCEME.js';import {b as b$2}from'./chunk-EK7ODJWE.js';import {Command}from'commander';import l from'chalk';import*as S from'path';import {createRequire}from'module';import*as
|
|
3
|
-
`),console.log(""),console.log(l.green("\u2714")+` DSN written to ${t.write}`),console.log(l.yellow("\u26A0")+" Add this file to .gitignore!");}});function
|
|
4
|
-
`,"utf8");try{Q.chmodSync(n,384);}catch{}}function
|
|
5
|
-
Failing: ${
|
|
6
|
-
Failing: findings detected at warn level or above.`)),process.exit(2));}if(
|
|
7
|
-
Failing fitness function: drift score ${
|
|
8
|
-
Failing fitness function: --drift-worsening requires --baseline to compare against previous drift.`)),process.exit(2)),
|
|
9
|
-
Failing fitness function: drift worsened by ${f.toFixed(2)}% (threshold ${
|
|
10
|
-
`)}function
|
|
11
|
-
./${p.path}`),
|
|
12
|
-
${p.runtime} \u2192 ${p.runtimeLatest} (${p.runtimeMajorsBehind} major${p.runtimeMajorsBehind>1?"s":""} behind)`);a
|
|
2
|
+
import'./chunk-YF3NML7I.js';import {d,c,e,f,b as b$1,a as a$1,h}from'./chunk-BHWXSLTQ.js';import {b,pa,ia,sa,ra,qa,ua,oa}from'./chunk-I65B3ZRL.js';import {a}from'./chunk-MKDRULJ6.js';import {p,b as b$3}from'./chunk-XTHPCEME.js';import {b as b$2}from'./chunk-EK7ODJWE.js';import {Command}from'commander';import l from'chalk';import*as S from'path';import {createRequire}from'module';import*as Te from'crypto';import {randomUUID}from'crypto';import*as Lt from'os';import*as Q from'fs';import {rmSync,existsSync}from'fs';import {execSync,spawn,spawnSync}from'child_process';import*as rn from'zlib';import {promisify}from'util';import*as J from'fs/promises';import {mkdtemp,rm}from'fs/promises';import {fileURLToPath}from'url';var Ot=new Command("init").description("Initialize vibgrate in a project").argument("[path]","Path to initialize",".").option("--baseline","Create initial baseline after init").option("--yes","Skip confirmation prompts").action(async(t,e)=>{let n=S.resolve(t),o=S.join(n,".vibgrate");await d(o),console.log(l.green("\u2714")+` Created ${l.bold(".vibgrate/")} directory`);let s=S.join(n,"vibgrate.config.ts");if(await c(s)?console.log(l.dim(" vibgrate.config.ts already exists, skipping")):(await b(n),console.log(l.green("\u2714")+` Created ${l.bold("vibgrate.config.ts")}`)),e.baseline){let{runBaseline:i}=await import('./baseline-2B6YIW6Z.js');await i(n);}console.log(""),console.log(l.bold("Next steps:")),console.log(` ${l.cyan("vibgrate scan .")} Scan for upgrade drift`),console.log(` ${l.cyan("vibgrate baseline .")} Create a drift baseline`),console.log("");});var yo=createRequire(import.meta.url),wo=yo("../package.json"),R=wo.version;var Ye=[{id:"us",label:"United States",ingestHost:"us.ingest.vibgrate.com",dashHost:"dash.vibgrate.com",available:true},{id:"eu",label:"European Union",ingestHost:"eu.ingest.vibgrate.com",dashHost:"dash.vibgrate.eu",available:true},{id:"apac",label:"Asia-Pacific (coming soon)",ingestHost:"apac.ingest.vibgrate.com",dashHost:"dash.vibgrate.com",available:false}],vo="us";function se(){return Ye.filter(t=>t.available).map(t=>t.id)}function _t(t){return Ye.find(e=>e.id===t)}function ee(t,e){if(e)try{return new URL(e).host}catch{throw new Error(`Invalid ingest URL: ${e}`)}let n=(t??vo).toLowerCase(),o=_t(n);if(!o)throw new Error(`Unknown region "${n}". Supported: ${se().join(", ")}`);if(!o.available)throw new Error(`Region "${n}" (${o.label}) is not yet available. Supported: ${se().join(", ")}`);return o.ingestHost}function ue(t){return Ye.find(n=>n.ingestHost===t)?.dashHost??"dash.vibgrate.com"}function Ft(t){return _t(t.toLowerCase())?.ingestHost}async function So(t,e,n,o,s){let i=`https://${o}/v1/provision`;try{let r=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json",Connection:"close"},body:JSON.stringify(s?{keyId:t,secret:e,workspaceId:n,region:s}:{keyId:t,secret:e,workspaceId:n})});return r.ok?{success:!0}:{success:!1,error:(await r.json()).error||`HTTP ${r.status}`}}catch(r){return {success:false,error:r instanceof Error?r.message:String(r)}}}var Qe=new Command("dsn").description("Manage DSN tokens");Qe.command("create").description("Create a new DSN token").option("--ingest <url>","Ingest API URL (overrides --region)").option("--region <region>",`Data residency region (${se().join(", ")})`,"us").requiredOption("--workspace <id>",'Workspace ID (use "new" to auto-generate)').option("--write <path>","Write DSN to file").action(async t=>{let e$1=Te.randomBytes(12).toString("hex"),n=Te.randomBytes(32).toString("hex"),o;try{o=ee(t.region,t.ingest);}catch(a){console.error(l.red(a instanceof Error?a.message:String(a))),process.exit(1);}let s=t.workspace,i=t.workspace.toLowerCase()==="new";i&&(s=Te.randomBytes(8).toString("hex"),console.log(l.dim(`Provisioning new workspace ${s}...`)));let r=t.ingest?void 0:t.region.toLowerCase();if(i){let a=await So(e$1,n,s,o,r);a.success||(console.error(l.red(`Failed to provision DSN: ${a.error}`)),process.exit(1));}let c=`vibgrate+https://${e$1}:${n}@${o}/${s}`;if(console.log(l.green("\u2714")+" DSN created"),console.log(""),console.log(l.bold("Region:")),console.log(` ${r??"custom"} (${o})`),console.log(""),console.log(l.bold("DSN:")),console.log(` ${c}`),console.log(""),console.log(l.bold("Key ID:")),console.log(` ${e$1}`),i&&(console.log(""),console.log(l.bold("Workspace ID:")),console.log(` ${s}`)),console.log(""),console.log(l.dim("Set this as VIBGRATE_DSN in your CI environment.")),i||console.log(l.dim("The secret must be registered on your Vibgrate ingest API.")),t.write){let a=S.resolve(t.write);await e(a,c+`
|
|
3
|
+
`),console.log(""),console.log(l.green("\u2714")+` DSN written to ${t.write}`),console.log(l.yellow("\u26A0")+" Add this file to .gitignore!");}});function Bt(){return S.join(Lt.homedir(),".vibgrate")}function ce(){return S.join(Bt(),"credentials.json")}function ko(){try{let t=Q.readFileSync(ce(),"utf8"),e=JSON.parse(t);return e&&typeof e.dsn=="string"&&e.dsn?e:null}catch{return null}}function Ut(t){let e=Bt();Q.mkdirSync(e,{recursive:true});let n=ce();Q.writeFileSync(n,JSON.stringify(t,null,2)+`
|
|
4
|
+
`,"utf8");try{Q.chmodSync(n,384);}catch{}}function Vt(){try{return Q.rmSync(ce()),!0}catch{return false}}function ge(t){return t||(process.env.VIBGRATE_DSN?process.env.VIBGRATE_DSN:ko()?.dsn??void 0)}function Ne(t,e){console.log(`VIBGRATE_INGEST_ID=${t}`),e?.unchanged&&console.log("VIBGRATE_INGEST_UNCHANGED=1");}function Ht(t,e){let n=`${t.scheme}://${e}/v1/ingest/scan`;return fetch(n,{method:"POST",headers:{"Content-Type":"application/json","Content-Encoding":t.contentEncoding,"X-Vibgrate-Timestamp":t.timestamp,Authorization:`VibgrateDSN ${t.keyId}:${t.secret}`,Connection:"close"},body:t.body})}async function Po(t){try{let e=await t.clone().json();return e?.code!=="REGION_MISMATCH"||!e.region?void 0:Ft(e.region)}catch{return}}async function Oe(t){let e=t.host,n=await Ht(t,e);if(n.status===409){let o=await Po(n);o&&o!==e&&(console.log(l.yellow(`\u21BB Workspace is pinned to a different region \u2014 retrying upload to ${o}...`)),e=o,n=await Ht(t,e));}return {response:n,host:e}}async function Io(t,e,n){let o=ge(n.dsn);if(!o){console.error(l.red("No DSN provided for push.")),console.error(l.dim('Run "vibgrate login", set VIBGRATE_DSN, or use the --dsn flag.')),n.strict&&process.exit(1);return}let s=pa(o);if(!s){console.error(l.red("Invalid DSN format.")),n.strict&&process.exit(1);return}let{body:i,contentEncoding:r}=await oa(t),c=String(Date.now()),a=s.host;if(n.region)try{a=ee(n.region);}catch(u){console.error(l.red(u instanceof Error?u.message:String(u))),n.strict&&process.exit(1);return}let p=JSON.stringify(t).length,g=i.length,f=((1-g/p)*100).toFixed(0);console.log(l.dim(`Uploading to ${a}... (${(g/1024).toFixed(0)} KB, ${f}% smaller)`));try{let{response:u,host:h}=await Oe({scheme:s.scheme,host:a,keyId:s.keyId,secret:s.secret,body:i,contentEncoding:r,timestamp:c});if(a=h,!u.ok){let m=await u.text();throw new Error(`HTTP ${u.status}: ${m}`)}let v=await u.json();if(v.unchanged){if(console.log(l.green("\u2714")+` Repository unchanged since ${v.lastScannedAt??"last scan"} \u2014 skipped upload (no credit used).`),v.previousIngestId){Ne(v.previousIngestId,{unchanged:!0});let m=`https://${ue(a)}/${s.workspaceId}/scan/${v.previousIngestId}`;console.log(l.dim(` Previous report: ${m}`));}else n.strict&&(console.error(l.red("Repository unchanged but no previous ingest id returned.")),process.exit(1));return}if(console.log(l.green("\u2714")+` Scan queued for processing (${v.ingestId??"ok"})`),v.ingestId){Ne(v.ingestId);let m=`https://${ue(a)}/${s.workspaceId}/scan/${v.ingestId}`,$=process.platform==="win32"?"\x1B[0G\x1B[2K":"";console.log(""),console.log($+l.dim(" Processing continues in the background. Results available shortly.")),console.log(""),console.log($+l.cyan("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log($+l.bold(" \u{1F4CA} View Scan Report")),console.log($+" "+l.underline.cyan(m)),console.log($+l.cyan("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(""),console.log("");}}catch(u){let h=u instanceof Error?u.message:String(u);console.error(l.red(`Upload failed: ${h}`)),n.strict&&process.exit(1);}}function jo(t,e){return [...e,...b$3(t)]}function Gt(t,e){if(t===void 0)return;let n=Number(t);if(!Number.isFinite(n)||n<0)throw new Error(`${e} must be a non-negative number.`);return n}var Jt=new Command("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("-e, --exclude <glob>",'Exclude paths matching a glob pattern. Repeatable, and a single value may list several patterns separated by commas or semicolons (e.g. --exclude "legacy/**,vendor/**"). Merged with excludes from the config file.',jo,[]).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("--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("--project-scan-timeout <seconds>","Per-project scan timeout in seconds (default: 180)").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").option("--repository-name <name>","Override the repository name recorded for this scan (defaults to the directory or package.json name)").action(async(t,e)=>{let n=S.resolve(t);await p(n)||(console.error(l.red(`Path does not exist: ${n}`)),process.exit(1));let o=!!ge(e.dsn),s=!e.offline&&(e.push||o),i;if(s&&o){let p=ge(e.dsn),g=pa(p);if(g){let f=e.region?ee(e.region):g.host,u=await ia(n),h=await sa(n,u),v=e.repositoryName?.trim()||await ra(n);try{let m=await qa(g,f,{repositoryName:v,vcsSha:h.vcsSha});if(i=m.region,m.vm&&!m.vm.allowed&&(console.error(l.red(m.error??"VM meter usage exhausted")),console.error(l.dim(`VM minutes: ${m.vm.used}/${m.vm.limit} (${m.plan.label} plan) \u2014 enable overages or upgrade your plan.`)),process.exit(1)),m.repositories&&!m.repositories.allowed){console.error(l.red(m.error??`Repository limit reached for the ${m.plan.label} plan \u2014 cannot scan a new repository.`));let $=m.repositories.max<0?"unlimited":String(m.repositories.max);console.error(l.dim(`Repositories: ${m.repositories.total}/${$} (${m.plan.label} plan) \u2014 archive a repository or upgrade your plan.`)),m.upgradeUrl&&console.error(l.dim(` Upgrade: ${m.upgradeUrl}`)),process.exit(1);}if((m.status==="error"||!m.scans.allowed)&&(console.error(l.red(m.error??"Scan ingestion not allowed for this workspace.")),console.error(l.dim(`Credits: ${m.scans.used}/${m.scans.limit} (${m.plan.label} plan)`)),e.strict&&process.exit(1),process.exit(1)),console.log(l.dim(`Plan: ${m.plan.label} \u2014 scan credits ${m.scans.used}/${m.scans.limit} this month`)),m.repository?.unchanged){if(console.log(l.green("\u2714")+` Repository unchanged at ${m.repository.lastVcsSha?.slice(0,7)??"same revision"} \u2014 skipping scan.`),m.repository.lastIngestId){Ne(m.repository.lastIngestId,{unchanged:!0});let $=`https://${ue(f)}/${g.workspaceId}/scan/${m.repository.lastIngestId}`;console.log(l.dim(` Latest report: ${$}`));}else e.strict&&(console.error(l.red("Repository unchanged but no previous ingest id available.")),process.exit(1));return}}catch(m){let $=m instanceof Error?m.message:String(m);console.error(l.yellow(`Preflight check failed: ${$}`)),e.strict&&process.exit(1);}}}let r={vibgrateVersion:R,out:e.out,format:e.format||"text",failOn:e.failOn,baseline:e.baseline,changedOnly:e.changedOnly,exclude:e.exclude,concurrency:parseInt(e.concurrency,10)||8,push:e.push,dsn:e.dsn,region:e.region??i,strict:e.strict,uiPurpose:e.uiPurpose,noLocalArtifacts:e.noLocalArtifacts,maxPrivacy:e.maxPrivacy,offline:e.offline,packageManifest:e.packageManifest,driftBudget:Gt(e.driftBudget,"--drift-budget"),driftWorseningPercent:Gt(e.driftWorsening,"--drift-worsening"),projectScanTimeout:e.projectScanTimeout&&parseInt(e.projectScanTimeout,10)||void 0,repositoryName:e.repositoryName?.trim()||void 0},c=await f(),a=await ua(n,r,c);if(e.failOn){let p=a.findings.some(f=>f.level==="error"),g=a.findings.some(f=>f.level==="warning");e.failOn==="error"&&p&&(console.error(l.red(`
|
|
5
|
+
Failing: ${a.findings.filter(f=>f.level==="error").length} error finding(s) detected.`)),process.exit(2)),e.failOn==="warn"&&(p||g)&&(console.error(l.red(`
|
|
6
|
+
Failing: findings detected at warn level or above.`)),process.exit(2));}if(r.driftBudget!==void 0&&a.drift.score>r.driftBudget&&(console.error(l.red(`
|
|
7
|
+
Failing fitness function: drift score ${a.drift.score}/100 exceeds budget ${r.driftBudget}.`)),process.exit(2)),r.driftWorseningPercent!==void 0&&(a.delta===void 0&&(console.error(l.red(`
|
|
8
|
+
Failing fitness function: --drift-worsening requires --baseline to compare against previous drift.`)),process.exit(2)),a.delta>0)){let p=a.drift.score-a.delta,g=Math.max(Math.abs(p),1e-4),f=a.delta/g*100;f>r.driftWorseningPercent&&(console.error(l.red(`
|
|
9
|
+
Failing fitness function: drift worsened by ${f.toFixed(2)}% (threshold ${r.driftWorseningPercent}%).`)),process.exit(2));}s&&await Io(a,n,r);});function Kt(t){let e=[],n=l.hex("#3FB0A4"),o=l.hex("#4FE3C1");e.push(""),e.push(" "+n("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u256E")+o("\u279C")),e.push(" "+l.dim("\u2524")+n("\u2502")+" "+o("\u25FC")+" "+o("\u25FC")+" "+n("\u2502")+l.dim("\u251C")+" "+l.bold.white("vibgrate")),e.push(" "+l.dim("\u2524")+n("\u2502")+" "+l.dim("\u2581\u2581")+" "+n("\u2502")+l.dim("\u251C")+" "+l.dim(`Drift Intelligence Engine v${R}`)),e.push(" "+n("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u256F")),e.push(""),e.push(n("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),e.push(n("\u2551 ")+l.bold.white("Vibgrate Drift Report")+n(" \u2551")),e.push(n("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),e.push("");for(let a of t.projects){if(e.push(l.bold(` \u2500\u2500 ${a.name} `)+l.dim(`(${a.type}) ${a.path}`)),a.runtime){let f=a.runtimeMajorsBehind!==void 0&&a.runtimeMajorsBehind>0?l.yellow(` (${a.runtimeMajorsBehind} major${a.runtimeMajorsBehind>1?"s":""} behind)`):l.green(" (current)");e.push(` Runtime: ${a.runtime}${f}`);}if(a.targetFramework&&e.push(` Target: ${a.targetFramework}`),a.frameworks.length>0){e.push(" Frameworks:");for(let f of a.frameworks){let u=f.majorsBehind!==null?f.majorsBehind===0?l.green("current"):l.yellow(`${f.majorsBehind} behind`):l.dim("unknown");e.push(` ${f.name}: ${f.currentVersion??"?"} \u2192 ${f.latestVersion??"?"} (${u})`);}}let p=a.dependencyAgeBuckets;p.current+p.oneBehind+p.twoPlusBehind+p.unknown>0&&(e.push(" Dependencies:"),e.push(` ${l.green(`${p.current} current`)} ${l.yellow(`${p.oneBehind} 1-behind`)} ${l.red(`${p.twoPlusBehind} 2+ behind`)} ${l.dim(`${p.unknown} unknown`)}`)),e.push("");}if(t.delta!==void 0){let a=t.delta>0?l.red(`+${t.delta}`):t.delta<0?l.green(`${t.delta}`):l.dim("0");e.push(l.bold(" Drift Delta: ")+a+" (vs baseline)"),e.push("");}if(t.extended&&e.push(...Eo(t.extended)),t.findings.length>0){let a=t.findings.filter(u=>u.level==="error"),p=t.findings.filter(u=>u.level==="warning"),g=t.findings.filter(u=>u.level==="note"),f=[a.length>0?l.red(`${a.length} error${a.length!==1?"s":""}`):"",p.length>0?l.yellow(`${p.length} warning${p.length!==1?"s":""}`):"",g.length>0?l.blue(`${g.length} note${g.length!==1?"s":""}`):""].filter(Boolean).join(l.dim(", "));e.push(l.bold.underline(" Findings")+l.dim(` (${f})`));for(let u of t.findings){let h=u.level==="error"?l.red("\u2716"):u.level==="warning"?l.yellow("\u26A0"):l.blue("\u2139");e.push(` ${h} ${u.message}`),e.push(l.dim(` ${u.ruleId} in ${u.location}`));}e.push("");}let s=Do(t);if(s.length>0){e.push(l.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),e.push(l.bold.cyan("\u2551 Top Priority Actions \u2551")),e.push(l.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),e.push("");for(let a=0;a<s.length;a++){let p=s[a],g=l.bold.cyan(` ${a+1}.`);e.push(`${g} ${l.bold(p.title)}`),e.push(l.dim(` ${p.explanation}`)),p.impact&&e.push(` Impact: ${l.green(p.impact)}`),e.push("");}}if(t.extended?.architecture&&e.push(...Ao(t.extended.architecture)),t.solutions&&t.solutions.length>0){e.push(l.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),e.push(l.bold.cyan("\u2551 Solution Drift Summary \u2551")),e.push(l.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),e.push("");for(let a of t.solutions){let p=a.drift?.score,g=typeof p=="number"?p<=30?l.green:p<=60?l.yellow:l.red:l.dim;e.push(` \u2022 ${a.name} (${a.projectPaths.length} projects) \u2014 ${typeof p=="number"?g(`${p}/100`):l.dim("n/a")}`);}e.push("");}let i=t.drift.score<=30?l.green:t.drift.score<=60?l.yellow:l.red;if(e.push(l.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),e.push(l.bold.cyan("\u2551 Drift Score Summary \u2551")),e.push(l.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),e.push(""),e.push(l.bold(" Drift Score: ")+i.bold(`${t.drift.score}/100`)),e.push(l.bold(" Risk Level: ")+Ro(t.drift.riskLevel)),e.push(l.bold(" Projects: ")+`${t.projects.length}`),t.vcs){let a=[t.vcs.type];t.vcs.branch&&a.push(t.vcs.branch),t.vcs.shortSha&&a.push(l.dim(t.vcs.shortSha)),e.push(l.bold(" VCS: ")+a.join(" "));}e.push("");let r=new Set(t.drift.measured??["runtime","framework","dependency","eol"]);e.push(" "+l.bold.underline("Score Breakdown")),e.push(` Runtime: ${r.has("runtime")?xe(t.drift.components.runtimeScore):l.dim("n/a")}`),e.push(` Frameworks: ${r.has("framework")?xe(t.drift.components.frameworkScore):l.dim("n/a")}`),e.push(` Dependencies: ${r.has("dependency")?xe(t.drift.components.dependencyScore):l.dim("n/a")}`),e.push(` EOL Risk: ${r.has("eol")?xe(t.drift.components.eolScore):l.dim("n/a")}`),e.push("");let c=[`Scanned at ${t.timestamp}`];if(t.durationMs!==void 0){let a=(t.durationMs/1e3).toFixed(1);c.push(`${a}s`);}return t.filesScanned!==void 0&&c.push(`${t.filesScanned} file${t.filesScanned!==1?"s":""} scanned`),t.treeSummary&&(c.push(`${t.treeSummary.totalFiles.toLocaleString()} workspace files`),c.push(`${t.treeSummary.totalDirs.toLocaleString()} dirs`)),e.push(l.dim(` ${c.join(" \xB7 ")}`)),e.push(""),e.join(`
|
|
10
|
+
`)}function Ro(t){switch(t){case "low":return l.bgGreen.black(" LOW ");case "moderate":return l.bgYellow.black(" MODERATE ");case "high":return l.bgRed.white(" HIGH ");default:return t}}function xe(t){let n=Math.round(t/100*20),o=20-n;return (t<=30?l.green:t<=60?l.yellow:l.red)("\u2588".repeat(n))+l.dim("\u2591".repeat(o))+` ${Math.round(t)}`}var Xt={frontend:"Frontend",metaFrameworks:"Meta-frameworks",bundlers:"Bundlers",css:"CSS / UI",backend:"Backend",orm:"ORM / Database",testing:"Testing",lintFormat:"Lint & Format",apiMessaging:"API & Messaging",observability:"Observability",payment:"Payment",auth:"Auth",email:"Email",cloud:"Cloud",databases:"Databases",messaging:"Messaging",crm:"CRM & Comms",storage:"Storage",search:"Search & AI"};function Eo(t){let e=[];if(t.toolingInventory){let n=t.toolingInventory,o=Object.entries(n).filter(([,s])=>s.length>0);if(o.length>0){e.push(l.bold.underline(" Tech Stack"));for(let[s,i]of o){let r=Xt[s]??s,c=i.map(a=>l.white(a.name)).join(l.dim(", "));e.push(` ${l.cyan(r)}: ${c}`);}e.push("");}}if(t.serviceDependencies){let n=t.serviceDependencies,o=Object.entries(n).filter(([,s])=>s.length>0);if(o.length>0){e.push(l.bold.underline(" Services & Integrations"));for(let[s,i]of o){let r=Xt[s]??s,c=i.map(a=>{let p=a.version?l.dim(` ${a.version}`):"";return l.white(a.name)+p}).join(l.dim(", "));e.push(` ${l.cyan(r)}: ${c}`);}e.push("");}}if(t.breakingChangeExposure){let n=t.breakingChangeExposure;if(n.deprecatedPackages.length>0||n.legacyPolyfills.length>0){e.push(l.bold.underline(" Breaking Change Exposure"));let o=n.exposureScore>=40?l.red:n.exposureScore>=20?l.yellow:l.green;e.push(` Exposure Score: ${o.bold(`${n.exposureScore}/100`)}`),n.deprecatedPackages.length>0&&e.push(` ${l.red("Deprecated")}: ${n.deprecatedPackages.map(i=>l.dim(i)).join(", ")}`),n.legacyPolyfills.length>0&&e.push(` ${l.yellow("Polyfills")}: ${n.legacyPolyfills.map(i=>l.dim(i)).join(", ")}`),n.peerConflictsDetected&&e.push(` ${l.red("\u26A0")} Peer dependency conflicts detected`),e.push(` Recommendation: ${l.bold(n.overallRecommendation)}`);let s=n.projectIntelligence.filter(i=>i.packages.length>0).slice(0,3);if(s.length>0){e.push(" Major Upgrade Intelligence:");for(let i of s){e.push(` - ${i.project} (${i.recommendation})`);for(let r of i.packages.slice(0,2))e.push(` \xB7 ${r.package} ${r.currentVersion??"?"} \u2192 ${r.targetVersion??"?"} | touched ~${r.usage.touchedPercent}% | ${r.automatable}`);}}e.push("");}}if(t.tsModernity&&t.tsModernity.typescriptVersion){let n=t.tsModernity;e.push(l.bold.underline(" TypeScript"));let o=[];o.push(`v${n.typescriptVersion}`),n.strict===true?o.push(l.green("strict \u2714")):n.strict===false&&o.push(l.yellow("strict \u2716")),n.moduleType&&o.push(n.moduleType.toUpperCase()),n.target&&o.push(`target: ${n.target}`),e.push(` ${o.join(l.dim(" \xB7 "))}`),e.push("");}if(t.buildDeploy){let n=t.buildDeploy;(n.ci.length>0||n.docker.dockerfileCount>0||n.packageManagers.length>0)&&(e.push(l.bold.underline(" Build & Deploy")),n.ci.length>0&&e.push(` CI: ${n.ci.join(", ")}`),n.docker.dockerfileCount>0&&e.push(` Docker: ${n.docker.dockerfileCount} Dockerfile${n.docker.dockerfileCount!==1?"s":""} (${n.docker.baseImages.join(", ")})`),n.packageManagers.length>0&&e.push(` Package Managers: ${n.packageManagers.join(", ")}`),n.monorepoTools.length>0&&e.push(` Monorepo: ${n.monorepoTools.join(", ")}`),n.iac.length>0&&e.push(` IaC: ${n.iac.join(", ")}`),e.push(""));}if(t.uiPurpose){let n=t.uiPurpose;e.push(l.bold.underline(" Product Purpose Signals")),e.push(` Frameworks: ${n.detectedFrameworks.length>0?n.detectedFrameworks.join(", "):l.dim("unknown")}`),e.push(` Evidence: ${n.topEvidence.length}${n.capped?l.dim(` of ${n.evidenceCount} (capped)`):""}`);let o=n.topEvidence.slice(0,8);if(o.length>0){e.push(" Top Signals:");for(let s of o)e.push(` - [${s.kind}] ${s.value} ${l.dim(`(${s.file})`)}`);}if(n.unknownSignals.length>0){e.push(" Unknowns:");for(let s of n.unknownSignals.slice(0,4))e.push(` - ${l.yellow(s)}`);}e.push("");}if(t.securityPosture){let n=t.securityPosture;e.push(l.bold.underline(" Security Posture"));let o=[];o.push(n.lockfilePresent?l.green("Lockfile \u2714"):l.red("Lockfile \u2716")),o.push(n.gitignoreCoversEnv?l.green(".env \u2714"):l.red(".env \u2716")),o.push(n.gitignoreCoversNodeModules?l.green("node_modules \u2714"):l.yellow("node_modules \u2716")),n.multipleLockfileTypes&&o.push(l.yellow("Multiple lockfiles \u26A0")),n.envFilesTracked&&o.push(l.red("Env files tracked \u2716")),e.push(` ${o.join(l.dim(" \xB7 "))}`),e.push("");}if(t.platformMatrix){let n=t.platformMatrix;(n.nativeModules.length>0||n.dockerBaseImages.length>0)&&(e.push(l.bold.underline(" Platform")),n.nativeModules.length>0&&e.push(` Native modules: ${n.nativeModules.map(o=>l.dim(o)).join(", ")}`),n.osAssumptions.length>0&&e.push(` OS assumptions: ${n.osAssumptions.join(", ")}`),e.push(""));}if(t.codeQuality){let n=t.codeQuality;if(e.push(l.bold.underline(" Code Quality")),e.push(` Files: ${l.white(`${n.filesAnalyzed}`)} \xB7 Functions: ${l.white(`${n.functionsAnalyzed}`)} \xB7 Avg complexity: ${l.white(`${n.avgCyclomaticComplexity}`)} \xB7 Avg length: ${l.white(`${n.avgFunctionLength}`)} lines`),e.push(` Max nesting: ${n.maxNestingDepth} \xB7 Circular deps: ${n.circularDependencies} \xB7 Dead code: ${n.deadCodePercent}%`),n.godFiles.length>0){let o=n.godFiles.slice(0,3).map(s=>`${s.path} (${s.lines} lines)`).join(", ");e.push(` ${l.yellow("God files")}: ${o}`);}e.push("");}if(t.dependencyGraph){let n=t.dependencyGraph;n.lockfileType&&(e.push(l.bold.underline(" Dependency Graph")),e.push(` ${n.lockfileType}: ${l.white(`${n.totalUnique}`)} unique, ${l.white(`${n.totalInstalled}`)} installed`),n.duplicatedPackages.length>0&&e.push(` ${l.yellow(`${n.duplicatedPackages.length} duplicated`)} packages`),n.phantomDependencies.length>0&&e.push(` ${l.red(`${n.phantomDependencies.length} phantom`)} dependencies`),e.push(""));}return e}function Ao(t){let e=[];if(e.push(l.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),e.push(l.bold.cyan("\u2551 Architecture Layers \u2551")),e.push(l.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),e.push(""),e.push(l.bold(" Archetype: ")+`${t.archetype}`+l.dim(` (${Math.round(t.archetypeConfidence*100)}% confidence)`)),e.push(` Files classified: ${t.totalClassified}`+(t.unclassified>0?l.dim(` (${t.unclassified} unclassified)`):"")),e.push(""),t.layers.length>0){for(let n of t.layers){let o=n.riskLevel==="none"?l.dim("none"):n.riskLevel==="low"?l.green("low"):n.riskLevel==="moderate"?l.yellow("moderate"):l.red("high");e.push(` ${l.bold(n.layer)} ${n.fileCount} file${n.fileCount!==1?"s":""} drift ${xe(n.driftScore)} risk ${o}`);}e.push("");}return e}function Do(t){let e=[],n=t.projects.filter(r=>r.runtimeMajorsBehind!==void 0&&r.runtimeMajorsBehind>=3);if(n.length>0){let r=n.map(p=>p.name).join(", "),c="End-of-life runtimes no longer receive security patches and block ecosystem upgrades.",a=[];for(let p of n)a.push(`
|
|
11
|
+
./${p.path}`),a.push(`
|
|
12
|
+
${p.runtime} \u2192 ${p.runtimeLatest} (${p.runtimeMajorsBehind} major${p.runtimeMajorsBehind>1?"s":""} behind)`);c+=a.join(""),e.push({title:`Upgrade EOL runtime${n.length>1?"s":""} in ${r}`,explanation:c,impact:`\u2212${Math.min(n.length*10,30)} drift points (runtime & EOL scores)`,severity:100});}let o=[];for(let r of t.projects)for(let c of r.frameworks)c.majorsBehind!==null&&c.majorsBehind>=3&&o.push({name:c.name,fw:`${c.currentVersion} \u2192 ${c.latestVersion}`,behind:c.majorsBehind,project:r.name,projectPath:r.path});if(o.length>0){let r=o.sort((u,h)=>h.behind-u.behind)[0],c=o.length>1?` (+${o.length-1} more)`:"",a=`${r.behind} major versions behind. Major framework drift increases breaking change risk and blocks access to security fixes and performance improvements.`,p=[],g=0;for(let u of o){if(g>=8)break;p.push(`
|
|
13
13
|
./${u.projectPath}`),p.push(`
|
|
14
|
-
${u.name}: ${u.fw} (${u.behind} major${u.behind>1?"s":""} behind)`),g++;}let f=o.length-g;
|
|
15
|
-
... and ${f} more`),e.push({title:`Upgrade ${
|
|
16
|
-
./${
|
|
17
|
-
${m.package}: ${$} \u2192 ${
|
|
18
|
-
... and ${v} more`);}e.push({title:`Reduce dependency rot in ${
|
|
14
|
+
${u.name}: ${u.fw} (${u.behind} major${u.behind>1?"s":""} behind)`),g++;}let f=o.length-g;a+=p.join(""),f>0&&(a+=`
|
|
15
|
+
... and ${f} more`),e.push({title:`Upgrade ${r.name} ${r.fw} in ${r.project}${c}`,explanation:a,impact:"\u22125\u201315 drift points",severity:90});}for(let r of t.projects){let c=r.dependencyAgeBuckets,a=c.current+c.oneBehind+c.twoPlusBehind;if(a===0)continue;let p=Math.round(c.twoPlusBehind/a*100);if(p>=40){let g=`${c.twoPlusBehind} of ${a} dependencies are 2+ majors behind. Run \`npm outdated\` and prioritise packages with known CVEs or breaking API changes.`,f=r.dependencies.filter(u=>u.majorsBehind!==null&&u.majorsBehind>=2).sort((u,h)=>(h.majorsBehind??0)-(u.majorsBehind??0));if(f.length>0){let u=[],h=0;u.push(`
|
|
16
|
+
./${r.path}`);for(let m of f){if(h>=8)break;let $=m.resolvedVersion??m.currentSpec,O=m.latestStable??"?";u.push(`
|
|
17
|
+
${m.package}: ${$} \u2192 ${O} (${m.majorsBehind} major${m.majorsBehind>1?"s":""} behind)`),h++;}let v=f.length-h;g+=u.join(""),v>0&&(g+=`
|
|
18
|
+
... and ${v} more`);}e.push({title:`Reduce dependency rot in ${r.name} (${p}% severely outdated)`,explanation:g,impact:"\u22125\u201310 drift points",severity:80+p/10});}}let s=[];for(let r of t.projects)for(let c of r.frameworks)c.majorsBehind===2&&s.push({name:c.name,project:r.name,projectPath:r.path,fw:`${c.currentVersion} \u2192 ${c.latestVersion}`});let i=[...new Map(s.map(r=>[r.name,r])).values()];if(i.length>0){let r=i.slice(0,3).map(u=>`${u.name} (${u.fw})`).join(", "),c=i.length>3?` +${i.length-3} more`:"",a="These frameworks are 2 major versions behind. Create upgrade tickets and check migration guides \u2014 the gap will widen with each new release.",p=[],g=0;for(let u of s){if(g>=8)break;p.push(`
|
|
19
19
|
./${u.projectPath}`),p.push(`
|
|
20
|
-
${u.name}: ${u.fw}`),g++;}let f=
|
|
21
|
-
... and ${f} more`),e.push({title:`Plan major framework upgrades: ${
|
|
22
|
-
./${m.path}`);for(let
|
|
23
|
-
${
|
|
24
|
-
... and ${v} more`),e.push({title:`Replace deprecated/legacy packages: ${
|
|
20
|
+
${u.name}: ${u.fw}`),g++;}let f=s.length-g;a+=p.join(""),f>0&&(a+=`
|
|
21
|
+
... and ${f} more`),e.push({title:`Plan major framework upgrades: ${r}${c}`,explanation:a,impact:"\u22125\u201310 drift points",severity:60});}if(t.extended?.breakingChangeExposure){let r=t.extended.breakingChangeExposure,c=r.deprecatedPackages.length+r.legacyPolyfills.length;if(c>0){let a=[...r.deprecatedPackages,...r.legacyPolyfills].slice(0,5).join(", "),p=c>5?` +${c-5} more`:"",g=`${c} package${c!==1?"s":""} are deprecated or legacy polyfills. These receive no updates and may have known vulnerabilities.`,f=new Set([...r.deprecatedPackages,...r.legacyPolyfills]),u=[],h=0;for(let m of t.projects){let $=m.dependencies.filter(O=>f.has(O.package));if($.length!==0){if(h>=10)break;u.push(`
|
|
22
|
+
./${m.path}`);for(let O of $){if(h>=10)break;let de=O.resolvedVersion??O.currentSpec,_=r.deprecatedPackages.includes(O.package)?"deprecated":"polyfill";u.push(`
|
|
23
|
+
${O.package}: ${de} (${_})`),h++;}}}let v=c-h;g+=u.join(""),v>0&&(g+=`
|
|
24
|
+
... and ${v} more`),e.push({title:`Replace deprecated/legacy packages: ${a}${p}`,explanation:g,severity:55});}}if(t.extended?.dependencyGraph){let r=t.extended.dependencyGraph,c=r.phantomDependencies.length;if(c>=10){let a="Packages used in code but not declared in package.json. These rely on transitive installs and can break unpredictably when other packages update.",p=r.phantomDependencyDetails;if(p&&p.length>0){let g=new Map;for(let v of p)g.has(v.sourcePath)||g.set(v.sourcePath,[]),g.get(v.sourcePath).push({package:v.package,spec:v.spec});let f=[],u=0;for(let[v,m]of g){if(u>=10)break;f.push(`
|
|
25
25
|
./${v}`);for(let $ of m){if(u>=10)break;f.push(`
|
|
26
|
-
${$.package}: ${$.spec}`),u++;}}let h=
|
|
27
|
-
... and ${h} more`);}e.push({title:`Fix ${
|
|
28
|
-
./.gitignore`,
|
|
29
|
-
Add: .env, .env.*, .env.local`):(
|
|
30
|
-
./`,
|
|
31
|
-
Missing: ${
|
|
32
|
-
${h.name}: ${h.versions.join(", ")} (${h.consumers} consumer${h.consumers!==1?"s":""})`),f++;}let u=
|
|
33
|
-
... and ${u} more`),e.push({title:"Deduplicate heavily-versioned packages",explanation:p,severity:35});}}return e.sort((
|
|
34
|
-
`)}var Kt=new Command("report").description("Generate a drift report from a scan artifact").option("--in <file>","Input artifact file",".vibgrate/scan_result.json").option("--format <format>","Output format (md|text|json)","text").action(async t=>{let e=S.resolve(t.in);await c(e)||(console.error(l.red(`Artifact not found: ${e}`)),console.error(l.dim('Run "vibgrate scan" first to generate a scan artifact.')),process.exit(1));let n=await b$1(e);switch(t.format){case "md":console.log(Jt(n));break;case "json":console.log(JSON.stringify(n,null,2));break;default:console.log(Wt(n));break}});function qt(t){let e=process.platform,n,o;e==="darwin"?(n="open",o=[t]):e==="win32"?(n="cmd",o=["/c","start","",t]):(n="xdg-open",o=[t]);try{let r=spawn(n,o,{stdio:"ignore",detached:!0});return r.on("error",()=>{}),r.unref(),!0}catch{return false}}var jo=t=>new Promise(e=>setTimeout(e,t)),Yt=new Command("login").description("Authenticate the CLI with your Vibgrate workspace via the browser").option("--ingest <url>","Ingest API URL (overrides --region)").option("--region <region>",`Data residency region (${se().join(", ")})`,"us").option("--no-browser","Do not attempt to open a browser automatically").action(async t=>{let e;try{e=ee(t.region,t.ingest);}catch(s){console.error(l.red(s instanceof Error?s.message:String(s))),process.exit(1);}let n=`https://${e}/v1/auth/device`,o;try{let s=await fetch(`${n}/start`,{method:"POST",headers:{"Content-Type":"application/json",Connection:"close"},body:"{}"});s.ok||(console.error(l.red(`Failed to start login (HTTP ${s.status}).`)),process.exit(1)),o=await s.json();}catch(s){console.error(l.red(`Could not reach ${e}: ${s instanceof Error?s.message:String(s)}`)),process.exit(1);}console.log(""),console.log("To finish signing in, open this URL and approve the request:"),console.log(""),console.log(" "+l.cyan(o.verificationUri)),console.log(""),console.log(" Your code: "+l.bold(o.userCode)),console.log(""),t.browser&&qt(o.verificationUriComplete)&&console.log(l.dim("Opening your browser\u2026 (if it does not open, use the URL above)")),console.log(l.dim("Waiting for approval\u2026"));let r=Math.max(2,o.interval||5)*1e3,c=Date.now()+(o.expiresIn||900)*1e3;for(;Date.now()<c;){await jo(r);let s;try{s=await(await fetch(`${n}/token`,{method:"POST",headers:{"Content-Type":"application/json",Connection:"close"},body:JSON.stringify({deviceCode:o.deviceCode})})).json();}catch{continue}if(s.status!=="authorization_pending"){if(s.status==="complete"&&s.dsn){Mt({dsn:s.dsn,workspaceId:s.workspaceId,keyId:s.keyId,ingestHost:s.ingestHost??e,savedAt:new Date().toISOString()}),console.log(""),console.log(l.green("\u2714")+" Logged in."),s.workspaceId&&console.log(" Workspace: "+l.bold(s.workspaceId)),console.log(l.dim(` Credentials saved to ${ce()}`)),console.log(l.dim(' You can now run "vibgrate scan --push".'));return}s.status==="access_denied"&&(console.error(l.red("\u2716 Login was denied in the browser.")),process.exit(1)),(s.status==="expired"||s.status==="invalid")&&(console.error(l.red('\u2716 Login request expired. Run "vibgrate login" again.')),process.exit(1)),s.status==="error"&&(console.error(l.red(`\u2716 ${s.error??"Login failed."}`)),process.exit(1));}}console.error(l.red('\u2716 Timed out waiting for approval. Run "vibgrate login" again.')),process.exit(1);});var Zt=new Command("logout").description("Clear stored Vibgrate login credentials").action(()=>{let t=Bt();console.log(t?l.green("\u2714")+" Logged out. Stored credentials removed.":l.dim(`No stored credentials found at ${ce()}.`));});var Eo=[{category:"pricing",pattern:/price|pricing|billing|subscri|trial|credit|plan|tier|upgrade|premium|pro|enterprise/i},{category:"auth",pattern:/sign[- ]?in|sign[- ]?up|log[- ]?in|log[- ]?out|auth|sso|oauth|password|register|invite|onboard/i},{category:"dashboard",pattern:/dashboard|overview|home|main|summary|stats/i},{category:"settings",pattern:/setting|config|preference|option|profile|account/i},{category:"users",pattern:/user|member|team|role|permission|access|admin|owner/i},{category:"integrations",pattern:/integrat|connect|webhook|api[- ]?key|sync|import|export/i},{category:"reports",pattern:/report|analy|metric|chart|graph|insight|track/i},{category:"workflows",pattern:/workflow|automat|schedule|trigger|action|job|task|pipeline/i},{category:"projects",pattern:/project|workspace|organization|folder|repo/i},{category:"navigation",pattern:/menu|nav|sidebar|header|footer|breadcrumb/i}];function en(t,e=3){let n=t.topEvidence,o=n.filter(g=>g.kind==="dependency").map(g=>g.value).slice(0,10),r=Oo(n.filter(g=>g.kind==="route").map(g=>g.value)).slice(0,15),c=n.filter(g=>g.kind!=="dependency"&&g.kind!=="route"&&g.kind!=="feature_flag"),s=new Map,a={};for(let g of c){let f=Ao(g.value);s.has(f)||s.set(f,new Set);let u=Do(g.value);u.length>=3&&s.get(f).add(u);}let i=[];for(let[g,f]of s){let u=To([...f]);a[g]=u.length;for(let h of u.slice(0,e))i.push({kind:"text",value:h,category:g});}let p=n.filter(g=>g.kind==="feature_flag");return p.length>0&&(a.feature_flags=p.length,i.push({kind:"feature_flag",value:"feature flags detected",category:"feature_flags"})),{samples:i,categoryCounts:a,originalCount:n.length,dependencies:o,routes:r,detectedFrameworks:t.detectedFrameworks}}function Ao(t){for(let{category:e,pattern:n}of Eo)if(n.test(t))return e;return "general"}function Do(t){return t.toLowerCase().replace(/[^a-z0-9\s-]/g," ").replace(/\s+/g," ").trim().slice(0,60)}function To(t){let e=t.sort((o,r)=>r.length-o.length),n=[];for(let o of e)n.some(c=>{let s=o.slice(0,6);return c.startsWith(s)||c.includes(o)||o.includes(c)})||n.push(o);return n}function Oo(t){let e=new Set,n=[];for(let o of t){let r=o.replace(/:[a-z_]+/gi,":param").replace(/\[\[*\.*\.*[a-z_]+\]*\]/gi,":param").replace(/\/+$/,"").toLowerCase();e.has(r)||(e.add(r),n.push(o));}return n}var No=promisify(tn.gzip),G=50;function xe(t){let e=t.match(/^(.+?)\s*\(/);return e?e[1].trim():t.trim()}function Fo(t){return {databaseTechnologies:t.databaseTechnologies.slice(0,10),connectionStrings:[],connectionPoolSettings:t.connectionPoolSettings.slice(0,G),replicationSettings:t.replicationSettings.slice(0,20),readReplicaSettings:t.readReplicaSettings.slice(0,20),failoverSettings:t.failoverSettings.slice(0,20),collationAndEncoding:t.collationAndEncoding.slice(0,20),queryTimeoutDefaults:t.queryTimeoutDefaults.slice(0,20),manualIndexes:t.manualIndexes.map(xe).slice(0,G),tables:t.tables.map(xe).slice(0,G),views:t.views.map(xe).slice(0,G),storedProcedures:t.storedProcedures.map(xe).slice(0,G),triggers:t.triggers.map(xe).slice(0,G),rowLevelSecurityPolicies:t.rowLevelSecurityPolicies.slice(0,20),otherServices:t.otherServices.slice(0,20)}}function Mo(t){let e=new Set;return {integrations:t.integrations.filter(o=>{let r=o.provider.split(":")[0];return e.has(r)?false:(e.add(r),true)}).slice(0,G).map(o=>({provider:o.provider,endpoint:"",version:o.version,parameters:[],configOptions:[],authHints:[],files:[]})),openApiSpecifications:t.openApiSpecifications.slice(0,10),webhookUrls:t.webhookUrls.slice(0,20),callbackEndpoints:t.callbackEndpoints.slice(0,20),apiVersionPins:t.apiVersionPins.slice(0,20),tokenExpirationPolicies:t.tokenExpirationPolicies.slice(0,20),rateLimitOverrides:t.rateLimitOverrides.slice(0,20),customHeaders:t.customHeaders.slice(0,20),corsPolicies:t.corsPolicies.slice(0,20),oauthScopes:t.oauthScopes.slice(0,20),apiTokens:[]}}function Bo(t){return {faviconFiles:t.faviconFiles.slice(0,1),productLogos:[]}}function Lo(t){let e={...t};if(e.extended){let n={...e.extended};if(n.dataStores&&(n.dataStores=Fo(n.dataStores)),n.apiSurface&&(n.apiSurface=Mo(n.apiSurface)),n.assetBranding&&(n.assetBranding=Bo(n.assetBranding)),n.uiPurpose){let o=en(n.uiPurpose);n.uiPurpose={enabled:n.uiPurpose.enabled,detectedFrameworks:o.detectedFrameworks,evidenceCount:o.originalCount,capped:n.uiPurpose.capped,topEvidence:[],unknownSignals:[],compacted:o};}if(n.runtimeConfiguration&&(n.runtimeConfiguration={...n.runtimeConfiguration,environmentVariables:n.runtimeConfiguration.environmentVariables.slice(0,100),hiddenConfigFiles:n.runtimeConfiguration.hiddenConfigFiles.slice(0,G),startupArguments:n.runtimeConfiguration.startupArguments.slice(0,100)}),n.operationalResilience){let o=n.operationalResilience;n.operationalResilience={implicitTimeouts:o.implicitTimeouts.slice(0,30),defaultPaginationSize:o.defaultPaginationSize.slice(0,30),implicitRetryLogic:o.implicitRetryLogic.slice(0,30),defaultLocale:o.defaultLocale.slice(0,20),defaultCurrency:o.defaultCurrency.slice(0,20),implicitTimezone:o.implicitTimezone.slice(0,20),defaultCharacterEncoding:o.defaultCharacterEncoding.slice(0,20),sessionStores:o.sessionStores.slice(0,20),distributedLocks:o.distributedLocks.slice(0,20),jobSchedulers:o.jobSchedulers.slice(0,30),idempotencyKeys:o.idempotencyKeys.slice(0,20),rateLimitingCounters:o.rateLimitingCounters.slice(0,20),circuitBreakerState:o.circuitBreakerState.slice(0,20),abTestToggles:o.abTestToggles.slice(0,20),regionalEnablementRules:o.regionalEnablementRules.slice(0,20),betaAccessGroups:o.betaAccessGroups.slice(0,20),licensingEnforcementLogic:o.licensingEnforcementLogic.slice(0,20),killSwitches:o.killSwitches.slice(0,20),connectorRetryLogic:o.connectorRetryLogic.slice(0,20),apiPollingIntervals:o.apiPollingIntervals.slice(0,20),fieldMappings:o.fieldMappings.slice(0,20),schemaRegistryRules:o.schemaRegistryRules.slice(0,20),deadLetterQueueBehavior:o.deadLetterQueueBehavior.slice(0,20),dataMaskingRules:o.dataMaskingRules.slice(0,20),transformationLogic:o.transformationLogic.slice(0,20),timezoneHandling:o.timezoneHandling.slice(0,20),encryptionSettings:o.encryptionSettings.slice(0,30),hardcodedSecretSignals:o.hardcodedSecretSignals.slice(0,20)};}n.dependencyGraph&&(n.dependencyGraph={...n.dependencyGraph,phantomDependencies:n.dependencyGraph.phantomDependencies.slice(0,G),phantomDependencyDetails:n.dependencyGraph.phantomDependencyDetails?.slice(0,G),duplicatedPackages:n.dependencyGraph.duplicatedPackages.slice(0,G)}),e.extended=n;}return e}async function Uo(t){let e=JSON.stringify(t);return No(e,{level:9})}async function nn(t){let e=Lo(t);return {body:await Uo(e),contentEncoding:"gzip"}}function _e(t){let n=t.replace(/[\x00-\x1F\x7F\uFEFF\u200B-\u200D\u2060]/g,"").trim().match(/^vibgrate\+(https?):?\/\/([^:]+):([^@]+)@([^/]+)\/(.+)$/);return n?{scheme:n[1],keyId:n[2],secret:n[3],host:n[4],workspaceId:n[5]}:null}function sn(t,e){return De.createHmac("sha256",e).update(t).digest("base64")}var an=new Command("push").description("Push scan results to Vibgrate API").option("--dsn <dsn>","DSN token (or use VIBGRATE_DSN env)").option("--region <region>",`Override data residency region (${se().join(", ")})`).option("--file <file>","Scan artifact file",".vibgrate/scan_result.json").option("--strict","Fail on upload errors").action(async t=>{let e=ge(t.dsn);if(!e){console.error(l.red("No DSN provided.")),console.error(l.dim('Run "vibgrate login", set VIBGRATE_DSN, or use the --dsn flag.')),t.strict&&process.exit(1);return}let n=_e(e);if(!n){console.error(l.red("Invalid DSN format.")),console.error(l.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>")),t.strict&&process.exit(1);return}let o=S.resolve(t.file);if(!await c(o)){console.error(l.red(`Scan artifact not found: ${o}`)),console.error(l.dim('Run "vibgrate scan" first.')),t.strict&&process.exit(1);return}let r=await b$1(o),{body:c$1,contentEncoding:s}=await nn(r),a=String(Date.now()),i=n.host;if(t.region)try{i=ee(t.region);}catch(u){console.error(l.red(u instanceof Error?u.message:String(u))),t.strict&&process.exit(1);return}let p=JSON.stringify(r).length,g=c$1.length,f=((1-g/p)*100).toFixed(0);console.log(l.dim(`Uploading to ${i}... (${(g/1024).toFixed(0)} KB, ${f}% smaller)`));try{let{response:u,host:h}=await Oe({scheme:n.scheme,host:i,keyId:n.keyId,secret:n.secret,body:c$1,contentEncoding:s,timestamp:a});if(i=h,!u.ok){let m=await u.text();throw new Error(`HTTP ${u.status}: ${m}`)}let v=await u.json();if(console.log(l.green("\u2714")+` Scan queued for processing (${v.ingestId??"ok"})`),console.log(),console.log(l.dim("Processing continues in the background. Results available shortly.")),console.log(),v.ingestId){let $=`https://${ue(i)}/${n.workspaceId}/scan/${v.ingestId}`;console.log(l.dim("View report: ")+l.underline($));}}catch(u){let h=u instanceof Error?u.message:String(u);console.error(l.red(`Upload failed: ${h}`)),t.strict&&process.exit(1);}});var Pe=b$2(a(),1);var ln="https://registry.npmjs.org/@vibgrate%2fcli/latest",dn=S.join(Nt.homedir(),".vibgrate"),pn=S.join(dn,"update-check.json"),Ho=720*60*1e3;async function un(){try{let t=await Go();if(t&&Date.now()-t.checkedAt<Ho)return {current:R,latest:t.latest,updateAvailable:Pe.default.gt(t.latest,R)};let e=new AbortController,n=setTimeout(()=>e.abort(),5e3);n.unref?.();let o;try{o=await fetch(ln,{headers:{Accept:"application/json"},signal:e.signal});}finally{clearTimeout(n);}if(!o.ok)return null;let c=(await o.json()).version;return !c||!Pe.default.valid(c)?null:(await fn({latest:c,checkedAt:Date.now()}),{current:R,latest:c,updateAvailable:Pe.default.gt(c,R)})}catch{return null}}async function gn(){try{let t=new AbortController,e=setTimeout(()=>t.abort(),1e4);e.unref?.();let n;try{n=await fetch(ln,{headers:{Accept:"application/json"},signal:t.signal});}finally{clearTimeout(e);}if(!n.ok)return null;let r=(await n.json()).version;return !r||!Pe.default.valid(r)?null:(await fn({latest:r,checkedAt:Date.now()}),r)}catch{return null}}async function Go(){try{let t=await J.readFile(pn,"utf-8"),e=JSON.parse(t);return e.latest&&typeof e.checkedAt=="number"?e:null}catch{return null}}async function fn(t){try{await J.mkdir(dn,{recursive:!0}),await J.writeFile(pn,JSON.stringify(t),"utf-8");}catch{}}function Xo(){let t=process.argv[1]||"";return (t.includes("/lib/node_modules/")||t.includes("\\node_modules\\"))&&!t.includes(process.cwd())?t.includes("pnpm")?"pnpm":t.includes("yarn")?"yarn":t.includes("bun")?"bun":"npm":null}function zo(t,e,n){let o=`${e}@${n}`;switch(t){case "pnpm":return `pnpm add -g ${o}`;case "yarn":return `yarn global add ${o}`;case "bun":return `bun add -g ${o}`;default:return `npm install -g ${o}`}}async function Ko(t){return await c(S.join(t,"pnpm-lock.yaml"))?"pnpm":await c(S.join(t,"bun.lockb"))?"bun":await c(S.join(t,"yarn.lock"))?"yarn":"npm"}function qo(t,e,n,o){let r=`${e}@${n}`;switch(t){case "pnpm":return o?`pnpm add -D ${r}`:`pnpm add ${r}`;case "yarn":return o?`yarn add --dev ${r}`:`yarn add ${r}`;case "bun":return o?`bun add -d ${r}`:`bun add ${r}`;default:return o?`npm install --save-dev ${r}`:`npm install ${r}`}}async function Yo(t){try{let e=S.join(t,"package.json"),n=await(await import('fs/promises')).readFile(e,"utf-8");return !!JSON.parse(n).devDependencies?.["@vibgrate/cli"]}catch{return true}}var mn=new Command("update").description("Update vibgrate to the latest version").option("--check","Only check for updates, do not install").option("--pm <manager>","Package manager to use (npm, pnpm, yarn, bun)").option("--global","Update global installation").action(async t=>{console.log(l.dim(`Current version: ${R}`)),console.log(l.dim("Checking npm registry..."));let e=await gn();if(e||(console.error(l.red("Could not reach the npm registry. Check your network connection.")),process.exit(1)),!(await import('./semver-TPPMM2NV.js')).gt(e,R)){console.log(l.green("\u2714")+` You are on the latest version (${R}).`);return}if(console.log(l.yellow(`Update available: ${R} \u2192 ${e}`)),t.check){console.log(l.dim('Run "vibgrate update" to install.'));return}let o=process.cwd(),r=Xo(),c=t.global||r!==null,s=t.pm||(r??await Ko(o)),a;if(c)a=zo(s,"@vibgrate/cli",e),console.log(l.dim(`Updating global installation with ${s}: ${a}`));else {let i=await Yo(o);a=qo(s,"@vibgrate/cli",e,i),console.log(l.dim(`Using ${s}: ${a}`));}try{execSync(a,{cwd:o,stdio:"inherit"}),console.log(l.green("\u2714")+` Updated to @vibgrate/cli@${e}`);}catch{console.error(l.red(`Update failed. Run manually: ${a}`)),process.exit(1);}});var er="https://openvex.dev/ns/v0.2.0",hn=["not_affected","affected","fixed","under_investigation"],bn=["component_not_present","vulnerable_code_not_present","vulnerable_code_not_in_execute_path","vulnerable_code_cannot_be_controlled_by_adversary","inline_mitigations_already_exist"],W=class extends Error{};function tr(t){let e=t.statements.map((n,o)=>{if(!n.vulnerability||typeof n.vulnerability!="string")throw new W(`statement[${o}]: "vulnerability" is required`);if(!hn.includes(n.status))throw new W(`statement[${o}] (${n.vulnerability}): invalid status "${n.status}". Expected one of: ${hn.join(", ")}`);let r=n.products&&n.products.length>0?n.products:t.defaultProduct?[t.defaultProduct]:[];if(r.length===0)throw new W(`statement[${o}] (${n.vulnerability}): no product. Set "products" on the statement or pass --product.`);if(n.status==="not_affected"&&!n.justification&&!n.impact_statement)throw new W(`statement[${o}] (${n.vulnerability}): "not_affected" requires a justification or impact_statement.`);if(n.justification&&!bn.includes(n.justification))throw new W(`statement[${o}] (${n.vulnerability}): invalid justification "${n.justification}". Expected one of: ${bn.join(", ")}`);if(n.status==="affected"&&!n.action_statement)throw new W(`statement[${o}] (${n.vulnerability}): "affected" requires an action_statement.`);let c={vulnerability:{name:n.vulnerability},products:r.map(s=>({"@id":s})),status:n.status};return n.justification&&(c.justification=n.justification),n.impact_statement&&(c.impact_statement=n.impact_statement),n.action_statement&&(c.action_statement=n.action_statement),c});return {"@context":er,"@id":t.id??`https://vibgrate.com/vex/${randomUUID()}`,author:t.author,timestamp:t.timestamp??new Date().toISOString(),version:1,statements:e}}async function nr(t){let e=await b$1(t),n=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.statements)?e.statements:null;if(!n)throw new W(`${t}: expected a JSON array of statements or an object with a "statements" array.`);return n}function or(t,e){let n;try{n=JSON.parse(t);}catch{throw new W(`--statement must be a JSON object: ${t.slice(0,60)}\u2026`)}return [...e,n]}var yn=new Command("vex").description("Generate an OpenVEX document (exploitability statements) for attestation").option("--from <file>",'Read statements from a JSON file (array, or an object with a "statements" array)').option("--statement <json>",`Add a statement as inline JSON, e.g. '{"vulnerability":"CVE-2024-1","status":"not_affected","justification":"vulnerable_code_not_present"}'. Repeatable.`,or,[]).option("--product <ref>","Default product reference applied to statements without their own (e.g. an image digest)").option("--author <name>","Document author","Vibgrate").option("--timestamp <iso>","Override the document timestamp (ISO 8601) for reproducible output").option("--id <uri>","Override the document @id (otherwise a uuid URN is generated)").option("--out <file>","Write the document to a file (default: stdout)").action(async t=>{try{let e$1=[];if(t.from){let r=S.resolve(t.from);await c(r)||(process.stderr.write(l.red(`Statements file not found: ${r}
|
|
35
|
-
`)),process.exit(1)),e$1.push(...await
|
|
26
|
+
${$.package}: ${$.spec}`),u++;}}let h=c-u;a+=f.join(""),h>0&&(a+=`
|
|
27
|
+
... and ${h} more`);}e.push({title:`Fix ${c} phantom dependencies`,explanation:a,severity:45});}}if(t.extended?.securityPosture){let r=t.extended.securityPosture;if(r.envFilesTracked||!r.lockfilePresent){let c=[];r.envFilesTracked&&c.push(".env files are tracked in git"),r.lockfilePresent||c.push("no lockfile found");let a;r.envFilesTracked?(a="Environment files may contain secrets. Add them to .gitignore and rotate any exposed credentials immediately.",a+=`
|
|
28
|
+
./.gitignore`,a+=`
|
|
29
|
+
Add: .env, .env.*, .env.local`):(a="Without a lockfile, installs are non-deterministic. Run the install command to generate one and commit it.",a+=`
|
|
30
|
+
./`,a+=`
|
|
31
|
+
Missing: ${r.lockfileTypes.length>0?r.lockfileTypes.join(", ")+" (multiple types detected)":"package-lock.json, pnpm-lock.yaml, or yarn.lock"}`),e.push({title:`Fix security posture: ${c.join(", ")}`,explanation:a,severity:95});}}if(t.extended?.dependencyGraph){let c=t.extended.dependencyGraph.duplicatedPackages.filter(a=>a.versions.length>=3);if(c.length>=3){c.slice(0,4).map(h=>`${h.name} (${h.versions.length}v)`).join(", ");let p=`${c.length} packages have 3+ versions installed. Run \`npm dedupe\` to reduce bundle size and install time.`,g=[],f=0;for(let h of c){if(f>=8)break;g.push(`
|
|
32
|
+
${h.name}: ${h.versions.join(", ")} (${h.consumers} consumer${h.consumers!==1?"s":""})`),f++;}let u=c.length-f;p+=g.join(""),u>0&&(p+=`
|
|
33
|
+
... and ${u} more`),e.push({title:"Deduplicate heavily-versioned packages",explanation:p,severity:35});}}return e.sort((r,c)=>c.severity-r.severity),e.slice(0,5)}function zt(t){let e=[];e.push("# Vibgrate Drift Report"),e.push(""),e.push("| Metric | Value |"),e.push("|--------|-------|"),e.push(`| **Drift Score** | ${t.drift.score}/100 _(lower is better; 0 = no drift)_ |`),e.push(`| **Risk Level** | ${t.drift.riskLevel.toUpperCase()} |`),e.push(`| **Projects** | ${t.projects.length} |`);let n=[t.timestamp];t.durationMs!==void 0&&n.push(`${(t.durationMs/1e3).toFixed(1)}s`),t.filesScanned!==void 0&&n.push(`${t.filesScanned} files`),t.treeSummary&&n.push(`${t.treeSummary.totalFiles.toLocaleString()} workspace files \xB7 ${t.treeSummary.totalDirs.toLocaleString()} dirs`),e.push(`| **Scanned** | ${n.join(" \xB7 ")} |`),t.vcs&&(e.push(`| **VCS** | ${t.vcs.type} |`),t.vcs.branch&&e.push(`| **Branch** | ${t.vcs.branch} |`),t.vcs.sha&&e.push(`| **Commit** | \`${t.vcs.shortSha}\` |`)),e.push(""),e.push("## Score Breakdown"),e.push(""),e.push("| Component | Score |"),e.push("|-----------|-------|"),e.push(`| Runtime | ${t.drift.components.runtimeScore} |`),e.push(`| Frameworks | ${t.drift.components.frameworkScore} |`),e.push(`| Dependencies | ${t.drift.components.dependencyScore} |`),e.push(`| EOL Risk | ${t.drift.components.eolScore} |`),e.push(""),e.push("## Projects"),e.push("");for(let o of t.projects){if(e.push(`### ${o.name} (${o.type})`),e.push(""),o.runtime){let r=o.runtimeMajorsBehind!==void 0&&o.runtimeMajorsBehind>0?` \u2014 ${o.runtimeMajorsBehind} major(s) behind`:" \u2014 current";e.push(`- **Runtime:** ${o.runtime}${r}`);}if(o.frameworks.length>0){e.push("- **Frameworks:**");for(let r of o.frameworks){let c=r.majorsBehind!==null?r.majorsBehind===0?"current":`${r.majorsBehind} behind`:"unknown";e.push(` - ${r.name}: ${r.currentVersion??"?"} \u2192 ${r.latestVersion??"?"} (${c})`);}}let s=o.dependencyAgeBuckets;s.current+s.oneBehind+s.twoPlusBehind+s.unknown>0&&e.push(`- **Dependencies:** ${s.current} current, ${s.oneBehind} 1-behind, ${s.twoPlusBehind} 2+ behind, ${s.unknown} unknown`),e.push("");}if(t.extended?.uiPurpose){let o=t.extended.uiPurpose;if(e.push("## Product Purpose Signals"),e.push(""),e.push(`- **Frameworks:** ${o.detectedFrameworks.length>0?o.detectedFrameworks.join(", "):"unknown"}`),e.push(`- **Evidence Items:** ${o.topEvidence.length}${o.capped?` (capped from ${o.evidenceCount})`:""}`),o.topEvidence.length>0){e.push("- **Top Evidence:**");for(let s of o.topEvidence.slice(0,10))e.push(` - [${s.kind}] ${s.value} (${s.file})`);}if(o.unknownSignals.length>0){e.push("- **Unknowns:**");for(let s of o.unknownSignals.slice(0,5))e.push(` - ${s}`);}e.push("");}if(t.extended?.standards&&t.extended.standards.recommended.length>0){let o=t.extended.standards;e.push("## Recommended Standards"),e.push("");let s=o.projectPurposes.map(i=>`${i.project} \u2192 ${i.category}`).join(", ");if(s&&e.push(`- **Detected purpose:** ${s}`),o.frameworks.length>0){e.push("- **Compliance framework coverage:**");for(let i of o.frameworks)e.push(` - ${i.name}: ${i.recommendedMembers}/${i.totalMembers} member standards apply`);}e.push("- **Top standards to consider:**");for(let i of o.recommended.slice(0,10)){let r=i.complianceRelevant?" _(compliance)_":"";e.push(` - **${i.name}** \u2014 ${i.reason}${r}`);}e.push("");}if(t.findings.length>0){e.push("## Findings"),e.push(""),e.push("| Level | Rule | Message | Location |"),e.push("|-------|------|---------|----------|");for(let o of t.findings){let s=o.level==="error"?"\u{1F534}":o.level==="warning"?"\u{1F7E1}":"\u{1F535}";e.push(`| ${s} ${o.level} | ${o.ruleId} | ${o.message} | ${o.location} |`);}e.push("");}if(t.delta!==void 0){let o=t.delta>0?"\u{1F4C8}":t.delta<0?"\u{1F4C9}":"\u27A1\uFE0F",s=t.delta>0?" _(worsened)_":t.delta<0?" _(improved)_":"";e.push(`## Drift Delta: ${o} ${t.delta>0?"+":""}${t.delta} vs baseline${s}`),e.push("");}return e.join(`
|
|
34
|
+
`)}var Qt=new Command("report").description("Generate a drift report from a scan artifact").option("--in <file>","Input artifact file",".vibgrate/scan_result.json").option("--format <format>","Output format (md|text|json)","text").action(async t=>{let e=S.resolve(t.in);await c(e)||(console.error(l.red(`Artifact not found: ${e}`)),console.error(l.dim('Run "vibgrate scan" first to generate a scan artifact.')),process.exit(1));let n=await b$1(e);switch(t.format){case "md":console.log(zt(n));break;case "json":console.log(JSON.stringify(n,null,2));break;default:console.log(Kt(n));break}});function Zt(t){let e=process.platform,n,o;e==="darwin"?(n="open",o=[t]):e==="win32"?(n="cmd",o=["/c","start","",t]):(n="xdg-open",o=[t]);try{let s=spawn(n,o,{stdio:"ignore",detached:!0});return s.on("error",()=>{}),s.unref(),!0}catch{return false}}var _o=t=>new Promise(e=>setTimeout(e,t)),en=new Command("login").description("Authenticate the CLI with your Vibgrate workspace via the browser").option("--ingest <url>","Ingest API URL (overrides --region)").option("--region <region>",`Data residency region (${se().join(", ")})`,"us").option("--no-browser","Do not attempt to open a browser automatically").action(async t=>{let e;try{e=ee(t.region,t.ingest);}catch(r){console.error(l.red(r instanceof Error?r.message:String(r))),process.exit(1);}let n=`https://${e}/v1/auth/device`,o;try{let r=await fetch(`${n}/start`,{method:"POST",headers:{"Content-Type":"application/json",Connection:"close"},body:"{}"});r.ok||(console.error(l.red(`Failed to start login (HTTP ${r.status}).`)),process.exit(1)),o=await r.json();}catch(r){console.error(l.red(`Could not reach ${e}: ${r instanceof Error?r.message:String(r)}`)),process.exit(1);}console.log(""),console.log("To finish signing in, open this URL and approve the request:"),console.log(""),console.log(" "+l.cyan(o.verificationUri)),console.log(""),console.log(" Your code: "+l.bold(o.userCode)),console.log(""),t.browser&&Zt(o.verificationUriComplete)&&console.log(l.dim("Opening your browser\u2026 (if it does not open, use the URL above)")),console.log(l.dim("Waiting for approval\u2026"));let s=Math.max(2,o.interval||5)*1e3,i=Date.now()+(o.expiresIn||900)*1e3;for(;Date.now()<i;){await _o(s);let r;try{r=await(await fetch(`${n}/token`,{method:"POST",headers:{"Content-Type":"application/json",Connection:"close"},body:JSON.stringify({deviceCode:o.deviceCode})})).json();}catch{continue}if(r.status!=="authorization_pending"){if(r.status==="complete"&&r.dsn){Ut({dsn:r.dsn,workspaceId:r.workspaceId,keyId:r.keyId,ingestHost:r.ingestHost??e,savedAt:new Date().toISOString()}),console.log(""),console.log(l.green("\u2714")+" Logged in."),r.workspaceId&&console.log(" Workspace: "+l.bold(r.workspaceId)),console.log(l.dim(` Credentials saved to ${ce()}`)),console.log(l.dim(' You can now run "vibgrate scan --push".'));return}r.status==="access_denied"&&(console.error(l.red("\u2716 Login was denied in the browser.")),process.exit(1)),(r.status==="expired"||r.status==="invalid")&&(console.error(l.red('\u2716 Login request expired. Run "vibgrate login" again.')),process.exit(1)),r.status==="error"&&(console.error(l.red(`\u2716 ${r.error??"Login failed."}`)),process.exit(1));}}console.error(l.red('\u2716 Timed out waiting for approval. Run "vibgrate login" again.')),process.exit(1);});var nn=new Command("logout").description("Clear stored Vibgrate login credentials").action(()=>{let t=Vt();console.log(t?l.green("\u2714")+" Logged out. Stored credentials removed.":l.dim(`No stored credentials found at ${ce()}.`));});var Mo=[{category:"pricing",pattern:/price|pricing|billing|subscri|trial|credit|plan|tier|upgrade|premium|pro|enterprise/i},{category:"auth",pattern:/sign[- ]?in|sign[- ]?up|log[- ]?in|log[- ]?out|auth|sso|oauth|password|register|invite|onboard/i},{category:"dashboard",pattern:/dashboard|overview|home|main|summary|stats/i},{category:"settings",pattern:/setting|config|preference|option|profile|account/i},{category:"users",pattern:/user|member|team|role|permission|access|admin|owner/i},{category:"integrations",pattern:/integrat|connect|webhook|api[- ]?key|sync|import|export/i},{category:"reports",pattern:/report|analy|metric|chart|graph|insight|track/i},{category:"workflows",pattern:/workflow|automat|schedule|trigger|action|job|task|pipeline/i},{category:"projects",pattern:/project|workspace|organization|folder|repo/i},{category:"navigation",pattern:/menu|nav|sidebar|header|footer|breadcrumb/i}];function on(t,e=3){let n=t.topEvidence,o=n.filter(g=>g.kind==="dependency").map(g=>g.value).slice(0,10),s=Vo(n.filter(g=>g.kind==="route").map(g=>g.value)).slice(0,15),i=n.filter(g=>g.kind!=="dependency"&&g.kind!=="route"&&g.kind!=="feature_flag"),r=new Map,c={};for(let g of i){let f=Lo(g.value);r.has(f)||r.set(f,new Set);let u=Bo(g.value);u.length>=3&&r.get(f).add(u);}let a=[];for(let[g,f]of r){let u=Uo([...f]);c[g]=u.length;for(let h of u.slice(0,e))a.push({kind:"text",value:h,category:g});}let p=n.filter(g=>g.kind==="feature_flag");return p.length>0&&(c.feature_flags=p.length,a.push({kind:"feature_flag",value:"feature flags detected",category:"feature_flags"})),{samples:a,categoryCounts:c,originalCount:n.length,dependencies:o,routes:s,detectedFrameworks:t.detectedFrameworks}}function Lo(t){for(let{category:e,pattern:n}of Mo)if(n.test(t))return e;return "general"}function Bo(t){return t.toLowerCase().replace(/[^a-z0-9\s-]/g," ").replace(/\s+/g," ").trim().slice(0,60)}function Uo(t){let e=t.sort((o,s)=>s.length-o.length),n=[];for(let o of e)n.some(i=>{let r=o.slice(0,6);return i.startsWith(r)||i.includes(o)||o.includes(i)})||n.push(o);return n}function Vo(t){let e=new Set,n=[];for(let o of t){let s=o.replace(/:[a-z_]+/gi,":param").replace(/\[\[*\.*\.*[a-z_]+\]*\]/gi,":param").replace(/\/+$/,"").toLowerCase();e.has(s)||(e.add(s),n.push(o));}return n}var Go=promisify(rn.gzip),G=50;function Pe(t){let e=t.match(/^(.+?)\s*\(/);return e?e[1].trim():t.trim()}function Wo(t){return {databaseTechnologies:t.databaseTechnologies.slice(0,10),connectionStrings:[],connectionPoolSettings:t.connectionPoolSettings.slice(0,G),replicationSettings:t.replicationSettings.slice(0,20),readReplicaSettings:t.readReplicaSettings.slice(0,20),failoverSettings:t.failoverSettings.slice(0,20),collationAndEncoding:t.collationAndEncoding.slice(0,20),queryTimeoutDefaults:t.queryTimeoutDefaults.slice(0,20),manualIndexes:t.manualIndexes.map(Pe).slice(0,G),tables:t.tables.map(Pe).slice(0,G),views:t.views.map(Pe).slice(0,G),storedProcedures:t.storedProcedures.map(Pe).slice(0,G),triggers:t.triggers.map(Pe).slice(0,G),rowLevelSecurityPolicies:t.rowLevelSecurityPolicies.slice(0,20),otherServices:t.otherServices.slice(0,20)}}function Jo(t){let e=new Set;return {integrations:t.integrations.filter(o=>{let s=o.provider.split(":")[0];return e.has(s)?false:(e.add(s),true)}).slice(0,G).map(o=>({provider:o.provider,endpoint:"",version:o.version,parameters:[],configOptions:[],authHints:[],files:[]})),openApiSpecifications:t.openApiSpecifications.slice(0,10),webhookUrls:t.webhookUrls.slice(0,20),callbackEndpoints:t.callbackEndpoints.slice(0,20),apiVersionPins:t.apiVersionPins.slice(0,20),tokenExpirationPolicies:t.tokenExpirationPolicies.slice(0,20),rateLimitOverrides:t.rateLimitOverrides.slice(0,20),customHeaders:t.customHeaders.slice(0,20),corsPolicies:t.corsPolicies.slice(0,20),oauthScopes:t.oauthScopes.slice(0,20),apiTokens:[]}}function Xo(t){return {faviconFiles:t.faviconFiles.slice(0,1),productLogos:[]}}function Ko(t){let e={...t};if(e.extended){let n={...e.extended};if(n.dataStores&&(n.dataStores=Wo(n.dataStores)),n.apiSurface&&(n.apiSurface=Jo(n.apiSurface)),n.assetBranding&&(n.assetBranding=Xo(n.assetBranding)),n.uiPurpose){let o=on(n.uiPurpose);n.uiPurpose={enabled:n.uiPurpose.enabled,detectedFrameworks:o.detectedFrameworks,evidenceCount:o.originalCount,capped:n.uiPurpose.capped,topEvidence:[],unknownSignals:[],compacted:o};}if(n.runtimeConfiguration&&(n.runtimeConfiguration={...n.runtimeConfiguration,environmentVariables:n.runtimeConfiguration.environmentVariables.slice(0,100),hiddenConfigFiles:n.runtimeConfiguration.hiddenConfigFiles.slice(0,G),startupArguments:n.runtimeConfiguration.startupArguments.slice(0,100)}),n.operationalResilience){let o=n.operationalResilience;n.operationalResilience={implicitTimeouts:o.implicitTimeouts.slice(0,30),defaultPaginationSize:o.defaultPaginationSize.slice(0,30),implicitRetryLogic:o.implicitRetryLogic.slice(0,30),defaultLocale:o.defaultLocale.slice(0,20),defaultCurrency:o.defaultCurrency.slice(0,20),implicitTimezone:o.implicitTimezone.slice(0,20),defaultCharacterEncoding:o.defaultCharacterEncoding.slice(0,20),sessionStores:o.sessionStores.slice(0,20),distributedLocks:o.distributedLocks.slice(0,20),jobSchedulers:o.jobSchedulers.slice(0,30),idempotencyKeys:o.idempotencyKeys.slice(0,20),rateLimitingCounters:o.rateLimitingCounters.slice(0,20),circuitBreakerState:o.circuitBreakerState.slice(0,20),abTestToggles:o.abTestToggles.slice(0,20),regionalEnablementRules:o.regionalEnablementRules.slice(0,20),betaAccessGroups:o.betaAccessGroups.slice(0,20),licensingEnforcementLogic:o.licensingEnforcementLogic.slice(0,20),killSwitches:o.killSwitches.slice(0,20),connectorRetryLogic:o.connectorRetryLogic.slice(0,20),apiPollingIntervals:o.apiPollingIntervals.slice(0,20),fieldMappings:o.fieldMappings.slice(0,20),schemaRegistryRules:o.schemaRegistryRules.slice(0,20),deadLetterQueueBehavior:o.deadLetterQueueBehavior.slice(0,20),dataMaskingRules:o.dataMaskingRules.slice(0,20),transformationLogic:o.transformationLogic.slice(0,20),timezoneHandling:o.timezoneHandling.slice(0,20),encryptionSettings:o.encryptionSettings.slice(0,30),hardcodedSecretSignals:o.hardcodedSecretSignals.slice(0,20)};}n.dependencyGraph&&(n.dependencyGraph={...n.dependencyGraph,phantomDependencies:n.dependencyGraph.phantomDependencies.slice(0,G),phantomDependencyDetails:n.dependencyGraph.phantomDependencyDetails?.slice(0,G),duplicatedPackages:n.dependencyGraph.duplicatedPackages.slice(0,G)}),e.extended=n;}return e}async function zo(t){let e=JSON.stringify(t);return Go(e,{level:9})}async function sn(t){let e=Ko(t);return {body:await zo(e),contentEncoding:"gzip"}}function _e(t){let n=t.replace(/[\x00-\x1F\x7F\uFEFF\u200B-\u200D\u2060]/g,"").trim().match(/^vibgrate\+(https?):?\/\/([^:]+):([^@]+)@([^/]+)\/(.+)$/);return n?{scheme:n[1],keyId:n[2],secret:n[3],host:n[4],workspaceId:n[5]}:null}function ln(t,e){return Te.createHmac("sha256",e).update(t).digest("base64")}var dn=new Command("push").description("Push scan results to Vibgrate API").option("--dsn <dsn>","DSN token (or use VIBGRATE_DSN env)").option("--region <region>",`Override data residency region (${se().join(", ")})`).option("--file <file>","Scan artifact file",".vibgrate/scan_result.json").option("--strict","Fail on upload errors").action(async t=>{let e=ge(t.dsn);if(!e){console.error(l.red("No DSN provided.")),console.error(l.dim('Run "vibgrate login", set VIBGRATE_DSN, or use the --dsn flag.')),t.strict&&process.exit(1);return}let n=_e(e);if(!n){console.error(l.red("Invalid DSN format.")),console.error(l.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>")),t.strict&&process.exit(1);return}let o=S.resolve(t.file);if(!await c(o)){console.error(l.red(`Scan artifact not found: ${o}`)),console.error(l.dim('Run "vibgrate scan" first.')),t.strict&&process.exit(1);return}let s=await b$1(o),{body:i,contentEncoding:r}=await sn(s),c$1=String(Date.now()),a=n.host;if(t.region)try{a=ee(t.region);}catch(u){console.error(l.red(u instanceof Error?u.message:String(u))),t.strict&&process.exit(1);return}let p=JSON.stringify(s).length,g=i.length,f=((1-g/p)*100).toFixed(0);console.log(l.dim(`Uploading to ${a}... (${(g/1024).toFixed(0)} KB, ${f}% smaller)`));try{let{response:u,host:h}=await Oe({scheme:n.scheme,host:a,keyId:n.keyId,secret:n.secret,body:i,contentEncoding:r,timestamp:c$1});if(a=h,!u.ok){let m=await u.text();throw new Error(`HTTP ${u.status}: ${m}`)}let v=await u.json();if(console.log(l.green("\u2714")+` Scan queued for processing (${v.ingestId??"ok"})`),console.log(),console.log(l.dim("Processing continues in the background. Results available shortly.")),console.log(),v.ingestId){let $=`https://${ue(a)}/${n.workspaceId}/scan/${v.ingestId}`;console.log(l.dim("View report: ")+l.underline($));}}catch(u){let h=u instanceof Error?u.message:String(u);console.error(l.red(`Upload failed: ${h}`)),t.strict&&process.exit(1);}});var Ce=b$2(a(),1);var un="https://registry.npmjs.org/@vibgrate%2fcli/latest",gn=S.join(Lt.homedir(),".vibgrate"),fn=S.join(gn,"update-check.json"),Yo=720*60*1e3;async function mn(){try{let t=await Qo();if(t&&Date.now()-t.checkedAt<Yo)return {current:R,latest:t.latest,updateAvailable:Ce.default.gt(t.latest,R)};let e=new AbortController,n=setTimeout(()=>e.abort(),5e3);n.unref?.();let o;try{o=await fetch(un,{headers:{Accept:"application/json"},signal:e.signal});}finally{clearTimeout(n);}if(!o.ok)return null;let i=(await o.json()).version;return !i||!Ce.default.valid(i)?null:(await bn({latest:i,checkedAt:Date.now()}),{current:R,latest:i,updateAvailable:Ce.default.gt(i,R)})}catch{return null}}async function hn(){try{let t=new AbortController,e=setTimeout(()=>t.abort(),1e4);e.unref?.();let n;try{n=await fetch(un,{headers:{Accept:"application/json"},signal:t.signal});}finally{clearTimeout(e);}if(!n.ok)return null;let s=(await n.json()).version;return !s||!Ce.default.valid(s)?null:(await bn({latest:s,checkedAt:Date.now()}),s)}catch{return null}}async function Qo(){try{let t=await J.readFile(fn,"utf-8"),e=JSON.parse(t);return e.latest&&typeof e.checkedAt=="number"?e:null}catch{return null}}async function bn(t){try{await J.mkdir(gn,{recursive:!0}),await J.writeFile(fn,JSON.stringify(t),"utf-8");}catch{}}function tr(){let t=process.argv[1]||"";return (t.includes("/lib/node_modules/")||t.includes("\\node_modules\\"))&&!t.includes(process.cwd())?t.includes("pnpm")?"pnpm":t.includes("yarn")?"yarn":t.includes("bun")?"bun":"npm":null}function nr(t,e,n){let o=`${e}@${n}`;switch(t){case "pnpm":return `pnpm add -g ${o}`;case "yarn":return `yarn global add ${o}`;case "bun":return `bun add -g ${o}`;default:return `npm install -g ${o}`}}async function or(t){return await c(S.join(t,"pnpm-lock.yaml"))?"pnpm":await c(S.join(t,"bun.lockb"))?"bun":await c(S.join(t,"yarn.lock"))?"yarn":"npm"}function rr(t,e,n,o){let s=`${e}@${n}`;switch(t){case "pnpm":return o?`pnpm add -D ${s}`:`pnpm add ${s}`;case "yarn":return o?`yarn add --dev ${s}`:`yarn add ${s}`;case "bun":return o?`bun add -d ${s}`:`bun add ${s}`;default:return o?`npm install --save-dev ${s}`:`npm install ${s}`}}async function sr(t){try{let e=S.join(t,"package.json"),n=await(await import('fs/promises')).readFile(e,"utf-8");return !!JSON.parse(n).devDependencies?.["@vibgrate/cli"]}catch{return true}}var yn=new Command("update").description("Update vibgrate to the latest version").option("--check","Only check for updates, do not install").option("--pm <manager>","Package manager to use (npm, pnpm, yarn, bun)").option("--global","Update global installation").action(async t=>{console.log(l.dim(`Current version: ${R}`)),console.log(l.dim("Checking npm registry..."));let e=await hn();if(e||(console.error(l.red("Could not reach the npm registry. Check your network connection.")),process.exit(1)),!(await import('./semver-TPPMM2NV.js')).gt(e,R)){console.log(l.green("\u2714")+` You are on the latest version (${R}).`);return}if(console.log(l.yellow(`Update available: ${R} \u2192 ${e}`)),t.check){console.log(l.dim('Run "vibgrate update" to install.'));return}let o=process.cwd(),s=tr(),i=t.global||s!==null,r=t.pm||(s??await or(o)),c;if(i)c=nr(r,"@vibgrate/cli",e),console.log(l.dim(`Updating global installation with ${r}: ${c}`));else {let a=await sr(o);c=rr(r,"@vibgrate/cli",e,a),console.log(l.dim(`Using ${r}: ${c}`));}try{execSync(c,{cwd:o,stdio:"inherit"}),console.log(l.green("\u2714")+` Updated to @vibgrate/cli@${e}`);}catch{console.error(l.red(`Update failed. Run manually: ${c}`)),process.exit(1);}});var cr="https://openvex.dev/ns/v0.2.0",wn=["not_affected","affected","fixed","under_investigation"],vn=["component_not_present","vulnerable_code_not_present","vulnerable_code_not_in_execute_path","vulnerable_code_cannot_be_controlled_by_adversary","inline_mitigations_already_exist"],W=class extends Error{};function lr(t){let e=t.statements.map((n,o)=>{if(!n.vulnerability||typeof n.vulnerability!="string")throw new W(`statement[${o}]: "vulnerability" is required`);if(!wn.includes(n.status))throw new W(`statement[${o}] (${n.vulnerability}): invalid status "${n.status}". Expected one of: ${wn.join(", ")}`);let s=n.products&&n.products.length>0?n.products:t.defaultProduct?[t.defaultProduct]:[];if(s.length===0)throw new W(`statement[${o}] (${n.vulnerability}): no product. Set "products" on the statement or pass --product.`);if(n.status==="not_affected"&&!n.justification&&!n.impact_statement)throw new W(`statement[${o}] (${n.vulnerability}): "not_affected" requires a justification or impact_statement.`);if(n.justification&&!vn.includes(n.justification))throw new W(`statement[${o}] (${n.vulnerability}): invalid justification "${n.justification}". Expected one of: ${vn.join(", ")}`);if(n.status==="affected"&&!n.action_statement)throw new W(`statement[${o}] (${n.vulnerability}): "affected" requires an action_statement.`);let i={vulnerability:{name:n.vulnerability},products:s.map(r=>({"@id":r})),status:n.status};return n.justification&&(i.justification=n.justification),n.impact_statement&&(i.impact_statement=n.impact_statement),n.action_statement&&(i.action_statement=n.action_statement),i});return {"@context":cr,"@id":t.id??`https://vibgrate.com/vex/${randomUUID()}`,author:t.author,timestamp:t.timestamp??new Date().toISOString(),version:1,statements:e}}async function dr(t){let e=await b$1(t),n=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.statements)?e.statements:null;if(!n)throw new W(`${t}: expected a JSON array of statements or an object with a "statements" array.`);return n}function pr(t,e){let n;try{n=JSON.parse(t);}catch{throw new W(`--statement must be a JSON object: ${t.slice(0,60)}\u2026`)}return [...e,n]}var $n=new Command("vex").description("Generate an OpenVEX document (exploitability statements) for attestation").option("--from <file>",'Read statements from a JSON file (array, or an object with a "statements" array)').option("--statement <json>",`Add a statement as inline JSON, e.g. '{"vulnerability":"CVE-2024-1","status":"not_affected","justification":"vulnerable_code_not_present"}'. Repeatable.`,pr,[]).option("--product <ref>","Default product reference applied to statements without their own (e.g. an image digest)").option("--author <name>","Document author","Vibgrate").option("--timestamp <iso>","Override the document timestamp (ISO 8601) for reproducible output").option("--id <uri>","Override the document @id (otherwise a uuid URN is generated)").option("--out <file>","Write the document to a file (default: stdout)").action(async t=>{try{let e$1=[];if(t.from){let s=S.resolve(t.from);await c(s)||(process.stderr.write(l.red(`Statements file not found: ${s}
|
|
35
|
+
`)),process.exit(1)),e$1.push(...await dr(s));}e$1.push(...t.statement);let n=lr({author:t.author,defaultProduct:t.product,timestamp:t.timestamp,id:t.id,statements:e$1}),o=JSON.stringify(n,null,2);t.out?(await e(S.resolve(t.out),o+`
|
|
36
36
|
`),process.stderr.write(l.green("\u2714")+` Wrote OpenVEX document (${n.statements.length} statement(s)) to ${S.resolve(t.out)}
|
|
37
37
|
`)):process.stdout.write(o+`
|
|
38
38
|
`);}catch(e){throw e instanceof W&&(process.stderr.write(l.red(`VEX validation error: ${e.message}
|
|
39
|
-
`)),process.exit(1)),e}});function
|
|
40
|
-
`)}async function
|
|
41
|
-
Expected: ${
|
|
42
|
-
`)){if(
|
|
43
|
-
`);let
|
|
44
|
-
`);let
|
|
45
|
-
`);return `sha256:${e.digest("hex")}`}function
|
|
46
|
-
`);
|
|
39
|
+
`)),process.exit(1)),e}});function xn(t){let e=[];for(let n of t.projects)for(let o of n.dependencies)e.push({project:n.name,package:o.package,version:o.resolvedVersion??o.currentSpec,currentSpec:o.currentSpec,drift:o.drift,majorsBehind:o.majorsBehind});return e}function ur(t){let e=xn(t);return {bomFormat:"CycloneDX",specVersion:"1.5",serialNumber:`urn:uuid:${randomUUID()}`,version:1,metadata:{timestamp:t.timestamp,tools:[{vendor:"Vibgrate",name:"@vibgrate/cli",version:t.vibgrateVersion}],component:{type:"application",name:t.rootPath}},components:e.map(n=>({type:"library",name:n.package,version:n.version,properties:[{name:"vibgrate:project",value:n.project},{name:"vibgrate:currentSpec",value:n.currentSpec},{name:"vibgrate:drift",value:n.drift},{name:"vibgrate:majorsBehind",value:String(n.majorsBehind??"unknown")}]}))}}function gr(t){let e=xn(t);return {spdxVersion:"SPDX-2.3",dataLicense:"CC0-1.0",SPDXID:"SPDXRef-DOCUMENT",name:`${t.rootPath}-sbom`,documentNamespace:`https://vibgrate.com/spdx/${t.rootPath}/${randomUUID()}`,creationInfo:{created:t.timestamp,creators:[`Tool: @vibgrate/cli-${t.vibgrateVersion}`]},packages:e.map((n,o)=>({name:n.package,SPDXID:`SPDXRef-Package-${o+1}`,versionInfo:n.version,downloadLocation:"NOASSERTION",filesAnalyzed:false,externalRefs:[{referenceCategory:"PACKAGE-MANAGER",referenceType:"purl",referenceLocator:`pkg:npm/${encodeURIComponent(n.package)}@${encodeURIComponent(n.version)}`}],annotations:[{annotationType:"OTHER",annotator:"Tool: @vibgrate/cli",annotationDate:t.timestamp,comment:`project=${n.project}; drift=${n.drift}; majorsBehind=${n.majorsBehind??"unknown"}`}]}))}}function Sn(t){let e=new Map;for(let n of t.projects)for(let o of n.dependencies)e.set(`${n.name}:${o.package}`,o);return e}function fr(t,e){let n=Sn(t),o=Sn(e),s=[],i=[],r=[];for(let[a,p]of o.entries()){if(!n.has(a)){s.push(`${a} @ ${p.resolvedVersion??p.currentSpec}`);continue}let g=n.get(a),f=g.resolvedVersion??g.currentSpec,u=p.resolvedVersion??p.currentSpec;(f!==u||g.majorsBehind!==p.majorsBehind)&&r.push(`${a} ${f} -> ${u} (majorsBehind ${g.majorsBehind??"unknown"} -> ${p.majorsBehind??"unknown"})`);}for(let[a,p]of n.entries())o.has(a)||i.push(`${a} @ ${p.resolvedVersion??p.currentSpec}`);return ["Vibgrate SBOM Delta","===================",`Baseline: ${t.timestamp}`,`Current: ${e.timestamp}`,`Drift score delta: ${(e.drift.score-t.drift.score).toFixed(2)} points`,"",`Added dependencies (${s.length})`,...s.map(a=>` + ${a}`),"",`Removed dependencies (${i.length})`,...i.map(a=>` - ${a}`),"",`Changed dependencies (${r.length})`,...r.map(a=>` * ${a}`)].join(`
|
|
40
|
+
`)}async function nt(t){let e=S.resolve(t);return await c(e)||(console.error(l.red(`Artifact not found: ${e}`)),process.exit(1)),b$1(e)}var mr=new Command("export").description("Export scan artifact as SBOM").option("--in <file>","Input artifact file",".vibgrate/scan_result.json").option("--out <file>","Output SBOM file").option("--format <format>","SBOM format (cyclonedx|spdx)","cyclonedx").action(async t=>{let e$1=await nt(t.in),n=t.format.toLowerCase();n!=="cyclonedx"&&n!=="spdx"&&(console.error(l.red("Invalid SBOM format. Use cyclonedx or spdx.")),process.exit(1));let o=n==="cyclonedx"?ur(e$1):gr(e$1),s=JSON.stringify(o,null,2);t.out?(await e(S.resolve(t.out),s),console.log(l.green("\u2714")+` SBOM written to ${t.out}`)):console.log(s);}),hr=new Command("delta").description("Show SBOM delta between two scan artifacts").requiredOption("--from <file>","Baseline scan artifact path").requiredOption("--to <file>","Current scan artifact path").option("--out <file>","Write report to file").action(async t=>{let e$1=await nt(t.from),n=await nt(t.to),o=fr(e$1,n);t.out?(await e(S.resolve(t.out),o),console.log(l.green("\u2714")+` SBOM delta report written to ${t.out}`)):console.log(o);}),Pn=new Command("sbom").description("Supply-chain evidence: SBOM export/delta and OpenVEX generation").addCommand(mr).addCommand(hr).addCommand($n);var wr=new URL("../../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url),rt=fileURLToPath(wr);function vr(){return existsSync(rt)}async function $r(){if(!vr())throw new Error(`WASM engine not built. Run \`pnpm --filter @vibgrate/hcs build\` first.
|
|
41
|
+
Expected: ${rt}`);return await import(rt)}async function Cn(t,e){let o=(await $r()).derive_behavioural_facts_from_lines(JSON.stringify(t),JSON.stringify(e));return Sr(o)}function Sr(t){let e=JSON.parse(t),n=e.filter(r=>r.factType==="BehaviouralAssertion").length,s=e.find(r=>r.factType==="BehaviouralSpec")?.payload,i=s?.coverage;return {envelopes:e,summary:{assertions:n,surfaceFacts:Number(i?.surfaceFacts??0),assertedFacts:Number(i?.assertedFacts??0),behaviouralConfidence:Number(s?.behaviouralConfidence??0)}}}async function In(t){try{return await kr(t)}catch{return {type:"unknown"}}}async function kr(t){let e=await xr(t);if(!e)return {type:"unknown"};let n=S.join(e,"HEAD"),o;try{o=(await J.readFile(n,"utf8")).trim();}catch{return {type:"unknown"}}let s,i;if(o.startsWith("ref: ")){let c=o.slice(5);i=c.startsWith("refs/heads/")?c.slice(11):c,s=await Pr(e,c);}else /^[0-9a-f]{40}$/i.test(o)&&(s=o);let r=await Cr(e);return {type:"git",sha:s??void 0,shortSha:s?s.slice(0,7):void 0,branch:i??void 0,remoteUrl:r}}async function xr(t){let e=S.resolve(t),n=S.parse(e).root;for(;e!==n;){let o=S.join(e,".git");try{let s=await J.stat(o);if(s.isDirectory())return o;if(s.isFile()){let i=(await J.readFile(o,"utf8")).trim();if(i.startsWith("gitdir: "))return S.resolve(e,i.slice(8))}}catch{}e=S.dirname(e);}return null}async function Pr(t,e){let n=S.join(t,e);try{let s=(await J.readFile(n,"utf8")).trim();if(/^[0-9a-f]{40}$/i.test(s))return s}catch{}let o=S.join(t,"packed-refs");try{let s=await J.readFile(o,"utf8");for(let i of s.split(`
|
|
42
|
+
`)){if(i.startsWith("#")||i.startsWith("^"))continue;let r=i.trim().split(" ");if(r.length>=2&&r[1]===e)return r[0]}}catch{}}async function Cr(t){let e=await Ir(t);if(e)try{let o=(await J.readFile(e,"utf8")).match(/\[remote\s+"origin"\]([\s\S]*?)(?=\n\[|$)/);return o?o[1]?.match(/\n\s*url\s*=\s*(.+)\s*/)?.[1]?.trim():void 0}catch{return}}async function Ir(t){let e=S.join(t,"config");try{if((await J.stat(e)).isFile())return e}catch{}let n=S.join(t,"commondir");try{let o=(await J.readFile(n,"utf8")).trim();if(!o)return;let s=S.resolve(t,o),i=S.join(s,"config");if((await J.stat(i)).isFile())return i}catch{return}}var En=/^[A-Za-z0-9._-]+@[A-Za-z0-9._-]+:.+$/;function it(t){return t?!!(/^(https?|ssh|git):\/\//i.test(t)||En.test(t)):false}function Be(t){if(!t||En.test(t)&&!t.includes("://"))return t;try{let e=new URL(t);return (e.username||e.password)&&(e.username="",e.password=""),e.toString()}catch{return t.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1")}}var L=class extends Error{constructor(e){super(e),this.name="CloneError";}};function Dr(){let t=spawnSync("git",["--version"],{stdio:"ignore"});return !t.error&&t.status===0}function Tr(){switch(process.platform){case "darwin":return "Install git with: brew install git (or xcode-select --install).";case "win32":return "Install git with: winget install Git.Git";default:return "Install git via your distro package manager (e.g. apt install git)."}}function st(t,e){return new Promise((n,o)=>{let s=spawn("git",t,{stdio:["ignore","ignore","pipe"],env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_ASKPASS:"echo"}}),i="",r=false,c=setTimeout(()=>{r=true,s.kill("SIGKILL");},e.timeoutMs);s.stderr.on("data",a=>{i.length<8192&&(i+=Nr(String(a)));}),s.on("error",a=>{clearTimeout(c),o(new L(`Failed to run git: ${a.message}`));}),s.on("close",a=>{if(clearTimeout(c),r){o(new L(`git clone timed out for ${e.redacted}`));return}n({code:a??0,stderr:i.trim()});});})}function Nr(t){return t.replace(/([a-z]+:\/\/)[^/\s@]+@/gi,"$1")}async function An(t,e){let n=Be(t);if(!it(t))throw new L(`Not a supported repository URL: ${n}. Use an http(s), ssh, git://, or scp-like (git@host:owner/repo.git) URL.`);if(/^file:\/\//i.test(t))throw new L("file:// URLs are not allowed for remote clone.");if(!Dr())throw new L(`git is required to clone ${n} but was not found on PATH. ${Tr()}`);let o=await mkdtemp(S.join(Lt.tmpdir(),"vibgrate-hcs-clone-")),s=async()=>{await rm(o,{recursive:true,force:true}).catch(()=>{});};try{e.verbose&&process.stderr.write(`Cloning ${n} \u2026
|
|
43
|
+
`);let i=await st(["clone","--depth","1","--quiet","--",t,o],{timeoutMs:e.timeoutMs,redacted:n});if(i.code!==0)throw new L(`git clone failed for ${n}: ${i.stderr||`exit ${i.code}`}`);if(e.ref){e.verbose&&process.stderr.write(`Checking out ${e.ref} \u2026
|
|
44
|
+
`);let c=(await st(["-C",o,"fetch","--depth","1","--quiet","origin",e.ref],{timeoutMs:e.timeoutMs,redacted:n})).code===0?"FETCH_HEAD":e.ref,a=await st(["-C",o,"checkout","--quiet","--detach",c],{timeoutMs:e.timeoutMs,redacted:n});if(a.code!==0)throw new L(`Could not check out ref "${e.ref}" from ${n}: ${a.stderr||`exit ${a.code}`}`)}return {dir:o,cleanup:s}}catch(i){throw await s(),i instanceof L?i:new L(String(i))}}function Or(t){let e=Te.createHash("sha256");for(let n of t)e.update(n),e.update(`
|
|
45
|
+
`);return `sha256:${e.digest("hex")}`}function at(t){if(!t)return;let o=t.replace(/^[a-z]+:\/\//i,"").replace(/^[^/@]+@/,"").replace(/^[^/:]+[/:]/,"").split("/").filter(Boolean);if(o.length===0)return;let s=o[o.length-1].replace(/\.git$/i,""),i=o.length>=2?o[o.length-2]:void 0;return i?`${i}/${s}`:s}function Tn(t){return {factType:"ScanManifest",manifestVersion:"1.0",emittedAt:t.emittedAt??new Date().toISOString(),repository:{remoteUrl:t.remoteUrl,name:t.repositoryName??at(t.remoteUrl)},vcs:{sha:t.sha,shortSha:t.shortSha,branch:t.branch,ref:t.ref},source:t.source,languages:[...t.languages].sort(),scanId:t.scanId,applicationId:t.applicationId,vibgrateVersion:t.vibgrateVersion,factCount:t.factLines.length,contentHash:Or(t.factLines)}}var Nn=0,Lr=1,je=2,Re=3,Br=4,F=5,Ln={typescript:new Set([".ts",".tsx",".mts",".cts"]),javascript:new Set([".js",".jsx",".mjs",".cjs"]),swift:new Set([".swift"]),rust:new Set([".rs"]),ruby:new Set([".rb",".rake",".gemspec"]),php:new Set([".php"]),dart:new Set([".dart"]),scala:new Set([".scala",".sc"]),cobol:new Set([".cbl",".cob",".cpy",".cob85",".cobol"]),vb6:new Set([".vbp",".bas",".cls",".frm",".ctl",".dsr"]),go:new Set([".go"]),python:new Set([".py"]),java:new Set([".java"]),csharp:new Set([".cs"]),cplusplus:new Set([".cpp",".cc",".cxx",".hpp",".hh",".hxx",".h",".ixx",".vcxproj"]),vbnet:new Set([".vb"])},On=new Set(Object.keys(Ln)),Ur=new Set(["node_modules",".git",".vibgrate",".hg",".svn","dist","build","out",".next",".nuxt",".output","bin","obj",".vs","target","vendor",".dart_tool",".build","DerivedData","Pods",".swiftpm","Carthage",".cargo",".pub-cache",".bloop",".metals",".idea","coverage","TestResults","__pycache__",".tox",".mypy_cache"]),Vr=[/[/\\]test[/\\]/i,/[/\\]tests[/\\]/i,/[/\\]__tests__[/\\]/i,/[/\\]spec[/\\]/i,/\.spec\./i,/\.test\./i,/[/\\]test-/i];function Hr(t){return Vr.some(e=>e.test(t))}function Gr(t){let e=t.trim().toLowerCase();return e==="vb.net"||e==="visualbasic"||e==="visual-basic"?"vbnet":e}async function Wr(t,e){let n=new Map;async function o(s,i){let r;try{r=await J.readdir(s,{withFileTypes:!0});}catch{return}for(let c of r){if(c.name.startsWith("."))continue;let a=S.join(s,c.name),p=S.join(i,c.name);if(c.isDirectory()){Ur.has(c.name)||await o(a,p);continue}if(!c.isFile()||!e&&Hr(p))continue;let g=S.extname(c.name).toLowerCase();for(let[f,u]of Object.entries(Ln))if(u.has(g)){n.set(f,(n.get(f)??0)+1);break}}}return await o(t,""),Array.from(n.entries()).map(([s,i])=>({language:s,fileCount:i})).sort((s,i)=>i.fileCount-s.fileCount)}function ct(t){let e;try{e=JSON.parse(t);}catch{return {valid:false,error:`Invalid JSON: ${t.substring(0,80)}...`}}let n=e;return n.factType==="Models"||n.factType==="References"?n.payload===void 0||n.payload===null?{valid:false,error:`Preamble ${n.factType} missing payload`}:{valid:true}:n.factType==="ScanManifest"?typeof n.manifestVersion!="string"?{valid:false,error:"ScanManifest missing manifestVersion"}:typeof n.emittedAt!="string"?{valid:false,error:"ScanManifest missing emittedAt"}:{valid:true}:typeof n.factId!="string"||!n.factId?{valid:false,error:"Missing or invalid factId"}:typeof n.m=="string"?n.payload===void 0||n.payload===null?{valid:false,error:"Compressed fact missing payload"}:{valid:true}:typeof n.factType!="string"||!n.factType?{valid:false,error:"Missing or invalid factType"}:typeof n.language!="string"?{valid:false,error:"Missing or invalid language"}:typeof n.scanner!="string"?{valid:false,error:"Missing or invalid scanner"}:typeof n.scannerVersion!="string"?{valid:false,error:"Missing or invalid scannerVersion"}:typeof n.emittedAt!="string"?{valid:false,error:"Missing or invalid emittedAt"}:n.payload===void 0||n.payload===null?{valid:false,error:"Missing payload"}:{valid:true}}function Jr(t){let e=[],n=[];for(let o of t){let s;try{s=JSON.parse(o);}catch{n.push(o);continue}let i=s;i.factType==="Models"||i.factType==="References"||i.factType==="ScanManifest"?e.push(o):n.push(o);}return {preamble:e,facts:n}}function Xr(){let t=import.meta.dirname??S.dirname(new URL(import.meta.url).pathname),e=S.resolve(t,"..","dist","hcs-worker.js");if(existsSync(e))return e;let n=S.resolve(t,"hcs-worker.js");if(existsSync(n))return n;try{let i=import.meta.resolve("@vibgrate/hcs-node-worker"),r=i.startsWith("file://")?new URL(i).pathname:i;if(existsSync(r))return r}catch{}let o=S.resolve(t,"..","..","..","vibgrate-hcs","node","dist","main.js");if(existsSync(o))return o;let s=S.resolve(t,"..","..","..","vibgrate-hcs","node","src","main.ts");if(existsSync(s))return s;throw new Error('Cannot locate HCS worker. Run "pnpm build" in the CLI package to bundle the worker into dist/.')}var Bn=new Set(["typescript","javascript"]),Kr=new Set(["swift","vb6","rust","ruby","php","dart","scala","cobol","cplusplus"]),Un=new Set([...Bn,...Kr]),zr=new Set(["go","python","java","csharp","vbnet"]),_n=new Set([...Un,...zr]),Vn={go:{command:"go",displayName:"Go toolchain",installGuideByPlatform:{darwin:"brew install go",linux:"Install Go 1.22+ from https://go.dev/dl/ or your distro package manager.",win32:"winget install GoLang.Go"},docsUrl:"https://go.dev/doc/install"},python:{command:"python3",displayName:"Python 3 runtime",installGuideByPlatform:{darwin:"brew install python",linux:"Install Python 3.10+ from your distro package manager (apt/dnf/pacman).",win32:"winget install Python.Python.3.12"},docsUrl:"https://www.python.org/downloads/"},java:{command:"java",displayName:"Java 17+ runtime",installGuideByPlatform:{darwin:"brew install --cask temurin",linux:"Install OpenJDK 17+ (for example: apt install openjdk-17-jre).",win32:"winget install EclipseAdoptium.Temurin.17.JRE"},docsUrl:"https://adoptium.net/"},csharp:{command:"dotnet",displayName:".NET SDK/runtime",installGuideByPlatform:{darwin:"brew install --cask dotnet-sdk",linux:"Install .NET 8 SDK/runtime from https://dotnet.microsoft.com/download.",win32:"winget install Microsoft.DotNet.SDK.8"},docsUrl:"https://dotnet.microsoft.com/download"},vbnet:{command:"dotnet",displayName:".NET SDK/runtime",installGuideByPlatform:{darwin:"brew install --cask dotnet-sdk",linux:"Install .NET 8 SDK/runtime from https://dotnet.microsoft.com/download.",win32:"winget install Microsoft.DotNet.SDK.8"},docsUrl:"https://dotnet.microsoft.com/download"}};function qr(t){let e=process.platform==="win32"?["/c",t,"--version"]:["--version"],n=process.platform==="win32"?"cmd":t,o=spawnSync(n,e,{stdio:"ignore"});return !o.error&&o.status===0}function lt(t){let e=Vn[t];return e?`${e.installGuideByPlatform[process.platform]??`Install ${e.displayName} and ensure '${e.command}' is available on PATH.`} More details: ${e.docsUrl}`:"See HCS runtime setup docs for prerequisites: https://vibgrate.com/help"}async function Yr(t,e,n){let o=Xr(),s=[];if(Bn.has(e))s.push("--project",t);else {s.push("--project",t);let i=`--${e}-project`;s.push(i,t),e==="cobol"&&n.copybookPaths&&s.push("--cobol-copybook-paths",n.copybookPaths);}return new Promise(i=>{let r=[],c=[],a="",p=false,g=spawn("node",["--enable-source-maps",o,...s],{cwd:t,stdio:["ignore","pipe","pipe"],env:{...process.env,NODE_OPTIONS:"--max-old-space-size=4096"}}),f=setTimeout(()=>{p=true,g.kill("SIGKILL");},n.timeoutMs);g.stdout.on("data",u=>{a+=u.toString();let h=a.split(`
|
|
46
|
+
`);a=h.pop();for(let v of h){let m=v.trim();m&&r.push(m);}}),g.stderr.on("data",u=>{let h=u.toString();for(let v of h.split(`
|
|
47
47
|
`)){let m=v.trim();if(m){if(m.startsWith("[progress] ")){try{let $=JSON.parse(m.slice(11));n.onProgress?.($);}catch{}continue}n.verbose&&process.stderr.write(l.dim(`[${e}] ${m}
|
|
48
|
-
`)),m.startsWith("[error]")&&
|
|
49
|
-
`));let p=
|
|
50
|
-
`);
|
|
48
|
+
`)),m.startsWith("[error]")&&c.push(m);}}}),g.on("close",u=>{clearTimeout(f),a.trim()&&r.push(a.trim()),i(p?{language:e,facts:r,errors:["Worker killed: timeout exceeded"],exitCode:Re}:{language:e,facts:r,errors:c,exitCode:u??0});}),g.on("error",u=>{clearTimeout(f),c.push(`Failed to spawn worker: ${u.message}`),i({language:e,facts:r,errors:c,exitCode:je});});})}function Qr(t){let n={win32:["hcs-worker-win-x64.exe"],linux:["hcs-worker-linux-x64"],darwin:["hcs-worker-osx-arm64","hcs-worker-osx-x64"],aix:[],android:[],freebsd:[],haiku:[],openbsd:[],cygwin:[],netbsd:[],sunos:[]}[process.platform]??[];for(let o of n){let s=S.join(t,o);if(existsSync(s))return s}return null}function Zr(t,e){let n=import.meta.dirname??S.dirname(new URL(import.meta.url).pathname),o=S.resolve(n,"..","..","vibgrate-hcs"),s=S.resolve(n,"..","..","..","vibgrate-hcs"),i=existsSync(o)?o:s,r=S.resolve(n,"workers");switch(t){case "go":{let c=S.join(r,process.platform==="win32"?"vibgrate-hcs-go.exe":"vibgrate-hcs-go");if(existsSync(c))return {cmd:c,args:["--project",e,"--output","ndjson"]};let a=S.join(i,"go");return existsSync(S.join(a,"main.go"))?{cmd:"go",args:["run",".","--project",e,"--output","ndjson"],cwd:a}:null}case "python":{let c=S.join(r,"vibgrate-hcs-python");if(existsSync(c))return {cmd:c,args:["--project",e,"--output","ndjson"]};let a=S.join(i,"python");return existsSync(S.join(a,"pyproject.toml"))?{cmd:"python3",args:["-m","vibgrate_hcs_python.main","--project",e,"--output","ndjson"],cwd:a}:null}case "java":{let c=S.join(r,"vibgrate-hcs-jvm.jar");if(existsSync(c))return {cmd:"java",args:["-jar",c,"--project",e,"--output","ndjson"]};let a=S.join(i,"jvm");if(existsSync(S.join(a,"build.gradle.kts"))){let p=S.join(a,process.platform==="win32"?"gradlew.bat":"gradlew");return {cmd:existsSync(p)?p:"gradle",args:["-q","--console=plain","run",`--args=--project ${e} --output ndjson`],cwd:a}}return null}case "csharp":case "vbnet":{let c=Qr(r);if(c)return {cmd:c,args:["--project",e,"--output","ndjson"]};let a=S.join(r,"VibgrateHcsWorker.dll");if(existsSync(a))return {cmd:"dotnet",args:[a,"--project",e,"--output","ndjson"]};let p=S.join(i,"dotnet","src","VibgrateHcsWorker","VibgrateHcsWorker.csproj");return existsSync(p)?{cmd:"dotnet",args:["run","--project",p,"--","--project",e,"--output","ndjson"]}:null}default:return null}}async function es(t,e,n){let o=Zr(e,t);return o?new Promise(s=>{let i=[],r=[],c="",a=false;n.verbose&&process.stderr.write(l.dim(`[${e}] Spawning: ${o.cmd} ${o.args.join(" ")}
|
|
49
|
+
`));let p=Vn[e];if(p&&o.cmd===p.command&&!qr(o.cmd)){s({language:e,facts:[],errors:[`[error] Required runtime command '${o.cmd}' is not available on PATH.`,`[hint] ${lt(e)}`,"[hint] You can also package native workers into dist/workers to avoid local toolchain requirements."],exitCode:je});return}let f=spawn(o.cmd,o.args,{cwd:o.cwd??t,stdio:["ignore","pipe","pipe"]}),u=setTimeout(()=>{a=true,f.kill("SIGKILL");},n.timeoutMs);f.stdout.on("data",h=>{c+=h.toString();let v=c.split(`
|
|
50
|
+
`);c=v.pop();for(let m of v){let $=m.trim();$&&i.push($);}}),f.stderr.on("data",h=>{let v=h.toString();for(let m of v.split(`
|
|
51
51
|
`)){let $=m.trim();$&&(n.verbose&&process.stderr.write(l.dim(`[${e}] ${$}
|
|
52
|
-
`)),$.startsWith("[error]")&&
|
|
52
|
+
`)),$.startsWith("[error]")&&r.push($));}}),f.on("close",h=>{clearTimeout(u),c.trim()&&i.push(c.trim()),s(a?{language:e,facts:i,errors:["Worker killed: timeout exceeded"],exitCode:Re}:{language:e,facts:i,errors:r,exitCode:h??0});}),f.on("error",h=>{clearTimeout(u);let v=h.code==="ENOENT";r.push(v?`[error] '${o.cmd}' not found. ${lt(e)}`:`[error] Failed to spawn native worker: ${h.message}`),s({language:e,facts:i,errors:r,exitCode:je});});}):{language:e,facts:[],errors:[`[error] No native worker found for '${e}'. Build/package workers for this platform or use source mode.`,`[hint] ${lt(e)}`],exitCode:je}}async function ts(t,e,n){let o=_e(e);if(!o)return process.stderr.write(l.red(`Invalid DSN format.
|
|
53
53
|
`)),process.stderr.write(l.dim(`Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>
|
|
54
|
-
`)),false;let
|
|
54
|
+
`)),false;let s=t.join(`
|
|
55
55
|
`)+`
|
|
56
|
-
`,
|
|
57
|
-
`));try{let
|
|
56
|
+
`,i=`${o.scheme}://${o.host}/v1/ingest/hcs`;n&&process.stderr.write(l.dim(`Pushing ${t.length} facts to ${o.host}...
|
|
57
|
+
`));try{let r=ln(s,o.secret),c=await fetch(i,{method:"POST",headers:{"Content-Type":"application/x-ndjson","X-Vibgrate-Key":o.keyId,"X-Vibgrate-Workspace":o.workspaceId,"X-Vibgrate-Signature":r,Connection:"close"},body:s});if(!c.ok){let a=await c.text().catch(()=>"");return process.stderr.write(l.red(`Push failed: HTTP ${c.status} ${a}
|
|
58
58
|
`)),!1}return n&&process.stderr.write(l.green(`\u2714 Pushed ${t.length} facts successfully
|
|
59
|
-
`)),!0}catch(
|
|
60
|
-
`)),false}}async function
|
|
61
|
-
`).filter(o=>o.trim());for(let o of n)try{JSON.parse(o);}catch{throw new Error(`Invalid NDJSON in feedback file at: ${o.substring(0,60)}...`)}return n}var
|
|
62
|
-
`)),process.exit(F)),
|
|
63
|
-
`)):process.once("exit",()=>{try{rmSync(P.dir,{recursive:!0,force:!0});}catch{}});}catch(P){let q=P instanceof
|
|
64
|
-
`)),process.exit(F);}}else {
|
|
65
|
-
`)),process.exit(F));let y;try{y=await J.stat(
|
|
66
|
-
`)),process.exit(F);}y.isDirectory()||(process.stderr.write(l.red(`Path must be a directory: ${
|
|
67
|
-
`)),process.exit(F));}let
|
|
68
|
-
`)),process.exit(F)),
|
|
59
|
+
`)),!0}catch(r){return process.stderr.write(l.red(`Push failed: ${r instanceof Error?r.message:String(r)}
|
|
60
|
+
`)),false}}async function ns(t){let n=(await J.readFile(t,"utf-8")).split(`
|
|
61
|
+
`).filter(o=>o.trim());for(let o of n)try{JSON.parse(o);}catch{throw new Error(`Invalid NDJSON in feedback file at: ${o.substring(0,60)}...`)}return n}var dt=class{constructor(e){this.languages=e;this.isTTY=process.stderr.isTTY??false;for(let n of e)this.langStatus.set(n,{phase:"waiting",fileIndex:0,fileCount:0,done:false,factCount:0});}isTTY;langStatus=new Map;totalFacts=0;lastRender=0;throttleMs=80;lastLineLen=0;onProgress(e,n){let o=this.langStatus.get(e);o&&(o.phase=n.phase,n.fileCount!==void 0&&(o.fileCount=n.fileCount),n.fileIndex!==void 0&&(o.fileIndex=n.fileIndex),n.file&&(o.file=n.file),n.phase==="done"&&(o.done=true),this.render());}onFact(){this.totalFacts++,this.render();}setLanguageFactCount(e,n){let o=this.langStatus.get(e);o&&(o.factCount=n);}render(){let e=Date.now();if(e-this.lastRender<this.throttleMs||(this.lastRender=e,!this.isTTY))return;let n=[];for(let[i,r]of this.langStatus)if(r.done)n.push(l.green(`${i} \u2713`));else if(r.phase==="waiting")n.push(l.dim(`${i} \xB7`));else if(r.phase==="discovering")n.push(l.yellow(`${i} \u2026`));else if(r.phase==="scanning"&&r.fileCount>0){let c=Math.round(r.fileIndex/r.fileCount*100);n.push(l.cyan(`${i} ${r.fileIndex}/${r.fileCount} ${c}%`));}else r.phase==="extracting"?n.push(l.cyan(`${i} extracting`)):n.push(l.dim(`${i} ${r.phase}`));let o=` ${n.join(" ")} ${l.dim(`${this.totalFacts} facts`)}`,s=Math.max(0,this.lastLineLen-o.length);process.stderr.write(`\r${o}${" ".repeat(s)}`),this.lastLineLen=o.length;}finish(e){this.isTTY&&process.stderr.write(`\r${" ".repeat(this.lastLineLen)}\r`);}},Hn=new Command("extract").description("Analyze source code and emit validated HCS facts (NDJSON)").argument("[path-or-url]","Path to source directory, or a public repository URL to clone",".").option("--repo-url <url>","Public repository URL to clone and analyze (alternative to passing a URL positionally)").option("--ref <ref>","Branch, tag, or commit SHA to check out when cloning a repository URL").option("--keep-clone","Do not delete the temporary clone after extraction (prints its path)").option("--clone-timeout-mins <mins>","Clone/fetch timeout in minutes","10").option("-o, --out <file>","Write NDJSON to file (default: stdout)").option("--language <langs>","Comma-separated languages to analyze (default: auto-detect)").option("--include-tests","Include test files in analysis").option("--push","Stream validated facts to dashboard API").option("--dsn <dsn>","DSN token for push (or use VIBGRATE_DSN env)").option("--concurrency <n>","Number of parallel file workers").option("--timeout-mins <mins>","Total analysis timeout in minutes","60").option("--feedback <file>","Load NDJSON diff artifact for refinement").option("--derive","Derive behavioural spec facts (BehaviouralAssertion/BehaviouralSpec) from extracted facts").option("--scan-id <id>",'Scan id for the derived BehaviouralSpec (default: "local")').option("--application-id <id>","Application id for the derived BehaviouralSpec (default: directory name)").option("--verbose","Print worker stderr and summary statistics").action(async(t,e)=>{let n=e.repoUrl??(it(t)?t:void 0),o=n?"url":"local",s,i;if(n){let y=parseInt(e.cloneTimeoutMins,10);(isNaN(y)||y<1)&&(process.stderr.write(l.red(`--clone-timeout-mins must be >= 1
|
|
62
|
+
`)),process.exit(F)),i=Be(n);try{let P=await An(n,{ref:e.ref,timeoutMs:y*60*1e3,verbose:e.verbose??!1});s=P.dir,e.keepClone?process.stderr.write(l.dim(`Clone retained at: ${P.dir}
|
|
63
|
+
`)):process.once("exit",()=>{try{rmSync(P.dir,{recursive:!0,force:!0});}catch{}});}catch(P){let q=P instanceof L||P instanceof Error?P.message:String(P);process.stderr.write(l.red(`Clone failed: ${q}
|
|
64
|
+
`)),process.exit(F);}}else {s=S.resolve(t),await c(s)||(process.stderr.write(l.red(`Path does not exist: ${s}
|
|
65
|
+
`)),process.exit(F));let y;try{y=await J.stat(s);}catch{process.stderr.write(l.red(`Cannot read path: ${s}
|
|
66
|
+
`)),process.exit(F);}y.isDirectory()||(process.stderr.write(l.red(`Path must be a directory: ${s}
|
|
67
|
+
`)),process.exit(F));}let r=e.dsn||process.env.VIBGRATE_DSN;e.push&&!r&&(process.stderr.write(l.red(`--push requires --dsn or VIBGRATE_DSN environment variable
|
|
68
|
+
`)),process.exit(F)),r&&!_e(r)&&(process.stderr.write(l.red(`Invalid DSN format.
|
|
69
69
|
`)),process.stderr.write(l.dim(`Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>
|
|
70
|
-
`)),process.exit(F));let
|
|
71
|
-
`)),process.exit(F));let
|
|
72
|
-
`)),process.exit(F));let p=
|
|
70
|
+
`)),process.exit(F));let c$1=e.concurrency?parseInt(e.concurrency,10):Lt.cpus().length;(isNaN(c$1)||c$1<1)&&(process.stderr.write(l.red(`--concurrency must be >= 1
|
|
71
|
+
`)),process.exit(F));let a=parseInt(e.timeoutMins,10);(isNaN(a)||a<1)&&(process.stderr.write(l.red(`--timeout-mins must be >= 1
|
|
72
|
+
`)),process.exit(F));let p=a*60*1e3;if(e.out){let y=S.dirname(S.resolve(e.out));await c(y)||(process.stderr.write(l.red(`Output directory does not exist: ${y}
|
|
73
73
|
`)),process.exit(F));try{(await J.stat(S.resolve(e.out))).isDirectory()&&(process.stderr.write(l.red(`--out cannot be a directory: ${e.out}
|
|
74
74
|
`)),process.exit(F));}catch{}}let g;if(e.feedback){let y=S.resolve(e.feedback);await c(y)||(process.stderr.write(l.red(`Feedback file not found: ${y}
|
|
75
|
-
`)),process.exit(F));try{g=await
|
|
76
|
-
`)),process.exit(F);}}let f;if(e.language){f=e.language.split(",").map(y=>
|
|
77
|
-
`)),process.stderr.write(l.dim(`Supported: ${[...
|
|
78
|
-
`)),process.exit(F));}else {let y=await
|
|
79
|
-
`)),process.exit(
|
|
75
|
+
`)),process.exit(F));try{g=await ns(y);}catch(P){process.stderr.write(l.red(`Invalid feedback file: ${P instanceof Error?P.message:String(P)}
|
|
76
|
+
`)),process.exit(F);}}let f;if(e.language){f=e.language.split(",").map(y=>Gr(y)).filter(Boolean);for(let y of f)On.has(y)||(process.stderr.write(l.red(`Unknown language: "${y}"
|
|
77
|
+
`)),process.stderr.write(l.dim(`Supported: ${[...On].sort().join(", ")}
|
|
78
|
+
`)),process.exit(F));}else {let y=await Wr(s,e.includeTests??false);if(y.length===0&&(process.stderr.write(l.yellow(`No supported source files detected.
|
|
79
|
+
`)),process.exit(Nn)),f=y.map(P=>P.language),e.verbose){process.stderr.write(l.dim(`Detected languages:
|
|
80
80
|
`));for(let P of y)process.stderr.write(l.dim(` ${P.language}: ${P.fileCount} files
|
|
81
|
-
`));}}let u=f.filter(y=>
|
|
81
|
+
`));}}let u=f.filter(y=>_n.has(y)),h=f.filter(y=>!_n.has(y));h.length>0&&e.verbose&&process.stderr.write(l.dim(`No worker registered for: ${h.join(", ")} \u2014 skipping.
|
|
82
82
|
`)),u.length===0&&(process.stderr.write(l.yellow(`No languages with available HCS workers found.
|
|
83
|
-
`)),process.exit(
|
|
84
|
-
`)+l.dim(`Languages: ${u.join(", ")} Concurrency: ${
|
|
85
|
-
`));let $=new
|
|
86
|
-
`)));}for(let Y of
|
|
87
|
-
`));}
|
|
88
|
-
`)+(
|
|
89
|
-
`:"");if(e.out){let y=S.resolve(e.out);await J.writeFile(y,
|
|
90
|
-
`));}else process.stdout.write(
|
|
83
|
+
`)),process.exit(Nn));let v=Date.now(),m=v+p;process.stderr.write(l.bold(`Extracting HCS facts from ${s}
|
|
84
|
+
`)+l.dim(`Languages: ${u.join(", ")} Concurrency: ${c$1} Timeout: ${a}m
|
|
85
|
+
`));let $=new dt(u),O=new a$1(c$1),de=[],_=[],U=[],ie=[],pe=false,Ae=false,ve=false,Ke=u.map(y=>O.run(async()=>{let P=m-Date.now();if(P<=0){ve=true;return}let q=Un.has(y)?await Yr(s,y,{includeTests:e.includeTests??false,verbose:e.verbose??false,timeoutMs:P,onProgress:Y=>$.onProgress(y,Y)}):await es(s,y,{verbose:e.verbose??false,timeoutMs:P});q.exitCode===Re&&(ve=true);let{preamble:ne,facts:$e}=Jr(q.facts);de.push(...ne),e.derive&&ie.push(...ne,...$e);let Se=0;for(let Y of [...ne,...$e]){let ze=ct(Y);ze.valid||(pe=true,U.push(`[${y}] Schema validation: ${ze.error}`),e.verbose&&process.stderr.write(l.red(`[${y}] Invalid fact: ${ze.error}
|
|
86
|
+
`)));}for(let Y of $e)ct(Y).valid&&(_.push(Y),Se++,$.onFact());$.setLanguageFactCount(y,Se),q.errors.length>0&&U.push(...q.errors.map(Y=>`[${y}] ${Y}`)),q.exitCode!==0&&q.exitCode!==Re&&(Ae=true);}));await Promise.all(Ke);let De=((Date.now()-v)/1e3).toFixed(1);if($.finish(De),e.derive){let y=e.scanId||"local",P=e.applicationId||S.basename(s),{envelopes:q,summary:ne}=await Cn(ie,{scanId:y,applicationId:P});for(let $e of q){let Se=JSON.stringify($e);ct(Se).valid?_.push(Se):(pe=true,U.push("[behavioural] derived fact failed schema validation"));}process.stderr.write(l.dim(`Derived ${ne.assertions} behavioural assertion(s) \xB7 confidence ${ne.behaviouralConfidence} (${ne.assertedFacts}/${ne.surfaceFacts} surface facts)
|
|
87
|
+
`));}_.sort();let b=e.scanId||"local",C=e.applicationId||(o==="url"?at(i):void 0)||S.basename(s),I;try{I=await In(s);}catch{I=void 0;}let k=Tn({remoteUrl:i??(I?.remoteUrl?Be(I.remoteUrl):void 0),sha:I?.sha,shortSha:I?.shortSha,branch:I?.branch,ref:e.ref,source:o,languages:u,scanId:b,applicationId:C,vibgrateVersion:R,factLines:_}),K=[JSON.stringify(k),...de,..._],z=K.join(`
|
|
88
|
+
`)+(K.length>0?`
|
|
89
|
+
`:"");if(e.out){let y=S.resolve(e.out);await J.writeFile(y,z,"utf-8"),process.stderr.write(l.green(`\u2714 Wrote ${_.length} facts to ${y}
|
|
90
|
+
`));}else process.stdout.write(z);if(e.push&&r&&_.length>0&&(await ts(K,r,e.verbose??false)||process.exit(Br)),e.verbose){if(process.stderr.write(l.dim(`
|
|
91
91
|
\u2500\u2500 Summary \u2500\u2500
|
|
92
|
-
`)),process.stderr.write(l.dim(` Facts emitted : ${
|
|
92
|
+
`)),process.stderr.write(l.dim(` Facts emitted : ${_.length}
|
|
93
93
|
`)),process.stderr.write(l.dim(` Languages : ${u.join(", ")}
|
|
94
|
-
`)),process.stderr.write(l.dim(` Elapsed : ${
|
|
94
|
+
`)),process.stderr.write(l.dim(` Elapsed : ${De}s
|
|
95
95
|
`)),U.length>0){process.stderr.write(l.dim(` Errors : ${U.length}
|
|
96
96
|
`));for(let y of U.slice(0,10))process.stderr.write(l.dim(` ${y}
|
|
97
97
|
`));U.length>10&&process.stderr.write(l.dim(` ... and ${U.length-10} more
|
|
98
98
|
`));}process.stderr.write(l.dim(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
99
99
|
|
|
100
|
-
`));}
|
|
101
|
-
`)),process.exit(
|
|
102
|
-
`)),process.exit(
|
|
103
|
-
`)),process.exit(
|
|
104
|
-
`)),process.exit(
|
|
105
|
-
`)),process.exit(
|
|
100
|
+
`));}ve&&(process.stderr.write(l.red(`Timeout exceeded (${a} minutes)
|
|
101
|
+
`)),process.exit(Re)),pe&&(process.stderr.write(l.red(`Fact schema validation failures detected
|
|
102
|
+
`)),process.exit(Lr)),Ae&&(process.stderr.write(l.red(`Parsing failures detected
|
|
103
|
+
`)),process.exit(je));});var ss=0,Ue=5,is=new URL("../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url),Gn=fileURLToPath(is);async function as(){return existsSync(Gn)?await import(Gn):null}var Wn=new Command("digest").description('Render HCS NDJSON facts (from "hcs extract") into Markdown, JSON, or HTML').option("--in <file>","HCS NDJSON file to read (default: stdin)").option("-o, --out <file>","Write output to file (default: stdout)").option("--format <format>","Output format: md | json | html","md").option("--level <level>","Detail level: concise | full","concise").option("--title <title>","Override document title").action(async t=>{let e=["md","json","html"];e.includes(t.format)||(process.stderr.write(l.red(`--format must be one of: ${e.join(", ")}
|
|
104
|
+
`)),process.exit(Ue));let n=["concise","full"];n.includes(t.level)||(process.stderr.write(l.red(`--level must be one of: ${n.join(", ")}
|
|
105
|
+
`)),process.exit(Ue));let o=await as();o||(process.stderr.write(`vibgrate hcs digest requires the HCS WASM engine.
|
|
106
106
|
Run: cd packages/vibgrate-hcs/wasm && ./build.sh
|
|
107
|
-
`),process.exit(1));let
|
|
108
|
-
`)),process.exit(
|
|
109
|
-
`)),process.exit(1);}if(t.out){let
|
|
110
|
-
`)),process.exit(
|
|
111
|
-
`));}else process.stdout.write(
|
|
112
|
-
`)),process.exit(
|
|
113
|
-
`)),process.exit(
|
|
114
|
-
`)),process.exit(
|
|
107
|
+
`),process.exit(1));let s;if(t.in){let c=S.resolve(t.in);existsSync(c)||(process.stderr.write(l.red(`Input file not found: ${c}
|
|
108
|
+
`)),process.exit(Ue)),s=await J.readFile(c,"utf-8");}else {let c=[];for await(let a of process.stdin)c.push(Buffer.isBuffer(a)?a:Buffer.from(a));s=Buffer.concat(c).toString("utf-8");}let i={format:t.format,level:t.level};t.title&&(i.title=t.title);let r;try{r=o.hcs_render_digest(s,JSON.stringify(i));}catch(c){process.stderr.write(l.red(`Digest rendering failed: ${c instanceof Error?c.message:String(c)}
|
|
109
|
+
`)),process.exit(1);}if(t.out){let c=S.resolve(t.out),a=S.dirname(c);existsSync(a)||(process.stderr.write(l.red(`Output directory does not exist: ${a}
|
|
110
|
+
`)),process.exit(Ue)),await J.writeFile(c,r,"utf-8"),process.stderr.write(l.green(`Wrote digest to ${c}
|
|
111
|
+
`));}else process.stdout.write(r);process.exit(ss);});var ds=0,He=5,Jn=fileURLToPath(new URL("../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url));async function ps(){return existsSync(Jn)?await import(Jn):null}async function us(t){if(t){let n=S.resolve(t);return existsSync(n)||(process.stderr.write(l.red(`Input file not found: ${n}
|
|
112
|
+
`)),process.exit(He)),J.readFile(n,"utf-8")}let e=[];for await(let n of process.stdin)e.push(Buffer.isBuffer(n)?n:Buffer.from(n));return Buffer.concat(e).toString("utf-8")}var ut=["json","md","mermaid"],gt=["integration","migration","governance"],Xn=new Command("map").description("Build the System Map (hcs-map/1.0) from HCS facts \u2014 routes, entities, auth, integrations, call-graph").option("--facts <file>","HCS NDJSON facts file to read (default: stdin)").option("-o, --out <file>","Write output to file (default: stdout)").option("--format <format>",`Output format: ${ut.join(" | ")}`,"json").option("--profile <profile>",`Consumer projection: ${gt.join(" | ")}`).option("--generated-at <iso>","Override generatedAt timestamp (for deterministic output)").action(async t=>{ut.includes(t.format)||(process.stderr.write(l.red(`--format must be one of: ${ut.join(", ")}
|
|
113
|
+
`)),process.exit(He)),t.profile&&!gt.includes(t.profile)&&(process.stderr.write(l.red(`--profile must be one of: ${gt.join(", ")}
|
|
114
|
+
`)),process.exit(He));let e=await ps();e||(process.stderr.write(`vibgrate hcs map requires the HCS WASM engine.
|
|
115
115
|
Run: cd packages/vibgrate-hcs/wasm && ./build.sh
|
|
116
|
-
`),process.exit(1));let n=await
|
|
116
|
+
`),process.exit(1));let n=await us(t.facts),o={format:t.format,profile:t.profile,generatedAt:t.generatedAt??new Date().toISOString()},s;try{s=e.hcs_build_map(n,JSON.stringify(o));}catch(i){process.stderr.write(l.red(`Map build failed: ${i instanceof Error?i.message:String(i)}
|
|
117
|
+
`)),process.exit(1);}if(t.out){let i=S.resolve(t.out);existsSync(S.dirname(i))||(process.stderr.write(l.red(`Output directory does not exist: ${S.dirname(i)}
|
|
118
|
+
`)),process.exit(He)),await J.writeFile(i,s+`
|
|
119
|
+
`,"utf-8"),process.stderr.write(l.green(`Wrote System Map to ${i}
|
|
120
|
+
`));}else process.stdout.write(s+`
|
|
121
|
+
`);process.exit(ds);});var ms=0,hs=2,We=5,Kn=fileURLToPath(new URL("../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url));async function bs(){return existsSync(Kn)?await import(Kn):null}async function ys(){let t=[];for await(let e of process.stdin)t.push(Buffer.isBuffer(e)?e:Buffer.from(e));return Buffer.concat(t).toString("utf-8")}async function mt(t,e){let n=S.resolve(t);return existsSync(n)||(process.stderr.write(l.red(`${e} file not found: ${n}
|
|
122
|
+
`)),process.exit(We)),J.readFile(n,"utf-8")}var ht=["text","json","sarif"],zn=new Command("gate").description("Continuous governance gate \u2014 diff two HCS fact streams and fail on material structural regressions").requiredOption("--baseline <file>",'Baseline HCS NDJSON facts file (the "before" stream)').option("--facts <file>",'Current HCS NDJSON facts file (the "after" stream; default: stdin)').option("--policy <file>","Gate policy JSON (.vibgrate/hcs-policy.json) \u2014 thresholds and disabled rules").option("-o, --out <file>","Write output to file (default: stdout)").option("--format <format>",`Output format: ${ht.join(" | ")}`,"text").action(async t=>{ht.includes(t.format)||(process.stderr.write(l.red(`--format must be one of: ${ht.join(", ")}
|
|
123
|
+
`)),process.exit(We));let e=await bs();e||(process.stderr.write(`vibgrate hcs gate requires the HCS WASM engine.
|
|
124
|
+
Run: cd packages/vibgrate-hcs/wasm && ./build.sh
|
|
125
|
+
`),process.exit(1));let n=await mt(t.baseline,"Baseline"),o=t.facts?await mt(t.facts,"Facts"):await ys(),s;if(t.policy){let c=await mt(t.policy,"Policy");try{s=JSON.parse(c);}catch(a){process.stderr.write(l.red(`Invalid policy JSON: ${a instanceof Error?a.message:String(a)}
|
|
126
|
+
`)),process.exit(We);}}let i,r;try{let c=e.hcs_evaluate_gate(n,o,JSON.stringify({format:"json",policy:s}));i=JSON.parse(c).pass,r=t.format==="json"?c:e.hcs_evaluate_gate(n,o,JSON.stringify({format:t.format,policy:s}));}catch(c){process.stderr.write(l.red(`Gate evaluation failed: ${c instanceof Error?c.message:String(c)}
|
|
117
127
|
`)),process.exit(1);}if(t.out){let c=S.resolve(t.out);existsSync(S.dirname(c))||(process.stderr.write(l.red(`Output directory does not exist: ${S.dirname(c)}
|
|
118
|
-
`)),process.exit(
|
|
119
|
-
`,"utf-8"),process.stderr.write(l.green(`
|
|
128
|
+
`)),process.exit(We)),await J.writeFile(c,r+`
|
|
129
|
+
`,"utf-8"),process.stderr.write((i?l.green:l.red)(`Gate ${i?"passed":"FAILED"} \u2014 wrote result to ${c}
|
|
120
130
|
`));}else process.stdout.write(r+`
|
|
121
|
-
`);process.exit(
|
|
122
|
-
`))
|
|
123
|
-
`)),process.exit(
|
|
124
|
-
|
|
125
|
-
`)
|
|
126
|
-
`))
|
|
127
|
-
`))
|
|
128
|
-
`))
|
|
129
|
-
|
|
130
|
-
`));}else process.stdout.write(s+`
|
|
131
|
-
`);process.exit(c?as:cs);});var Xn=new Command("hcs").description("Holistic Code Specification \u2014 extract and render code facts").addCommand(Ln).addCommand(Vn).addCommand(Gn).addCommand(Jn);var bt=2;var zn=5,gs=new Set(["ndjson","json","patch"]),Kn=new Set([".git",".hg",".svn","node_modules",".vibgrate"]);async function qn(t,e,n){let o=[];async function r(c,s){let a;try{a=await J.readdir(c,{withFileTypes:!0});}catch{return}for(let i of a){if(i.name.startsWith(".")&&Kn.has(i.name))continue;let p=S.join(c,i.name),g=S.join(s,i.name);if(i.isDirectory()){Kn.has(i.name)||await r(p,g);continue}i.isFile()&&(e&&e.length>0&&!Yn(g,e)||n&&n.length>0&&Yn(g,n)||o.push({relPath:g,absPath:p}));}}return await r(t,""),o}function Yn(t,e){for(let n of e)if(fs(t,n))return true;return false}function fs(t,e){let n=e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(n,"i").test(t)}function Qn(t,e,n,o){let r=o?t.map(g=>g.trim()):t,c=o?e.map(g=>g.trim()):e,s=ms(r,c),a=0,i=0;for(let g of s)g.type==="insert"&&a++,g.type==="delete"&&i++;return {hunks:hs(t,e,s,n),insertions:a,deletions:i}}function ms(t,e){let n=t.length,o=e.length;if(n===0&&o===0)return [];if(n===0)return e.map((i,p)=>({type:"insert",aIndex:0,bIndex:p}));if(o===0)return t.map((i,p)=>({type:"delete",aIndex:p,bIndex:0}));let r=Array.from({length:n+1},()=>new Array(o+1).fill(0));for(let i=1;i<=n;i++)for(let p=1;p<=o;p++)t[i-1]===e[p-1]?r[i][p]=r[i-1][p-1]+1:r[i][p]=Math.max(r[i-1][p],r[i][p-1]);let c=[],s=n,a=o;for(;s>0||a>0;)s>0&&a>0&&t[s-1]===e[a-1]?(c.unshift({type:"equal",aIndex:s-1,bIndex:a-1}),s--,a--):a>0&&(s===0||r[s][a-1]>=r[s-1][a])?(c.unshift({type:"insert",aIndex:s,bIndex:a-1}),a--):(c.unshift({type:"delete",aIndex:s-1,bIndex:a}),s--);return c}function hs(t,e,n,o){let r=[],c=null,s=-1;for(let a=0;a<n.length;a++){let i=n[a];if(i.type==="equal"){if(c&&a-s>o*2){for(let p=s+1;p<=Math.min(s+o,a);p++){let g=n[p];g&&g.type==="equal"&&(c.lines.push(` ${t[g.aIndex]??""}`),c.originalCount++,c.generatedCount++);}r.push(c),c=null;}continue}if(!c){let p=Math.max(0,a-o),g=n[p]?.aIndex??0,f=n[p]?.bIndex??0;c={originalStart:g+1,originalCount:0,generatedStart:f+1,generatedCount:0,lines:[]};for(let u=p;u<a;u++){let h=n[u];h&&h.type==="equal"&&(c.lines.push(` ${t[h.aIndex]??""}`),c.originalCount++,c.generatedCount++);}}i.type==="delete"?(c.lines.push(`-${t[i.aIndex]??""}`),c.originalCount++):i.type==="insert"&&(c.lines.push(`+${e[i.bIndex]??""}`),c.generatedCount++),s=a;}if(c){for(let a=s+1;a<Math.min(n.length,s+1+o);a++){let i=n[a];i&&i.type==="equal"&&(c.lines.push(` ${t[i.aIndex]??""}`),c.originalCount++,c.generatedCount++);}r.push(c);}return r}function bs(t,e){if(t===e||t.length===0&&e.length===0)return 1;if(t.length===0||e.length===0)return 0;let n=t.split(`
|
|
131
|
+
`);process.exit(i?ms:hs);});var $s=new URL("../../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url),yt=fileURLToPath($s);function wt(){return existsSync(yt)}async function Ss(){if(!wt())throw new Error(`WASM engine not built. Run \`pnpm --filter @vibgrate/hcs build\` first.
|
|
132
|
+
Expected: ${yt}`);return await import(yt)}var qn={SCHEMA_INVALID:1};async function Yn(t){let e=await Ss();return JSON.parse(e.validate_lines_json(JSON.stringify(t)))}var eo=new Command("validate").description("Validate an HCS model (NDJSON) against the v0.5 spec (FR-VAL)").argument("<file>","Path to an HCS NDJSON model file (e.g. extract output)").option("--json","Emit the full ValidationReport as JSON on stdout").action(async(t,e)=>{wt()||(process.stderr.write(l.red("HCS WASM engine not built. Run `pnpm --filter @vibgrate/hcs build` first.\n")),process.exit(1));let n=S.resolve(t);await c(n)||(process.stderr.write(l.red(`Model file not found: ${n}
|
|
133
|
+
`)),process.exit(qn.SCHEMA_INVALID));let s=(await J.readFile(n,"utf-8")).split(`
|
|
134
|
+
`).filter(r=>r.trim()),i=await Yn(s);if(e.json)process.stdout.write(JSON.stringify(i,null,2)+`
|
|
135
|
+
`);else if(i.ok)process.stderr.write(l.green(`\u2714 Conformant \u2014 model satisfies the HCS v0.5 spec.
|
|
136
|
+
`));else {process.stderr.write(l.red(`\u2718 ${i.errors.length} validation error(s) (exit ${i.exitCode}):
|
|
137
|
+
`));for(let r of i.errors.slice(0,50))process.stderr.write(l.dim(` [${r.code}] ${r.factId||"(model)"}: ${r.message}
|
|
138
|
+
`));i.errors.length>50&&process.stderr.write(l.dim(` \u2026 and ${i.errors.length-50} more
|
|
139
|
+
`));}process.exit(i.exitCode);});var to=new Command("hcs").description("Holistic Code Specification \u2014 extract and render code facts").addCommand(Hn).addCommand(Wn).addCommand(Xn).addCommand(zn).addCommand(eo);var vt=2;var no=5,Cs=new Set(["ndjson","json","patch"]),oo=new Set([".git",".hg",".svn","node_modules",".vibgrate"]);async function ro(t,e,n){let o=[];async function s(i,r){let c;try{c=await J.readdir(i,{withFileTypes:!0});}catch{return}for(let a of c){if(a.name.startsWith(".")&&oo.has(a.name))continue;let p=S.join(i,a.name),g=S.join(r,a.name);if(a.isDirectory()){oo.has(a.name)||await s(p,g);continue}a.isFile()&&(e&&e.length>0&&!so(g,e)||n&&n.length>0&&so(g,n)||o.push({relPath:g,absPath:p}));}}return await s(t,""),o}function so(t,e){for(let n of e)if(Is(t,n))return true;return false}function Is(t,e){let n=e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(n,"i").test(t)}function io(t,e,n,o){let s=o?t.map(g=>g.trim()):t,i=o?e.map(g=>g.trim()):e,r=js(s,i),c=0,a=0;for(let g of r)g.type==="insert"&&c++,g.type==="delete"&&a++;return {hunks:Rs(t,e,r,n),insertions:c,deletions:a}}function js(t,e){let n=t.length,o=e.length;if(n===0&&o===0)return [];if(n===0)return e.map((a,p)=>({type:"insert",aIndex:0,bIndex:p}));if(o===0)return t.map((a,p)=>({type:"delete",aIndex:p,bIndex:0}));let s=Array.from({length:n+1},()=>new Array(o+1).fill(0));for(let a=1;a<=n;a++)for(let p=1;p<=o;p++)t[a-1]===e[p-1]?s[a][p]=s[a-1][p-1]+1:s[a][p]=Math.max(s[a-1][p],s[a][p-1]);let i=[],r=n,c=o;for(;r>0||c>0;)r>0&&c>0&&t[r-1]===e[c-1]?(i.unshift({type:"equal",aIndex:r-1,bIndex:c-1}),r--,c--):c>0&&(r===0||s[r][c-1]>=s[r-1][c])?(i.unshift({type:"insert",aIndex:r,bIndex:c-1}),c--):(i.unshift({type:"delete",aIndex:r-1,bIndex:c}),r--);return i}function Rs(t,e,n,o){let s=[],i=null,r=-1;for(let c=0;c<n.length;c++){let a=n[c];if(a.type==="equal"){if(i&&c-r>o*2){for(let p=r+1;p<=Math.min(r+o,c);p++){let g=n[p];g&&g.type==="equal"&&(i.lines.push(` ${t[g.aIndex]??""}`),i.originalCount++,i.generatedCount++);}s.push(i),i=null;}continue}if(!i){let p=Math.max(0,c-o),g=n[p]?.aIndex??0,f=n[p]?.bIndex??0;i={originalStart:g+1,originalCount:0,generatedStart:f+1,generatedCount:0,lines:[]};for(let u=p;u<c;u++){let h=n[u];h&&h.type==="equal"&&(i.lines.push(` ${t[h.aIndex]??""}`),i.originalCount++,i.generatedCount++);}}a.type==="delete"?(i.lines.push(`-${t[a.aIndex]??""}`),i.originalCount++):a.type==="insert"&&(i.lines.push(`+${e[a.bIndex]??""}`),i.generatedCount++),r=c;}if(i){for(let c=r+1;c<Math.min(n.length,r+1+o);c++){let a=n[c];a&&a.type==="equal"&&(i.lines.push(` ${t[a.aIndex]??""}`),i.originalCount++,i.generatedCount++);}s.push(i);}return s}function Es(t,e){if(t===e||t.length===0&&e.length===0)return 1;if(t.length===0||e.length===0)return 0;let n=t.split(`
|
|
132
140
|
`),o=e.split(`
|
|
133
|
-
`),
|
|
141
|
+
`),s=n.length,i=o.length;if(s*i>1e6){let r=[...n.slice(0,100),...n.slice(-100)],c=[...o.slice(0,100),...o.slice(-100)];return ao(r,c)}return ao(n,o)}function ao(t,e){let n=t.length,o=e.length,s=Array.from({length:n+1},()=>new Array(o+1).fill(0));for(let r=1;r<=n;r++)for(let c=1;c<=o;c++)t[r-1]===e[c-1]?s[r][c]=s[r-1][c-1]+1:s[r][c]=Math.max(s[r-1][c],s[r][c-1]);return 2*s[n][o]/(n+o)}function Xe(t,e){return `hcs:delta:${Te.createHash("sha256").update(`${t}:${e}`).digest("hex").substring(0,16)}`}function As(t){return t.map(e=>JSON.stringify(e)).join(`
|
|
134
142
|
`)+(t.length>0?`
|
|
135
|
-
`:"")}function
|
|
136
|
-
`}function
|
|
137
|
-
`)}var
|
|
138
|
-
`)),process.exit(
|
|
139
|
-
`)),process.exit(
|
|
140
|
-
`)),process.exit(
|
|
141
|
-
`)),process.exit(
|
|
142
|
-
`)),process.exit(
|
|
143
|
+
`:"")}function Ds(t){return JSON.stringify({deltas:t,count:t.length},null,2)+`
|
|
144
|
+
`}function Ts(t,e,n){let o=[];for(let s of t){let i=s.originalPath?S.join("a",s.originalPath):"/dev/null",r=s.generatedPath?S.join("b",s.generatedPath):"/dev/null";if(s.changeKind==="renamed"&&s.originalPath&&s.generatedPath?(o.push(`diff --vibgrate ${i} ${r}`),o.push(`similarity index ${Math.round((s.similarity??0)*100)}%`),o.push(`rename from ${s.originalPath}`),o.push(`rename to ${s.generatedPath}`)):o.push(`diff --vibgrate ${i} ${r}`),o.push(`--- ${s.changeKind==="added"?"/dev/null":i}`),o.push(`+++ ${s.changeKind==="removed"?"/dev/null":r}`),s.hunks)for(let c of s.hunks)o.push(`@@ -${c.originalStart},${c.originalCount} +${c.generatedStart},${c.generatedCount} @@`),o.push(...c.lines);o.push("");}return o.join(`
|
|
145
|
+
`)}var lo=new Command("diff").description("Compare two directory trees and emit structured delta facts").argument("<original_path>","Original source directory").argument("<generated_path>","Generated source directory").option("-o, --out <file>","Output file path","vibgrate.diff.ndjson").option("--format <fmt>","Output format (ndjson|json|patch)","ndjson").option("--ignore-whitespace","Ignore whitespace-only changes").option("--context <n>","Context lines for patch output","3").option("--include <globs>","Only include matching files (comma-separated)").option("--exclude <globs>","Exclude matching files (comma-separated)").option("--stats","Include insertions/deletions summary per file").option("--verbose","Print file match decisions and rename detection").action(async(t,e,n)=>{let o=S.resolve(t),s=S.resolve(e);for(let[b,C]of [["original_path",o],["generated_path",s]]){await c(C)||(process.stderr.write(l.red(`${b} does not exist: ${C}
|
|
146
|
+
`)),process.exit(vt));let I;try{I=await J.stat(C);}catch{process.stderr.write(l.red(`Cannot read ${b}: ${C}
|
|
147
|
+
`)),process.exit(vt);}I.isDirectory()||(process.stderr.write(l.red(`${b} must be a directory: ${C}
|
|
148
|
+
`)),process.exit(vt));}let i=n.format.toLowerCase();Cs.has(i)||(process.stderr.write(l.red(`Invalid format: "${n.format}". Allowed: ndjson, json, patch
|
|
149
|
+
`)),process.exit(no));let r=parseInt(n.context,10);(isNaN(r)||r<0)&&(process.stderr.write(l.red(`--context must be >= 0
|
|
150
|
+
`)),process.exit(no));let c$1=n.include?n.include.split(",").map(b=>b.trim()).filter(Boolean):void 0,a=n.exclude?n.exclude.split(",").map(b=>b.trim()).filter(Boolean):void 0,[p,g]=await Promise.all([ro(o,c$1,a),ro(s,c$1,a)]),f=new Map(p.map(b=>[b.relPath,b])),u=new Map(g.map(b=>[b.relPath,b]));n.verbose&&(process.stderr.write(l.dim(`Original: ${p.length} files
|
|
143
151
|
`)),process.stderr.write(l.dim(`Generated: ${g.length} files
|
|
144
|
-
`)));let h=[],v=new Set,m=new Set;for(let[b,C]of f){let I=u.get(b);if(I){v.add(b),m.add(b);let k=await J.readFile(C.absPath,"utf-8"),X=await J.readFile(I.absPath,"utf-8"),
|
|
152
|
+
`)));let h=[],v=new Set,m=new Set;for(let[b,C]of f){let I=u.get(b);if(I){v.add(b),m.add(b);let k=await J.readFile(C.absPath,"utf-8"),X=await J.readFile(I.absPath,"utf-8"),K=n.ignoreWhitespace?k.replace(/\s+/g," ").trim():k,z=n.ignoreWhitespace?X.replace(/\s+/g," ").trim():X;if(K!==z){let y=io(k.split(`
|
|
145
153
|
`),X.split(`
|
|
146
|
-
`),
|
|
147
|
-
`));}}}let $=p.filter(b=>!v.has(b.relPath)),
|
|
148
|
-
`),
|
|
149
|
-
`),
|
|
150
|
-
`));}}for(let b of $){if(
|
|
154
|
+
`),r,n.ignoreWhitespace??false),P={deltaId:Xe("modified",b),changeKind:"modified",originalPath:b,generatedPath:b,hunks:y.hunks};n.stats&&(P.stats={insertions:y.insertions,deletions:y.deletions}),h.push(P),n.verbose&&process.stderr.write(l.dim(` modified: ${b} (+${y.insertions} -${y.deletions})
|
|
155
|
+
`));}}}let $=p.filter(b=>!v.has(b.relPath)),O=g.filter(b=>!m.has(b.relPath)),de=.8,_=new Set,U=new Set;if($.length>0&&O.length>0){let b=new Map,C=new Map;await Promise.all([...$.map(async k=>{try{b.set(k.relPath,await J.readFile(k.absPath,"utf-8"));}catch{}}),...O.map(async k=>{try{C.set(k.relPath,await J.readFile(k.absPath,"utf-8"));}catch{}})]);let I=[];for(let[k,X]of b)for(let[K,z]of C){if(S.extname(k)!==S.extname(K))continue;let y=Es(X,z);y>=de&&I.push({origPath:k,genPath:K,similarity:y});}I.sort((k,X)=>X.similarity-k.similarity);for(let k of I){if(_.has(k.origPath)||U.has(k.genPath))continue;_.add(k.origPath),U.add(k.genPath);let X=b.get(k.origPath)??"",K=C.get(k.genPath)??"",z=io(X.split(`
|
|
156
|
+
`),K.split(`
|
|
157
|
+
`),r,n.ignoreWhitespace??false),y={deltaId:Xe("renamed",`${k.origPath} -> ${k.genPath}`),changeKind:"renamed",originalPath:k.origPath,generatedPath:k.genPath,similarity:k.similarity,hunks:z.hunks};n.stats&&(y.stats={insertions:z.insertions,deletions:z.deletions}),h.push(y),n.verbose&&process.stderr.write(l.dim(` renamed: ${k.origPath} \u2192 ${k.genPath} (${(k.similarity*100).toFixed(0)}% similar)
|
|
158
|
+
`));}}for(let b of $){if(_.has(b.relPath))continue;let C={deltaId:Xe("removed",b.relPath),changeKind:"removed",originalPath:b.relPath,generatedPath:null};if(n.stats)try{let I=await J.readFile(b.absPath,"utf-8");C.stats={insertions:0,deletions:I.split(`
|
|
151
159
|
`).length};}catch{C.stats={insertions:0,deletions:0};}h.push(C),n.verbose&&process.stderr.write(l.dim(` removed: ${b.relPath}
|
|
152
|
-
`));}for(let b of
|
|
160
|
+
`));}for(let b of O){if(U.has(b.relPath))continue;let C={deltaId:Xe("added",b.relPath),changeKind:"added",originalPath:null,generatedPath:b.relPath};if(n.stats)try{let I=await J.readFile(b.absPath,"utf-8");C.stats={insertions:I.split(`
|
|
153
161
|
`).length,deletions:0};}catch{C.stats={insertions:0,deletions:0};}h.push(C),n.verbose&&process.stderr.write(l.dim(` added: ${b.relPath}
|
|
154
|
-
`));}h.sort((b,C)=>{let I=b.originalPath??b.generatedPath??"",k=C.originalPath??C.generatedPath??"";return I.localeCompare(k)});let ie;switch(
|
|
162
|
+
`));}h.sort((b,C)=>{let I=b.originalPath??b.generatedPath??"",k=C.originalPath??C.generatedPath??"";return I.localeCompare(k)});let ie;switch(i){case "ndjson":ie=As(h);break;case "json":ie=Ds(h);break;case "patch":ie=Ts(h);break}let pe=S.resolve(n.out);await J.writeFile(pe,ie,"utf-8");let Ae=h.filter(b=>b.changeKind==="added").length,ve=h.filter(b=>b.changeKind==="removed").length,Ke=h.filter(b=>b.changeKind==="modified").length,De=h.filter(b=>b.changeKind==="renamed").length;if(process.stderr.write(l.green("\u2714 ")+`${h.length} changes: `+l.green(`+${Ae} added`)+", "+l.red(`-${ve} removed`)+", "+l.yellow(`~${Ke} modified`)+", "+l.blue(`\u2192${De} renamed`)+`
|
|
155
163
|
`),process.stderr.write(l.dim(` Written to ${pe}
|
|
156
164
|
`)),n.verbose&&n.stats){let b=0,C=0;for(let I of h)I.stats&&(b+=I.stats.insertions,C+=I.stats.deletions);process.stderr.write(l.dim(` Total: +${b} insertions, -${C} deletions
|
|
157
|
-
`));}});var Ss="https://vibgrate.com/help";function ks(){console.log(""),console.log(l.dim(`See ${Ss} for more guidance`));}var yt={scan:()=>{console.log(""),console.log(l.bold.underline("vibgrate scan")+l.dim(" \u2014 Scan a project for upgrade drift")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate scan [path] [options]"),console.log(""),console.log(l.bold("Arguments:")),console.log(` ${l.cyan("[path]")} Path to scan (default: current directory)`),console.log(""),console.log(l.bold("Output options:")),console.log(` ${l.cyan("--format <format>")} Output format: ${l.white("text")} | json | sarif | md (default: text)`),console.log(` ${l.cyan("--out <file>")} Write output to a file instead of stdout`),console.log(""),console.log(l.bold("Baseline & gating:")),console.log(` ${l.cyan("--baseline <file>")} Compare results against a saved baseline`),console.log(` ${l.cyan("--drift-budget <score>")} Fail if drift score exceeds this value (0\u2013100)`),console.log(` ${l.cyan("--drift-worsening <percent>")} Fail if drift worsens by more than % since baseline`),console.log(` ${l.cyan("--fail-on <level>")} Fail exit code on warn or error findings`),console.log(""),console.log(l.bold("Performance:")),console.log(` ${l.cyan("--concurrency <n>")} Max concurrent registry calls (default: 8)`),console.log(` ${l.cyan("--changed-only")} Only scan files changed since last git commit`),console.log(""),console.log(l.bold("Privacy & offline:")),console.log(` ${l.cyan("--offline")} Run without any network calls; skip result upload`),console.log(` ${l.cyan("--package-manifest <file>")} Use a local package-version manifest (JSON or ZIP) for offline mode`),console.log(` ${l.cyan("--no-local-artifacts")} Do not write .vibgrate JSON artifacts to disk`),console.log(` ${l.cyan("--max-privacy")} Strongest privacy mode: minimal scanners + no local artifacts`),console.log(""),console.log(l.bold("Tooling:")),console.log(` ${l.cyan("--ui-purpose")} Enable UI purpose evidence extraction (slower)`),console.log(""),console.log(l.bold("Uploading results:")),console.log(` ${l.cyan("--push")} Auto-push results to Vibgrate API after scan`),console.log(` ${l.cyan("--dsn <dsn>")} DSN token for push (or set VIBGRATE_DSN env var)`),console.log(` ${l.cyan("--region <region>")} Data residency region: us | eu (default: us)`),console.log(` ${l.cyan("--strict")} Fail if the upload to Vibgrate API fails`),console.log(""),console.log(l.bold("Examples:")),console.log(` ${l.dim("# Scan the current directory and display a text report")}`),console.log(" vibgrate scan ."),console.log(""),console.log(` ${l.dim("# Scan, fail if drift score > 40, and write SARIF for GitHub Actions")}`),console.log(" vibgrate scan . --drift-budget 40 --format sarif --out drift.sarif"),console.log(""),console.log(` ${l.dim("# Scan and automatically upload results via a DSN")}`),console.log(" vibgrate scan . --push --dsn $VIBGRATE_DSN"),console.log(""),console.log(` ${l.dim("# Offline scan using a pre-downloaded package manifest")}`),console.log(" vibgrate scan . --offline --package-manifest ./manifest.zip");},init:()=>{console.log(""),console.log(l.bold.underline("vibgrate init")+l.dim(" \u2014 Initialise vibgrate in a project directory")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate init [path] [options]"),console.log(""),console.log(l.bold("Arguments:")),console.log(` ${l.cyan("[path]")} Directory to initialise (default: current directory)`),console.log(""),console.log(l.bold("Options:")),console.log(` ${l.cyan("--baseline")} Create an initial drift baseline after init`),console.log(` ${l.cyan("--yes")} Skip all confirmation prompts`),console.log(""),console.log(l.bold("What it does:")),console.log(" \u2022 Creates a .vibgrate/ directory"),console.log(" \u2022 Writes a vibgrate.config.ts starter config"),console.log(" \u2022 Optionally runs an initial baseline scan (--baseline)"),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate init"),console.log(" vibgrate init ./my-project --baseline");},baseline:()=>{console.log(""),console.log(l.bold.underline("vibgrate baseline")+l.dim(" \u2014 Save a drift baseline snapshot")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate baseline [path]"),console.log(""),console.log(l.bold("Arguments:")),console.log(` ${l.cyan("[path]")} Path to baseline (default: current directory)`),console.log(""),console.log(l.bold("What it does:")),console.log(" Runs a full scan and saves the result as .vibgrate/baseline.json."),console.log(" Future scans can compare against this file using --baseline."),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate baseline ."),console.log(" vibgrate scan . --baseline .vibgrate/baseline.json --drift-worsening 10");},report:()=>{console.log(""),console.log(l.bold.underline("vibgrate report")+l.dim(" \u2014 Generate a report from a saved scan artifact")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate report [options]"),console.log(""),console.log(l.bold("Options:")),console.log(` ${l.cyan("--in <file>")} Input artifact file (default: .vibgrate/scan_result.json)`),console.log(` ${l.cyan("--format <format>")} Output format: ${l.white("text")} | md | json (default: text)`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate report"),console.log(" vibgrate report --format md > DRIFT-REPORT.md"),console.log(" vibgrate report --in ./ci/scan_result.json --format json");},sbom:()=>{console.log(""),console.log(l.bold.underline("vibgrate sbom")+l.dim(" \u2014 Supply-chain evidence: SBOM export/delta and OpenVEX")),console.log(""),console.log(l.bold("Subcommands:")),console.log(` ${l.cyan("vibgrate sbom export")} Emit a CycloneDX or SPDX SBOM from a scan artifact`),console.log(` ${l.cyan("vibgrate sbom delta")} Compare dependencies between two scan artifacts`),console.log(` ${l.cyan("vibgrate sbom vex")} Emit an OpenVEX document (exploitability statements)`),console.log(""),console.log(l.bold("sbom export options:")),console.log(` ${l.cyan("--in <file>")} Input artifact (default: .vibgrate/scan_result.json)`),console.log(` ${l.cyan("--format <format>")} SBOM format: ${l.white("cyclonedx")} | spdx (default: cyclonedx)`),console.log(` ${l.cyan("--out <file>")} Write SBOM to file instead of stdout`),console.log(""),console.log(l.bold("sbom vex options:")),console.log(` ${l.cyan("--from <file>")} Read OpenVEX statements from a JSON file`),console.log(` ${l.cyan("--statement <json>")} Add a statement as inline JSON (repeatable)`),console.log(` ${l.cyan("--product <ref>")} Default product for statements (e.g. an image digest)`),console.log(` ${l.cyan("--out <file>")} Write the document to file instead of stdout`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate sbom export --format cyclonedx --out sbom.json"),console.log(" vibgrate sbom export --format spdx --out sbom.spdx.json"),console.log(' vibgrate sbom vex --product "$IMAGE_REF" --out openvex.json');},push:()=>{console.log(""),console.log(l.bold.underline("vibgrate push")+l.dim(" \u2014 Upload a scan artifact to the Vibgrate API")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate push [options]"),console.log(""),console.log(l.bold("Options:")),console.log(` ${l.cyan("--dsn <dsn>")} DSN token (or set VIBGRATE_DSN env var)`),console.log(` ${l.cyan("--file <file>")} Artifact to upload (default: .vibgrate/scan_result.json)`),console.log(` ${l.cyan("--region <region>")} Override data residency region: us | eu`),console.log(` ${l.cyan("--strict")} Fail with non-zero exit code on upload error`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate push --dsn $VIBGRATE_DSN"),console.log(" vibgrate push --file ./ci/scan_result.json --strict");},dsn:()=>{console.log(""),console.log(l.bold.underline("vibgrate dsn")+l.dim(" \u2014 Manage DSN tokens for API authentication")),console.log(""),console.log(l.bold("Subcommands:")),console.log(` ${l.cyan("vibgrate dsn create")} Generate a new DSN token`),console.log(""),console.log(l.bold("dsn create options:")),console.log(` ${l.cyan("--workspace <id>")} Workspace ID or "new" to auto-generate ${l.red("(required)")}`),console.log(` ${l.cyan("--region <region>")} Data residency region: us | eu (default: us)`),console.log(` ${l.cyan("--ingest <url>")} Override ingest API URL`),console.log(` ${l.cyan("--write <path>")} Write the DSN to a file (add to .gitignore!)`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate dsn create --workspace new"),console.log(" vibgrate dsn create --workspace abc123"),console.log(" vibgrate dsn create --workspace new --region eu --write .vibgrate/.dsn");},update:()=>{console.log(""),console.log(l.bold.underline("vibgrate update")+l.dim(" \u2014 Update the vibgrate CLI to the latest version")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate update [options]"),console.log(""),console.log(l.bold("Options:")),console.log(` ${l.cyan("--check")} Check for a newer version without installing`),console.log(` ${l.cyan("--pm <manager>")} Force a package manager: npm | pnpm | yarn | bun`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate update"),console.log(" vibgrate update --check"),console.log(" vibgrate update --pm pnpm");},hcs:()=>{console.log(""),console.log(l.bold.underline("vibgrate hcs")+l.dim(" \u2014 Holistic Code Specification: extract and render code facts")),console.log(""),console.log(l.bold("Subcommands:")),console.log(` ${l.cyan("vibgrate hcs extract")} Analyze source code and emit HCS facts as NDJSON`),console.log(` ${l.cyan("vibgrate hcs digest")} Render HCS NDJSON facts into Markdown, JSON, or HTML`),console.log(""),console.log(l.bold("hcs extract options:")),console.log(` ${l.cyan("[path]")} Path to source directory (default: .)`),console.log(` ${l.cyan("-o, --out <file>")} Write NDJSON to file (default: stdout)`),console.log(` ${l.cyan("--language <langs>")} Comma-separated languages to analyze (default: auto-detect)`),console.log(` ${l.cyan("--include-tests")} Include test files in analysis`),console.log(` ${l.cyan("--push")} Stream facts to Vibgrate dashboard API`),console.log(` ${l.cyan("--dsn <dsn>")} DSN token for push (or use VIBGRATE_DSN env)`),console.log(` ${l.cyan("--concurrency <n>")} Number of parallel workers`),console.log(` ${l.cyan("--timeout-mins <mins>")} Total analysis timeout in minutes (default: 60)`),console.log(` ${l.cyan("--verbose")} Print worker stderr and summary statistics`),console.log(""),console.log(l.bold("hcs digest options:")),console.log(` ${l.cyan("--in <file>")} HCS NDJSON file to read (default: stdin)`),console.log(` ${l.cyan("-o, --out <file>")} Write output to file (default: stdout)`),console.log(` ${l.cyan("--format <format>")} Output format: ${l.white("md")} | json | html (default: md)`),console.log(` ${l.cyan("--level <level>")} Detail level: ${l.white("concise")} | full (default: concise)`),console.log(` ${l.cyan("--title <title>")} Override document title`),console.log(""),console.log(l.bold("Examples:")),console.log(` ${l.dim("# Extract HCS facts from current directory")}`),console.log(" vibgrate hcs extract . --out facts.ndjson"),console.log(""),console.log(` ${l.dim("# Render facts as Markdown")}`),console.log(" vibgrate hcs digest --in facts.ndjson --format md > DIGEST.md"),console.log(""),console.log(` ${l.dim("# Full pipeline: extract and pipe directly to digest")}`),console.log(" vibgrate hcs extract . | vibgrate hcs digest --format html --out digest.html");}};function no(){console.log(""),console.log(l.bold("vibgrate")+l.dim(" \u2014 Continuous Drift Intelligence")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate <command> [options]"),console.log(" vibgrate help [command] Show detailed help for a command"),console.log(""),console.log(l.bold("Getting started:")),console.log(` ${l.cyan("init")} Initialise vibgrate in a project (creates config & .vibgrate/ dir)`),console.log(` ${l.cyan("login")} Sign the CLI into your workspace via the browser`),console.log(` ${l.cyan("logout")} Clear stored login credentials`),console.log(""),console.log(l.bold("Core scanning:")),console.log(` ${l.cyan("scan")} Scan a project for upgrade drift and generate a report`),console.log(` ${l.cyan("baseline")} Save a baseline snapshot to compare future scans against`),console.log(""),console.log(l.bold("Reporting & export:")),console.log(` ${l.cyan("report")} Re-generate a report from a previously saved scan artifact`),console.log(` ${l.cyan("sbom")} Supply-chain evidence: SBOM (CycloneDX/SPDX) export/delta + OpenVEX`),console.log(""),console.log(l.bold("HCS (Holistic Code Specification):")),console.log(` ${l.cyan("hcs")} Extract and render Holistic Code Specification facts`),console.log(` ${l.cyan("hcs extract")} Analyze source code and emit validated HCS facts (NDJSON)`),console.log(` ${l.cyan("hcs digest")} Render HCS NDJSON facts into Markdown, JSON, or HTML`),console.log(""),console.log(l.bold("CI/CD integration:")),console.log(` ${l.cyan("push")} Upload a scan artifact to the Vibgrate API`),console.log(` ${l.cyan("dsn")} Create and manage DSN tokens for API authentication`),console.log(""),console.log(l.bold("Maintenance:")),console.log(` ${l.cyan("update")} Update the vibgrate CLI to the latest version`),console.log(""),console.log(l.dim("Run")+` ${l.cyan("vibgrate help <command>")} `+l.dim("for detailed options, e.g.")+` ${l.cyan("vibgrate help scan")}`);}var oo=new Command("help").description("Show help for vibgrate commands").argument("[command]","Command to show detailed help for").helpOption(false).action(t=>{let e=t?.toLowerCase().trim();e&&yt[e]?yt[e]():(e&&(console.log(""),console.log(l.red(`Unknown command: ${e}`)),console.log(l.dim(`Available commands: ${Object.keys(yt).join(", ")}`))),no()),ks();});var O=new Command;O.name("vibgrate").description("Continuous Drift Intelligence").version(R).addHelpText("after",`
|
|
158
|
-
See https://vibgrate.com/help for more guidance`);
|
|
165
|
+
`));}});var Os="https://vibgrate.com/help";function _s(){console.log(""),console.log(l.dim(`See ${Os} for more guidance`));}var $t={scan:()=>{console.log(""),console.log(l.bold.underline("vibgrate scan")+l.dim(" \u2014 Scan a project for upgrade drift")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate scan [path] [options]"),console.log(""),console.log(l.bold("Arguments:")),console.log(` ${l.cyan("[path]")} Path to scan (default: current directory)`),console.log(""),console.log(l.bold("Output options:")),console.log(` ${l.cyan("--format <format>")} Output format: ${l.white("text")} | json | sarif | md (default: text)`),console.log(` ${l.cyan("--out <file>")} Write output to a file instead of stdout`),console.log(""),console.log(l.bold("Baseline & gating:")),console.log(` ${l.cyan("--baseline <file>")} Compare results against a saved baseline`),console.log(` ${l.cyan("--drift-budget <score>")} Fail if drift score exceeds this value (0\u2013100)`),console.log(` ${l.cyan("--drift-worsening <percent>")} Fail if drift worsens by more than % since baseline`),console.log(` ${l.cyan("--fail-on <level>")} Fail exit code on warn or error findings`),console.log(""),console.log(l.bold("Performance:")),console.log(` ${l.cyan("--concurrency <n>")} Max concurrent registry calls (default: 8)`),console.log(` ${l.cyan("--changed-only")} Only scan files changed since last git commit`),console.log(""),console.log(l.bold("Privacy & offline:")),console.log(` ${l.cyan("--offline")} Run without any network calls; skip result upload`),console.log(` ${l.cyan("--package-manifest <file>")} Use a local package-version manifest (JSON or ZIP) for offline mode`),console.log(` ${l.cyan("--no-local-artifacts")} Do not write .vibgrate JSON artifacts to disk`),console.log(` ${l.cyan("--max-privacy")} Strongest privacy mode: minimal scanners + no local artifacts`),console.log(""),console.log(l.bold("Tooling:")),console.log(` ${l.cyan("--ui-purpose")} Enable UI purpose evidence extraction (slower)`),console.log(""),console.log(l.bold("Uploading results:")),console.log(` ${l.cyan("--push")} Auto-push results to Vibgrate API after scan`),console.log(` ${l.cyan("--dsn <dsn>")} DSN token for push (or set VIBGRATE_DSN env var)`),console.log(` ${l.cyan("--region <region>")} Data residency region: us | eu (default: us)`),console.log(` ${l.cyan("--strict")} Fail if the upload to Vibgrate API fails`),console.log(""),console.log(l.bold("Examples:")),console.log(` ${l.dim("# Scan the current directory and display a text report")}`),console.log(" vibgrate scan ."),console.log(""),console.log(` ${l.dim("# Scan, fail if drift score > 40, and write SARIF for GitHub Actions")}`),console.log(" vibgrate scan . --drift-budget 40 --format sarif --out drift.sarif"),console.log(""),console.log(` ${l.dim("# Scan and automatically upload results via a DSN")}`),console.log(" vibgrate scan . --push --dsn $VIBGRATE_DSN"),console.log(""),console.log(` ${l.dim("# Offline scan using a pre-downloaded package manifest")}`),console.log(" vibgrate scan . --offline --package-manifest ./manifest.zip");},init:()=>{console.log(""),console.log(l.bold.underline("vibgrate init")+l.dim(" \u2014 Initialise vibgrate in a project directory")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate init [path] [options]"),console.log(""),console.log(l.bold("Arguments:")),console.log(` ${l.cyan("[path]")} Directory to initialise (default: current directory)`),console.log(""),console.log(l.bold("Options:")),console.log(` ${l.cyan("--baseline")} Create an initial drift baseline after init`),console.log(` ${l.cyan("--yes")} Skip all confirmation prompts`),console.log(""),console.log(l.bold("What it does:")),console.log(" \u2022 Creates a .vibgrate/ directory"),console.log(" \u2022 Writes a vibgrate.config.ts starter config"),console.log(" \u2022 Optionally runs an initial baseline scan (--baseline)"),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate init"),console.log(" vibgrate init ./my-project --baseline");},baseline:()=>{console.log(""),console.log(l.bold.underline("vibgrate baseline")+l.dim(" \u2014 Save a drift baseline snapshot")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate baseline [path]"),console.log(""),console.log(l.bold("Arguments:")),console.log(` ${l.cyan("[path]")} Path to baseline (default: current directory)`),console.log(""),console.log(l.bold("What it does:")),console.log(" Runs a full scan and saves the result as .vibgrate/baseline.json."),console.log(" Future scans can compare against this file using --baseline."),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate baseline ."),console.log(" vibgrate scan . --baseline .vibgrate/baseline.json --drift-worsening 10");},report:()=>{console.log(""),console.log(l.bold.underline("vibgrate report")+l.dim(" \u2014 Generate a report from a saved scan artifact")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate report [options]"),console.log(""),console.log(l.bold("Options:")),console.log(` ${l.cyan("--in <file>")} Input artifact file (default: .vibgrate/scan_result.json)`),console.log(` ${l.cyan("--format <format>")} Output format: ${l.white("text")} | md | json (default: text)`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate report"),console.log(" vibgrate report --format md > DRIFT-REPORT.md"),console.log(" vibgrate report --in ./ci/scan_result.json --format json");},sbom:()=>{console.log(""),console.log(l.bold.underline("vibgrate sbom")+l.dim(" \u2014 Supply-chain evidence: SBOM export/delta and OpenVEX")),console.log(""),console.log(l.bold("Subcommands:")),console.log(` ${l.cyan("vibgrate sbom export")} Emit a CycloneDX or SPDX SBOM from a scan artifact`),console.log(` ${l.cyan("vibgrate sbom delta")} Compare dependencies between two scan artifacts`),console.log(` ${l.cyan("vibgrate sbom vex")} Emit an OpenVEX document (exploitability statements)`),console.log(""),console.log(l.bold("sbom export options:")),console.log(` ${l.cyan("--in <file>")} Input artifact (default: .vibgrate/scan_result.json)`),console.log(` ${l.cyan("--format <format>")} SBOM format: ${l.white("cyclonedx")} | spdx (default: cyclonedx)`),console.log(` ${l.cyan("--out <file>")} Write SBOM to file instead of stdout`),console.log(""),console.log(l.bold("sbom vex options:")),console.log(` ${l.cyan("--from <file>")} Read OpenVEX statements from a JSON file`),console.log(` ${l.cyan("--statement <json>")} Add a statement as inline JSON (repeatable)`),console.log(` ${l.cyan("--product <ref>")} Default product for statements (e.g. an image digest)`),console.log(` ${l.cyan("--out <file>")} Write the document to file instead of stdout`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate sbom export --format cyclonedx --out sbom.json"),console.log(" vibgrate sbom export --format spdx --out sbom.spdx.json"),console.log(' vibgrate sbom vex --product "$IMAGE_REF" --out openvex.json');},push:()=>{console.log(""),console.log(l.bold.underline("vibgrate push")+l.dim(" \u2014 Upload a scan artifact to the Vibgrate API")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate push [options]"),console.log(""),console.log(l.bold("Options:")),console.log(` ${l.cyan("--dsn <dsn>")} DSN token (or set VIBGRATE_DSN env var)`),console.log(` ${l.cyan("--file <file>")} Artifact to upload (default: .vibgrate/scan_result.json)`),console.log(` ${l.cyan("--region <region>")} Override data residency region: us | eu`),console.log(` ${l.cyan("--strict")} Fail with non-zero exit code on upload error`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate push --dsn $VIBGRATE_DSN"),console.log(" vibgrate push --file ./ci/scan_result.json --strict");},dsn:()=>{console.log(""),console.log(l.bold.underline("vibgrate dsn")+l.dim(" \u2014 Manage DSN tokens for API authentication")),console.log(""),console.log(l.bold("Subcommands:")),console.log(` ${l.cyan("vibgrate dsn create")} Generate a new DSN token`),console.log(""),console.log(l.bold("dsn create options:")),console.log(` ${l.cyan("--workspace <id>")} Workspace ID or "new" to auto-generate ${l.red("(required)")}`),console.log(` ${l.cyan("--region <region>")} Data residency region: us | eu (default: us)`),console.log(` ${l.cyan("--ingest <url>")} Override ingest API URL`),console.log(` ${l.cyan("--write <path>")} Write the DSN to a file (add to .gitignore!)`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate dsn create --workspace new"),console.log(" vibgrate dsn create --workspace abc123"),console.log(" vibgrate dsn create --workspace new --region eu --write .vibgrate/.dsn");},update:()=>{console.log(""),console.log(l.bold.underline("vibgrate update")+l.dim(" \u2014 Update the vibgrate CLI to the latest version")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate update [options]"),console.log(""),console.log(l.bold("Options:")),console.log(` ${l.cyan("--check")} Check for a newer version without installing`),console.log(` ${l.cyan("--pm <manager>")} Force a package manager: npm | pnpm | yarn | bun`),console.log(""),console.log(l.bold("Examples:")),console.log(" vibgrate update"),console.log(" vibgrate update --check"),console.log(" vibgrate update --pm pnpm");},hcs:()=>{console.log(""),console.log(l.bold.underline("vibgrate hcs")+l.dim(" \u2014 Holistic Code Specification: extract and render code facts")),console.log(""),console.log(l.bold("Subcommands:")),console.log(` ${l.cyan("vibgrate hcs extract")} Analyze source code and emit HCS facts as NDJSON`),console.log(` ${l.cyan("vibgrate hcs digest")} Render HCS NDJSON facts into Markdown, JSON, or HTML`),console.log(""),console.log(l.bold("hcs extract options:")),console.log(` ${l.cyan("[path]")} Path to source directory (default: .)`),console.log(` ${l.cyan("-o, --out <file>")} Write NDJSON to file (default: stdout)`),console.log(` ${l.cyan("--language <langs>")} Comma-separated languages to analyze (default: auto-detect)`),console.log(` ${l.cyan("--include-tests")} Include test files in analysis`),console.log(` ${l.cyan("--push")} Stream facts to Vibgrate dashboard API`),console.log(` ${l.cyan("--dsn <dsn>")} DSN token for push (or use VIBGRATE_DSN env)`),console.log(` ${l.cyan("--concurrency <n>")} Number of parallel workers`),console.log(` ${l.cyan("--timeout-mins <mins>")} Total analysis timeout in minutes (default: 60)`),console.log(` ${l.cyan("--verbose")} Print worker stderr and summary statistics`),console.log(""),console.log(l.bold("hcs digest options:")),console.log(` ${l.cyan("--in <file>")} HCS NDJSON file to read (default: stdin)`),console.log(` ${l.cyan("-o, --out <file>")} Write output to file (default: stdout)`),console.log(` ${l.cyan("--format <format>")} Output format: ${l.white("md")} | json | html (default: md)`),console.log(` ${l.cyan("--level <level>")} Detail level: ${l.white("concise")} | full (default: concise)`),console.log(` ${l.cyan("--title <title>")} Override document title`),console.log(""),console.log(l.bold("Examples:")),console.log(` ${l.dim("# Extract HCS facts from current directory")}`),console.log(" vibgrate hcs extract . --out facts.ndjson"),console.log(""),console.log(` ${l.dim("# Render facts as Markdown")}`),console.log(" vibgrate hcs digest --in facts.ndjson --format md > DIGEST.md"),console.log(""),console.log(` ${l.dim("# Full pipeline: extract and pipe directly to digest")}`),console.log(" vibgrate hcs extract . | vibgrate hcs digest --format html --out digest.html");}};function po(){console.log(""),console.log(l.bold("vibgrate")+l.dim(" \u2014 Continuous Drift Intelligence")),console.log(""),console.log(l.bold("Usage:")),console.log(" vibgrate <command> [options]"),console.log(" vibgrate help [command] Show detailed help for a command"),console.log(""),console.log(l.bold("Getting started:")),console.log(` ${l.cyan("init")} Initialise vibgrate in a project (creates config & .vibgrate/ dir)`),console.log(` ${l.cyan("login")} Sign the CLI into your workspace via the browser`),console.log(` ${l.cyan("logout")} Clear stored login credentials`),console.log(""),console.log(l.bold("Core scanning:")),console.log(` ${l.cyan("scan")} Scan a project for upgrade drift and generate a report`),console.log(` ${l.cyan("baseline")} Save a baseline snapshot to compare future scans against`),console.log(""),console.log(l.bold("Reporting & export:")),console.log(` ${l.cyan("report")} Re-generate a report from a previously saved scan artifact`),console.log(` ${l.cyan("sbom")} Supply-chain evidence: SBOM (CycloneDX/SPDX) export/delta + OpenVEX`),console.log(""),console.log(l.bold("HCS (Holistic Code Specification):")),console.log(` ${l.cyan("hcs")} Extract and render Holistic Code Specification facts`),console.log(` ${l.cyan("hcs extract")} Analyze source code and emit validated HCS facts (NDJSON)`),console.log(` ${l.cyan("hcs digest")} Render HCS NDJSON facts into Markdown, JSON, or HTML`),console.log(""),console.log(l.bold("CI/CD integration:")),console.log(` ${l.cyan("push")} Upload a scan artifact to the Vibgrate API`),console.log(` ${l.cyan("dsn")} Create and manage DSN tokens for API authentication`),console.log(""),console.log(l.bold("Maintenance:")),console.log(` ${l.cyan("update")} Update the vibgrate CLI to the latest version`),console.log(""),console.log(l.dim("Run")+` ${l.cyan("vibgrate help <command>")} `+l.dim("for detailed options, e.g.")+` ${l.cyan("vibgrate help scan")}`);}var uo=new Command("help").description("Show help for vibgrate commands").argument("[command]","Command to show detailed help for").helpOption(false).action(t=>{let e=t?.toLowerCase().trim();e&&$t[e]?$t[e]():(e&&(console.log(""),console.log(l.red(`Unknown command: ${e}`)),console.log(l.dim(`Available commands: ${Object.keys($t).join(", ")}`))),po()),_s();});var N=new Command;N.name("vibgrate").description("Continuous Drift Intelligence").version(R).addHelpText("after",`
|
|
166
|
+
See https://vibgrate.com/help for more guidance`);N.addCommand(uo);N.addCommand(Ot);N.addCommand(Jt);N.addCommand(h);N.addCommand(Qt);N.addCommand(en);N.addCommand(nn);N.addCommand(Qe);N.addCommand(dn);N.addCommand(yn);N.addCommand(Pn);N.addCommand(to);N.addCommand(lo);function Ms(){mn().then(t=>{t?.updateAvailable&&(console.error(""),console.error(l.yellow(` Update available: ${t.current} \u2192 ${t.latest}`)),console.error(l.dim(' Run "vibgrate update" to install the latest version.')),console.error(""));}).catch(()=>{});}N.parseAsync().then(()=>{Ms();}).catch(t=>{console.error(t),process.exit(1);});
|