#!/usr/bin/env node
import {n,m,o as o$1,t,r as r$1}from'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import {a as a$1}from'./chunk-LKAT7IAK.js';import'./chunk-XHJ27CER.js';import*as a from'fs';import*as r from'path';import o from'chalk';import {execSync}from'child_process';import*as F from'js-yaml';var W=/[@#$%^!?&~][a-zA-Z][a-zA-Z0-9_-]*/g,_=[/\.(get|post|put|patch|delete)\s*\(\s*['"`]([^'"`]+)['"`]/gi,/export\s+(async\s+)?function\s+(GET|POST|PUT|PATCH|DELETE)/gi];async function G(n$1={}){let i=process.cwd(),b=a$1.command("review").start("Running review pipeline",{cwd:i}),u=[],m$1=[];try{if(n$1.pr)u=execSync(`gh pr diff ${n$1.pr} --name-only`,{cwd:i,encoding:"utf8",timeout:15e3}).trim().split(`
`).filter(Boolean);else {let e=execSync("git diff --cached --name-only",{cwd:i,encoding:"utf8",timeout:5e3}).trim(),t=execSync("git diff --name-only",{cwd:i,encoding:"utf8",timeout:5e3}).trim();u=[...new Set([...e.split(`
`).filter(Boolean),...t.split(`
`).filter(Boolean)])];}}catch(e){let t=e.message;n$1.json||a$1.command("review").error(`Failed to get changed files: ${t}`),b.error("Failed to get changed files"),n$1.ci&&process.exit(1);return}if(u.length===0){n$1.json?console.log(JSON.stringify({findings:[],summary:{total:0,blocking:0,improvements:0,notes:0}})):console.log(o.green(`
  No modified files to review.
`)),b.success("No files to review");return}try{for(let e of u)if(e.endsWith(".purpose")){let t=r.join(i,e);if(a.existsSync(t)){let g=a.readFileSync(t,"utf-8").match(W)||[];m$1.push(...g);}}m$1=[...new Set(m$1)];}catch{}let s=[],$=n();try{let e=await m(i);$=o$1(e);}catch{}let R=r.join(i,"portal.yaml"),h=null;if(a.existsSync(R))try{h=F.load(a.readFileSync(R,"utf-8"));}catch{}for(let e of m$1)t($,e).length===0&&s.push({type:"blocking",category:"purpose-coverage",message:`Symbol "${e}" is not registered in any .purpose file`,suggestion:"Add to nearest .purpose file using paradigm_purpose_add_component."});let N=h?.routes?Object.keys(h.routes):[];for(let e of u){let t=r.isAbsolute(e)?e:r.join(i,e);if(!a.existsSync(t))continue;let l;try{l=a.readFileSync(t,"utf-8");}catch{continue}for(let g of _){g.lastIndex=0;let d;for(;(d=g.exec(l))!==null;){let f=d[2]||d[0];f&&f.startsWith("/")&&(N.some(p=>p.replace(/\s+(GET|POST|PUT|PATCH|DELETE)\s*$/,"").trim()===f)||s.push({type:h?"blocking":"improvement",category:"route-coverage",message:`Route "${f}" in ${e} not in portal.yaml`,file:e,suggestion:"Add route to portal.yaml with ^gates."}));}}}let O=h?Object.keys(h.gates||{}).map(e=>e.startsWith("^")?e.slice(1):e):[];for(let e of m$1)if(e.startsWith("^")){let t=e.slice(1);O.includes(t)||s.push({type:"blocking",category:"portal-compliance",message:`Gate "${e}" referenced but not declared in portal.yaml`,suggestion:`Add ${e} to portal.yaml with description and check expression.`});}try{let e=r$1($,"aspect");for(let t of e){let l=t.appliesTo||[];if(l.length!==0){for(let g of l)for(let d of m$1)if(I(g,d)){let c=t.anchors||[];if(c.length===0)s.push({type:"improvement",category:"aspect-anchors",message:`Aspect "${t.symbol}" applies to "${d}" but has no code anchors`,suggestion:`Add anchors to ${t.symbol} in .purpose file.`});else for(let p of c){let T=r.isAbsolute(p.path)?p.path:r.join(i,p.path);a.existsSync(T)||s.push({type:"improvement",category:"aspect-anchors",message:`Aspect "${t.symbol}" anchor "${p.raw}" points to missing file`,suggestion:`Update anchors for ${t.symbol} in .purpose file.`});}}}}}catch{}for(let e of m$1){let t$1=t($,e);if(t$1.length===0)continue;let l=t$1[0];l.parentSymbol&&t($,l.parentSymbol).length===0&&s.push({type:"improvement",category:"broken-reference",message:`Symbol "${e}" references parent "${l.parentSymbol}" which does not exist`,suggestion:"Create the parent symbol or update the parent reference."});}if(n$1.deep)for(let e of u){let t=r.isAbsolute(e)?e:r.join(i,e);if(!a.existsSync(t))continue;let l=r.extname(e);if(![".ts",".tsx",".js",".jsx",".py",".rs"].includes(l))continue;let g;try{g=a.readFileSync(t,"utf-8");}catch{continue}let d=g.split(`
`);for(let f=0;f<d.length;f++){let c=d[f],p=f+1;/\beval\s*\(/.test(c)&&!c.trimStart().startsWith("//")&&s.push({type:"blocking",category:"security",message:"eval() detected \u2014 potential code injection risk",file:e,line:p,suggestion:"Replace eval() with a safer alternative."}),/(?:password|secret|api_key|apikey|token)\s*[:=]\s*['"][^'"]{8,}['"]/i.test(c)&&!c.trimStart().startsWith("//")&&!c.trimStart().startsWith("#")&&s.push({type:"blocking",category:"security",message:"Possible hardcoded secret detected",file:e,line:p,suggestion:"Move secrets to environment variables or a secrets manager."}),/\bconsole\.(log|debug|info|warn)\b/.test(c)&&!e.includes("test")&&!e.includes("spec")&&(c.trimStart().startsWith("//")||s.push({type:"note",category:"convention",message:"console.log detected \u2014 use Paradigm logger instead",file:e,line:p,suggestion:"Use log.component(), log.gate(), etc. from the Paradigm logger."}));}}let y=s.filter(e=>e.type==="blocking"),w=s.filter(e=>e.type==="improvement"),S=s.filter(e=>e.type==="note");if(n$1.json)console.log(JSON.stringify({findings:s,summary:{total:s.length,blocking:y.length,improvements:w.length,notes:S.length,filesReviewed:u.length,symbolsChecked:m$1.length}},null,2));else if(console.log(o.blue(`
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510`)),console.log(o.blue("\u2502")+o.white.bold("  paradigm review                                 ")+o.blue("\u2502")),console.log(o.blue("\u2502")+o.gray(`  ${u.length} files, ${m$1.length} symbols${n$1.deep?", deep mode":""}`.padEnd(50))+o.blue("\u2502")),console.log(o.blue(`\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
`)),s.length===0)console.log(o.green(`  All checks passed \u2014 no findings.
`));else {if(y.length>0){console.log(o.red.bold(`  Blocking (${y.length})`));for(let e of y)console.log(`    ${o.red("x")} ${e.message}`),e.file&&console.log(`      ${o.gray(e.file)}${e.line?`:${e.line}`:""}`),e.suggestion&&console.log(`      ${o.yellow("->")} ${e.suggestion}`);console.log("");}if(w.length>0){console.log(o.yellow(`  Improvements (${w.length})`));for(let e of w)console.log(`    ${o.yellow("*")} ${e.message}`),e.file&&console.log(`      ${o.gray(e.file)}${e.line?`:${e.line}`:""}`),e.suggestion&&console.log(`      ${o.yellow("->")} ${e.suggestion}`);console.log("");}if(S.length>0){console.log(o.gray(`  Notes (${S.length})`));for(let e of S)console.log(`    ${o.gray("o")} ${e.message}`),e.file&&console.log(`      ${o.gray(e.file)}${e.line?`:${e.line}`:""}`);console.log("");}}n$1.ci&&y.length>0&&(b.error(`${y.length} blocking findings`),process.exit(1)),b.success(`Review complete: ${s.length} findings`);}function I(n,i){return n.includes("*")?new RegExp("^"+n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\\\*/g,".*")+"$").test(i):n===i}export{G as reviewCommand};