@vibgrate/cli 2026.625.1 → 2026.628.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 CHANGED
@@ -1,166 +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 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(`
2
+ import'./chunk-CKBCROBF.js';import {d,c,e,f,b as b$1,a as a$1,h}from'./chunk-ROPIO52N.js';import {b,pa,ia,sa,ra,qa,ua,oa}from'./chunk-RKH4N26K.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 Ne from'crypto';import {randomUUID}from'crypto';import*as Ut from'os';import*as ee from'fs';import {rmSync,existsSync}from'fs';import {execSync,spawn,spawnSync}from'child_process';import*as ln from'zlib';import {promisify}from'util';import*as K from'fs/promises';import {mkdtemp,rm}from'fs/promises';import {fileURLToPath}from'url';var Ft=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 r=S.join(n,"vibgrate.config.ts");if(await c(r)?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:a}=await import('./baseline-QM3PG3RY.js');await a(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 So=createRequire(import.meta.url),ko=So("../package.json"),E=ko.version;var et=[{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}],xo="us";function ae(){return et.filter(t=>t.available).map(t=>t.id)}function Mt(t){return et.find(e=>e.id===t)}function ne(t,e){if(e)try{return new URL(e).host}catch{throw new Error(`Invalid ingest URL: ${e}`)}let n=(t??xo).toLowerCase(),o=Mt(n);if(!o)throw new Error(`Unknown region "${n}". Supported: ${ae().join(", ")}`);if(!o.available)throw new Error(`Region "${n}" (${o.label}) is not yet available. Supported: ${ae().join(", ")}`);return o.ingestHost}function ge(t){return et.find(n=>n.ingestHost===t)?.dashHost??"dash.vibgrate.com"}function Lt(t){return Mt(t.toLowerCase())?.ingestHost}async function Co(t,e,n,o,r){let a=`https://${o}/v1/provision`;try{let s=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json",Connection:"close"},body:JSON.stringify(r?{keyId:t,secret:e,workspaceId:n,region:r}:{keyId:t,secret:e,workspaceId:n})});return s.ok?{success:!0}:{success:!1,error:(await s.json()).error||`HTTP ${s.status}`}}catch(s){return {success:false,error:s instanceof Error?s.message:String(s)}}}var tt=new Command("dsn").description("Manage DSN tokens");tt.command("create").description("Create a new DSN token").option("--ingest <url>","Ingest API URL (overrides --region)").option("--region <region>",`Data residency region (${ae().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=Ne.randomBytes(12).toString("hex"),n=Ne.randomBytes(32).toString("hex"),o;try{o=ne(t.region,t.ingest);}catch(c){console.error(l.red(c instanceof Error?c.message:String(c))),process.exit(1);}let r=t.workspace,a=t.workspace.toLowerCase()==="new";a&&(r=Ne.randomBytes(8).toString("hex"),console.log(l.dim(`Provisioning new workspace ${r}...`)));let s=t.ingest?void 0:t.region.toLowerCase();if(a){let c=await Co(e$1,n,r,o,s);c.success||(console.error(l.red(`Failed to provision DSN: ${c.error}`)),process.exit(1));}let i=`vibgrate+https://${e$1}:${n}@${o}/${r}`;if(console.log(l.green("\u2714")+" DSN created"),console.log(""),console.log(l.bold("Region:")),console.log(` ${s??"custom"} (${o})`),console.log(""),console.log(l.bold("DSN:")),console.log(` ${i}`),console.log(""),console.log(l.bold("Key ID:")),console.log(` ${e$1}`),a&&(console.log(""),console.log(l.bold("Workspace ID:")),console.log(` ${r}`)),console.log(""),console.log(l.dim("Set this as VIBGRATE_DSN in your CI environment.")),a||console.log(l.dim("The secret must be registered on your Vibgrate ingest API.")),t.write){let c=S.resolve(t.write);await e(c,i+`
3
+ `),console.log(""),console.log(l.green("\u2714")+` DSN written to ${t.write}`),console.log(l.yellow("\u26A0")+" Add this file to .gitignore!");}});function Vt(){return S.join(Ut.homedir(),".vibgrate")}function de(){return S.join(Vt(),"credentials.json")}function Io(){try{let t=ee.readFileSync(de(),"utf8"),e=JSON.parse(t);return e&&typeof e.dsn=="string"&&e.dsn?e:null}catch{return null}}function Ht(t){let e=Vt();ee.mkdirSync(e,{recursive:true});let n=de();ee.writeFileSync(n,JSON.stringify(t,null,2)+`
4
+ `,"utf8");try{ee.chmodSync(n,384);}catch{}}function Gt(){try{return ee.rmSync(de()),!0}catch{return false}}function fe(t){return t||(process.env.VIBGRATE_DSN?process.env.VIBGRATE_DSN:Io()?.dsn??void 0)}function Oe(t,e){console.log(`VIBGRATE_INGEST_ID=${t}`),e?.unchanged&&console.log("VIBGRATE_INGEST_UNCHANGED=1");}function Wt(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 Ro(t){try{let e=await t.clone().json();return e?.code!=="REGION_MISMATCH"||!e.region?void 0:Lt(e.region)}catch{return}}async function Fe(t){let e=t.host,n=await Wt(t,e);if(n.status===409){let o=await Ro(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 Wt(t,e));}return {response:n,host:e}}var Eo=[{files:["CLAUDE.md",".claude"],name:"claude"},{files:[".cursor",".cursorrules"],name:"cursor"},{files:[".windsurf"],name:"windsurf"},{files:[".github/copilot-instructions.md",".copilot"],name:"copilot"},{files:[".gemini"],name:"gemini"},{files:[".continuerc.json"],name:"continue"},{files:[".codex"],name:"codex"}];async function Xt(t){for(let e of Eo)for(let n of e.files)if(await p(S.join(t,n)))return e.name;return null}function Kt(t){let e=l.hex("#3FB0A4"),n=l.hex("#4FE3C1"),o=t?`vg install ${t}`:"vg install --all",r=t?l.dim(` (${t} config detected)`):"";console.log(""),console.log(e(" \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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),console.log(e(" \u2551")+" "+n("\u25C6")+" "+l.bold.white("Get AI-aware answers in your editor")+" "+e("\u2551")),console.log(e(" \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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),console.log(""),console.log(" "+l.bold.white(o)+r),console.log(""),console.log(" "+e("\xB7")+" "+l.white("Code map in your assistant")+l.dim(" \u2014 call trees, impact surfaces, import paths")),console.log(" "+e("\xB7")+" "+l.white("Offline drift")+l.dim(" \u2014 DriftScore and upgrade priorities, right inside your editor")),console.log(" "+e("\xB7")+" "+l.white("Version-correct library docs")+l.dim(" \u2014 pinned to your lockfile, no hallucinated APIs")),console.log("");}async function Do(t,e,n){let o=fe(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 r=pa(o);if(!r){console.error(l.red("Invalid DSN format.")),n.strict&&process.exit(1);return}let{body:a,contentEncoding:s}=await oa(t),i=String(Date.now()),c=r.host;if(n.region)try{c=ne(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=a.length,m=((1-g/p)*100).toFixed(0);console.log(l.dim(`Uploading to ${c}... (${(g/1024).toFixed(0)} KB, ${m}% smaller)`));try{let{response:u,host:f}=await Fe({scheme:r.scheme,host:c,keyId:r.keyId,secret:r.secret,body:a,contentEncoding:s,timestamp:i});if(c=f,!u.ok){let $=await u.text();throw new Error(`HTTP ${u.status}: ${$}`)}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){Oe(v.previousIngestId,{unchanged:!0});let $=`https://${ge(c)}/${r.workspaceId}/scan/${v.previousIngestId}`;console.log(l.dim(` Previous report: ${$}`));}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){Oe(v.ingestId);let $=`https://${ge(c)}/${r.workspaceId}/scan/${v.ingestId}`,k=process.platform==="win32"?"\x1B[0G\x1B[2K":"";console.log(""),console.log(k+l.dim(" Processing continues in the background. Results available shortly.")),console.log(""),console.log(k+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(k+l.bold(" \u{1F4CA} View Scan Report")),console.log(k+" "+l.underline.cyan($)),console.log(k+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 f=u instanceof Error?u.message:String(u);console.error(l.red(`Upload failed: ${f}`)),n.strict&&process.exit(1);}}function To(t,e){return [...e,...b$3(t)]}function zt(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 qt=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.',To,[]).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=!!fe(e.dsn),r=!e.offline&&(e.push||o),a=!await p(S.join(n,".vibgrate","scan_result.json")),s;if(r&&o){let m=fe(e.dsn),u=pa(m);if(u){let f=e.region?ne(e.region):u.host,v=await ia(n),$=await sa(n,v),k=e.repositoryName?.trim()||await ra(n);try{let w=await qa(u,f,{repositoryName:k,vcsSha:$.vcsSha});if(s=w.region,w.vm&&!w.vm.allowed&&(console.error(l.red(w.error??"VM meter usage exhausted")),console.error(l.dim(`VM minutes: ${w.vm.used}/${w.vm.limit} (${w.plan.label} plan) \u2014 enable overages or upgrade your plan.`)),process.exit(1)),w.repositories&&!w.repositories.allowed){console.error(l.red(w.error??`Repository limit reached for the ${w.plan.label} plan \u2014 cannot scan a new repository.`));let U=w.repositories.max<0?"unlimited":String(w.repositories.max);console.error(l.dim(`Repositories: ${w.repositories.total}/${U} (${w.plan.label} plan) \u2014 archive a repository or upgrade your plan.`)),w.upgradeUrl&&console.error(l.dim(` Upgrade: ${w.upgradeUrl}`)),process.exit(1);}if((w.status==="error"||!w.scans.allowed)&&(console.error(l.red(w.error??"Scan ingestion not allowed for this workspace.")),console.error(l.dim(`Credits: ${w.scans.used}/${w.scans.limit} (${w.plan.label} plan)`)),e.strict&&process.exit(1),process.exit(1)),console.log(l.dim(`Plan: ${w.plan.label} \u2014 scan credits ${w.scans.used}/${w.scans.limit} this month`)),w.repository?.unchanged){if(console.log(l.green("\u2714")+` Repository unchanged at ${w.repository.lastVcsSha?.slice(0,7)??"same revision"} \u2014 skipping scan.`),w.repository.lastIngestId){Oe(w.repository.lastIngestId,{unchanged:!0});let U=`https://${ge(f)}/${u.workspaceId}/scan/${w.repository.lastIngestId}`;console.log(l.dim(` Latest report: ${U}`));}else e.strict&&(console.error(l.red("Repository unchanged but no previous ingest id available.")),process.exit(1));return}}catch(w){let U=w instanceof Error?w.message:String(w);console.error(l.yellow(`Preflight check failed: ${U}`)),e.strict&&process.exit(1);}}}let i={vibgrateVersion:E,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??s,strict:e.strict,uiPurpose:e.uiPurpose,noLocalArtifacts:e.noLocalArtifacts,maxPrivacy:e.maxPrivacy,offline:e.offline,packageManifest:e.packageManifest,driftBudget:zt(e.driftBudget,"--drift-budget"),driftWorseningPercent:zt(e.driftWorsening,"--drift-worsening"),projectScanTimeout:e.projectScanTimeout&&parseInt(e.projectScanTimeout,10)||void 0,repositoryName:e.repositoryName?.trim()||void 0},c=await f(),p$1=await ua(n,i,c);if(e.failOn){let m=p$1.findings.some(f=>f.level==="error"),u=p$1.findings.some(f=>f.level==="warning");e.failOn==="error"&&m&&(console.error(l.red(`
5
+ Failing: ${p$1.findings.filter(f=>f.level==="error").length} error finding(s) detected.`)),process.exit(2)),e.failOn==="warn"&&(m||u)&&(console.error(l.red(`
6
+ Failing: findings detected at warn level or above.`)),process.exit(2));}if(i.driftBudget!==void 0&&p$1.drift.score>i.driftBudget&&(console.error(l.red(`
7
+ Failing fitness function: drift score ${p$1.drift.score}/100 exceeds budget ${i.driftBudget}.`)),process.exit(2)),i.driftWorseningPercent!==void 0&&(p$1.delta===void 0&&(console.error(l.red(`
8
+ Failing fitness function: --drift-worsening requires --baseline to compare against previous drift.`)),process.exit(2)),p$1.delta>0)){let m=p$1.drift.score-p$1.delta,u=Math.max(Math.abs(m),1e-4),f=p$1.delta/u*100;f>i.driftWorseningPercent&&(console.error(l.red(`
9
+ Failing fitness function: drift worsened by ${f.toFixed(2)}% (threshold ${i.driftWorseningPercent}%).`)),process.exit(2));}if(r&&await Do(p$1,n,i),i.format==="text"&&!o&&!e.offline&&!e.noLocalArtifacts&&!e.maxPrivacy&&a){let m=await Xt(n);Kt(m);}});function Qt(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${E}`)),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 c of t.projects){if(e.push(l.bold(` \u2500\u2500 ${c.name} `)+l.dim(`(${c.type}) ${c.path}`)),c.runtime){let m=c.runtimeMajorsBehind!==void 0&&c.runtimeMajorsBehind>0?l.yellow(` (${c.runtimeMajorsBehind} major${c.runtimeMajorsBehind>1?"s":""} behind)`):l.green(" (current)");e.push(` Runtime: ${c.runtime}${m}`);}if(c.targetFramework&&e.push(` Target: ${c.targetFramework}`),c.frameworks.length>0){e.push(" Frameworks:");for(let m of c.frameworks){let u=m.majorsBehind!==null?m.majorsBehind===0?l.green("current"):l.yellow(`${m.majorsBehind} behind`):l.dim("unknown");e.push(` ${m.name}: ${m.currentVersion??"?"} \u2192 ${m.latestVersion??"?"} (${u})`);}}let p=c.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 c=t.delta>0?l.red(`+${t.delta}`):t.delta<0?l.green(`${t.delta}`):l.dim("0");e.push(l.bold(" Drift Delta: ")+c+" (vs baseline)"),e.push("");}if(t.extended&&e.push(...No(t.extended)),t.findings.length>0){let c=t.findings.filter(u=>u.level==="error"),p=t.findings.filter(u=>u.level==="warning"),g=t.findings.filter(u=>u.level==="note"),m=[c.length>0?l.red(`${c.length} error${c.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(` (${m})`));for(let u of t.findings){let f=u.level==="error"?l.red("\u2716"):u.level==="warning"?l.yellow("\u26A0"):l.blue("\u2139");e.push(` ${f} ${u.message}`),e.push(l.dim(` ${u.ruleId} in ${u.location}`));}e.push("");}let r=Fo(t);if(r.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 c=0;c<r.length;c++){let p=r[c],g=l.bold.cyan(` ${c+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(...Oo(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 c of t.solutions){let p=c.drift?.score,g=typeof p=="number"?p<=30?l.green:p<=60?l.yellow:l.red:l.dim;e.push(` \u2022 ${c.name} (${c.projectPaths.length} projects) \u2014 ${typeof p=="number"?g(`${p}/100`):l.dim("n/a")}`);}e.push("");}let a=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: ")+a.bold(`${t.drift.score}/100`)),e.push(l.bold(" Risk Level: ")+_o(t.drift.riskLevel)),e.push(l.bold(" Projects: ")+`${t.projects.length}`),t.vcs){let c=[t.vcs.type];t.vcs.branch&&c.push(t.vcs.branch),t.vcs.shortSha&&c.push(l.dim(t.vcs.shortSha)),e.push(l.bold(" VCS: ")+c.join(" "));}e.push("");let s=new Set(t.drift.measured??["runtime","framework","dependency","eol"]);e.push(" "+l.bold.underline("Score Breakdown")),e.push(` Runtime: ${s.has("runtime")?Ce(t.drift.components.runtimeScore):l.dim("n/a")}`),e.push(` Frameworks: ${s.has("framework")?Ce(t.drift.components.frameworkScore):l.dim("n/a")}`),e.push(` Dependencies: ${s.has("dependency")?Ce(t.drift.components.dependencyScore):l.dim("n/a")}`),e.push(` EOL Risk: ${s.has("eol")?Ce(t.drift.components.eolScore):l.dim("n/a")}`),e.push("");let i=[`Scanned at ${t.timestamp}`];if(t.durationMs!==void 0){let c=(t.durationMs/1e3).toFixed(1);i.push(`${c}s`);}return t.filesScanned!==void 0&&i.push(`${t.filesScanned} file${t.filesScanned!==1?"s":""} scanned`),t.treeSummary&&(i.push(`${t.treeSummary.totalFiles.toLocaleString()} workspace files`),i.push(`${t.treeSummary.totalDirs.toLocaleString()} dirs`)),e.push(l.dim(` ${i.join(" \xB7 ")}`)),e.push(""),e.join(`
10
+ `)}function _o(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 Ce(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 Yt={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 No(t){let e=[];if(t.toolingInventory){let n=t.toolingInventory,o=Object.entries(n).filter(([,r])=>r.length>0);if(o.length>0){e.push(l.bold.underline(" Tech Stack"));for(let[r,a]of o){let s=Yt[r]??r,i=a.map(c=>l.white(c.name)).join(l.dim(", "));e.push(` ${l.cyan(s)}: ${i}`);}e.push("");}}if(t.serviceDependencies){let n=t.serviceDependencies,o=Object.entries(n).filter(([,r])=>r.length>0);if(o.length>0){e.push(l.bold.underline(" Services & Integrations"));for(let[r,a]of o){let s=Yt[r]??r,i=a.map(c=>{let p=c.version?l.dim(` ${c.version}`):"";return l.white(c.name)+p}).join(l.dim(", "));e.push(` ${l.cyan(s)}: ${i}`);}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(a=>l.dim(a)).join(", ")}`),n.legacyPolyfills.length>0&&e.push(` ${l.yellow("Polyfills")}: ${n.legacyPolyfills.map(a=>l.dim(a)).join(", ")}`),n.peerConflictsDetected&&e.push(` ${l.red("\u26A0")} Peer dependency conflicts detected`),e.push(` Recommendation: ${l.bold(n.overallRecommendation)}`);let r=n.projectIntelligence.filter(a=>a.packages.length>0).slice(0,3);if(r.length>0){e.push(" Major Upgrade Intelligence:");for(let a of r){e.push(` - ${a.project} (${a.recommendation})`);for(let s of a.packages.slice(0,2))e.push(` \xB7 ${s.package} ${s.currentVersion??"?"} \u2192 ${s.targetVersion??"?"} | touched ~${s.usage.touchedPercent}% | ${s.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 r of o)e.push(` - [${r.kind}] ${r.value} ${l.dim(`(${r.file})`)}`);}if(n.unknownSignals.length>0){e.push(" Unknowns:");for(let r of n.unknownSignals.slice(0,4))e.push(` - ${l.yellow(r)}`);}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(r=>`${r.path} (${r.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 Oo(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 ${Ce(n.driftScore)} risk ${o}`);}e.push("");}return e}function Fo(t){let e=[],n=t.projects.filter(s=>s.runtimeMajorsBehind!==void 0&&s.runtimeMajorsBehind>=3);if(n.length>0){let s=n.map(p=>p.name).join(", "),i="End-of-life runtimes no longer receive security patches and block ecosystem upgrades.",c=[];for(let p of n)c.push(`
11
+ ./${p.path}`),c.push(`
12
+ ${p.runtime} \u2192 ${p.runtimeLatest} (${p.runtimeMajorsBehind} major${p.runtimeMajorsBehind>1?"s":""} behind)`);i+=c.join(""),e.push({title:`Upgrade EOL runtime${n.length>1?"s":""} in ${s}`,explanation:i,impact:`\u2212${Math.min(n.length*10,30)} drift points (runtime & EOL scores)`,severity:100});}let o=[];for(let s of t.projects)for(let i of s.frameworks)i.majorsBehind!==null&&i.majorsBehind>=3&&o.push({name:i.name,fw:`${i.currentVersion} \u2192 ${i.latestVersion}`,behind:i.majorsBehind,project:s.name,projectPath:s.path});if(o.length>0){let s=o.sort((u,f)=>f.behind-u.behind)[0],i=o.length>1?` (+${o.length-1} more)`:"",c=`${s.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;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(`
14
+ ${u.name}: ${u.fw} (${u.behind} major${u.behind>1?"s":""} behind)`),g++;}let m=o.length-g;c+=p.join(""),m>0&&(c+=`
15
+ ... and ${m} more`),e.push({title:`Upgrade ${s.name} ${s.fw} in ${s.project}${i}`,explanation:c,impact:"\u22125\u201315 drift points",severity:90});}for(let s of t.projects){let i=s.dependencyAgeBuckets,c=i.current+i.oneBehind+i.twoPlusBehind;if(c===0)continue;let p=Math.round(i.twoPlusBehind/c*100);if(p>=40){let g=`${i.twoPlusBehind} of ${c} dependencies are 2+ majors behind. Run \`npm outdated\` and prioritise packages with known CVEs or breaking API changes.`,m=s.dependencies.filter(u=>u.majorsBehind!==null&&u.majorsBehind>=2).sort((u,f)=>(f.majorsBehind??0)-(u.majorsBehind??0));if(m.length>0){let u=[],f=0;u.push(`
16
+ ./${s.path}`);for(let $ of m){if(f>=8)break;let k=$.resolvedVersion??$.currentSpec,w=$.latestStable??"?";u.push(`
17
+ ${$.package}: ${k} \u2192 ${w} (${$.majorsBehind} major${$.majorsBehind>1?"s":""} behind)`),f++;}let v=m.length-f;g+=u.join(""),v>0&&(g+=`
18
+ ... and ${v} more`);}e.push({title:`Reduce dependency rot in ${s.name} (${p}% severely outdated)`,explanation:g,impact:"\u22125\u201310 drift points",severity:80+p/10});}}let r=[];for(let s of t.projects)for(let i of s.frameworks)i.majorsBehind===2&&r.push({name:i.name,project:s.name,projectPath:s.path,fw:`${i.currentVersion} \u2192 ${i.latestVersion}`});let a=[...new Map(r.map(s=>[s.name,s])).values()];if(a.length>0){let s=a.slice(0,3).map(u=>`${u.name} (${u.fw})`).join(", "),i=a.length>3?` +${a.length-3} more`:"",c="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 r){if(g>=8)break;p.push(`
19
19
  ./${u.projectPath}`),p.push(`
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
- ./${v}`);for(let $ of m){if(u>=10)break;f.push(`
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+`
20
+ ${u.name}: ${u.fw}`),g++;}let m=r.length-g;c+=p.join(""),m>0&&(c+=`
21
+ ... and ${m} more`),e.push({title:`Plan major framework upgrades: ${s}${i}`,explanation:c,impact:"\u22125\u201310 drift points",severity:60});}if(t.extended?.breakingChangeExposure){let s=t.extended.breakingChangeExposure,i=s.deprecatedPackages.length+s.legacyPolyfills.length;if(i>0){let c=[...s.deprecatedPackages,...s.legacyPolyfills].slice(0,5).join(", "),p=i>5?` +${i-5} more`:"",g=`${i} package${i!==1?"s":""} are deprecated or legacy polyfills. These receive no updates and may have known vulnerabilities.`,m=new Set([...s.deprecatedPackages,...s.legacyPolyfills]),u=[],f=0;for(let $ of t.projects){let k=$.dependencies.filter(w=>m.has(w.package));if(k.length!==0){if(f>=10)break;u.push(`
22
+ ./${$.path}`);for(let w of k){if(f>=10)break;let U=w.resolvedVersion??w.currentSpec,O=s.deprecatedPackages.includes(w.package)?"deprecated":"polyfill";u.push(`
23
+ ${w.package}: ${U} (${O})`),f++;}}}let v=i-f;g+=u.join(""),v>0&&(g+=`
24
+ ... and ${v} more`),e.push({title:`Replace deprecated/legacy packages: ${c}${p}`,explanation:g,severity:55});}}if(t.extended?.dependencyGraph){let s=t.extended.dependencyGraph,i=s.phantomDependencies.length;if(i>=10){let c="Packages used in code but not declared in package.json. These rely on transitive installs and can break unpredictably when other packages update.",p=s.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 m=[],u=0;for(let[v,$]of g){if(u>=10)break;m.push(`
25
+ ./${v}`);for(let k of $){if(u>=10)break;m.push(`
26
+ ${k.package}: ${k.spec}`),u++;}}let f=i-u;c+=m.join(""),f>0&&(c+=`
27
+ ... and ${f} more`);}e.push({title:`Fix ${i} phantom dependencies`,explanation:c,severity:45});}}if(t.extended?.securityPosture){let s=t.extended.securityPosture;if(s.envFilesTracked||!s.lockfilePresent){let i=[];s.envFilesTracked&&i.push(".env files are tracked in git"),s.lockfilePresent||i.push("no lockfile found");let c;s.envFilesTracked?(c="Environment files may contain secrets. Add them to .gitignore and rotate any exposed credentials immediately.",c+=`
28
+ ./.gitignore`,c+=`
29
+ Add: .env, .env.*, .env.local`):(c="Without a lockfile, installs are non-deterministic. Run the install command to generate one and commit it.",c+=`
30
+ ./`,c+=`
31
+ Missing: ${s.lockfileTypes.length>0?s.lockfileTypes.join(", ")+" (multiple types detected)":"package-lock.json, pnpm-lock.yaml, or yarn.lock"}`),e.push({title:`Fix security posture: ${i.join(", ")}`,explanation:c,severity:95});}}if(t.extended?.dependencyGraph){let i=t.extended.dependencyGraph.duplicatedPackages.filter(c=>c.versions.length>=3);if(i.length>=3){i.slice(0,4).map(f=>`${f.name} (${f.versions.length}v)`).join(", ");let p=`${i.length} packages have 3+ versions installed. Run \`npm dedupe\` to reduce bundle size and install time.`,g=[],m=0;for(let f of i){if(m>=8)break;g.push(`
32
+ ${f.name}: ${f.versions.join(", ")} (${f.consumers} consumer${f.consumers!==1?"s":""})`),m++;}let u=i.length-m;p+=g.join(""),u>0&&(p+=`
33
+ ... and ${u} more`),e.push({title:"Deduplicate heavily-versioned packages",explanation:p,severity:35});}}return e.sort((s,i)=>i.severity-s.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 s=o.runtimeMajorsBehind!==void 0&&o.runtimeMajorsBehind>0?` \u2014 ${o.runtimeMajorsBehind} major(s) behind`:" \u2014 current";e.push(`- **Runtime:** ${o.runtime}${s}`);}if(o.frameworks.length>0){e.push("- **Frameworks:**");for(let s of o.frameworks){let i=s.majorsBehind!==null?s.majorsBehind===0?"current":`${s.majorsBehind} behind`:"unknown";e.push(` - ${s.name}: ${s.currentVersion??"?"} \u2192 ${s.latestVersion??"?"} (${i})`);}}let r=o.dependencyAgeBuckets;r.current+r.oneBehind+r.twoPlusBehind+r.unknown>0&&e.push(`- **Dependencies:** ${r.current} current, ${r.oneBehind} 1-behind, ${r.twoPlusBehind} 2+ behind, ${r.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 r of o.topEvidence.slice(0,10))e.push(` - [${r.kind}] ${r.value} (${r.file})`);}if(o.unknownSignals.length>0){e.push("- **Unknowns:**");for(let r of o.unknownSignals.slice(0,5))e.push(` - ${r}`);}e.push("");}if(t.extended?.standards&&t.extended.standards.recommended.length>0){let o=t.extended.standards;e.push("## Recommended Standards"),e.push("");let r=o.projectPurposes.map(a=>`${a.project} \u2192 ${a.category}`).join(", ");if(r&&e.push(`- **Detected purpose:** ${r}`),o.frameworks.length>0){e.push("- **Compliance framework coverage:**");for(let a of o.frameworks)e.push(` - ${a.name}: ${a.recommendedMembers}/${a.totalMembers} member standards apply`);}e.push("- **Top standards to consider:**");for(let a of o.recommended.slice(0,10)){let s=a.complianceRelevant?" _(compliance)_":"";e.push(` - **${a.name}** \u2014 ${a.reason}${s}`);}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 r=o.level==="error"?"\u{1F534}":o.level==="warning"?"\u{1F7E1}":"\u{1F535}";e.push(`| ${r} ${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",r=t.delta>0?" _(worsened)_":t.delta<0?" _(improved)_":"";e.push(`## Drift Delta: ${o} ${t.delta>0?"+":""}${t.delta} vs baseline${r}`),e.push("");}return e.join(`
34
+ `)}var nn=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(Qt(n));break}});function on(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 Uo=t=>new Promise(e=>setTimeout(e,t)),rn=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 (${ae().join(", ")})`,"us").option("--no-browser","Do not attempt to open a browser automatically").action(async t=>{let e;try{e=ne(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&&on(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,a=Date.now()+(o.expiresIn||900)*1e3;for(;Date.now()<a;){await Uo(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){Ht({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 ${de()}`)),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 an=new Command("logout").description("Clear stored Vibgrate login credentials").action(()=>{let t=Gt();console.log(t?l.green("\u2714")+" Logged out. Stored credentials removed.":l.dim(`No stored credentials found at ${de()}.`));});var Ho=[{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 cn(t,e=3){let n=t.topEvidence,o=n.filter(g=>g.kind==="dependency").map(g=>g.value).slice(0,10),r=Xo(n.filter(g=>g.kind==="route").map(g=>g.value)).slice(0,15),a=n.filter(g=>g.kind!=="dependency"&&g.kind!=="route"&&g.kind!=="feature_flag"),s=new Map,i={};for(let g of a){let m=Go(g.value);s.has(m)||s.set(m,new Set);let u=Wo(g.value);u.length>=3&&s.get(m).add(u);}let c=[];for(let[g,m]of s){let u=Jo([...m]);i[g]=u.length;for(let f of u.slice(0,e))c.push({kind:"text",value:f,category:g});}let p=n.filter(g=>g.kind==="feature_flag");return p.length>0&&(i.feature_flags=p.length,c.push({kind:"feature_flag",value:"feature flags detected",category:"feature_flags"})),{samples:c,categoryCounts:i,originalCount:n.length,dependencies:o,routes:r,detectedFrameworks:t.detectedFrameworks}}function Go(t){for(let{category:e,pattern:n}of Ho)if(n.test(t))return e;return "general"}function Wo(t){return t.toLowerCase().replace(/[^a-z0-9\s-]/g," ").replace(/\s+/g," ").trim().slice(0,60)}function Jo(t){let e=t.sort((o,r)=>r.length-o.length),n=[];for(let o of e)n.some(a=>{let s=o.slice(0,6);return a.startsWith(s)||a.includes(o)||o.includes(a)})||n.push(o);return n}function Xo(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 zo=promisify(ln.gzip),J=50;function Ie(t){let e=t.match(/^(.+?)\s*\(/);return e?e[1].trim():t.trim()}function qo(t){return {databaseTechnologies:t.databaseTechnologies.slice(0,10),connectionStrings:[],connectionPoolSettings:t.connectionPoolSettings.slice(0,J),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(Ie).slice(0,J),tables:t.tables.map(Ie).slice(0,J),views:t.views.map(Ie).slice(0,J),storedProcedures:t.storedProcedures.map(Ie).slice(0,J),triggers:t.triggers.map(Ie).slice(0,J),rowLevelSecurityPolicies:t.rowLevelSecurityPolicies.slice(0,20),otherServices:t.otherServices.slice(0,20)}}function Yo(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,J).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 Qo(t){return {faviconFiles:t.faviconFiles.slice(0,1),productLogos:[]}}function Zo(t){let e={...t};if(e.extended){let n={...e.extended};if(n.dataStores&&(n.dataStores=qo(n.dataStores)),n.apiSurface&&(n.apiSurface=Yo(n.apiSurface)),n.assetBranding&&(n.assetBranding=Qo(n.assetBranding)),n.uiPurpose){let o=cn(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,J),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,J),phantomDependencyDetails:n.dependencyGraph.phantomDependencyDetails?.slice(0,J),duplicatedPackages:n.dependencyGraph.duplicatedPackages.slice(0,J)}),e.extended=n;}return e}async function er(t){let e=JSON.stringify(t);return zo(e,{level:9})}async function dn(t){let e=Zo(t);return {body:await er(e),contentEncoding:"gzip"}}function Le(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 gn(t,e){return Ne.createHmac("sha256",e).update(t).digest("base64")}var fn=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 (${ae().join(", ")})`).option("--file <file>","Scan artifact file",".vibgrate/scan_result.json").option("--strict","Fail on upload errors").action(async t=>{let e=fe(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=Le(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:a,contentEncoding:s}=await dn(r),i=String(Date.now()),c$1=n.host;if(t.region)try{c$1=ne(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=a.length,m=((1-g/p)*100).toFixed(0);console.log(l.dim(`Uploading to ${c$1}... (${(g/1024).toFixed(0)} KB, ${m}% smaller)`));try{let{response:u,host:f}=await Fe({scheme:n.scheme,host:c$1,keyId:n.keyId,secret:n.secret,body:a,contentEncoding:s,timestamp:i});if(c$1=f,!u.ok){let $=await u.text();throw new Error(`HTTP ${u.status}: ${$}`)}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 k=`https://${ge(c$1)}/${n.workspaceId}/scan/${v.ingestId}`;console.log(l.dim("View report: ")+l.underline(k));}}catch(u){let f=u instanceof Error?u.message:String(u);console.error(l.red(`Upload failed: ${f}`)),t.strict&&process.exit(1);}});var je=b$2(a(),1);var hn="https://registry.npmjs.org/@vibgrate%2fcli/latest",bn=S.join(Ut.homedir(),".vibgrate"),yn=S.join(bn,"update-check.json"),nr=720*60*1e3;async function wn(){try{let t=await or();if(t&&Date.now()-t.checkedAt<nr)return {current:E,latest:t.latest,updateAvailable:je.default.gt(t.latest,E)};let e=new AbortController,n=setTimeout(()=>e.abort(),5e3);n.unref?.();let o;try{o=await fetch(hn,{headers:{Accept:"application/json"},signal:e.signal});}finally{clearTimeout(n);}if(!o.ok)return null;let a=(await o.json()).version;return !a||!je.default.valid(a)?null:(await $n({latest:a,checkedAt:Date.now()}),{current:E,latest:a,updateAvailable:je.default.gt(a,E)})}catch{return null}}async function vn(){try{let t=new AbortController,e=setTimeout(()=>t.abort(),1e4);e.unref?.();let n;try{n=await fetch(hn,{headers:{Accept:"application/json"},signal:t.signal});}finally{clearTimeout(e);}if(!n.ok)return null;let r=(await n.json()).version;return !r||!je.default.valid(r)?null:(await $n({latest:r,checkedAt:Date.now()}),r)}catch{return null}}async function or(){try{let t=await K.readFile(yn,"utf-8"),e=JSON.parse(t);return e.latest&&typeof e.checkedAt=="number"?e:null}catch{return null}}async function $n(t){try{await K.mkdir(bn,{recursive:!0}),await K.writeFile(yn,JSON.stringify(t),"utf-8");}catch{}}function ir(){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 ar(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 cr(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 lr(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 dr(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 Sn=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: ${E}`)),console.log(l.dim("Checking npm registry..."));let e=await vn();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,E)){console.log(l.green("\u2714")+` You are on the latest version (${E}).`);return}if(console.log(l.yellow(`Update available: ${E} \u2192 ${e}`)),t.check){console.log(l.dim('Run "vibgrate update" to install.'));return}let o=process.cwd(),r=ir(),a=t.global||r!==null,s=t.pm||(r??await cr(o)),i;if(a)i=ar(s,"@vibgrate/cli",e),console.log(l.dim(`Updating global installation with ${s}: ${i}`));else {let c=await dr(o);i=lr(s,"@vibgrate/cli",e,c),console.log(l.dim(`Using ${s}: ${i}`));}try{execSync(i,{cwd:o,stdio:"inherit"}),console.log(l.green("\u2714")+` Updated to @vibgrate/cli@${e}`);}catch{console.error(l.red(`Update failed. Run manually: ${i}`)),process.exit(1);}});var gr="https://openvex.dev/ns/v0.2.0",kn=["not_affected","affected","fixed","under_investigation"],xn=["component_not_present","vulnerable_code_not_present","vulnerable_code_not_in_execute_path","vulnerable_code_cannot_be_controlled_by_adversary","inline_mitigations_already_exist"],X=class extends Error{};function fr(t){let e=t.statements.map((n,o)=>{if(!n.vulnerability||typeof n.vulnerability!="string")throw new X(`statement[${o}]: "vulnerability" is required`);if(!kn.includes(n.status))throw new X(`statement[${o}] (${n.vulnerability}): invalid status "${n.status}". Expected one of: ${kn.join(", ")}`);let r=n.products&&n.products.length>0?n.products:t.defaultProduct?[t.defaultProduct]:[];if(r.length===0)throw new X(`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 X(`statement[${o}] (${n.vulnerability}): "not_affected" requires a justification or impact_statement.`);if(n.justification&&!xn.includes(n.justification))throw new X(`statement[${o}] (${n.vulnerability}): invalid justification "${n.justification}". Expected one of: ${xn.join(", ")}`);if(n.status==="affected"&&!n.action_statement)throw new X(`statement[${o}] (${n.vulnerability}): "affected" requires an action_statement.`);let a={vulnerability:{name:n.vulnerability},products:r.map(s=>({"@id":s})),status:n.status};return n.justification&&(a.justification=n.justification),n.impact_statement&&(a.impact_statement=n.impact_statement),n.action_statement&&(a.action_statement=n.action_statement),a});return {"@context":gr,"@id":t.id??`https://vibgrate.com/vex/${randomUUID()}`,author:t.author,timestamp:t.timestamp??new Date().toISOString(),version:1,statements:e}}async function mr(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 X(`${t}: expected a JSON array of statements or an object with a "statements" array.`);return n}function hr(t,e){let n;try{n=JSON.parse(t);}catch{throw new X(`--statement must be a JSON object: ${t.slice(0,60)}\u2026`)}return [...e,n]}var Pn=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.`,hr,[]).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 mr(r));}e$1.push(...t.statement);let n=fr({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
- `);}catch(e){throw e instanceof W&&(process.stderr.write(l.red(`VEX validation error: ${e.message}
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
- `)){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]")&&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
- `)){let $=m.trim();$&&(n.verbose&&process.stderr.write(l.dim(`[${e}] ${$}
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.
38
+ `);}catch(e){throw e instanceof X&&(process.stderr.write(l.red(`VEX validation error: ${e.message}
39
+ `)),process.exit(1)),e}});function jn(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 br(t){let e=jn(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 yr(t){let e=jn(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 Cn(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 wr(t,e){let n=Cn(t),o=Cn(e),r=[],a=[],s=[];for(let[c,p]of o.entries()){if(!n.has(c)){r.push(`${c} @ ${p.resolvedVersion??p.currentSpec}`);continue}let g=n.get(c),m=g.resolvedVersion??g.currentSpec,u=p.resolvedVersion??p.currentSpec;(m!==u||g.majorsBehind!==p.majorsBehind)&&s.push(`${c} ${m} -> ${u} (majorsBehind ${g.majorsBehind??"unknown"} -> ${p.majorsBehind??"unknown"})`);}for(let[c,p]of n.entries())o.has(c)||a.push(`${c} @ ${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 (${r.length})`,...r.map(c=>` + ${c}`),"",`Removed dependencies (${a.length})`,...a.map(c=>` - ${c}`),"",`Changed dependencies (${s.length})`,...s.map(c=>` * ${c}`)].join(`
40
+ `)}async function st(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 vr=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 st(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"?br(e$1):yr(e$1),r=JSON.stringify(o,null,2);t.out?(await e(S.resolve(t.out),r),console.log(l.green("\u2714")+` SBOM written to ${t.out}`)):console.log(r);}),$r=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 st(t.from),n=await st(t.to),o=wr(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);}),Rn=new Command("sbom").description("Supply-chain evidence: SBOM export/delta and OpenVEX generation").addCommand(vr).addCommand($r).addCommand(Pn);var xr=new URL("../../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url),at=fileURLToPath(xr);function Pr(){return existsSync(at)}async function Cr(){if(!Pr())throw new Error(`WASM engine not built. Run \`pnpm --filter @vibgrate/hcs build\` first.
41
+ Expected: ${at}`);return await import(at)}async function En(t,e){let o=(await Cr()).derive_behavioural_facts_from_lines(JSON.stringify(t),JSON.stringify(e));return Ir(o)}function Ir(t){let e=JSON.parse(t),n=e.filter(s=>s.factType==="BehaviouralAssertion").length,r=e.find(s=>s.factType==="BehaviouralSpec")?.payload,a=r?.coverage;return {envelopes:e,summary:{assertions:n,surfaceFacts:Number(a?.surfaceFacts??0),assertedFacts:Number(a?.assertedFacts??0),behaviouralConfidence:Number(r?.behaviouralConfidence??0)}}}async function An(t){try{return await jr(t)}catch{return {type:"unknown"}}}async function jr(t){let e=await Rr(t);if(!e)return {type:"unknown"};let n=S.join(e,"HEAD"),o;try{o=(await K.readFile(n,"utf8")).trim();}catch{return {type:"unknown"}}let r,a;if(o.startsWith("ref: ")){let i=o.slice(5);a=i.startsWith("refs/heads/")?i.slice(11):i,r=await Er(e,i);}else /^[0-9a-f]{40}$/i.test(o)&&(r=o);let s=await Ar(e);return {type:"git",sha:r??void 0,shortSha:r?r.slice(0,7):void 0,branch:a??void 0,remoteUrl:s}}async function Rr(t){let e=S.resolve(t),n=S.parse(e).root;for(;e!==n;){let o=S.join(e,".git");try{let r=await K.stat(o);if(r.isDirectory())return o;if(r.isFile()){let a=(await K.readFile(o,"utf8")).trim();if(a.startsWith("gitdir: "))return S.resolve(e,a.slice(8))}}catch{}e=S.dirname(e);}return null}async function Er(t,e){let n=S.join(t,e);try{let r=(await K.readFile(n,"utf8")).trim();if(/^[0-9a-f]{40}$/i.test(r))return r}catch{}let o=S.join(t,"packed-refs");try{let r=await K.readFile(o,"utf8");for(let a of r.split(`
42
+ `)){if(a.startsWith("#")||a.startsWith("^"))continue;let s=a.trim().split(" ");if(s.length>=2&&s[1]===e)return s[0]}}catch{}}async function Ar(t){let e=await Dr(t);if(e)try{let o=(await K.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 Dr(t){let e=S.join(t,"config");try{if((await K.stat(e)).isFile())return e}catch{}let n=S.join(t,"commondir");try{let o=(await K.readFile(n,"utf8")).trim();if(!o)return;let r=S.resolve(t,o),a=S.join(r,"config");if((await K.stat(a)).isFile())return a}catch{return}}var _n=/^[A-Za-z0-9._-]+@[A-Za-z0-9._-]+:.+$/;function lt(t){return t?!!(/^(https?|ssh|git):\/\//i.test(t)||_n.test(t)):false}function He(t){if(!t||_n.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 Fr(){let t=spawnSync("git",["--version"],{stdio:"ignore"});return !t.error&&t.status===0}function Mr(){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 ct(t,e){return new Promise((n,o)=>{let r=spawn("git",t,{stdio:["ignore","ignore","pipe"],env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_ASKPASS:"echo"}}),a="",s=false,i=setTimeout(()=>{s=true,r.kill("SIGKILL");},e.timeoutMs);r.stderr.on("data",c=>{a.length<8192&&(a+=Lr(String(c)));}),r.on("error",c=>{clearTimeout(i),o(new L(`Failed to run git: ${c.message}`));}),r.on("close",c=>{if(clearTimeout(i),s){o(new L(`git clone timed out for ${e.redacted}`));return}n({code:c??0,stderr:a.trim()});});})}function Lr(t){return t.replace(/([a-z]+:\/\/)[^/\s@]+@/gi,"$1")}async function Nn(t,e){let n=He(t);if(!lt(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(!Fr())throw new L(`git is required to clone ${n} but was not found on PATH. ${Mr()}`);let o=await mkdtemp(S.join(Ut.tmpdir(),"vibgrate-hcs-clone-")),r=async()=>{await rm(o,{recursive:true,force:true}).catch(()=>{});};try{e.verbose&&process.stderr.write(`Cloning ${n} \u2026
43
+ `);let a=await ct(["clone","--depth","1","--quiet","--",t,o],{timeoutMs:e.timeoutMs,redacted:n});if(a.code!==0)throw new L(`git clone failed for ${n}: ${a.stderr||`exit ${a.code}`}`);if(e.ref){e.verbose&&process.stderr.write(`Checking out ${e.ref} \u2026
44
+ `);let i=(await ct(["-C",o,"fetch","--depth","1","--quiet","origin",e.ref],{timeoutMs:e.timeoutMs,redacted:n})).code===0?"FETCH_HEAD":e.ref,c=await ct(["-C",o,"checkout","--quiet","--detach",i],{timeoutMs:e.timeoutMs,redacted:n});if(c.code!==0)throw new L(`Could not check out ref "${e.ref}" from ${n}: ${c.stderr||`exit ${c.code}`}`)}return {dir:o,cleanup:r}}catch(a){throw await r(),a instanceof L?a:new L(String(a))}}function Br(t){let e=Ne.createHash("sha256");for(let n of t)e.update(n),e.update(`
45
+ `);return `sha256:${e.digest("hex")}`}function dt(t){if(!t)return;let o=t.replace(/^[a-z]+:\/\//i,"").replace(/^[^/@]+@/,"").replace(/^[^/:]+[/:]/,"").split("/").filter(Boolean);if(o.length===0)return;let r=o[o.length-1].replace(/\.git$/i,""),a=o.length>=2?o[o.length-2]:void 0;return a?`${a}/${r}`:r}function Fn(t){return {factType:"ScanManifest",manifestVersion:"1.0",emittedAt:t.emittedAt??new Date().toISOString(),repository:{remoteUrl:t.remoteUrl,name:t.repositoryName??dt(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:Br(t.factLines)}}var Mn=0,Gr=1,Ee=2,Ae=3,Wr=4,F=5,Hn={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"])},Ln=new Set(Object.keys(Hn)),Jr=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"]),Xr=[/[/\\]test[/\\]/i,/[/\\]tests[/\\]/i,/[/\\]__tests__[/\\]/i,/[/\\]spec[/\\]/i,/\.spec\./i,/\.test\./i,/[/\\]test-/i];function Kr(t){return Xr.some(e=>e.test(t))}function zr(t){let e=t.trim().toLowerCase();return e==="vb.net"||e==="visualbasic"||e==="visual-basic"?"vbnet":e}async function qr(t,e){let n=new Map;async function o(r,a){let s;try{s=await K.readdir(r,{withFileTypes:!0});}catch{return}for(let i of s){if(i.name.startsWith("."))continue;let c=S.join(r,i.name),p=S.join(a,i.name);if(i.isDirectory()){Jr.has(i.name)||await o(c,p);continue}if(!i.isFile()||!e&&Kr(p))continue;let g=S.extname(i.name).toLowerCase();for(let[m,u]of Object.entries(Hn))if(u.has(g)){n.set(m,(n.get(m)??0)+1);break}}}return await o(t,""),Array.from(n.entries()).map(([r,a])=>({language:r,fileCount:a})).sort((r,a)=>a.fileCount-r.fileCount)}function pt(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 Yr(t){let e=[],n=[];for(let o of t){let r;try{r=JSON.parse(o);}catch{n.push(o);continue}let a=r;a.factType==="Models"||a.factType==="References"||a.factType==="ScanManifest"?e.push(o):n.push(o);}return {preamble:e,facts:n}}function Qr(){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 a=import.meta.resolve("@vibgrate/hcs-node-worker"),s=a.startsWith("file://")?new URL(a).pathname:a;if(existsSync(s))return s}catch{}let o=S.resolve(t,"..","..","..","vibgrate-hcs","node","dist","main.js");if(existsSync(o))return o;let r=S.resolve(t,"..","..","..","vibgrate-hcs","node","src","main.ts");if(existsSync(r))return r;throw new Error('Cannot locate HCS worker. Run "pnpm build" in the CLI package to bundle the worker into dist/.')}var Gn=new Set(["typescript","javascript"]),Zr=new Set(["swift","vb6","rust","ruby","php","dart","scala","cobol","cplusplus"]),Wn=new Set([...Gn,...Zr]),es=new Set(["go","python","java","csharp","vbnet"]),Bn=new Set([...Wn,...es]),Jn={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 ts(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 ut(t){let e=Jn[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 ns(t,e,n){let o=Qr(),r=[];if(Gn.has(e))r.push("--project",t);else {r.push("--project",t);let a=`--${e}-project`;r.push(a,t),e==="cobol"&&n.copybookPaths&&r.push("--cobol-copybook-paths",n.copybookPaths);}return new Promise(a=>{let s=[],i=[],c="",p=false,g=spawn("node",["--enable-source-maps",o,...r],{cwd:t,stdio:["ignore","pipe","pipe"],env:{...process.env,NODE_OPTIONS:"--max-old-space-size=4096"}}),m=setTimeout(()=>{p=true,g.kill("SIGKILL");},n.timeoutMs);g.stdout.on("data",u=>{c+=u.toString();let f=c.split(`
46
+ `);c=f.pop();for(let v of f){let $=v.trim();$&&s.push($);}}),g.stderr.on("data",u=>{let f=u.toString();for(let v of f.split(`
47
+ `)){let $=v.trim();if($){if($.startsWith("[progress] ")){try{let k=JSON.parse($.slice(11));n.onProgress?.(k);}catch{}continue}n.verbose&&process.stderr.write(l.dim(`[${e}] ${$}
48
+ `)),$.startsWith("[error]")&&i.push($);}}}),g.on("close",u=>{clearTimeout(m),c.trim()&&s.push(c.trim()),a(p?{language:e,facts:s,errors:["Worker killed: timeout exceeded"],exitCode:Ae}:{language:e,facts:s,errors:i,exitCode:u??0});}),g.on("error",u=>{clearTimeout(m),i.push(`Failed to spawn worker: ${u.message}`),a({language:e,facts:s,errors:i,exitCode:Ee});});})}function os(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 r=S.join(t,o);if(existsSync(r))return r}return null}function rs(t,e){let n=import.meta.dirname??S.dirname(new URL(import.meta.url).pathname),o=S.resolve(n,"..","..","vibgrate-hcs"),r=S.resolve(n,"..","..","..","vibgrate-hcs"),a=existsSync(o)?o:r,s=S.resolve(n,"workers");switch(t){case "go":{let i=S.join(s,process.platform==="win32"?"vibgrate-hcs-go.exe":"vibgrate-hcs-go");if(existsSync(i))return {cmd:i,args:["--project",e,"--output","ndjson"]};let c=S.join(a,"go");return existsSync(S.join(c,"main.go"))?{cmd:"go",args:["run",".","--project",e,"--output","ndjson"],cwd:c}:null}case "python":{let i=S.join(s,"vibgrate-hcs-python");if(existsSync(i))return {cmd:i,args:["--project",e,"--output","ndjson"]};let c=S.join(a,"python");return existsSync(S.join(c,"pyproject.toml"))?{cmd:"python3",args:["-m","vibgrate_hcs_python.main","--project",e,"--output","ndjson"],cwd:c}:null}case "java":{let i=S.join(s,"vibgrate-hcs-jvm.jar");if(existsSync(i))return {cmd:"java",args:["-jar",i,"--project",e,"--output","ndjson"]};let c=S.join(a,"jvm");if(existsSync(S.join(c,"build.gradle.kts"))){let p=S.join(c,process.platform==="win32"?"gradlew.bat":"gradlew");return {cmd:existsSync(p)?p:"gradle",args:["-q","--console=plain","run",`--args=--project ${e} --output ndjson`],cwd:c}}return null}case "csharp":case "vbnet":{let i=os(s);if(i)return {cmd:i,args:["--project",e,"--output","ndjson"]};let c=S.join(s,"VibgrateHcsWorker.dll");if(existsSync(c))return {cmd:"dotnet",args:[c,"--project",e,"--output","ndjson"]};let p=S.join(a,"dotnet","src","VibgrateHcsWorker","VibgrateHcsWorker.csproj");return existsSync(p)?{cmd:"dotnet",args:["run","--project",p,"--","--project",e,"--output","ndjson"]}:null}default:return null}}async function ss(t,e,n){let o=rs(e,t);return o?new Promise(r=>{let a=[],s=[],i="",c=false;n.verbose&&process.stderr.write(l.dim(`[${e}] Spawning: ${o.cmd} ${o.args.join(" ")}
49
+ `));let p=Jn[e];if(p&&o.cmd===p.command&&!ts(o.cmd)){r({language:e,facts:[],errors:[`[error] Required runtime command '${o.cmd}' is not available on PATH.`,`[hint] ${ut(e)}`,"[hint] You can also package native workers into dist/workers to avoid local toolchain requirements."],exitCode:Ee});return}let m=spawn(o.cmd,o.args,{cwd:o.cwd??t,stdio:["ignore","pipe","pipe"]}),u=setTimeout(()=>{c=true,m.kill("SIGKILL");},n.timeoutMs);m.stdout.on("data",f=>{i+=f.toString();let v=i.split(`
50
+ `);i=v.pop();for(let $ of v){let k=$.trim();k&&a.push(k);}}),m.stderr.on("data",f=>{let v=f.toString();for(let $ of v.split(`
51
+ `)){let k=$.trim();k&&(n.verbose&&process.stderr.write(l.dim(`[${e}] ${k}
52
+ `)),k.startsWith("[error]")&&s.push(k));}}),m.on("close",f=>{clearTimeout(u),i.trim()&&a.push(i.trim()),r(c?{language:e,facts:a,errors:["Worker killed: timeout exceeded"],exitCode:Ae}:{language:e,facts:a,errors:s,exitCode:f??0});}),m.on("error",f=>{clearTimeout(u);let v=f.code==="ENOENT";s.push(v?`[error] '${o.cmd}' not found. ${ut(e)}`:`[error] Failed to spawn native worker: ${f.message}`),r({language:e,facts:a,errors:s,exitCode:Ee});});}):{language:e,facts:[],errors:[`[error] No native worker found for '${e}'. Build/package workers for this platform or use source mode.`,`[hint] ${ut(e)}`],exitCode:Ee}}async function is(t,e,n){let o=Le(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 s=t.join(`
54
+ `)),false;let r=t.join(`
55
55
  `)+`
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}
56
+ `,a=`${o.scheme}://${o.host}/v1/ingest/hcs`;n&&process.stderr.write(l.dim(`Pushing ${t.length} facts to ${o.host}...
57
+ `));try{let s=gn(r,o.secret),i=await fetch(a,{method:"POST",headers:{"Content-Type":"application/x-ndjson","X-Vibgrate-Key":o.keyId,"X-Vibgrate-Workspace":o.workspaceId,"X-Vibgrate-Signature":s,Connection:"close"},body:r});if(!i.ok){let c=await i.text().catch(()=>"");return process.stderr.write(l.red(`Push failed: HTTP ${i.status} ${c}
58
58
  `)),!1}return n&&process.stderr.write(l.green(`\u2714 Pushed ${t.length} facts successfully
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.
59
+ `)),!0}catch(s){return process.stderr.write(l.red(`Push failed: ${s instanceof Error?s.message:String(s)}
60
+ `)),false}}async function as(t){let n=(await K.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 gt=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[a,s]of this.langStatus)if(s.done)n.push(l.green(`${a} \u2713`));else if(s.phase==="waiting")n.push(l.dim(`${a} \xB7`));else if(s.phase==="discovering")n.push(l.yellow(`${a} \u2026`));else if(s.phase==="scanning"&&s.fileCount>0){let i=Math.round(s.fileIndex/s.fileCount*100);n.push(l.cyan(`${a} ${s.fileIndex}/${s.fileCount} ${i}%`));}else s.phase==="extracting"?n.push(l.cyan(`${a} extracting`)):n.push(l.dim(`${a} ${s.phase}`));let o=` ${n.join(" ")} ${l.dim(`${this.totalFacts} facts`)}`,r=Math.max(0,this.lastLineLen-o.length);process.stderr.write(`\r${o}${" ".repeat(r)}`),this.lastLineLen=o.length;}finish(e){this.isTTY&&process.stderr.write(`\r${" ".repeat(this.lastLineLen)}\r`);}},Xn=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??(lt(t)?t:void 0),o=n?"url":"local",r,a;if(n){let b=parseInt(e.cloneTimeoutMins,10);(isNaN(b)||b<1)&&(process.stderr.write(l.red(`--clone-timeout-mins must be >= 1
62
+ `)),process.exit(F)),a=He(n);try{let C=await Nn(n,{ref:e.ref,timeoutMs:b*60*1e3,verbose:e.verbose??!1});r=C.dir,e.keepClone?process.stderr.write(l.dim(`Clone retained at: ${C.dir}
63
+ `)):process.once("exit",()=>{try{rmSync(C.dir,{recursive:!0,force:!0});}catch{}});}catch(C){let Q=C instanceof L||C instanceof Error?C.message:String(C);process.stderr.write(l.red(`Clone failed: ${Q}
64
+ `)),process.exit(F);}}else {r=S.resolve(t),await c(r)||(process.stderr.write(l.red(`Path does not exist: ${r}
65
+ `)),process.exit(F));let b;try{b=await K.stat(r);}catch{process.stderr.write(l.red(`Cannot read path: ${r}
66
+ `)),process.exit(F);}b.isDirectory()||(process.stderr.write(l.red(`Path must be a directory: ${r}
67
+ `)),process.exit(F));}let s=e.dsn||process.env.VIBGRATE_DSN;e.push&&!s&&(process.stderr.write(l.red(`--push requires --dsn or VIBGRATE_DSN environment variable
68
+ `)),process.exit(F)),s&&!Le(s)&&(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 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
- `)),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
- `)),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 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
- `));for(let P of y)process.stderr.write(l.dim(` ${P.language}: ${P.fileCount} files
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.
70
+ `)),process.exit(F));let i=e.concurrency?parseInt(e.concurrency,10):Ut.cpus().length;(isNaN(i)||i<1)&&(process.stderr.write(l.red(`--concurrency must be >= 1
71
+ `)),process.exit(F));let c$1=parseInt(e.timeoutMins,10);(isNaN(c$1)||c$1<1)&&(process.stderr.write(l.red(`--timeout-mins must be >= 1
72
+ `)),process.exit(F));let p=c$1*60*1e3;if(e.out){let b=S.dirname(S.resolve(e.out));await c(b)||(process.stderr.write(l.red(`Output directory does not exist: ${b}
73
+ `)),process.exit(F));try{(await K.stat(S.resolve(e.out))).isDirectory()&&(process.stderr.write(l.red(`--out cannot be a directory: ${e.out}
74
+ `)),process.exit(F));}catch{}}let g;if(e.feedback){let b=S.resolve(e.feedback);await c(b)||(process.stderr.write(l.red(`Feedback file not found: ${b}
75
+ `)),process.exit(F));try{g=await as(b);}catch(C){process.stderr.write(l.red(`Invalid feedback file: ${C instanceof Error?C.message:String(C)}
76
+ `)),process.exit(F);}}let m;if(e.language){m=e.language.split(",").map(b=>zr(b)).filter(Boolean);for(let b of m)Ln.has(b)||(process.stderr.write(l.red(`Unknown language: "${b}"
77
+ `)),process.stderr.write(l.dim(`Supported: ${[...Ln].sort().join(", ")}
78
+ `)),process.exit(F));}else {let b=await qr(r,e.includeTests??false);if(b.length===0&&(process.stderr.write(l.yellow(`No supported source files detected.
79
+ `)),process.exit(Mn)),m=b.map(C=>C.language),e.verbose){process.stderr.write(l.dim(`Detected languages:
80
+ `));for(let C of b)process.stderr.write(l.dim(` ${C.language}: ${C.fileCount} files
81
+ `));}}let u=m.filter(b=>Bn.has(b)),f=m.filter(b=>!Bn.has(b));f.length>0&&e.verbose&&process.stderr.write(l.dim(`No worker registered for: ${f.join(", ")} \u2014 skipping.
82
82
  `)),u.length===0&&(process.stderr.write(l.yellow(`No languages with available HCS workers found.
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(`
83
+ `)),process.exit(Mn));let v=Date.now(),$=v+p;process.stderr.write(l.bold(`Extracting HCS facts from ${r}
84
+ `)+l.dim(`Languages: ${u.join(", ")} Concurrency: ${i} Timeout: ${c$1}m
85
+ `));let k=new gt(u),w=new a$1(i),U=[],O=[],V=[],ce=[],ue=false,Te=false,$e=false,Ye=u.map(b=>w.run(async()=>{let C=$-Date.now();if(C<=0){$e=true;return}let Q=Wn.has(b)?await ns(r,b,{includeTests:e.includeTests??false,verbose:e.verbose??false,timeoutMs:C,onProgress:Z=>k.onProgress(b,Z)}):await ss(r,b,{verbose:e.verbose??false,timeoutMs:C});Q.exitCode===Ae&&($e=true);let{preamble:re,facts:Se}=Yr(Q.facts);U.push(...re),e.derive&&ce.push(...re,...Se);let ke=0;for(let Z of [...re,...Se]){let Qe=pt(Z);Qe.valid||(ue=true,V.push(`[${b}] Schema validation: ${Qe.error}`),e.verbose&&process.stderr.write(l.red(`[${b}] Invalid fact: ${Qe.error}
86
+ `)));}for(let Z of Se)pt(Z).valid&&(O.push(Z),ke++,k.onFact());k.setLanguageFactCount(b,ke),Q.errors.length>0&&V.push(...Q.errors.map(Z=>`[${b}] ${Z}`)),Q.exitCode!==0&&Q.exitCode!==Ae&&(Te=true);}));await Promise.all(Ye);let _e=((Date.now()-v)/1e3).toFixed(1);if(k.finish(_e),e.derive){let b=e.scanId||"local",C=e.applicationId||S.basename(r),{envelopes:Q,summary:re}=await En(ce,{scanId:b,applicationId:C});for(let Se of Q){let ke=JSON.stringify(Se);pt(ke).valid?O.push(ke):(ue=true,V.push("[behavioural] derived fact failed schema validation"));}process.stderr.write(l.dim(`Derived ${re.assertions} behavioural assertion(s) \xB7 confidence ${re.behaviouralConfidence} (${re.assertedFacts}/${re.surfaceFacts} surface facts)
87
+ `));}O.sort();let h=e.scanId||"local",I=e.applicationId||(o==="url"?dt(a):void 0)||S.basename(r),j;try{j=await An(r);}catch{j=void 0;}let x=Fn({remoteUrl:a??(j?.remoteUrl?He(j.remoteUrl):void 0),sha:j?.sha,shortSha:j?.shortSha,branch:j?.branch,ref:e.ref,source:o,languages:u,scanId:h,applicationId:I,vibgrateVersion:E,factLines:O}),q=[JSON.stringify(x),...U,...O],Y=q.join(`
88
+ `)+(q.length>0?`
89
+ `:"");if(e.out){let b=S.resolve(e.out);await K.writeFile(b,Y,"utf-8"),process.stderr.write(l.green(`\u2714 Wrote ${O.length} facts to ${b}
90
+ `));}else process.stdout.write(Y);if(e.push&&s&&O.length>0&&(await is(q,s,e.verbose??false)||process.exit(Wr)),e.verbose){if(process.stderr.write(l.dim(`
91
91
  \u2500\u2500 Summary \u2500\u2500
92
- `)),process.stderr.write(l.dim(` Facts emitted : ${_.length}
92
+ `)),process.stderr.write(l.dim(` Facts emitted : ${O.length}
93
93
  `)),process.stderr.write(l.dim(` Languages : ${u.join(", ")}
94
- `)),process.stderr.write(l.dim(` Elapsed : ${De}s
95
- `)),U.length>0){process.stderr.write(l.dim(` Errors : ${U.length}
96
- `));for(let y of U.slice(0,10))process.stderr.write(l.dim(` ${y}
97
- `));U.length>10&&process.stderr.write(l.dim(` ... and ${U.length-10} more
94
+ `)),process.stderr.write(l.dim(` Elapsed : ${_e}s
95
+ `)),V.length>0){process.stderr.write(l.dim(` Errors : ${V.length}
96
+ `));for(let b of V.slice(0,10))process.stderr.write(l.dim(` ${b}
97
+ `));V.length>10&&process.stderr.write(l.dim(` ... and ${V.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
- `));}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.
100
+ `));}$e&&(process.stderr.write(l.red(`Timeout exceeded (${c$1} minutes)
101
+ `)),process.exit(Ae)),ue&&(process.stderr.write(l.red(`Fact schema validation failures detected
102
+ `)),process.exit(Gr)),Te&&(process.stderr.write(l.red(`Parsing failures detected
103
+ `)),process.exit(Ee));});var ds=0,Ge=5,ps=new URL("../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url),Kn=fileURLToPath(ps);async function us(){return existsSync(Kn)?await import(Kn):null}var zn=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(Ge));let n=["concise","full"];n.includes(t.level)||(process.stderr.write(l.red(`--level must be one of: ${n.join(", ")}
105
+ `)),process.exit(Ge));let o=await us();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 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.
107
+ `),process.exit(1));let r;if(t.in){let i=S.resolve(t.in);existsSync(i)||(process.stderr.write(l.red(`Input file not found: ${i}
108
+ `)),process.exit(Ge)),r=await K.readFile(i,"utf-8");}else {let i=[];for await(let c of process.stdin)i.push(Buffer.isBuffer(c)?c:Buffer.from(c));r=Buffer.concat(i).toString("utf-8");}let a={format:t.format,level:t.level};t.title&&(a.title=t.title);let s;try{s=o.hcs_render_digest(r,JSON.stringify(a));}catch(i){process.stderr.write(l.red(`Digest rendering failed: ${i instanceof Error?i.message:String(i)}
109
+ `)),process.exit(1);}if(t.out){let i=S.resolve(t.out),c=S.dirname(i);existsSync(c)||(process.stderr.write(l.red(`Output directory does not exist: ${c}
110
+ `)),process.exit(Ge)),await K.writeFile(i,s,"utf-8"),process.stderr.write(l.green(`Wrote digest to ${i}
111
+ `));}else process.stdout.write(s);process.exit(ds);});var ms=0,Je=5,qn=fileURLToPath(new URL("../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url));async function hs(){return existsSync(qn)?await import(qn):null}async function bs(t){if(t){let n=S.resolve(t);return existsSync(n)||(process.stderr.write(l.red(`Input file not found: ${n}
112
+ `)),process.exit(Je)),K.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 mt=["json","md","mermaid"],ht=["integration","migration","governance"],Yn=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: ${mt.join(" | ")}`,"json").option("--profile <profile>",`Consumer projection: ${ht.join(" | ")}`).option("--generated-at <iso>","Override generatedAt timestamp (for deterministic output)").action(async t=>{mt.includes(t.format)||(process.stderr.write(l.red(`--format must be one of: ${mt.join(", ")}
113
+ `)),process.exit(Je)),t.profile&&!ht.includes(t.profile)&&(process.stderr.write(l.red(`--profile must be one of: ${ht.join(", ")}
114
+ `)),process.exit(Je));let e=await hs();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 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)}
116
+ `),process.exit(1));let n=await bs(t.facts),o={format:t.format,profile:t.profile,generatedAt:t.generatedAt??new Date().toISOString()},r;try{r=e.hcs_build_map(n,JSON.stringify(o));}catch(a){process.stderr.write(l.red(`Map build failed: ${a instanceof Error?a.message:String(a)}
117
+ `)),process.exit(1);}if(t.out){let a=S.resolve(t.out);existsSync(S.dirname(a))||(process.stderr.write(l.red(`Output directory does not exist: ${S.dirname(a)}
118
+ `)),process.exit(Je)),await K.writeFile(a,r+`
119
+ `,"utf-8"),process.stderr.write(l.green(`Wrote System Map to ${a}
120
+ `));}else process.stdout.write(r+`
121
+ `);process.exit(ms);});var vs=0,$s=2,Ke=5,Qn=fileURLToPath(new URL("../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url));async function Ss(){return existsSync(Qn)?await import(Qn):null}async function ks(){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 yt(t,e){let n=S.resolve(t);return existsSync(n)||(process.stderr.write(l.red(`${e} file not found: ${n}
122
+ `)),process.exit(Ke)),K.readFile(n,"utf-8")}var wt=["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: ${wt.join(" | ")}`,"text").action(async t=>{wt.includes(t.format)||(process.stderr.write(l.red(`--format must be one of: ${wt.join(", ")}
123
+ `)),process.exit(Ke));let e=await Ss();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 yt(t.baseline,"Baseline"),o=t.facts?await yt(t.facts,"Facts"):await ks(),r;if(t.policy){let i=await yt(t.policy,"Policy");try{r=JSON.parse(i);}catch(c){process.stderr.write(l.red(`Invalid policy JSON: ${c instanceof Error?c.message:String(c)}
126
+ `)),process.exit(Ke);}}let a,s;try{let i=e.hcs_evaluate_gate(n,o,JSON.stringify({format:"json",policy:r}));a=JSON.parse(i).pass,s=t.format==="json"?i:e.hcs_evaluate_gate(n,o,JSON.stringify({format:t.format,policy:r}));}catch(i){process.stderr.write(l.red(`Gate evaluation failed: ${i instanceof Error?i.message:String(i)}
117
127
  `)),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}
128
+ `)),process.exit(Ke)),await K.writeFile(i,s+`
129
+ `,"utf-8"),process.stderr.write((a?l.green:l.red)(`Gate ${a?"passed":"FAILED"} \u2014 wrote result to ${i}
120
130
  `));}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)}
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)}
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}
130
- `));}else process.stdout.write(r+`
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(`
131
+ `);process.exit(a?vs:$s);});var Cs=new URL("../../../../vibgrate-hcs/wasm/pkg/vibgrate_hcs_wasm.js",import.meta.url),$t=fileURLToPath(Cs);function St(){return existsSync($t)}async function Is(){if(!St())throw new Error(`WASM engine not built. Run \`pnpm --filter @vibgrate/hcs build\` first.
132
+ Expected: ${$t}`);return await import($t)}var eo={SCHEMA_INVALID:1};async function to(t){let e=await Is();return JSON.parse(e.validate_lines_json(JSON.stringify(t)))}var ro=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)=>{St()||(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(eo.SCHEMA_INVALID));let r=(await K.readFile(n,"utf-8")).split(`
134
+ `).filter(s=>s.trim()),a=await to(r);if(e.json)process.stdout.write(JSON.stringify(a,null,2)+`
135
+ `);else if(a.ok)process.stderr.write(l.green(`\u2714 Conformant \u2014 model satisfies the HCS v0.5 spec.
136
+ `));else {process.stderr.write(l.red(`\u2718 ${a.errors.length} validation error(s) (exit ${a.exitCode}):
137
+ `));for(let s of a.errors.slice(0,50))process.stderr.write(l.dim(` [${s.code}] ${s.factId||"(model)"}: ${s.message}
138
+ `));a.errors.length>50&&process.stderr.write(l.dim(` \u2026 and ${a.errors.length-50} more
139
+ `));}process.exit(a.exitCode);});var so=new Command("hcs").description("Holistic Code Specification \u2014 extract and render code facts").addCommand(Xn).addCommand(zn).addCommand(Yn).addCommand(Zn).addCommand(ro);var kt=2;var io=5,As=new Set(["ndjson","json","patch"]),ao=new Set([".git",".hg",".svn","node_modules",".vibgrate"]);async function co(t,e,n){let o=[];async function r(a,s){let i;try{i=await K.readdir(a,{withFileTypes:!0});}catch{return}for(let c of i){if(c.name.startsWith(".")&&ao.has(c.name))continue;let p=S.join(a,c.name),g=S.join(s,c.name);if(c.isDirectory()){ao.has(c.name)||await r(p,g);continue}c.isFile()&&(e&&e.length>0&&!lo(g,e)||n&&n.length>0&&lo(g,n)||o.push({relPath:g,absPath:p}));}}return await r(t,""),o}function lo(t,e){for(let n of e)if(Ds(t,n))return true;return false}function Ds(t,e){let n=e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(n,"i").test(t)}function po(t,e,n,o){let r=o?t.map(g=>g.trim()):t,a=o?e.map(g=>g.trim()):e,s=Ts(r,a),i=0,c=0;for(let g of s)g.type==="insert"&&i++,g.type==="delete"&&c++;return {hunks:_s(t,e,s,n),insertions:i,deletions:c}}function Ts(t,e){let n=t.length,o=e.length;if(n===0&&o===0)return [];if(n===0)return e.map((c,p)=>({type:"insert",aIndex:0,bIndex:p}));if(o===0)return t.map((c,p)=>({type:"delete",aIndex:p,bIndex:0}));let r=Array.from({length:n+1},()=>new Array(o+1).fill(0));for(let c=1;c<=n;c++)for(let p=1;p<=o;p++)t[c-1]===e[p-1]?r[c][p]=r[c-1][p-1]+1:r[c][p]=Math.max(r[c-1][p],r[c][p-1]);let a=[],s=n,i=o;for(;s>0||i>0;)s>0&&i>0&&t[s-1]===e[i-1]?(a.unshift({type:"equal",aIndex:s-1,bIndex:i-1}),s--,i--):i>0&&(s===0||r[s][i-1]>=r[s-1][i])?(a.unshift({type:"insert",aIndex:s,bIndex:i-1}),i--):(a.unshift({type:"delete",aIndex:s-1,bIndex:i}),s--);return a}function _s(t,e,n,o){let r=[],a=null,s=-1;for(let i=0;i<n.length;i++){let c=n[i];if(c.type==="equal"){if(a&&i-s>o*2){for(let p=s+1;p<=Math.min(s+o,i);p++){let g=n[p];g&&g.type==="equal"&&(a.lines.push(` ${t[g.aIndex]??""}`),a.originalCount++,a.generatedCount++);}r.push(a),a=null;}continue}if(!a){let p=Math.max(0,i-o),g=n[p]?.aIndex??0,m=n[p]?.bIndex??0;a={originalStart:g+1,originalCount:0,generatedStart:m+1,generatedCount:0,lines:[]};for(let u=p;u<i;u++){let f=n[u];f&&f.type==="equal"&&(a.lines.push(` ${t[f.aIndex]??""}`),a.originalCount++,a.generatedCount++);}}c.type==="delete"?(a.lines.push(`-${t[c.aIndex]??""}`),a.originalCount++):c.type==="insert"&&(a.lines.push(`+${e[c.bIndex]??""}`),a.generatedCount++),s=i;}if(a){for(let i=s+1;i<Math.min(n.length,s+1+o);i++){let c=n[i];c&&c.type==="equal"&&(a.lines.push(` ${t[c.aIndex]??""}`),a.originalCount++,a.generatedCount++);}r.push(a);}return r}function Ns(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(`
140
140
  `),o=e.split(`
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(`
141
+ `),r=n.length,a=o.length;if(r*a>1e6){let s=[...n.slice(0,100),...n.slice(-100)],i=[...o.slice(0,100),...o.slice(-100)];return uo(s,i)}return uo(n,o)}function uo(t,e){let n=t.length,o=e.length,r=Array.from({length:n+1},()=>new Array(o+1).fill(0));for(let s=1;s<=n;s++)for(let i=1;i<=o;i++)t[s-1]===e[i-1]?r[s][i]=r[s-1][i-1]+1:r[s][i]=Math.max(r[s-1][i],r[s][i-1]);return 2*r[n][o]/(n+o)}function qe(t,e){return `hcs:delta:${Ne.createHash("sha256").update(`${t}:${e}`).digest("hex").substring(0,16)}`}function Os(t){return t.map(e=>JSON.stringify(e)).join(`
142
142
  `)+(t.length>0?`
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
+ `:"")}function Fs(t){return JSON.stringify({deltas:t,count:t.length},null,2)+`
144
+ `}function Ms(t,e,n){let o=[];for(let r of t){let a=r.originalPath?S.join("a",r.originalPath):"/dev/null",s=r.generatedPath?S.join("b",r.generatedPath):"/dev/null";if(r.changeKind==="renamed"&&r.originalPath&&r.generatedPath?(o.push(`diff --vibgrate ${a} ${s}`),o.push(`similarity index ${Math.round((r.similarity??0)*100)}%`),o.push(`rename from ${r.originalPath}`),o.push(`rename to ${r.generatedPath}`)):o.push(`diff --vibgrate ${a} ${s}`),o.push(`--- ${r.changeKind==="added"?"/dev/null":a}`),o.push(`+++ ${r.changeKind==="removed"?"/dev/null":s}`),r.hunks)for(let i of r.hunks)o.push(`@@ -${i.originalStart},${i.originalCount} +${i.generatedStart},${i.generatedCount} @@`),o.push(...i.lines);o.push("");}return o.join(`
145
+ `)}var fo=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),r=S.resolve(e);for(let[h,I]of [["original_path",o],["generated_path",r]]){await c(I)||(process.stderr.write(l.red(`${h} does not exist: ${I}
146
+ `)),process.exit(kt));let j;try{j=await K.stat(I);}catch{process.stderr.write(l.red(`Cannot read ${h}: ${I}
147
+ `)),process.exit(kt);}j.isDirectory()||(process.stderr.write(l.red(`${h} must be a directory: ${I}
148
+ `)),process.exit(kt));}let a=n.format.toLowerCase();As.has(a)||(process.stderr.write(l.red(`Invalid format: "${n.format}". Allowed: ndjson, json, patch
149
+ `)),process.exit(io));let s=parseInt(n.context,10);(isNaN(s)||s<0)&&(process.stderr.write(l.red(`--context must be >= 0
150
+ `)),process.exit(io));let i=n.include?n.include.split(",").map(h=>h.trim()).filter(Boolean):void 0,c$1=n.exclude?n.exclude.split(",").map(h=>h.trim()).filter(Boolean):void 0,[p,g]=await Promise.all([co(o,i,c$1),co(r,i,c$1)]),m=new Map(p.map(h=>[h.relPath,h])),u=new Map(g.map(h=>[h.relPath,h]));n.verbose&&(process.stderr.write(l.dim(`Original: ${p.length} files
151
151
  `)),process.stderr.write(l.dim(`Generated: ${g.length} files
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(`
153
- `),X.split(`
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(`
159
- `).length};}catch{C.stats={insertions:0,deletions:0};}h.push(C),n.verbose&&process.stderr.write(l.dim(` removed: ${b.relPath}
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(`
161
- `).length,deletions:0};}catch{C.stats={insertions:0,deletions:0};}h.push(C),n.verbose&&process.stderr.write(l.dim(` added: ${b.relPath}
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`)+`
163
- `),process.stderr.write(l.dim(` Written to ${pe}
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
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);});
152
+ `)));let f=[],v=new Set,$=new Set;for(let[h,I]of m){let j=u.get(h);if(j){v.add(h),$.add(h);let x=await K.readFile(I.absPath,"utf-8"),z=await K.readFile(j.absPath,"utf-8"),q=n.ignoreWhitespace?x.replace(/\s+/g," ").trim():x,Y=n.ignoreWhitespace?z.replace(/\s+/g," ").trim():z;if(q!==Y){let b=po(x.split(`
153
+ `),z.split(`
154
+ `),s,n.ignoreWhitespace??false),C={deltaId:qe("modified",h),changeKind:"modified",originalPath:h,generatedPath:h,hunks:b.hunks};n.stats&&(C.stats={insertions:b.insertions,deletions:b.deletions}),f.push(C),n.verbose&&process.stderr.write(l.dim(` modified: ${h} (+${b.insertions} -${b.deletions})
155
+ `));}}}let k=p.filter(h=>!v.has(h.relPath)),w=g.filter(h=>!$.has(h.relPath)),U=.8,O=new Set,V=new Set;if(k.length>0&&w.length>0){let h=new Map,I=new Map;await Promise.all([...k.map(async x=>{try{h.set(x.relPath,await K.readFile(x.absPath,"utf-8"));}catch{}}),...w.map(async x=>{try{I.set(x.relPath,await K.readFile(x.absPath,"utf-8"));}catch{}})]);let j=[];for(let[x,z]of h)for(let[q,Y]of I){if(S.extname(x)!==S.extname(q))continue;let b=Ns(z,Y);b>=U&&j.push({origPath:x,genPath:q,similarity:b});}j.sort((x,z)=>z.similarity-x.similarity);for(let x of j){if(O.has(x.origPath)||V.has(x.genPath))continue;O.add(x.origPath),V.add(x.genPath);let z=h.get(x.origPath)??"",q=I.get(x.genPath)??"",Y=po(z.split(`
156
+ `),q.split(`
157
+ `),s,n.ignoreWhitespace??false),b={deltaId:qe("renamed",`${x.origPath} -> ${x.genPath}`),changeKind:"renamed",originalPath:x.origPath,generatedPath:x.genPath,similarity:x.similarity,hunks:Y.hunks};n.stats&&(b.stats={insertions:Y.insertions,deletions:Y.deletions}),f.push(b),n.verbose&&process.stderr.write(l.dim(` renamed: ${x.origPath} \u2192 ${x.genPath} (${(x.similarity*100).toFixed(0)}% similar)
158
+ `));}}for(let h of k){if(O.has(h.relPath))continue;let I={deltaId:qe("removed",h.relPath),changeKind:"removed",originalPath:h.relPath,generatedPath:null};if(n.stats)try{let j=await K.readFile(h.absPath,"utf-8");I.stats={insertions:0,deletions:j.split(`
159
+ `).length};}catch{I.stats={insertions:0,deletions:0};}f.push(I),n.verbose&&process.stderr.write(l.dim(` removed: ${h.relPath}
160
+ `));}for(let h of w){if(V.has(h.relPath))continue;let I={deltaId:qe("added",h.relPath),changeKind:"added",originalPath:null,generatedPath:h.relPath};if(n.stats)try{let j=await K.readFile(h.absPath,"utf-8");I.stats={insertions:j.split(`
161
+ `).length,deletions:0};}catch{I.stats={insertions:0,deletions:0};}f.push(I),n.verbose&&process.stderr.write(l.dim(` added: ${h.relPath}
162
+ `));}f.sort((h,I)=>{let j=h.originalPath??h.generatedPath??"",x=I.originalPath??I.generatedPath??"";return j.localeCompare(x)});let ce;switch(a){case "ndjson":ce=Os(f);break;case "json":ce=Fs(f);break;case "patch":ce=Ms(f);break}let ue=S.resolve(n.out);await K.writeFile(ue,ce,"utf-8");let Te=f.filter(h=>h.changeKind==="added").length,$e=f.filter(h=>h.changeKind==="removed").length,Ye=f.filter(h=>h.changeKind==="modified").length,_e=f.filter(h=>h.changeKind==="renamed").length;if(process.stderr.write(l.green("\u2714 ")+`${f.length} changes: `+l.green(`+${Te} added`)+", "+l.red(`-${$e} removed`)+", "+l.yellow(`~${Ye} modified`)+", "+l.blue(`\u2192${_e} renamed`)+`
163
+ `),process.stderr.write(l.dim(` Written to ${ue}
164
+ `)),n.verbose&&n.stats){let h=0,I=0;for(let j of f)j.stats&&(h+=j.stats.insertions,I+=j.stats.deletions);process.stderr.write(l.dim(` Total: +${h} insertions, -${I} deletions
165
+ `));}});var Bs="https://vibgrate.com/help";function Us(){console.log(""),console.log(l.dim(`See ${Bs} for more guidance`));}var xt={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 Cloud 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 mo(){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 ho=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&&xt[e]?xt[e]():(e&&(console.log(""),console.log(l.red(`Unknown command: ${e}`)),console.log(l.dim(`Available commands: ${Object.keys(xt).join(", ")}`))),mo()),Us();});var N=new Command;N.name("vibgrate").description("Continuous Drift Intelligence").version(E).addHelpText("after",`
166
+ See https://vibgrate.com/help for more guidance`);N.addCommand(ho);N.addCommand(Ft);N.addCommand(qt);N.addCommand(h);N.addCommand(nn);N.addCommand(rn);N.addCommand(an);N.addCommand(tt);N.addCommand(fn);N.addCommand(Sn);N.addCommand(Rn);N.addCommand(so);N.addCommand(fo);function Hs(){wn().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(()=>{Hs();}).catch(t=>{console.error(t),process.exit(1);});