cc-safety-net 2.3.2 → 2.3.4

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.
@@ -1,44 +1,44 @@
1
1
  #!/usr/bin/env node
2
- import{b as mi,c as gi,d as V,e as hi,f as br,g as ct,h as He,i as Mr,j as be,k as Rs,l as Kr,m as vn,n as Ps,o as Ds,p as bn}from"../chunks/index-jnb1nckj.js";import{$a as _r,A as it,Aa as Es,Ab as Ot,B as he,Ba as ye,Bb as _s,C as ja,Ca as Nt,D as Zi,Da as Vr,E as Pe,Ea as zr,F as yn,Fa as as,G as Pt,Ga as ls,H as xr,Ha as ki,I as je,Ia as st,J as Se,Ja as cs,K as Ne,Ka as ds,L as re,La as Ar,M as Cr,Ma as Er,Na as Xi,O as oe,Oa as Rr,P as se,Pa as ge,Qa as Qi,R as ie,Ra as Gi,S as It,Sa as Bi,T as Nd,Ta as iu,U as Ae,Ua as Ci,V as U,Va as Si,W as Re,Wa as Ee,Xa as Ri,Y as we,Ya as Ge,Z,Za as Pi,_ as Ms,_a as q,aa as Me,ab as Fr,ba as Ln,bb as jr,ca as Ut,cb as J,da as Ei,db as su,ea as _i,eb as ve,fa as $t,fb as au,ga as Ue,gb as cn,ha as Ur,hb as lu,ia as Ti,ib as cu,ja as Ii,jb as du,ka as Le,kb as Be,la as As,lb as Y,ma as Jr,mb as uu,na as Ts,nb as pu,oa as Is,ob as us,pa as Gr,pb as ps,qa as rs,qb as fs,ra as Li,rb as ms,s as Mt,sa as os,sb as Dt,t as ns,ta as is,tb as De,u as H,ua as ss,ub as W,v as Rt,va as Br,vb as es,w as x,wa as wi,wb as Dr,x as St,xa as $i,xb as _t,y as w,ya as S,yb as z,z as B,za as qr,zb as Ht}from"../chunks/index-6fvz7zfr.js";var Lu=["-h","--help"];function E(e,t){let n=Object.entries(e.booleans??{}),r=Object.entries(e.values??{}),o=Object.entries(e.lists??{}),i=Object.fromEntries(n.map(([g])=>[g,!1])),s={},a=Object.fromEntries(o.map(([g])=>[g,[]])),l=[],c=[],d=!1,m=-1;for(let[g,u]of t.entries()){if(g<=m)continue;if(u==="--"){l.push(...t.slice(g+1));break}if(Lu.includes(u)){d=!0;continue}let p=n.find(([,L])=>L.includes(u));if(p){i[p[0]]=!0;continue}let f=r.find(([,L])=>L.includes(u));if(f){let L=t[g+1];if(L===void 0||L.startsWith("-")){c.push(`${u} requires a value`);continue}s[f[0]]=L,m=g+1;continue}let b=o.find(([,L])=>L.includes(u));if(b){let L=t.slice(g+1),h=L.findIndex((v)=>v.startsWith("-")),R=L.slice(0,h===-1?L.length:h);if(R.length===0){c.push(`${u} requires at least one value`);continue}a[b[0]]=[...a[b[0]]??[],...R],m=g+R.length;continue}if(u.startsWith("-")){c.push(`Unknown option for ${e.label}: ${u}`);continue}if(e.positionals==="tail"){l.push(...t.slice(g));break}l.push(u)}if(e.positionals!=="list"&&e.positionals!=="tail")c.push(...l.map((g)=>`Unexpected argument for ${e.label}: ${g}`));return{flags:i,values:s,lists:a,positionals:l,help:d,errors:c}}function fe(e){for(let t of e)console.error(t);return e.length>0}import{readdirSync as wp,statSync as vs,unlinkSync as kp}from"node:fs";import{basename as bs,dirname as xp,join as Cp,resolve as Sp}from"node:path";function F(e){return Array.from(e,(t)=>{let n=t.charCodeAt(0);if(n<=31||n>=127&&n<=159)return`\\x${n.toString(16).padStart(2,"0")}`;return t}).join("")}var gr=(e)=>{let t=Date.now()-new Date(e).getTime();if(!Number.isFinite(t))return"";let n=Math.floor(t/60000),r=Math.floor(n/60),o=Math.floor(r/24);if(o>0)return`${o}d ago`;if(r>0)return`${r}h ago`;if(n>0)return`${n}m ago`;return"just now"},rt=(e)=>{let t=(e??"").trim().split(/\s+/).filter((o)=>o&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(o)),n=t[0]?.split("/").pop();if(!n)return null;let r=t[1];return r&&/^[a-z][a-z0-9-]*$/.test(r)?`${n} ${r}`:n};import{existsSync as wu,readdirSync as ku,readFileSync as xu}from"node:fs";import{join as Cu}from"node:path";function Ce(e,t){try{return ku(e,{withFileTypes:!0,encoding:"utf8"}).flatMap((n)=>{let r=Cu(e,n.name);if(n.isDirectory())return Ce(r,t);if(n.name.endsWith(".jsonl"))return[r];return[]})}catch{if(t&&wu(e))t.count++;return[]}}function hr(e){let t=(o)=>`${o.sessionId}
3
- ${rt(o.segment||o.command)}`,n=e.filter((o)=>o.decision!=="allow"),r=n.filter((o)=>o.sessionId).reduce((o,i)=>o.set(t(i),(o.get(t(i))??0)+1),new Map);return new Set(n.filter((o)=>o.failureStage||(r.get(t(o))??0)>=2))}var Su=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function Ru(e){if(!e||typeof e!=="object"||Array.isArray(e))return!1;let t=e;if(typeof t.ts!=="string"||typeof t.command!=="string")return!1;return Su.every((n)=>t[n]===void 0||typeof t[n]==="string")}function Fe(e,t){try{return xu(e,"utf-8").split(`
4
- `).filter(Boolean).flatMap((n)=>{try{let r=JSON.parse(n);if(!Ru(r)){if(t)t.count++;return[]}return[r]}catch{if(t)t.count++;return[]}})}catch{if(t)t.count++;return[]}}import{resolve as up}from"node:path";var Pu=["AKIA","ASIA","ghp_","gho_","ghu_","ghs_","ghr_","github_pat_","glpat-","xox","npm_","pypi-","rk_","sk-","sk_","gsk_","xai-","pplx-","bastn_","tgp_v1_","flp_","wfr_","fw_","fwp_","tp-","psk-"];function yi(e){let t=0,n={allocateSegment(){return t++},getNextSegmentIndex(){return t},recordGlobal(r){e.record({kind:"step",scope:"global",step:r})},recordSegment(r,o=n.currentSegmentIndex){if(o===void 0)return;e.record({kind:"step",scope:"segment",segmentIndex:o,step:r})}};return n}function vi(e={}){let t=[],n=e.maxEvents??512,r={maxTextLength:e.maxTextLength??2048,maxListLength:e.maxListLength??128,maxObjectProperties:e.maxObjectProperties??e.maxListLength??128,maxDepth:e.maxDepth??16},o=0,i,s=new Set;return{record(a){if(i)return;try{if(!a||t.length>=n){o++;return}t.push(vr(Du(a,r,s)))}catch{o++}},finish(a){if(i)return i;try{i=vr({events:Object.freeze(t),droppedEvents:o,terminal:Au(a,r,s)})}catch{o++,i=Object.freeze({events:Object.freeze(t),droppedEvents:o,terminal:Object.freeze({result:"blocked",reason:"trace unavailable".slice(0,r.maxTextLength),segment:"trace unavailable".slice(0,r.maxTextLength)})})}return i}}}function Du(e,t,n){if(e.kind!=="step")throw TypeError("invalid trace event");let{scope:r,step:o}=e;pn(o,n,t);let i=ot(o,t,n);if(r==="global")return{kind:"step",scope:"global",step:i};if(r!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:e.segmentIndex,step:i}}function Au(e,t,n){let r=e.result;if(r==="allowed")return Object.freeze({result:"allowed"});if(r!=="blocked")throw TypeError("invalid trace terminal");let o=e.ruleId;return Object.freeze({result:"blocked",reason:ot(e.reason,t,n),segment:ot(e.segment,t,n),...o?{ruleId:ot(o,t,n)}:{}})}function pn(e,t,n,r=0,o=new WeakSet){if(typeof e==="string"){let a=e.slice(0,n.maxTextLength);if(!br(a))return;for(let l of hi(a))for(let c of l.match(/[^\s"'()$]+/g)??[])t.add(bi(c));return}if(!e||typeof e!=="object"||r>=n.maxDepth||o.has(e))return;if(o.add(e),Array.isArray(e)){let a=Math.min(e.length,n.maxListLength);for(let l=0;l<a;l++)pn(e[l],t,n,r+1,o);return}let i=0,s=new Set;for(let a in e){if(!Object.hasOwn(e,a))continue;if(i>=n.maxObjectProperties)break;i++,pn(a,t,n);let l=yr(a,n,t);if(s.has(l))continue;s.add(l),pn(e[a],t,n,r+1,o)}}function ot(e,t,n,r=0,o=new WeakSet){if(typeof e==="string")return yr(e,t,n);if(!e||typeof e!=="object")return e;if(r>=t.maxDepth)return;if(o.has(e))return;if(o.add(e),Array.isArray(e)){let a=[],l=Math.min(e.length,t.maxListLength);for(let c=0;c<l;c++)a.push(ot(e[c],t,n,r+1,o));return a}let i={},s=0;for(let a in e){if(!Object.hasOwn(e,a))continue;if(s>=t.maxObjectProperties)break;s++;let l=yr(a,t,n);if(Object.hasOwn(i,l))continue;Object.defineProperty(i,l,{value:ot(e[a],t,n,r+1,o),enumerable:!0,configurable:!0,writable:!0})}return i}function yr(e,t,n){let r=e.slice(0,t.maxTextLength),o=br(r)?gi(r):r,i=n.size>0?_u(o,n):o;return(Eu(i)?mi(i):i).slice(0,t.maxTextLength)}function Eu(e){return e.includes("PRIVATE KEY")||e.includes("://")||e.includes("eyJ")||e.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(e)||e.length>=14&&Pu.some((t)=>e.includes(t))||e.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(e)}function _u(e,t){return e.replace(/[^\s"'()$]+/g,(n)=>t.has(bi(n))?"<redacted>":n)}function bi(e){let t=2166136261,n=2166136261;for(let r=0;r<e.length;r++)t=Math.imul(t^e.charCodeAt(r),16777619),n=Math.imul(n^e.charCodeAt(e.length-r-1),16777619);return`${t>>>0}:${n>>>0}:${e.length}`}function vr(e){if(e&&typeof e==="object"&&!Object.isFrozen(e)){for(let t of Object.values(e))vr(t);Object.freeze(e)}return e}function xi(e,t,n){let r=n??Li(),o=r.getCommandProgram(e,t.shell??"auto"),i=vi(),s=yi(i),a=o.dialect==="powershell"?r.getCommandProgram(e,"posix"):o,l=wi(a);s.recordGlobal({type:"parse",input:e,segments:l.map((m)=>[...m])});let c=ki(e,{...t,analyzePartialProgram:!0,trace:s},o,r),d=s.getNextSegmentIndex();if(c&&d>0&&d<l.length)s.recordSegment({type:"segment-skipped",index:d,reason:"prior-segment-blocked"},d);return Object.freeze({decision:c,trace:i.finish(c?{result:"blocked",reason:c.reason,segment:c.evidence.find((m)=>m.kind==="command")?.segment??e,...c.ruleId?{ruleId:c.ruleId}:{}}:{result:"allowed"})})}import{resolve as Tu}from"node:path";function Lr(e){let t=Ci().safeParse(e);return{errors:t.success?[]:Ri(t.error.issues),ruleNames:new Set(Si(e).map((n)=>n.toLowerCase()))}}function wr(e){let t=Di(e);if(!t.ok)return t.result;return Lr(t.parsed)}function Di(e){let t=[],n=new Set;try{let r=typeof e==="string"?St(e):e,o=w(r);if(o===null)return t.push(`File not found: ${r.path}`),{ok:!1,result:{errors:t,ruleNames:n}};if(!o.trim())return t.push("Config file is empty"),{ok:!1,result:{errors:t,ruleNames:n}};return{ok:!0,parsed:JSON.parse(o)}}catch(r){if(r instanceof H)return t.push(r.message),{ok:!1,result:{errors:t,ruleNames:n}};let o=r instanceof Error?r.message:String(r);return t.push(r instanceof SyntaxError?"Invalid JSON":o),{ok:!1,result:{errors:t,ruleNames:n}}}}function Ai(e){return Tu(e??process.cwd(),".safety-net.json")}function me(e){let t=Di(e);if(!t.ok)return t.result;let n=Pi(t.parsed);return{errors:n.errors,ruleNames:n.sources}}import{join as Tr,resolve as qu}from"node:path";import{dirname as mn}from"node:path";var Iu="custom.";function fn(e){if(e.rulebook_version!==2)return[];let t=e.rules.map((n)=>({name:n.name,command:n.command,block_args:[],match:n.match,reason:n.reason,intent:n.intent}));return(e.tests??[]).flatMap((n,r)=>{let o=kr(Ii(n.command));if(o.length===0)return[`tests[${r}]: could not parse fixture command: ${n.command}`];let i=o.reduce((s,a)=>s??$i(a,t)?.id.slice(Iu.length),void 0);if(n.expect==="blocked"){if(i===n.rule)return[];let s=i?`"${i}" matched first`:"no rule matched";return[`tests[${r}]: expected "${n.rule}" to block "${n.command}" but ${s}`]}return i?[`tests[${r}]: expected "${n.command}" to be allowed but "${i}" matched`]:[]})}function kr(e){return e.nodes.flatMap((t)=>{if(t.kind==="group"||t.kind==="function")return kr(t.body);if(t.kind!=="command")return[];let n=Ti(_i(t.dialect,t.words)).words.map(Ei);return[...n.length>0?[n]:[],...t.nested.flatMap((r)=>kr(r))]})}var $u=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function Oi(e,t){let n=Ni(e.rules,t);if(n.length>0)return{ok:!0,specs:n};return ji(e.rules,t)}function Fi(e,t){let n=Ni(e,t);if(n.length>0)return{ok:!0,specs:n};let r=Fu(e,t);if(r.length>0)return{ok:!0,specs:r};let o=ju(e,t);if(!o.ok)return o;if(o.specs.length>0)return{ok:!0,specs:o.specs};return ji(e,t)}function ji(e,t){let n=e.filter((r)=>Sr(r)?.name===t);if(n.length===1)return{ok:!0,specs:n};return Ou(t,n)}function Ou(e,t){return{ok:!1,result:{ok:!1,errors:t.length===0?[`No configured rulebook matches ${e}`]:[`Ambiguous rulebook match ${e}: ${t.join(", ")}`],entries:[]}}}function Ni(e,t){return e.filter((n)=>n===t)}function Fu(e,t){let n=t.match($u),r=n?.[1],o=n?.[2],i=n?.[3];if(!r||!o||!i||!Ne(i))return[];return Hi(e,(s)=>s.owner===r&&s.repo===o&&s.ref===i)}function ju(e,t){if(!Se(t))return{ok:!0,specs:[]};let[n,r]=t.split("/"),o=Hi(e,(s)=>s.owner===n&&s.repo===r);if(new Set(o.map((s)=>Sr(s)?.ref).filter((s)=>!!s)).size<2)return{ok:!0,specs:o};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${t}. Use an explicit ref:`,` cc-safety-net rule remove ${t}#<ref>`],entries:[]}}}function Sr(e){try{return je(e)}catch{return null}}function Hi(e,t){return e.filter((n)=>{let r=Sr(n);return r?t(r):!1})}var qi=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function Mi(e,t,n=Rt(mn(mn(t)),"rules policy"),r=ge()){if(re(e))return Uu(e,r);return Mu(e,t,n)}async function Vi(e,t,n,r,o,i){if(!re(e))return Mi(e,t,n,r);let s=o?null:Nu(e,t,n);if(s)return s;if(!o&&!i)throw Error(`${e} is not vendored; run rule update ${e} to vendor it`);return Mi(e,t,n,r)}function Nu(e,t,n=Rt(mn(mn(t)),"rules policy")){let r=je(e),o=Re(t,r.name),i=w(x(n,o));if(i===null)return null;let s=Dt(Pr(i,`Invalid rulebook ${o}.`));if(s.name!==r.name)throw Error(`rulebook name "${s.name}" in ${o} must match "${r.name}"`);return{spec:e,rulebook:s,content:i}}async function zi(e,t={}){if(!Se(e))throw Error(`Invalid GitHub repository source: ${e}`);let[n,r]=e.split("/");if(!n||!r)throw Error(`Invalid GitHub repository source: ${e}`);if(t.ref!==void 0&&!Ne(t.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${t.ref}`);let o=t.operation??ge(),i=t.ref??await Hu(n,r,e,o),s=await Ji(n,r,i,e,o),a=await gn(`https://api.github.com/repos/${n}/${r}/git/trees/${s}?recursive=1`,"tree",o),l=a.response;if(!l.ok)throw Error(`Failed to inspect ${e}: GitHub tree returned ${l.status}`);let c=JSON.parse(a.content);if(!Array.isArray(c?.tree))throw Error(`Failed to inspect ${e}: unexpected GitHub tree response`);let d=c.tree,m=[...new Set(d.flatMap((g)=>{if(!g||typeof g!=="object")return[];let u=g;if(u.type!=="blob"||typeof u.path!=="string")return[];let p=u.path.match(xr);return p?.[1]?[p[1]]:[]}))].sort();if(m.length===0)throw Error(`No rulebooks found in ${e} under ${Pt}/`);return{source:e,owner:n,repo:r,ref:i,commit:s,names:m}}async function Hu(e,t,n,r){let o=await gn(`https://api.github.com/repos/${e}/${t}`,"metadata",r),i=o.response;if(!i.ok)throw Error(`Failed to inspect ${n}: GitHub returned ${i.status}`);let a=JSON.parse(o.content)?.default_branch;if(typeof a!=="string"||a==="")throw Error(`Failed to inspect ${n}: missing default branch`);if(!Ne(a))throw Error(`GitHub returned an invalid default branch: ${a}`);return a}function Mu(e,t,n){Cr(e);let r=Re(t,e),o=w(x(n,r));if(o===null)throw Error(`Rulebook source not found: ${e}`);let i=Ki(Pr(o,"Invalid local rulebook source."));if(i.name!==e)throw Error(`rulebook name "${i.name}" must match local source "${e}"`);return{spec:e,rulebook:i,content:o}}async function Uu(e,t){let n=je(e),r=await Ji(n.owner,n.repo,n.ref,e,t),o=await gn(`https://raw.githubusercontent.com/${n.owner}/${n.repo}/${r}/${n.path}`,"raw",t),i=o.response;if(!i.ok)throw Error(`Failed to fetch ${e}: GitHub raw returned ${i.status}`);let s=o.content,a=Ki(Pr(s,"Invalid GitHub rulebook response."));if(a.name!==n.name)throw Error(`rulebook name "${a.name}" must match GitHub source "${n.name}"`);return{spec:e,rulebook:a,content:s}}function Ki(e){let t=Dt(e),n=fn(t);if(n.length>0)throw Error(n.join("; "));return t}function Pr(e,t){try{return JSON.parse(e)}catch{throw Error(t)}}async function Ji(e,t,n,r,o){let i=await gn(`https://api.github.com/repos/${e}/${t}/commits/${encodeURIComponent(n)}`,"commit",o),s=i.response;if(!s.ok)throw Error(`Failed to resolve ${r}: GitHub returned ${s.status}`);let a=JSON.parse(i.content);if(typeof a?.sha!=="string"||a.sha==="")throw Error(`Failed to resolve commit for ${r}`);return a.sha}async function Gu(e,t,n={}){if(n.signal?.aborted)throw n.signal.reason;let r=n.budget??Rr(),o=new AbortController,i=()=>o.abort(n.signal?.reason);n.signal?.addEventListener("abort",i,{once:!0});let s=!1,a=setTimeout(()=>{if(o.signal.aborted)return;s=!0,o.abort()},n.timeoutMs??qi.timeoutMs);try{if(n.signal?.aborted)throw n.signal.reason;Gi(r);let l=await(n.fetch??fetch)(e,{signal:o.signal,redirect:"error"});if(!l.ok)return Wi(l),{response:l,content:""};return{response:l,content:await Bu(l,t,r,()=>o.abort())}}catch(l){if(s)throw Error("GitHub request timed out",{cause:l});if(n.signal?.aborted)throw n.signal.reason;throw l}finally{clearTimeout(a),n.signal?.removeEventListener("abort",i)}}function gn(e,t,n){return Gu(n.resolveUrl?.(e)??e,t,{budget:n.budget,signal:n.controller.signal})}async function Bu(e,t,n=Rr(),r){let o=qi[`${t}Bytes`],i=Number(e.headers.get("content-length"));if(Number.isFinite(i)&&i>o)throw Wi(e),Error(`GitHub ${t} response exceeds ${o} bytes`);if(!e.body)return"";let s=e.body.getReader(),a=[],l=0;while(!0){let c=await s.read();if(c.done)break;try{Bi(n,c.value.byteLength)}catch(d){throw r?.(),Ui(s),d}if(l+=c.value.byteLength,l>o)throw r?.(),Ui(s),Error(`GitHub ${t} response exceeds ${o} bytes`);a.push(Buffer.from(c.value))}return Buffer.concat(a,l).toString("utf-8")}function Wi(e){if(!e.body)return;Yi(()=>e.body?.cancel())}function Ui(e){Yi(()=>e.cancel())}function Yi(e){try{Promise.resolve(e()).catch(()=>{})}catch{}}async function Tt(e={}){let t=$r(e);return Vu(t,await hn(t,ge()))}function Vu(e,t){if(!t.ok)return t;let n=U(e),r=[...new Set(W(n.configPath,n.filesystemScope))];if(r.length===0)return t;return{ok:!1,errors:r,entries:t.entries}}async function hn(e,t,n={},r=new Set,o=new Set){try{let i=U(e),s=_r(i.configTarget);if(!s.ok)return s.result;let a=s.config;if(e.check)return ap(a,i,e);let l=e.only?Oi(a,e.only):{ok:!0,specs:a.rules};if(!l.ok)return l.result;let c=new Set([...e.refresh?l.specs:[],...r]),d=(v)=>Vi(v,i.configDir,i.filesystemScope,t,c.has(v),!e.refresh||c.has(v)),m=await np(a.rules,e.refresh?(v)=>d(v).then((P)=>({ok:!0,item:P})).catch((P)=>{if(Qi(P))throw P;return{ok:!1,spec:v,message:P instanceof Error?P.message:String(P)}}):async(v)=>({ok:!0,item:await d(v)}),t),g=m.filter((v)=>!v.ok),u=m.filter((v)=>v.ok).map((v)=>v.item),p=u.flatMap((v)=>zu(v,a.rules)),f=u.flatMap((v)=>Ku(v,o,i)),b=new Set([...p,...f].map((v)=>v.spec)),L=[...g,...p,...f],h=[],R=Wu(h,()=>u.flatMap((v)=>b.has(v.spec)||L.length>0&&o.has(v.spec)?[]:Ju(v,i,n,h)));return{ok:L.length===0,errors:L.map((v)=>`Failed to update ${v.spec}: ${v.message}`),entries:u.map(Zu),changes:R}}catch(i){return Et(i)}}function zu(e,t){if(!re(e.spec))return[];let n=Dr(e.spec),r=t.filter((o)=>o!==e.spec&&Dr(o).toLowerCase()===n.toLowerCase());if(r.length===0)return[];return[{ok:!1,spec:e.spec,message:`rulebook name "${n}" is also claimed by ${r.join(", ")}; rename one of them`}]}function Ku(e,t,n){if(!t.has(e.spec)||!re(e.spec))return[];let r=Re(n.configDir,e.rulebook.name),o=w(x(n.filesystemScope,r));if(o===null||o===e.content)return[];return[{ok:!1,spec:e.spec,message:`${r} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Ju(e,t,n,r){if(!re(e.spec))return[];let o=Re(t.configDir,e.rulebook.name),i=x(t.filesystemScope,o),s=w(i);if(s===e.content)return[];return r?.push({target:i,previous:s}),B(i,e.content,void 0,n._testAfterPolicyRename),Yu(e,s)}function Wu(e,t){try{return t()}catch(n){for(let r of[...e].reverse()){if(r.previous===null){he(r.target);continue}B(r.target,r.previous)}throw n}}function Yu(e,t){if(t===null)return[`Vendored ${e.spec} (${e.rulebook.version})`];let n=_t(t),r="problem"in n?null:n.rulebook,o=new Map(r?.rules.map((s)=>[s.name,JSON.stringify(s)])??[]),i=new Set(e.rulebook.rules.map((s)=>s.name));return[`Updated ${e.spec} (${r?.version??"unreadable"} -> ${e.rulebook.version})`,...[...i].filter((s)=>!o.has(s)).map((s)=>` + ${s}`),...[...o.keys()].filter((s)=>!i.has(s)).map((s)=>` - ${s}`),...e.rulebook.rules.filter((s)=>{let a=o.get(s.name);return a!==void 0&&a!==JSON.stringify(s)}).map((s)=>` ~ ${s.name}`)]}function Zu(e){return{spec:e.spec,name:e.rulebook.name,version:e.rulebook.version,ruleCount:e.rulebook.rules.length}}async function Ir(e,t={}){return Xu(e,op(t),ge())}async function Xu(e,t,n,r={}){let o=null,i=!1;try{let s=U(t),a=w(s.configTarget);o={target:s.configTarget,content:a};let l=_r(s.configTarget);if(!l.ok)return l.result;let c=l.config,d=Se(e);Qu(e,t,d);let m=d?await zi(e,{ref:t.ref,operation:n}):null,g=m?ep(m,t.rulebooks):[],u=m?g.map((h)=>tp(c.rules,m,h)??`${e}#${m.ref}/${h}`):[e],p=u.filter((h)=>!c.rules.includes(h)),f=[...c.rules,...p];if(f.length>Ar)return rp();if(f.length!==c.rules.length)i=!0,J(s.configTarget,{version:1,rules:f,overrides:c.overrides??{},transparent_wrappers:c.transparent_wrappers??[]},void 0,r._testAfterPolicyRename);let b=await hn(t,n,r,new Set(p),new Set(p));if(!b.ok)At(s.configTarget,a);if(!b.ok||!m)return b;let L=g.filter((h,R)=>p.includes(u[R]??""));return{...b,add:{source:e,ref:m.ref,selected:g,added:L,alreadyConfigured:g.filter((h)=>!L.includes(h)),commits:p.length>0?[m.commit]:[]}}}catch(s){if(i&&o)try{At(o.target,o.content)}catch(a){return Et(a)}return Et(s)}}function Qu(e,t,n){if(!n&&t.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!n&&t.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${e}`);if(t.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let r=t.rulebooks?.filter((o)=>!Pe.test(o))??[];if(r.length>0)throw Error(`Invalid rulebook names: ${r.join(", ")}`)}function ep(e,t){let n=t?[...new Set(t)]:e.names,r=n.filter((o)=>!e.names.includes(o));if(r.length>0)throw Error(`Rulebooks not found in ${e.source} at ${e.ref}: ${r.join(", ")}
5
- Available rulebooks: ${e.names.join(", ")}`);return n}function tp(e,t,n){let r=`${t.source}#${t.ref}/${n}`;if(e.includes(r))return r;let o=`${t.source}#${t.commit}/${n}`;return e.find((i)=>i===o)}async function np(e,t,n=ge()){if(e.length>Ar)throw Error(Er);let r=Array(e.length),o=0,i,s=Array.from({length:Math.min(e.length,Xi.concurrency)},async()=>{while(!i){let a=o;if(a>=e.length)return;o++;try{r[a]=await t(e[a],a,n.controller.signal)}catch(l){if(!i)i={value:l},o=e.length,n.controller.abort(l);return}}});if(await Promise.all(s),i)throw i.value;return r}function rp(){return{ok:!1,errors:[Er],entries:[]}}function $r(e){return{cwd:e.cwd,userConfigDir:e.userConfigDir,userConfigPath:e.userConfigPath,projectConfigPath:e.projectConfigPath,global:e.global,check:e.check,only:e.only,refresh:e.refresh}}function op(e){return{...$r(e),ref:e.ref,rulebooks:e.rulebooks}}function ip(e){return{...$r(e),deleteSource:e.deleteSource}}async function Or(e,t={}){try{return await sp(e,ip(t),{})}catch(n){return Et(n)}}async function sp(e,t,n){let r=U(t),o=q(r.configTarget);if(o.errors.length>0)return{ok:!1,errors:o.errors,entries:[]};if(!o.config)return{ok:!1,errors:[`No config found at ${r.configPath}`],entries:[]};let i=Fi(o.config.rules,e);if(!i.ok)return i.result;let s=t.deleteSource?lp(r.configDir,i.specs,r.filesystemScope):{ok:!0,dirs:[]};if(!s.ok)return s.result;let a=w(r.configTarget);if(a===null)return Et(Error("Rules config is unavailable."));try{J(r.configTarget,{version:1,rules:o.config.rules.filter((d)=>!i.specs.includes(d)),overrides:o.config.overrides??{},transparent_wrappers:o.config.transparent_wrappers??[]},void 0,n._testAfterPolicyRename)}catch(d){throw At(r.configTarget,a),d}let l=await hn(t,ge(),n);if(!l.ok)return At(r.configTarget,a),l;let c=cp(s.dirs,n,r.filesystemScope);if(!c.ok){At(r.configTarget,a);let d=await hn(t,ge(),n);if(!d.ok)return{ok:!1,errors:[...c.result.errors,...d.errors],entries:d.entries};return c.result}return l}async function ap(e,t,n){let r=es(e,t.configDir,n.global?"user":"project",t.filesystemScope);return{ok:r.errors.length===0&&r.warnings.length===0,errors:[...r.errors,...r.warnings],entries:r.entries}}function lp(e,t,n){let r=t.flatMap((a)=>Pe.test(a)?[]:["--delete-source can only delete local rulebook sources"]),o=t.map((a)=>Tr(e,a)),i=r.length>0?[]:o.flatMap((a)=>ts(a,n)),s=[...r,...i];return s.length>0?{ok:!1,result:{ok:!1,errors:s,entries:[]}}:{ok:!0,dirs:o}}function ts(e,t){let n=qu(e),r=x(t,n),o=it(r);if(!o)return[`Local rulebook source directory not found: ${e}`];let i=o.find((s)=>s.name==="rulebook.json");if(!i)return[`Local rulebook source directory is missing rulebook.json: ${e}`];if(i.kind!=="file")throw new H(t.label);if(w(x(t,Tr(n,"rulebook.json"))),o.length>1)return[`Local rulebook source directory contains extra files: ${e}. delete manually if you really want to remove the directory.`];return[]}function cp(e,t,n){let r=e.flatMap((o)=>{try{if(!it(x(n,o)))return[];let i=ts(o,n);if(i.length>0)return i;return dp(o,t,n),[]}catch(i){return[`Failed to delete local rulebook source ${o}: ${i instanceof Error?i.message:String(i)}`]}});return r.length>0?{ok:!1,result:{ok:!1,errors:r,entries:[]}}:{ok:!0}}function dp(e,t,n){if(t._testDeleteLocalSourceDir){t._testDeleteLocalSourceDir(e);return}he(x(n,Tr(e,yn))),Zi(x(n,e))}function At(e,t){if(t===null){he(e);return}B(e,t)}function Et(e){return{ok:!1,errors:[e instanceof Error?e.message:String(e)],entries:[]}}function at(e,t){let n=fp(t),r=as(n),o={effectiveLevel:r.effectiveLevel,selectedPreset:n.policySnapshot.policy.safety.level??"standard",...n.policySnapshot.policyScopes?{safetyPresetScope:n.policySnapshot.policyScopes.levelScope}:{},effectiveCapabilities:r.effectiveCapabilities,destructiveCommandRuleOverrides:n.policySnapshot.policy.destructiveCommandRuleOverrides},{configSource:i,configValid:s}=pp({cwd:t?.cwd,userConfigDir:t?.userConfigDir});if(!e||!e.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:i,configValid:s,...o};let a=mp(e,n);if(a)return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:a.rule,matched:!0,reason:a.reason}]}]},result:"blocked",reason:V(a.reason),segment:V(a.target),...a.ruleId?{ruleId:V(a.ruleId)}:{},configSource:i,configValid:s,...o};let l=xi(e,n),c=l.decision,d=c?.ruleId??gp(e,n),m=$t.find((u)=>u.id===d&&u.activationCapability),g=m?r.policy.effectiveDestructiveCommandRules[m.id]:void 0;return{trace:yp(l.trace),result:c?"blocked":"allowed",reason:c?V(c.reason):void 0,segment:c?V(c.evidence.find((u)=>u.kind==="command")?.segment??e):void 0,ruleId:c?.ruleId?V(c.ruleId):void 0,customRule:hp(vp(c?.ruleId,n.policySnapshot)),configSource:i,configValid:s,...o,...m&&g?{ruleActivation:{id:m.id,...g}}:{}}}function pp(e){let t=oe(e?.cwd),n=e?.userConfigPath??ie(e),r=Ae({cwd:e?.cwd,userConfigDir:e?.userConfigDir,userConfigPath:e?.userConfigPath});try{if(w(r.projectConfigTarget)!==null){if(me(r.projectConfigTarget).errors.length===0)return{configSource:t,configValid:!0};return{configSource:t,configValid:!1}}}catch(o){if(o instanceof H)return{configSource:t,configValid:!1};throw o}try{if(w(r.userConfigTarget)!==null){let o=me(r.userConfigTarget);return{configSource:n,configValid:o.errors.length===0}}return{configSource:null,configValid:!0}}catch(o){if(o instanceof H)return{configSource:n,configValid:!1};throw o}}function fp(e){let t=up(e?.cwd??process.cwd()),n=e?.policySnapshot??z({cwd:t,userConfigDir:e?.userConfigDir}),r=ye(n.policy);return{cwd:t,effectiveCwd:t,policySnapshot:n,environment:ns(),protectedGitMetadata:ss([t]),effectiveCapabilities:r.capabilities,strict:e?.strict??r.strict,paranoidRm:r.paranoidRm,paranoidInterpreters:r.paranoidInterpreters,worktreeMode:r.worktreeMode}}function mp(e,t){let n=t.cwd??process.cwd(),r=rs(st("",{command:e},{kind:"command",shell:"posix"},{executionCwd:n,configCwd:n},e)),o=ps(r);if(o)return{reason:us,target:o.target,ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};let i=ds(r);if(i)return{reason:cs,target:i.target,ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};let s=is(r,t.protectedGitMetadata);if(s)return{reason:os,target:s.target,ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};let a=t.policySnapshot.policy,l=a.secretProtection.enabled===!1?null:ms(r,a.secretProtection,{strict:t.strict});if(l)return{reason:fs,target:l.target,ruleId:l.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"};return null}function gp(e,t){let n=t.policySnapshot.policy,r=Ot({...n,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...n.destructiveCommandRuleOverrides,...Object.fromEntries($t.flatMap((o)=>o.activationCapability?[[o.id,"on"]]:[]))}},t.policySnapshot.state==="degraded"?{diagnostics:t.policySnapshot.diagnostics,reason:t.policySnapshot.reason}:void 0);return ls(e,{...t,policySnapshot:r,strict:!0,paranoidRm:!0,paranoidInterpreters:!0})?.ruleId}function hp(e){if(!e)return;return{id:V(e.id),...e.rulebook?{rulebook:{name:V(e.rulebook.name),version:V(e.rulebook.version)}}:{},...e.source?{source:V(e.source)}:{},...e.override?{override:{type:"reason",reason:V(e.override.reason)}}:{}}}function yp(e){let t=e.events.flatMap((r)=>r.kind==="step"&&r.scope==="global"?[r.step]:[]),n=new Map;for(let r of e.events){if(r.kind!=="step"||r.scope!=="segment")continue;let o=n.get(r.segmentIndex)??{index:r.segmentIndex,steps:[]};o.steps.push(r.step),n.set(r.segmentIndex,o)}return{steps:t,segments:[...n.values()]}}function vp(e,t){let n=e?.replace(/^custom\./,"");if(!n||!t.policy.rules.some((r)=>r.name===n))return;return t.ruleMetadata[n]??Object.freeze({id:n})}import{existsSync as hs,readFileSync as bp}from"node:fs";function gs(e,t){return{"safety.level":e.safety.level,...Nr("safety.overrides",e.safety.overrides),"workflow.worktree_mode":String(e.workflow.worktree_mode),"destructive_command_protection.enabled":String(e.destructive_command_protection.enabled),...Nr("destructive_command_protection.overrides",e.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Hr(e.destructive_command_protection.allow_paths),"secret_protection.enabled":String(e.secret_protection.enabled),...Nr("secret_protection.overrides",e.secret_protection.overrides),"secret_protection.deny_paths":Hr(e.secret_protection.deny_paths),"secret_protection.allow_paths":Hr(e.secret_protection.allow_paths),...t?{"audit.retention_days":String(e.audit.retention_days)}:{}}}function Ft(e,t,n){let r=gs(e,n),o=gs(t,n);return[...new Set([...Object.keys(r),...Object.keys(o)])].flatMap((i)=>r[i]===o[i]?[]:[{field:i,before:r[i],after:o[i]}])}function lt(e){let t=ve(e);if(!hs(t))return{baseline:Y(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__),diagnostics:[]};let n=_e(t);return{baseline:Y(n.value),diagnostics:n.errors.length>0?n.errors:Ee(n.value)}}function _e(e){if(!hs(e))return{errors:[`${e}: file not found`]};try{return{value:JSON.parse(bp(e,"utf-8")),errors:[]}}catch(t){let n=t instanceof Error?t.message:String(t);return{errors:[`${e}: ${t instanceof SyntaxError?`Invalid JSON: ${n}`:n}`]}}}function jt(e,t){let n=Lp(e)?e:{};return{version:t.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((r)=>n[r]!==void 0).map((r)=>[r,n[r]]))}}function Nr(e,t){return Object.fromEntries(Object.entries(t).flatMap(([n,r])=>r===void 0?[]:[[`${e}.${n}`,String(r)]]))}function Hr(e){return e.length===0?"(none)":e.join(", ")}function Lp(e){return!!e&&typeof e==="object"&&!Array.isArray(e)}function Rp(e){let t=ct(),n=E({label:"logs",booleans:{all:["--all"],suspect:["--suspect"],json:["--json"],pruneLegacy:["--prune-legacy"],dryRun:["--dry-run"]},values:{id:["--id"],limit:["--limit"],since:["--since"],agent:["--agent"],rule:["--rule"],session:["--session"],project:["--project"]}},e);if(fe(n.errors))return null;if(n.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(n.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let r=n.values.limit===void 0?20:ys(n.values.limit);if(r===null)return console.error("--limit must be a positive number"),null;let o=n.values.since===void 0?Math.min(30,t):ys(n.values.since);if(o===null||o>t)return console.error(`--since must be a positive number of days no greater than ${t}`),null;let i={limit:r,limitExplicit:n.values.limit!==void 0,since:o,sinceExplicit:n.values.since!==void 0,all:n.flags.all,json:n.flags.json,suspect:n.flags.suspect,pruneLegacy:n.flags.pruneLegacy,dryRun:n.flags.dryRun,id:n.values.id,agent:n.values.agent,rule:n.values.rule,session:n.values.session,project:n.values.project===void 0?void 0:Sp(n.values.project)};if(i.id&&(i.agent!==void 0||i.rule!==void 0||i.session!==void 0||i.project!==void 0||i.suspect||i.sinceExplicit||i.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(i.pruneLegacy&&(i.id!==void 0||i.agent!==void 0||i.rule!==void 0||i.session!==void 0||i.project!==void 0||i.suspect||i.all||i.sinceExplicit||i.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(i.dryRun&&!i.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return i}async function Ls(e,t={}){let n=Rp(e);if(!n)return 1;let r=t.logsDir??be();if(n.pruneLegacy)return Pp(r,n.json,n.dryRun);if(!r)return console.log(n.json?"[]":n.id?`No retained audit log entry found for id ${F(n.id)}.`:"No audit log entries found."),0;He(r);let o={count:0},i=Ce(r,o).flatMap((d)=>Fe(d,o).map((m)=>({entry:m,file:d})));if(o.count>0)console.error(`warning: ${o.count} audit log ${o.count===1?"source":"sources"} could not be read; these results are incomplete`);if(n.id)return _p(i,n,t.timeZone);let s=Date.now()-n.since*24*60*60*1000,a=i.filter((d)=>Tp(d,n,r,s)),l=n.suspect?hr(a.map((d)=>d.entry)):null,c=(l?a.filter((d)=>l.has(d.entry)):a).sort((d,m)=>Date.parse(m.entry.ts)-Date.parse(d.entry.ts)).slice(0,n.limit);if(n.json)return console.log(JSON.stringify(c.map((d)=>d.entry),null,2)),0;if(c.length===0)return console.log("No audit log entries found."),0;for(let d of c)console.log(Op(d.entry,t.timeZone));return 0}function Pp(e,t,n){let r=e?Ap(e).map((a)=>Cp(e,a)):[];if(n)return Dp(r,t);let o=[],i=0,s=0;for(let a of r){let l=vs(a,{throwIfNoEntry:!1})?.size??0,c=Ep(a);if(c){o.push(`${bs(a)}: ${c}`);continue}i++,s+=l}if(t)return console.log(JSON.stringify({removedFiles:i,removedBytes:s,failedFiles:o.length})),o.length===0?0:1;console.log(i===0&&o.length===0?"No legacy audit log files found.":`Removed ${i} legacy audit log ${i===1?"file":"files"} (${ws(s)}).`);for(let a of o)console.error(`Could not remove ${F(a)}`);if(console.log("Nested v2 audit logs were not changed."),i>0)console.log("This deletion cannot be undone.");return o.length===0?0:1}function Dp(e,t){let n=e.reduce((r,o)=>r+(vs(o,{throwIfNoEntry:!1})?.size??0),0);if(t)return console.log(JSON.stringify({dryRun:!0,files:e.length,bytes:n})),0;if(console.log(e.length===0?"No legacy audit log files found.":`Would remove ${e.length} legacy audit log ${e.length===1?"file":"files"} (${ws(n)}).`),console.log("Nested v2 audit logs are not included."),e.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Ap(e){try{return wp(e,{withFileTypes:!0}).filter((t)=>t.isFile()&&t.name.endsWith(".jsonl")).map((t)=>t.name)}catch{return[]}}function Ep(e){try{return kp(e),null}catch(t){return t instanceof Error?t.message:String(t)}}function ws(e){let t=["B","KiB","MiB","GiB"],n=Math.min(Math.floor(Math.log2(Math.max(e,1))/10),t.length-1);return`${Math.round(e/1024**n*10)/10} ${t[n]}`}function _p(e,t,n){let r=e.filter((i)=>i.entry.id===t.id);if(r.length>1)return console.error(`Multiple audit log entries found for id ${F(t.id??"")}.`),1;if(t.json)return console.log(JSON.stringify(r.map((i)=>i.entry),null,2)),0;let o=r[0];if(!o)return console.log(`No retained audit log entry found for id ${F(t.id??"")}.`),0;return console.log(Fp(o.entry,n)),0}function Tp(e,t,n,r){if(!t.all&&e.entry.decision==="allow")return!1;if(Date.parse(e.entry.ts)<r)return!1;if(t.agent!==void 0&&e.entry.agent!==t.agent)return!1;if(t.rule!==void 0&&e.entry.ruleId!==t.rule)return!1;if(t.session!==void 0&&!Ip(e,n,t.session))return!1;if(t.project!==void 0&&!$p(e.entry.cwd,t.project))return!1;return!0}function Ip(e,t,n){if(e.entry.sessionId===n)return!0;return xp(e.file)===t&&bs(e.file,".jsonl")===n}function $p(e,t){if(!e)return!1;return e===t||e.startsWith(`${t}/`)}function Op(e,t){let n=F(e.id??"-"),r=F(e.decision??"deny"),o=e.cwd?` [${F(e.cwd)}]`:"",i=e.segment||e.command,s=i===e.command?"":"↳ ",a=i.length>50?`${i.slice(0,50)}…`:i;return`${n.padEnd(16)} ${F(ks(e.ts,t))} ${r.padEnd(5)} ${F(e.agent??"-").padEnd(15)} ${F(e.ruleId??"-").padEnd(20)} ${s}${F(a)}${o}`}function Fp(e,t){let n=(o)=>F(o===void 0||o===null||o===""?"-":o),r=e.shape?`${e.agent??"-"} (shape: ${e.shape})`:e.agent??"-";return[`id: ${n(e.id)}`,`ts: ${n(ks(e.ts,t))}`,`decision: ${n(e.decision)}`,`agent: ${n(r)}`,`level: ${n(e.level)}`,`tool: ${n(e.toolName)}`,`rule: ${n(e.ruleId)}`,`intent: ${n(e.intent)}`,`stage: ${n(e.failureStage)}`,`error: ${n(e.errorCode)}`,`session: ${n(e.sessionId)}`,`cwd: ${n(e.cwd)}`,`version: ${n(e.v)}`,`truncated: ${n(e.truncated===!0?"yes":void 0)}`,`reason: ${n(e.reason)}`,`command: ${n(e.command)}`,`segment: ${n(e.segment)}`].join(`
6
- `)}function ks(e,t){let n=new Date(e);if(Number.isNaN(n.getTime()))return e;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:t}).format(n)}function ys(e){let t=Number(e);return Number.isFinite(t)&&t>0?t:null}var xs={name:"doctor",aliases:["--doctor"],description:"Run diagnostic checks to verify installation and configuration",usage:"doctor [options]",options:[{flags:"--json",description:"Output diagnostics as JSON"},{flags:"--skip-update-check",description:"Skip npm registry version check"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net doctor","cc-safety-net doctor --json","cc-safety-net doctor --skip-update-check"]};var Cs={name:"explain",description:"Show step-by-step analysis trace of how a command would be analyzed",usage:"explain [options] <command>",argument:"<command>",options:[{flags:"--json",description:"Output analysis as JSON"},{flags:"--cwd",argument:"<path>",description:"Use custom working directory"},{flags:"-h, --help",description:"Show this help"}],examples:['cc-safety-net explain "git reset --hard"','cc-safety-net explain --json "rm -rf /"','cc-safety-net explain --cwd /tmp "git status"']};var Ss={name:"gui",description:"Open the local policy editor GUI",usage:"gui [options]",options:[{flags:"--no-open",description:"Print the URL without opening a browser"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net gui","cc-safety-net gui --no-open"]};import{isAbsolute as $s,join as Kp,relative as Jp}from"node:path";var jp=8388608;function Np(e,t){console.log(JSON.stringify(e(Ps(t))))}async function Hp(e){let t;try{t=(await Wr(process.stdin)).trim()}catch{e({reason:"Failed to parse hook input JSON."});return}if(!t){e({reason:"Missing hook input JSON."});return}return Yr(t,e,"Failed to parse hook input JSON.")}async function Wr(e){let t=[],n=0;for await(let r of e){let o=typeof r==="string"?Buffer.from(r,"utf-8"):Buffer.from(r.buffer,r.byteOffset,r.byteLength);if(n+=o.byteLength,n>jp)throw Mp(e),Error("hook input byte limit exceeded");t.push(o)}return Buffer.concat(t,n).toString("utf-8")}function Mp(e){let t=e.destroy??e.cancel;if(!t)return;try{Promise.resolve(t.call(e)).catch(()=>{})}catch{}}function Yr(e,t,n){try{return JSON.parse(e)}catch{t({reason:n});return}}function j(e,t){let n=t.get(e);return n?{kind:"command",shell:n}:{kind:As(e)}}function ae(e,t,n,r){let o=e===void 0?process.cwd():e,i=typeof o==="string"&&o.trim()!==""?Z([o]):void 0;if(i)return{configCwd:i,executionCwd:i};return T(r,t,n,qp(o)),null}function T(e,t,n,r){let o;try{o=Jr(t)}catch(i){if(!(i instanceof Le))throw i}e(vn({command:o,segment:r,toolName:n}))}async function Up(e){let t=await Hp(e.outputDeny);if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t)){T(e.outputDeny);return}if(!e.isSupported(t))return;let n=e.getAgent?.(t)??e.agent,r=e.agent===n?void 0:e.agent,o=zp(t),i=(u,p)=>{Rs(u,()=>e.getSessionId(t),{agent:n,shape:r,toolName:p,cwd:o}),e.outputDeny(u)},s=e.getToolName(t);if(typeof s!=="string"||s.trim()===""){T((u)=>i(u),Vp(t));return}let a=s,l=(u)=>i(u,a),c;try{c=e.getToolInput(t,a,l)}catch(u){if(!(u instanceof Le))throw u;T(l,void 0,a);return}if(!c.ok)return;let d=e.getContext(t,c.input,a,l);if(!d)return;let m;try{m=Jr(c.input)}catch(u){if(!(u instanceof Le))throw u;T(l,void 0,a);return}let g=st(a,c.input,c.route,d,m??null);try{let u=bn(g,{guard:{auditAllowed:Es(),dependencies:e.guardDependencies},audit:{agent:n,shape:r,getSessionId:()=>e.getSessionId(t)}}),p=Kr(u,{includeEvidence:!0,toolName:u.stage==="command-analysis"?void 0:a});if(p){e.outputDeny(p);return}e.outputAllow?.()}catch(u){if(!(u instanceof _s))throw u;Gp(u);let p=Kr(u.evaluation,{includeEvidence:!0,toolName:u.evaluation.stage==="command-analysis"?void 0:a});if(p)e.outputDeny(p);return}}function Gp(e){if(!Nt(S.debug))return;console.error(`CC Safety Net debug: ${Bp(e.stage)}: ${Ds(e.cause)}`)}function Bp(e){if(e==="policy-protection")return"hook policy protection failed";if(e==="config-load")return"hook config loading failed";if(e==="secret-protection")return"hook secret protection failed";return"hook analysis failed"}function qp(e){return typeof e==="string"?e:void 0}function Vp(e){if(!e||typeof e!=="object"||Array.isArray(e))return;if(Object.hasOwn(e,"tool_input"))return e.tool_input;let t=e.toolCall;if(t&&typeof t==="object"&&!Array.isArray(t))return t.args;return}function zp(e){if(!e||typeof e!=="object"||Array.isArray(e))return null;let t=e.cwd;if(typeof t==="string")return t;let n=e.toolCall;if(!n||typeof n!=="object"||Array.isArray(n))return null;let r=n.args;if(!r||typeof r!=="object"||Array.isArray(r))return null;let o=r.Cwd;return typeof o==="string"?o:null}async function N(e){let t=(o)=>Np(e.createDenyOutput,o),n=e.createAllowOutput;await Up({...e,outputDeny:t,outputAllow:n?()=>console.log(JSON.stringify(n())):void 0})}function Gt(e){return Kp(e,".gemini","config","hooks.json")}var Wp=new Map([["run_command","auto"]]),Yp=new Set(["absolutepath","directorypath","file_path","filepath","path","searchdirectory","searchpath","target_file","targetfile"]);function Os(e){return j(e,Wp)}async function Fs(){await N({agent:"antigravity-cli",createDenyOutput:(e)=>({decision:"deny",reason:e}),isSupported:()=>!0,getToolName:(e)=>e.toolCall?.name,getToolInput:(e,t)=>({ok:!0,input:t2(e.toolCall?.args,t),route:Os(t)}),getContext:Zp,getSessionId:(e)=>e.conversationId})}function Zp(e,t,n,r){let i=e2(e).flatMap((c)=>{let d=Z([c]);return d?[d]:[]});if(!i[0])return qe(r,t,n),null;if(n!=="run_command"){let c;try{c=Xp(t,n,i)}catch(d){if(d instanceof Le)return qe(r,void 0,n),null;if(!(d instanceof Me))throw d;return qe(r,t,n),null}if(!c)return qe(r,t,n),null;return{configCwd:c,executionCwd:c}}let s=e.toolCall?.args;if(!s||!Object.hasOwn(s,"Cwd"))return{configCwd:i[0],executionCwd:i[0]};let a=s.Cwd;if(typeof a!=="string"||a.trim()==="")return qe(r,t,n),null;let l=we(a,i);if(l){let c=js(l,i);if(!c)return qe(r,t,n,a),null;return{configCwd:c,executionCwd:l}}return qe(r,t,n,a),null}function Xp(e,t,n){let r=Os(t),o=[...Ts(e,Yp),...r.kind==="patch"?Is(e):[]].filter($s),i=Ln(),s=new Set(o.flatMap((a)=>{let l=js(Ut(a,Mt,i),n);return l?[l]:[]}));if(s.size>1)return null;return[...s][0]??n[0]??null}function js(e,t){return t.filter((n)=>Qp(e,n)).reduce((n,r)=>r.length>n.length?r:n,"")||null}function Qp(e,t){let n=Jp(t,e);return n===""||!n.startsWith("..")&&!$s(n)}function qe(e,t,n,r){let o=t&&typeof t==="object"?t.command:void 0;e(vn({command:typeof o==="string"?o:void 0,segment:r,toolName:n}))}function e2(e){if(e.workspacePaths===void 0)return[process.cwd()];let t=Array.isArray(e.workspacePaths)?e.workspacePaths.filter((n)=>typeof n==="string"&&n.trim()!==""):[];return Z(t)?t:[]}function t2(e,t){if(!e)return;if(t!=="run_command")return e;return{...e,command:typeof e.CommandLine==="string"&&e.CommandLine!==""?e.CommandLine:void 0}}var Bt=[{id:"antigravity-cli",displayName:"Antigravity CLI",doctorOrder:3,runtime:{order:1,flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:2,flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",doctorOrder:1,runtime:{order:2,displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{order:3,flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",doctorOrder:4,runtime:{order:3,flags:["-cx","--codex"],description:"Run as a Codex PreToolUse hook",legacyTopLevelFlags:[]},install:{order:4,flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",doctorOrder:7,runtime:{order:6,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:7,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:6,runtime:{order:5,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:6,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",doctorOrder:8,runtime:{order:7,flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:9,runtime:{order:8,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:9,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:10,runtime:{order:9,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:10,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:11,install:{order:11,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:12,install:{order:12,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:13,install:{order:13,flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",doctorOrder:5,runtime:{order:4,flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{order:5,flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],wn=Bt.slice().sort((e,t)=>e.doctorOrder-t.doctorOrder).map((e)=>e.id),Ns=Bt.filter((e)=>("runtime"in e)).slice().sort((e,t)=>e.runtime.order-t.runtime.order).map((e)=>({id:e.id,displayName:"displayName"in e.runtime?e.runtime.displayName:e.displayName,flags:e.runtime.flags,legacyFlags:"legacyFlags"in e.runtime?e.runtime.legacyFlags:[],description:e.runtime.description,legacyTopLevelFlags:e.runtime.legacyTopLevelFlags})),X=Bt.slice().sort((e,t)=>e.install.order-t.install.order).map((e)=>({id:e.id,...e.install})).map(({order:e,...t})=>t),Yv=Object.fromEntries(Bt.map((e)=>[e.id,e.displayName]));function D(e){return Bt.find((t)=>t.id===e)?.displayName??e}import{homedir as n2}from"node:os";import{isAbsolute as Hs,join as Zr}from"node:path";function Us(e){if(e!==void 0&&e!==null&&typeof e!=="string")return"unknown";if(typeof e==="string"&&!Hs(e))return"unknown";try{let t=Ln(),n=typeof e==="string"&&e?Ut(e,Mt,t):void 0,r=process.env.HOME||n2(),o=[["codex",process.env.CODEX_HOME||Zr(r,".codex")],["copilot-cli",process.env.COPILOT_HOME||Zr(r,".copilot")],["claude-code",process.env.CLAUDE_CONFIG_DIR||Zr(r,".claude")]],i=n?o.flatMap(([s,a])=>{if(!Hs(a))return[];return Ms(n,Ut(a,Mt,t))?[s]:[]}):[];if(i.length===1)return i[0]??"unknown";if(i.length>1)return"unknown"}catch(t){if(t instanceof Me)return"unknown";return"unknown"}if(process.env.CLAUDECODE==="1"||Boolean(process.env.CLAUDE_CODE_ENTRYPOINT))return"claude-code";return"unknown"}var Xr="PreToolUse",Gs="BeforeTool",Bs="pre_tool_call",Qr="PreToolUse";async function kn(e){await N({agent:e.agent,...e.getAgent?{getAgent:e.getAgent}:{},createDenyOutput:(t)=>({hookSpecificOutput:{hookEventName:Xr,permissionDecision:"deny",permissionDecisionReason:t}}),isSupported:(t)=>t.hook_event_name===Xr,getToolName:(t)=>t.tool_name,getToolInput:(t,n)=>({ok:!0,input:t.tool_input,route:e.getToolRoute(n)}),getContext:(t,n,r,o)=>ae(t.cwd,n,r,o),getSessionId:(t)=>t.session_id})}var r2=new Map([["Bash","posix"],["PowerShell","powershell"]]);function o2(e){return j(e,r2)}async function qs(){await kn({agent:"claude-code",getAgent:(e)=>Us(e.transcript_path),getToolRoute:o2})}var i2=new Map([["Bash","auto"]]);async function Vs(){await kn({agent:"codex",getToolRoute:(e)=>j(e,i2)})}var s2=new Map([["bash","auto"],["Bash","auto"],["powershell","powershell"],["PowerShell","powershell"]]);function a2(e){return j(e,s2)}async function zs(){await N({agent:"copilot-cli",createDenyOutput:(e)=>({permissionDecision:"deny",permissionDecisionReason:e}),isSupported:()=>!0,getToolName:(e)=>e.toolName,getToolInput:(e,t,n)=>{if(typeof e.toolArgs!=="string")return n({reason:"Failed to parse toolArgs JSON."}),{ok:!1};let r=Yr(e.toolArgs,n,"Failed to parse toolArgs JSON.");if(r===void 0)return{ok:!1};return{ok:!0,input:r,route:a2(t)}},getContext:(e,t,n,r)=>ae(e.cwd,t,n,r),getSessionId:(e)=>typeof e.sessionId==="string"&&e.sessionId.trim()?e.sessionId:void 0})}var l2=new Map([["Shell","auto"]]);function c2(e){return j(e,l2)}async function Ks(){await N({agent:"cursor",createDenyOutput:(e)=>({permission:"deny",user_message:e,agent_message:e}),createAllowOutput:()=>({permission:"allow"}),isSupported:()=>!0,getToolName:(e)=>e.tool_name,getToolInput:(e,t)=>({ok:!0,input:e.tool_input,route:c2(t)}),getContext:d2,getSessionId:(e)=>e.conversation_id})}function d2(e,t,n,r){let o=u2(e);if(!o[0])return T(r,t,n),null;let i=we(f2(e.cwd),o);if(!i)return T(r,t,n,typeof e.cwd==="string"?e.cwd:void 0),null;if(t===null||typeof t!=="object"||Array.isArray(t))return{configCwd:i,executionCwd:i};if(!Object.hasOwn(t,"working_directory"))return{configCwd:i,executionCwd:i};let s=t.working_directory;if(typeof s!=="string"||s.trim()==="")return T(r,t,n),null;let a=we(s,o);if(!a)return T(r,t,n,s),null;return{configCwd:i,executionCwd:a}}function u2(e){return p2(e).flatMap((t)=>{let n=Z([t]);return n?[n]:[]})}function p2(e){if(e.workspace_roots===void 0)return typeof e.cwd==="string"&&e.cwd.trim()!==""?[e.cwd]:[];if(!Array.isArray(e.workspace_roots))return[];return e.workspace_roots.filter((t)=>typeof t==="string"&&t.trim()!=="")}function f2(e){return typeof e==="string"&&e.trim()!==""?e:"."}var m2=new Map([["run_shell_command","auto"]]);function g2(e){return j(e,m2)}async function Js(){await N({agent:"gemini-cli",createDenyOutput:(e)=>({decision:"deny",reason:e,systemMessage:e}),isSupported:(e)=>e.hook_event_name===Gs,getToolName:(e)=>e.tool_name,getToolInput:(e,t)=>({ok:!0,input:e.tool_input,route:g2(t)}),getContext:(e,t,n,r)=>ae(e.cwd,t,n,r),getSessionId:(e)=>e.session_id})}var h2=new Map([["run_terminal_command","auto"]]);function y2(e){return j(e,h2)}async function Ws(){await N({agent:"grok-build",createDenyOutput:(e)=>({decision:"deny",reason:e}),createAllowOutput:()=>({decision:"allow"}),isSupported:()=>!0,getToolName:(e)=>e.toolName,getToolInput:(e,t,n)=>{if(e.toolInputTruncated===!0)return T(n,e.toolInput,t),{ok:!1};return{ok:!0,input:e.toolInput,route:y2(t)}},getContext:v2,getSessionId:(e)=>e.sessionId})}function v2(e,t,n,r){let o=Z(b2(e));if(!o)return T(r,t,n),null;let i=we(L2(e.cwd),[o]);if(!i)return T(r,t,n,typeof e.cwd==="string"?e.cwd:void 0),null;return{configCwd:i,executionCwd:i}}function b2(e){let t=e.workspaceRoot===void 0?e.cwd:e.workspaceRoot;return typeof t==="string"&&t.trim()!==""?[t]:[]}function L2(e){return typeof e==="string"&&e.trim()!==""?e:"."}import{resolve as w2}from"node:path";var k2=new Map([["terminal","posix"]]);async function Ys(){await N({agent:"hermes-agent",createDenyOutput:(e)=>({action:"block",message:e}),isSupported:(e)=>e.hook_event_name===Bs,getToolName:(e)=>e.tool_name,getToolInput:(e,t)=>({ok:!0,input:e.tool_input,route:j(t,k2)}),getContext:x2,getSessionId:(e)=>e.session_id})}function x2(e,t,n,r){let o=ae(e.cwd,t,n,r);if(!o)return null;if(!t||typeof t!=="object"||Array.isArray(t))return o;if(!Object.hasOwn(t,"workdir"))return o;let i=t.workdir;if(typeof i!=="string"||i.trim()==="")return T(r,t,n),null;let s=Z([w2(o.configCwd,i)]);if(!s)return T(r,t,n,i),null;return{...o,executionCwd:s}}var Zs=new Map([["Bash","posix"]]);function C2(e){return j(e,Zs)}async function Xs(){await N({agent:"kimi-code",createDenyOutput:(e)=>({hookSpecificOutput:{hookEventName:Qr,permissionDecision:"deny",permissionDecisionReason:e}}),isSupported:(e)=>e.hook_event_name===Qr,getToolName:(e)=>e.tool_name,getToolInput:(e,t)=>({ok:!0,input:e.tool_input,route:C2(t)}),getContext:(e,t,n,r)=>{let o=ae(e.cwd,t,n,r);if(!o)return null;let i=e.tool_input;if(!Zs.has(n)||!i||!Object.hasOwn(i,"cwd"))return o;let s=i.cwd;if(typeof s!=="string"||s.trim()==="")return T(r,t,n),null;let a=we(s,[o.configCwd]);if(!a)return T(r,t,n,s),null;return{configCwd:o.configCwd,executionCwd:a}},getSessionId:(e)=>e.session_id})}var S2={"antigravity-cli":Fs,"claude-code":qs,codex:Vs,"copilot-cli":zs,cursor:Ks,"gemini-cli":Js,"grok-build":Ws,"hermes-agent":Ys,"kimi-code":Xs},dt=Ns.map((e)=>({...e,run:S2[e.id]}));function Qs(e){let t=E({label:"hook",booleans:Object.fromEntries(dt.map((r)=>[r.id,[...r.flags,...r.legacyFlags]]))},e);if(t.errors.length>0)return;let n=dt.filter((r)=>t.flags[r.id]);return n.length===1?n[0]:void 0}function ea(e){return dt.find((t)=>t.legacyTopLevelFlags.some((n)=>n===e))}var R2=dt.map((e)=>({flags:e.flags.join(", "),description:e.description})),P2=dt.flatMap((e)=>e.flags.map((t)=>`cc-safety-net hook ${t}`)),ta={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...R2,{flags:"-h, --help",description:"Show this help"}],examples:P2};var na={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...X.map((e)=>({flags:e.flag,description:`Install ${D(e.id)} ${e.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...X.map((e)=>`cc-safety-net install ${e.flag}`)]},ra={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...X.map((e)=>({flags:e.flag,description:`Uninstall ${D(e.id)} ${e.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...X.map((e)=>`cc-safety-net uninstall ${e.flag}`)]},oa={name:"update",description:"Update every installed CC Safety Net integration to the latest version",usage:"update",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net update"]};var ia={name:"logs",description:"Browse audit log entries recorded by hooks",usage:"logs [options]",options:[{flags:"--id",argument:"<id>",description:"Show one entry from retained history by its 16-character id (not guaranteed once it is older than the configured retention)"},{flags:"--limit",argument:"<n>",description:"Maximum entries to print",default:"20"},{flags:"--since",argument:"<days>",description:"Only include entries newer than this many days (max: the configured audit retention, 1-365)",default:"30"},{flags:"--agent",argument:"<name>",description:"Filter by agent name"},{flags:"--rule",argument:"<ruleId>",description:"Filter by rule id"},{flags:"--session",argument:"<id>",description:"Filter by session id"},{flags:"--project",argument:"<path>",description:"Filter by project path"},{flags:"--suspect",description:"Only denials that look like false positives"},{flags:"--all",description:"Include allow entries"},{flags:"--prune-legacy",description:"Permanently delete all legacy root-level logs; nested logs are untouched"},{flags:"--dry-run",description:"With --prune-legacy, report what would be deleted and delete nothing"},{flags:"--json",description:"Output entries as JSON"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net logs --id 3fa9c2d1a70e8b42","cc-safety-net logs --agent claude-code","cc-safety-net logs --project . --since 7","cc-safety-net logs --suspect --since 7","cc-safety-net logs --json","cc-safety-net logs --prune-legacy --dry-run","cc-safety-net logs --prune-legacy"]};var xn={name:"policy",description:"Check and apply project or user policy proposals",usage:"policy <subcommand>",subcommands:[{usage:"check <file>",description:"Validate a policy proposal and print its diff"},{usage:"apply <file>",description:"Apply a proposal after confirming in a terminal"}],options:[{flags:"-g, --global",description:"Use the user-scope policy instead of the project one"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net policy check proposal.json","cc-safety-net policy apply proposal.json","cc-safety-net policy apply proposal.json --global"]};var eo=[{flags:"--ref",argument:"<ref>",description:"Use a branch, tag, or commit"},{flags:"--only",argument:"<rulebook...>",description:"Add only these repository rulebooks"},{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"-h, --help",description:"Show this help"}],to=["cc-safety-net rule add project-rules","cc-safety-net rule add acme/safety-rules","cc-safety-net rule add acme/safety-rules --only aws gcloud","cc-safety-net rule add acme/safety-rules --ref v2 --only aws","cc-safety-net rule add --only terraform aws"],ut={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add [source] [--ref <ref>] [--only <rulebook...>]",description:"Add rulebook sources and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Re-fetch and vendor remote rulebooks"},{usage:"sync",description:"Deprecated: migrate lock and cache leftovers"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},...eo.slice(0,2),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net rule init","cc-safety-net rule init --example","cc-safety-net rule wrapper add rtk",...to,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var sa={name:"status",description:"Show what the runtime is enforcing right now",usage:"status",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net status"]};var aa={name:"statusline",description:"Print status line with mode indicators for shell integration",usage:"statusline --claude-code",options:[{flags:"-cc, --claude-code",description:"Print status line for Claude Code"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net statusline -cc","cc-safety-net statusline --claude-code"]};var Cn=[sa,xs,ia,Cs,ut,xn,na,oa,ra,ta,Ss,aa];function D2(e){return e.aliases??[]}function Sn(e){let t=e.toLowerCase();return Cn.find((n)=>n.name.toLowerCase()===t||D2(n).some((r)=>r.toLowerCase()===t))}import{basename as A2}from"node:path";function Rn(e=7,t=be()){let n=Date.now()-e*24*60*60*1000,r=[],o=new Set,i=0,s,a,l,c;if(t)He(t);let d={count:0},m=t?Ce(t,d):[];for(let u of m)for(let p of Fe(u,d)){if(p.decision==="allow")continue;let f=new Date(p.ts).getTime();if(f>=n){if(i++,o.add(p.sessionId??A2(u,".jsonl")),a===void 0||f<=a)s=p.ts,a=f;if(c===void 0||f>c)l=p.ts,c=f;E2(r,p,f)}}let g=r.map((u)=>({timestamp:u.ts,command:u.command,reason:u.reason,relativeTime:gr(new Date(u.ts))}));return{totalBlocked:i,sessionCount:o.size,recentEntries:g,oldestEntry:s,newestEntry:l,unreadable:d.count}}function E2(e,t,n){let r=e.findIndex((o)=>n>new Date(o.ts).getTime());if(r===-1){if(e.length<3)e.push(t);return}if(e.splice(r,0,t),e.length>3)e.pop()}import{dirname as _2}from"node:path";function la(e,t,n){let r;try{if(w(t)===null)return{path:e,exists:!1,valid:!1,ruleCount:0};r=me(t),r.errors.push(...W(e,n))}catch(o){if(!(o instanceof H))throw o;r={errors:[o.message],ruleNames:new Set}}return{path:e,exists:!0,valid:r.errors.length===0,ruleCount:r.ruleNames.size,...r.errors.length>0?{errors:r.errors}:{}}}function T2(e,t){return{source:t,name:e.name,command:e.command,subcommand:e.subcommand,blockArgs:[...e.block_args],reason:e.reason}}function ca(e,t){let n=t?.userConfigPath??ie(),r=t?.projectConfigPath??oe(e),o=_2(n),i=De({cwd:e,userConfigPath:n,projectConfigPath:r,userConfigDir:o}),s=Ae({cwd:e,userConfigPath:n,projectConfigPath:r,userConfigDir:o}),a=new Map(i.rulebooks.flatMap((l)=>l.rules.map((c)=>[c,l.source])));return{userConfig:la(n,s.userConfigTarget,s.userScope),projectConfig:la(r,s.projectConfigTarget,s.projectScope),effectiveRules:i.rules.map((l)=>T2(l,a.get(l.name)??"project")),shadowedRules:[]}}var I2=[{flag:S.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:S.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:S.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:S.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:S.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:S.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:S.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:S.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function da(){return[...I2.map((e)=>({name:e.flag.name,value:Vr(e.flag),isSet:zr(e.flag),legacyName:e.flag.legacyName,legacyValue:e.flag.legacyName?process.env[e.flag.legacyName]:void 0,legacyIsSet:e.flag.legacyName?process.env[e.flag.legacyName]!==void 0:void 0,description:e.description,defaultBehavior:e.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:process.env.CC_SAFETY_NET_HOME,isSet:process.env.CC_SAFETY_NET_HOME!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var ua={error:0,warning:1,info:2},$2=["policy","config","audit"];function O2(e){return e.map((t)=>{if(t==="ownership")return"is not owned by the current user";if(t==="permissions")return"has unsafe permissions";if(t==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var F2=[{derive:(e)=>e.hooks.length>0&&e.hooks.every((t)=>!t.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(e)=>e.hooks.filter((t)=>t.inspectionStatus==="failed").map((t)=>{let n=D(t.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${n} inspection failed`,detail:`Doctor could not verify the ${n} integration configuration.`,fixHint:`Correct the reported ${n} configuration error, then run \`cc-safety-net doctor\` again.`,integration:t.platform}})},{derive:(e)=>e.userConfig.exists&&!e.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:e.userConfig.path}]:[]},{derive:(e)=>e.projectConfig.exists&&!e.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:e.projectConfig.path}]:[]},{derive:(e)=>e.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${e.configState.reason}`,fixHint:"Fix the file named in the reason, or run `cc-safety-net rule update` to vendor a remote source, then rerun doctor."}]:[]},{derive:(e)=>e.v2Leftovers&&e.v2Leftovers.length>0?[{checkId:"config.v2-leftovers",severity:"info",title:"Rulebook lock and cache leftovers detected",detail:`Files an earlier version left behind are no longer read: ${e.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(e)=>{let t=e.environment.find((n)=>n.name==="CC_SAFETY_NET_AUDIT_SCOPE");return qr(t?.value)==="invalid"?[{checkId:"environment.audit-scope-invalid",severity:"warning",title:"Audit scope value is invalid",detail:"CC_SAFETY_NET_AUDIT_SCOPE is not `all` or `blocked`, so allowed command decisions are not recorded.",fixHint:"Set CC_SAFETY_NET_AUDIT_SCOPE to `all` or `blocked`, then restart the integration."}]:[]}},...$2.map((e)=>({derive:(t)=>t.posture.directories.filter((n)=>n.kind===e&&n.status==="unsafe").map((n)=>({checkId:`posture.${e}-directory-unsafe`,severity:"error",title:`${e[0]?.toUpperCase()}${e.slice(1)} directory is unsafe`,detail:`The ${e} directory ${O2(n.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...n.path?{path:n.path}:{}}))})),{derive:(e)=>{let t=[...e.effectiveSafety.weakenedRuleOverrides].sort();return t.length>0?[{checkId:"posture.rule-overrides-weaken-preset",severity:"warning",title:"Rule overrides weaken the selected preset",detail:`Explicit overrides disable rules the resolved preset would enable: ${t.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${t.join(", ")}.`}]:[]}}];function pa(e){return F2.flatMap((t,n)=>t.derive(e).map((r,o)=>({finding:r,catalogOrder:n,occurrence:o}))).sort((t,n)=>ua[t.finding.severity]-ua[n.finding.severity]||t.catalogOrder-n.catalogOrder||t.occurrence-n.occurrence).map((t)=>t.finding)}function le(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var j2=(e)=>le()?`\x1B[32m${e}\x1B[0m`:e,N2=(e)=>le()?`\x1B[33m${e}\x1B[0m`:e,H2=(e)=>le()?`\x1B[34m${e}\x1B[0m`:e,M2=(e)=>le()?`\x1B[35m${e}\x1B[0m`:e,U2=(e)=>le()?`\x1B[36m${e}\x1B[0m`:e,G2=(e)=>le()?`\x1B[31m${e}\x1B[0m`:e,B2=(e)=>le()?`\x1B[2m${e}\x1B[0m`:e,q2=(e)=>le()?`\x1B[1m${e}\x1B[0m`:e,y={green:j2,yellow:N2,blue:H2,magenta:M2,cyan:U2,red:G2,dim:B2,bold:q2},V2="\x1B[0m",z2=[39,82,198,226,208,51,196,46,201,214,93,154,220,27,49,190,200,33,129,227,45,160,63,118,123,202];function K2(e){let t=e;return()=>(t=(t*1664525+1013904223)%4294967296,t/4294967296)}function J2(e){let t=[...z2],n=K2(e);for(let r=t.length-1;r>0;r--){let o=Math.floor(n()*(r+1)),i=t[r];t[r]=t[o],t[o]=i}return t}function W2(e,t=0){if(!le())return"";let n=J2(t);return`\x1B[38;5;${n[e%n.length]}m`}function fa(e,t,n=0){if(!le())return`"${e}"`;return`${W2(t,n)}"${e}"${V2}`}function Pn(e){return e==="default"?"built-in default":`${e} policy`}var Y2=new RegExp("\x1B\\[[0-9;]*m","g"),no=(e)=>e.replace(Y2,"").length;function Ve(e){let t=(e.headers??e.rows[0]??[]).map((s,a)=>{let l=Math.max(...e.rows.map((c)=>no(c[a]??"")));return Math.max(no(s),l)}),n=(s,a)=>s+" ".repeat(Math.max(0,a-no(s))),r=(s,a)=>a[0]+t.map((l)=>s.repeat(l+2)).join(a[1])+a[2],o=(s)=>`│ ${s.map((a,l)=>n(a,t[l]??0)).join(" │ ")} │`,i=e.headers?[` ${o(e.headers)}`,` ${r("─",["├","┼","┤"])}`]:[];return[` ${r("─",["┌","┬","┐"])}`,...i,...e.rows.map((s)=>` ${o(s)}`),` ${r("─",["└","┴","┘"])}`].join(`
7
- `)}function ma(e){let t=[];t.push("Hook Integration"),t.push(Z2(e));let n=[],r=[];for(let o of e){let i=D(o.platform);if(o.errors&&o.errors.length>0)for(let s of o.errors)if(o.configured)n.push({platform:i,message:s});else r.push({platform:i,message:s})}for(let o of n)t.push(` Warning (${o.platform}): ${o.message}`);for(let o of r)t.push(y.red(` Error (${o.platform}): ${o.message}`));return t.join(`
8
- `)}function Z2(e){let t=["Platform","Discovery","Configuration","Inspection"],n=e.map((r)=>{let o=D(r.platform);if(r.inspectionStatus==="not-inspected"){let l=y.dim("Not inspected");return[o,l,l,l]}let i=r.detected?y.green("Detected"):r.inspectionStatus==="failed"?y.red("Unknown"):y.dim("Not detected"),s=r.configured?y.green("Configured"):r.detected?y.yellow("Not configured"):r.inspectionStatus==="failed"?y.red("Unknown"):y.dim("Not applicable"),a=r.inspectionStatus==="verified"?y.green("Verified"):r.inspectionStatus==="failed"?y.red("Failed"):y.dim("Not applicable");return[o,i,s,a]});return Ve({headers:t,rows:n})}function ga(e){let n=["Guard Engine Verification",` Synthetic self-test: ${e.failed>0?y.red(`${e.passed}/${e.total} FAIL`):y.green(`${e.passed}/${e.total} passed`)}`],r=e.results.filter((o)=>!o.passed);if(r.length>0){n.push(""),n.push(y.red(" Failures:"));for(let o of r)n.push(y.red(` • ${o.description}`)),n.push(y.red(` expected ${o.expected}, got ${o.actual}`))}return n.join(`
9
- `)}function X2(e){if(e.length===0)return" (no custom rules)";let t=["Source","Name","Command","Block Args"],n=e.map((r)=>[r.source,r.name,r.subcommand?`${r.command} ${r.subcommand}`:r.command,r.blockArgs.join(", ")]);return Ve({headers:t,rows:n})}function ha(e){let t=[];if(t.push("Configuration"),t.push(Q2(e.userConfig,e.projectConfig)),t.push(""),e.effectiveRules.length>0)t.push(` Effective rules (${e.effectiveRules.length} total):`),t.push(X2(e.effectiveRules));else t.push(" Effective rules: (none - using built-in rules only)");for(let n of e.shadowedRules)t.push(""),t.push(` Note: Project rule "${n.name}" shadows user rule with same name`);return t.join(`
10
- `)}function Q2(e,t){let n=["Scope","Status"],r=(i)=>{if(!i.exists)return y.dim("N/A");if(!i.valid)return y.red(`Invalid (${i.errors?.[0]??"unknown error"})`);return y.green("Configured")},o=[["User",r(e)],["Project",r(t)]];return Ve({headers:n,rows:o})}function ya(e){let t=[];return t.push("Environment"),t.push(ef(e)),t.join(`
11
- `)}function va(e){let t=e.effectiveSafety.policyScopes,n=["Effective Safety",` Selected preset: ${e.effectiveSafety.selectedPreset}${t?` (${Pn(t.levelScope)})`:""}`,` Effective: ${e.effectiveSafety.level}`],r=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[o,i]of r){let s=e.effectiveSafety.capabilities[o],a=s.enabled?y.green("ON"):y.dim("OFF"),l=s.sources.length>0?` (${s.sources.join(", ")})`:"";n.push(` ${i}: ${a} via ${s.source}${l}`)}if(t&&t.weakenings.length>0){n.push(" Project policy deltas:");for(let o of t.weakenings)n.push(` ${o}`)}n.push(` Stored rule customizations: ${e.effectiveSafety.ruleCounts.stored}`),n.push(` Effective rule customizations: ${e.effectiveSafety.ruleCounts.effective}`);for(let[o,i]of Object.entries(e.effectiveSafety.ruleOverrides))n.push(` ${o}: ${i}`);return n.join(`
12
- `)}function ba(e){let t=["Findings"];if(e.length===0)return t.push(" No findings from inspected doctor facts."),t.join(`
13
- `);for(let n of e){let r=`[${n.severity.toUpperCase()}] ${n.checkId}: ${F(n.title)}`,o=n.severity==="error"?y.red:n.severity==="warning"?y.yellow:y.blue;if(t.push(` ${o(r)}`),t.push(` ${F(n.detail)}`),n.path)t.push(` Path: ${F(n.path)}`);if(n.fixHint)t.push(` Fix: ${F(n.fixHint)}`)}return t.join(`
14
- `)}function ef(e){let t=["Variable","Status","Legacy"],n=e.map((r)=>{let o=r.isSet?y.green("✓"):y.dim("✗"),i=r.legacyName&&r.legacyIsSet?`${r.legacyName} ${y.green("✓")}`:r.legacyName??"";return[r.name,o,i]});return Ve({headers:t,rows:n})}function La(e){let t=[];if(e.totalBlocked===0)t.push("Recent Activity"),t.push(" No blocked commands in the last 7 days"),t.push(" Tip: This is normal for new installations");else t.push(`Recent Activity · last 7 days (${e.totalBlocked} blocked / ${e.sessionCount} sessions)`),t.push(tf(e.recentEntries));if(e.unreadable>0)t.push(` Warning: ${e.unreadable} audit log ${e.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return t.join(`
15
- `)}function tf(e){let t=["Time","Command"],n=e.map((r)=>{let o=F(r.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),i=o.length>40?`${o.slice(0,37)}...`:o;return[r.relativeTime,i]});return Ve({headers:t,rows:n})}function wa(e){let t=[];if(t.push("Update Check"),e.latestVersion===null&&!e.error)return t.push(Dn([["Status",y.dim("Skipped")],["Installed",e.currentVersion]])),t.join(`
16
- `);if(e.error)return t.push(Dn([["Status",`${y.yellow("⚠")} Error`],["Installed",e.currentVersion],["Error",y.dim(e.error)]])),t.join(`
17
- `);if(e.updateAvailable)return t.push(Dn([["Status",`${y.yellow("⚠")} Update Available`],["Current",e.currentVersion],["Latest",y.green(e.latestVersion??"")]])),t.push(""),t.push(" Run: bunx cc-safety-net@latest doctor"),t.push(" Or: npx cc-safety-net@latest doctor"),t.join(`
18
- `);return t.push(Dn([["Status",`${y.green("✓")} Up to date`],["Version",e.currentVersion]])),t.join(`
19
- `)}function Dn(e){return Ve({rows:e})}function ka(e){let t=[];return t.push("System Info"),t.push(nf(e)),t.join(`
20
- `)}function nf(e){let t=["Component","Version"],n=(i)=>{if(i===null)return y.dim("not found");return i},o=[{label:"cc-safety-net",value:e.version},...wn.map((i)=>({label:D(i),value:e.versions[i]??null})),{label:"Node.js",value:e.nodeVersion},{label:"npm",value:e.npmVersion},{label:"Bun",value:e.bunVersion},{label:"Platform",value:e.platform}].map((i)=>[i.label,n(i.value)]);return Ve({headers:t,rows:o})}function xa(e){if(e.findings.length===0)return y.green(`
21
- No findings from inspected doctor facts.`);let t={error:e.findings.filter((i)=>i.severity==="error").length,warning:e.findings.filter((i)=>i.severity==="warning").length,info:e.findings.filter((i)=>i.severity==="info").length},n=["error","warning","info"].filter((i)=>t[i]>0).map((i)=>`${t[i]} ${i}`),r=e.findings.length===1?"finding":"findings",o=`
22
- ${e.findings.length} ${r}: ${n.join(", ")}.`;if(t.error>0)return y.red(o);if(t.warning>0)return y.yellow(o);return y.blue(o)}import{lstatSync as rf}from"node:fs";import{dirname as ro}from"node:path";function oo(e,t){try{let n=rf(t);if(n.isSymbolicLink())return{kind:e,path:t,status:"unsafe",issues:["symlink"]};if(!n.isDirectory())return{kind:e,path:t,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:e,path:t,status:"unknown",issues:[]};let r=[...n.uid!==process.getuid()?["ownership"]:[],...(n.mode&18)!==0?["permissions"]:[]];return{kind:e,path:t,status:r.length>0?"unsafe":"safe",issues:r}}catch(n){if(typeof n==="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return{kind:e,path:t,status:"not-applicable",issues:[]};return{kind:e,path:t,status:"unknown",issues:[]}}}function Ca(e){let t=be();return{directories:[oo("policy",ro(ro(e))),oo("config",ro(e)),...t?[oo("audit",t)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as of}from"node:child_process";import{existsSync as Sa}from"node:fs";import{delimiter as sf,extname as af,join as lf}from"node:path";import{stripVTControlCharacters as Ra}from"node:util";var Da="2.3.2",cf=5000,df="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function I(){return Da}function io(e,t){let n=e[t];if(n)return n;let r=Object.keys(e).find((o)=>o.toLowerCase()===t.toLowerCase()&&!!e[o]);return r?e[r]:n}function uf(e){return(io(e,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((t)=>t.length>0)}function pf(e,t){let n=af(e)?[e]:[...uf(t).map((r)=>`${e}${r}`),e];if(e.includes("/")||e.includes("\\"))return n.find((r)=>Sa(r))??e;return(io(t,"PATH")??"").split(sf).flatMap((r)=>n.map((o)=>lf(r,o))).find((r)=>Sa(r))??e}function Pa(e){if(!/[\s"&|<>^]/.test(e))return e;return`"${e.replace(/"/g,'""')}"`}function ze(e,t){let[n,...r]=e,o=t[df]==="win32"?"win32":process.platform;if(!n||o!=="win32")return{cmd:n??"",args:r};let i=pf(n,t);if(!/\.(?:bat|cmd)$/i.test(i))return{cmd:i,args:r};return{cmd:io(t,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",Pa(i),...r.map(Pa)].join(" ")]}}var pt=async(e,t=cf)=>{let n=await ff(e,{timeoutMs:t});if(n.code!==0)return null;return Ra(n.stdout).trim()||Ra(n.stderr).trim()||null};function ff(e,t){let[n,...r]=e;if(!n)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((o)=>{try{let i=ze([n,...r],process.env),s=of(i.cmd,i.args,{stdio:["ignore","pipe","pipe"]}),a=!1,l="",c="";s.stdout.on("data",(g)=>{l+=g.toString()}),s.stderr.on("data",(g)=>{c+=g.toString()});let d=(g)=>{if(a)return;a=!0,clearTimeout(m),o(g)},m=setTimeout(()=>{s.kill(),d({code:null,stdout:l,stderr:c})},t.timeoutMs);s.on("close",(g)=>{d({code:g,stdout:l,stderr:c})}),s.on("error",()=>{d({code:null,stdout:l,stderr:c})})}catch{o({code:null,stdout:"",stderr:""})}})}function An(e){if(!e)return null;let t=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(e);if(t)return t[1]??null;let n=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(e);if(n)return n[1]??null;return e.split(`
23
- `)[0]?.trim()||null}async function qt(e=pt){let[t,n,r,o,i,s]=await Promise.all([Promise.all(X.map(async(a)=>[a.id,An(await e([...a.probeCommand]))])),e(["codex","plugin","list"],30000),e(["amp","plugins","list"],30000),e(["node","--version"]),e(["npm","--version"]),e(["bun","--version"])]);return{version:Da,versions:Object.fromEntries(t),codexPluginListOutput:n,ampPluginListOutput:r,nodeVersion:An(o),npmVersion:An(i),bunVersion:An(s),platform:`${process.platform} ${process.arch}`}}function so(e,t){if(t==="dev")return!1;let n=e.split(".").map(Number),r=t.split(".").map(Number),[o=0,i=0,s=0]=n,[a=0,l=0,c=0]=r;if(o!==a)return o>a;if(i!==l)return i>l;return s>c}async function Te(){let e=I(),t=new AbortController,n=setTimeout(()=>t.abort(),3000);try{let r=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:t.signal});if(!r.ok)return{currentVersion:e,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${r.status}`};let o=await r.json(),i=so(o.version,e);return{currentVersion:e,latestVersion:o.version,updateAvailable:i}}catch(r){return{currentVersion:e,latestVersion:null,updateAvailable:!1,error:r instanceof Error?r.message:"Network error"}}finally{clearTimeout(n)}}import*as Fa from"node:readline";var Ta=(e)=>`\x1B[${e}B`,mf=(e)=>`\x1B[${e}A`;var Aa=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function gf(e){return new Promise((t)=>setTimeout(t,e))}function hf(e,t,n){if(!n)return t(e);if(n.aborted)return Promise.resolve();return new Promise((r,o)=>{let i=()=>n.removeEventListener("abort",s),s=()=>{i(),r()};n.addEventListener("abort",s,{once:!0}),t(e).then(()=>{i(),r()},(a)=>{i(),o(a)})})}function Vt(e,t){return e&&e>0?e:t}function En(e){return Math.max(0,Math.min(1,e))}function ft(e){return Math.max(0,Math.min(255,Math.round(e)))}function ao(e){return e<=0.0031308?12.92*e:1.055*e**0.4166666666666667-0.055}function yf(e,t,n){let r=n*Math.PI/180,o=t*Math.cos(r),i=t*Math.sin(r),s=(e+0.3963377774*o+0.2158037573*i)**3,a=(e-0.1055613458*o-0.0638541728*i)**3,l=(e-0.0894841775*o-1.291485548*i)**3;return{blue:ft(ao(En(-0.0041960863*s-0.7034186147*a+1.707614701*l))*255),green:ft(ao(En(-1.2684380046*s+2.6097574011*a-0.3413193965*l))*255),red:ft(ao(En(4.0767416621*s-3.3077115913*a+0.2309699292*l))*255)}}function lo(e,t){let n=(t*e*180/Math.PI%360+360)%360;return yf(0.72,0.15,n)}function Ia(e,t=0.1){let n=lo(t,e);return`\x1B[38;2;${n.red};${n.green};${n.blue}m`}function vf(e,t){return{blue:ft(e.blue+(255-e.blue)*t),green:ft(e.green+(255-e.green)*t),red:ft(e.red+(255-e.red)*t)}}function $a(e,t,n){let r=Math.imul(e+2654435769,2246822507)^Math.imul(t+3266489909,668265263)^Math.imul(n+374761393,2654435761),o=r^r>>>15,i=Math.imul(o,739982445),s=i^i>>>12,a=Math.imul(s,695872825);return((a^a>>>15)>>>0)/4294967296}function bf(e,t,n){let r=Math.floor($a(e,t,n)*Aa.length);return Aa[r]??"░"}function Ea(e){let t=En(e);return t*t*t*(t*(t*6-15)+10)}function Lf(e){if(e.length===0)return"";let t=[],n=!1,r="";for(let o of e){let i=`${o.red};${o.green};${o.blue}`;if(o.bold!==n)t.push(o.bold?"\x1B[1m":"\x1B[22m"),n=o.bold;if(i!==r)t.push(`\x1B[38;2;${i}m`),r=i;t.push(o.character)}return`${t.join("")}\x1B[22m\x1B[39m`}function wf(e,t,n,r,o){return e.map((i,s)=>({...lo(n,r+t+s/o),bold:!1,character:i}))}function kf(e,t,n,r,o,i,s,a){let l=Math.max(1,r*0.75),c=Math.min(1,n/l),d=o*Ea(c),m=Math.max(0,(n-l)/Math.max(1,r-l)),g=(1-Ea(n/r))*a*2,u=0.35*Math.max(0,1-m*2),p=c>=1,f=Math.min(e.length,Math.ceil(d+2+1));return e.slice(0,f).map((b,L)=>{let h=lo(i,s+t+L/a+g),R=L+$a(t,L,7919)*2-1;if(R>d+2)return{...h,bold:!1,character:" "};let v=d-R,P=0.8*Math.exp(-(v*v)/12.5),ne=Math.min(0.9,P+u),un=!p&&R>d-4;return{...vf(h,ne),bold:ne>0.3,character:un?bf(t,L,n):b}})}function _a(e){return`\x1B[?2026h${e.map((t,n)=>`\x1B8${n>0?Ta(n):""}${Lf(t)}`).join("")}\x1B[?2026l`}async function co(e,t={}){if(!e)return;let n=t.output??process.stdout,r=t.sleep??gf,o=Vt(t.frequency,0.1),i=t.seed??0,s=Vt(t.speed,40),a=Vt(t.spread,3),l=Vt(t.frameRate,60),c=Math.max(1,Math.floor(Vt(t.duration,12))),d=e.split(`
24
- `).map((f)=>Array.from(f)),m=Math.max(...d.map((f)=>f.length)),g=1000*c*d.filter((f)=>f.length>0).length/s,u=m>0?Math.max(1,Math.ceil(g/(1000/l))):0,p=u>0?g/u:0;n.write(`\x1B[?25l${d.length>1?`${`
25
- `.repeat(d.length-1)}${mf(d.length-1)}`:""}\x1B7`);try{for(let f=1;f<=u;f+=1){if(t.signal?.aborted)break;n.write(_a(d.map((b,L)=>kf(b,L,f,u,m,o,i,a)))),await hf(p,r,t.signal)}}finally{if(n.write(_a(d.map((f,b)=>wf(f,b,o,i,a)))),n.write("\x1B8"),d.length>1)n.write(Ta(d.length-1));n.write(`
26
- \x1B[0m\x1B[?25h`)}}var Oa=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
27
- `);function xf(e){return Boolean(e.isTTY)}async function zt(e={}){let t=e.output??process.stdout;if(!xf(t))return;let n=e.input??process.stdin,r={duration:e.duration,frequency:e.frequency,output:t,seed:e.seed??Math.random()*8192,sleep:e.sleep,speed:e.speed,spread:e.spread};if(!n.isTTY||typeof n.setRawMode!=="function"){await co(Oa,r);return}let o=new AbortController,i=n.readableFlowing===!0,s=n.isRaw===!0,a=!1,l=(c,d)=>{if(d.ctrl&&d.name==="c")a=!0;if(a||d.name==="return"||d.name==="enter")o.abort()};Fa.emitKeypressEvents(n),n.on("keypress",l),n.setRawMode(!0),n.resume();try{await co(Oa,{...r,signal:o.signal})}finally{if(n.off("keypress",l),n.setRawMode(s),!i)n.pause()}if(!a)return;if(e.onInterrupt){e.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as Cf}from"node:crypto";import{existsSync as Na}from"node:fs";import{dirname as _n,join as Ha}from"node:path";var Sf="`cc-safety-net rule sync` is deprecated: rulebooks are live files that need no synchronization. This run only migrates the lock and cache an earlier version left behind.",Rf="cache",Pf="rulebooks";function Ma(e={}){let t=U(e),n=x(t.filesystemScope,Ga(t.configDir)),r=w(t.lockTarget);if(console.log(Sf),r===null&&!Na(n.path))return console.log(`No v2 lock or cache leftovers found in ${_n(t.configDir)}; nothing to migrate.`),0;let o=Tf(r),i=q(t.configTarget);if(!i.config&&(w(t.configTarget)!==null||o.size>0))return console.error(`Cannot migrate: the rules config in ${_n(t.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let s=i.config?.rules??[];for(let a of s.flatMap((l)=>Df(l,o,t,n,e.global===!0)))console.log(a);return he(t.lockTarget),ja(n),console.log(`Removed the v2 lock and cache under ${_n(t.configDir)}.`),0}function Ua(e){return[...new Set([{cwd:e},{cwd:e,global:!0}].flatMap((t)=>{let n=U(t);return[n.lockPath,Ga(n.configDir)]}))].filter((t)=>Na(t))}function Df(e,t,n,r,o){if(!re(e))return[];let i=je(e).name,s=x(n.filesystemScope,Re(n.configDir,i)),a=w(s);if(a!==null&&Af(a,i))return[];let l=t.get(e),c=l?Ef(l,i,r.path,n.filesystemScope):null;if(c===null)return[`Could not migrate ${e} from the v2 cache. Run \`cc-safety-net rule update ${e}${o?" --global":""}\` to vendor it.`];if(B(s,c),a!==null)return[`Restored ${e} from the v2 cache over an invalid file.`];return[`Vendored ${e} from the v2 cache.`]}function Af(e,t){let n=_t(e);return!("problem"in n)&&n.rulebook.name===t}function Ef(e,t,n,r){let o=Ha(n,Pf,`${_f(e)}--${e.digest.replace("sha256:","").slice(0,12)}`,yn),i=w(x(r,o));if(i===null||Of(i)!==e.digest)return null;let s=_t(i);if("problem"in s||s.rulebook.name!==t)return null;return i}function Ga(e){return Ha(_n(e),Rf)}function _f(e){return([e.owner,e.repo,e.display_ref,e.name].every((r)=>typeof r==="string"&&r!=="")?`${e.owner}/${e.repo}#${e.display_ref}/${e.name}`:e.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function Tf(e){let t=e===null?null:$f(e),n=Ba(t)&&Array.isArray(t.rulebooks)?t.rulebooks:[];return new Map(n.filter(If).map((r)=>[r.spec,r]))}function If(e){return Ba(e)&&typeof e.spec==="string"&&typeof e.digest==="string"}function Ba(e){return!!e&&typeof e==="object"}function $f(e){try{return JSON.parse(e)}catch{return null}}function Of(e){return`sha256:${Cf("sha256").update(e).digest("hex")}`}var qa="\r\x1B[2K",Ff="\x1B[?25l",jf="\x1B[39m",Nf="\x1B[?25h",Hf=100,Mf=0.55,Uf=80,Va=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function Gf(e){return new Promise((t)=>setTimeout(t,e))}async function Tn(e,t={}){let n=t.output??process.stdout;if(!n.isTTY)return e;let r=t.sleep??Gf,o=!1,i=e.then((a)=>(o=!0,a),(a)=>{throw o=!0,a});if(await Promise.race([i.then(()=>!0),r(Hf).then(()=>!1)]))return i;n.write(Ff);try{for(let a=0;!o;a+=1)n.write(`${qa}${Ia(a*Mf)}${Va[a%Va.length]}${jf} ${t.loadingMessage??"Loading…"}`),await Promise.race([i,r(Uf)]);return await i}finally{n.write(`${qa}${Nf}`)}}async function Kt(e,t,n,r={}){let o=t();if(e)await n();if(e&&o.ready)await Tn(o.ready,r);return o.finish()}import{homedir as yg}from"node:os";import{stripVTControlCharacters as Bf}from"node:util";var In="amp plugins list",qf=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function za(e){if(!e.ampPluginListOutput)return{platform:"amp",status:"n/a"};let t=Bf(e.ampPluginListOutput).split(`
28
- `).map((n)=>qf.exec(n)?.[1]).find((n)=>n!==void 0);if(!t)return{platform:"amp",status:"n/a"};if(t!=="active")return{platform:"amp",status:"disabled",method:In,configPath:In,errors:[`Amp personal plugin cc-safety-net is ${t}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:In,configPath:In}}import{existsSync as Vf,readFileSync as zf}from"node:fs";var Kf=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Jf(e){if(!e||typeof e!=="object"||Array.isArray(e))return[];return Object.values(e).flatMap((t)=>{if(!t||typeof t!=="object"||Array.isArray(t))return[];let n=t,r=n.PreToolUse;if(!Array.isArray(r))return[];return r.flatMap((o)=>{if(!o||typeof o!=="object"||Array.isArray(o))return[];let i=o.hooks;if(!Array.isArray(i))return[];return i.flatMap((s)=>{if(!s||typeof s!=="object"||Array.isArray(s))return[];let a=s.command;if(typeof a!=="string"||!Kf.test(a))return[];return[{command:a,enabled:n.enabled!==!1}]})})})}function Ka(e){let t=Gt(e.homeDir);if(!Vf(t))return{platform:"antigravity-cli",status:"n/a",configPath:t};let n;try{n=Jf(JSON.parse(zf(t,"utf-8")))}catch(r){return{platform:"antigravity-cli",status:"n/a",configPath:t,errors:[`Failed to parse Antigravity hooks config ${t}: ${r instanceof Error?r.message:String(r)}`]}}if(n.some((r)=>r.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:t};if(n.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:t};return{platform:"antigravity-cli",status:"n/a",configPath:t}}import{join as Ja}from"node:path";import{existsSync as Wf,lstatSync as Yf,readFileSync as Zf}from"node:fs";function ce(e,t=(n)=>n){if(!Wf(e))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(t(Zf(e,"utf-8")))}}catch{return{kind:"unreadable"}}}function _(e){try{return Yf(e)}catch{return}}function $n(e,t){let n=_(t);if(!n)return{platform:e,status:"n/a",configPath:t};if(!n.isSymbolicLink()&&n.isDirectory())return;return{platform:e,status:"n/a",configPath:t,errors:[`${t} is a symlink or not a directory; move or remove it before installing`]}}function k(e,t){return typeof e==="object"&&e!==null?e[t]:void 0}var uo="cc-safety-net@cc-marketplace";function Wa(e){return Ja(e,".claude","plugins","installed_plugins.json")}function Ya(e,t){let n=k(k(e,"plugins"),t);return Array.isArray(n)&&n.length>0}function On(e,t){let n=ce(Wa(e));return n.kind==="ok"&&Ya(n.value,t)}function po(e){let t=Wa(e),n=ce(t);if(n.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(n.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!Ya(n.value,uo))return{platform:"claude-code",status:"n/a"};let r=Ja(e,".claude","settings.json"),o=ce(r);if(o.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(o.kind==="ok"&&k(k(o.value,"enabledPlugins"),uo)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:r,errors:[`${uo} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:t}}function Za(e){return po(e.homeDir)}function Xa(e){if(!e.codexPluginListOutput)return{platform:"codex",status:"n/a"};let t=e.codexPluginListOutput.split(`
29
- `).find((n)=>n.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!t)return{platform:"codex",status:"n/a"};if(!t.includes("installed,"))return{platform:"codex",status:"n/a"};if(!t.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list"}}import{existsSync as Hn,readdirSync as Xf,readFileSync as Qf}from"node:fs";import{join as M}from"node:path";var de="cc-safety-net@cc-marketplace",Fn=["cc-marketplace","cc-safety-net"],Qa=["_direct","copilot-safety-net"],el=["cc-marketplace","safety-net"],tl="safety-net@cc-marketplace";function jn(e,t){let n=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${n}([^a-z0-9-]|$)`,"m").test(e??"")}function nl(e){return jn(e,"cc-safety-net@cc-marketplace")}function rl(e){return jn(e,"cc-marketplace")}function ol(e){return jn(e,"copilot-safety-net")}function il(e){return jn(e,"safety-net@cc-marketplace")}function K(e){let t="",n=0,r=!1,o=!1,i=-1;while(n<e.length){let s=e[n],a=e[n+1];if(o){t+=s,o=!1,n++;continue}if(s==='"'&&!r){r=!0,i=-1,t+=s,n++;continue}if(s==='"'&&r){r=!1,t+=s,n++;continue}if(s==="\\"&&r){o=!0,t+=s,n++;continue}if(r){t+=s,n++;continue}if(s==="/"&&a==="/"){while(n<e.length&&e[n]!==`
30
- `)n++;continue}if(s==="/"&&a==="*"){n+=2;while(n<e.length-1){if(e[n]==="*"&&e[n+1]==="/"){n+=2;break}n++}continue}if(s===","){i=t.length,t+=s,n++;continue}if(s==="}"||s==="]"){if(i!==-1){let l=t.slice(i+1);if(/^\s*$/.test(l))t=t.slice(0,i)+l}i=-1,t+=s,n++;continue}if(!/\s/.test(s))i=-1;t+=s,n++}return t}function fo(e){if(!e?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(e)}function al(e,t){if(!e)return null;let n=e.match(/(\d+)\.(\d+)\.(\d+)/);if(!n)return null;let r=[Number(n[1]),Number(n[2]),Number(n[3])];for(let o=0;o<t.length;o++){let i=r[o]??0,s=t[o]??0;if(i!==s)return i>s}return!0}function em(e){return al(e,[0,0,422])}function tm(e){return al(e,[1,0,8])}function Jt(e){return process.env.COPILOT_HOME||M(e,".copilot")}function mo(e){return(e.hooks?.preToolUse??[]).some((n)=>{if(n.type!=="command")return!1;return fo(n.command)||fo(n.bash)||fo(n.powershell)})}function Nn(e){return e===void 0||typeof e==="string"}function nm(e){if(!e||typeof e!=="object"||Array.isArray(e))return!1;let t=e;if(t.disableAllHooks!==void 0&&typeof t.disableAllHooks!=="boolean")return!1;if(t.hooks===void 0)return!0;if(!t.hooks||typeof t.hooks!=="object"||Array.isArray(t.hooks))return!1;let n=t.hooks.preToolUse;if(n===void 0)return!0;return Array.isArray(n)&&n.every((r)=>r!==null&&typeof r==="object"&&!Array.isArray(r)&&Nn(r.type)&&Nn(r.command)&&Nn(r.bash)&&Nn(r.powershell))}function go(e,t){try{let n=JSON.parse(K(Qf(e,"utf-8")));if(!nm(n)){t?.push(`Invalid hook config ${e}: hooks.preToolUse must be an array of hook objects`);return}return n}catch(n){t?.push(`Failed to parse ${e}: ${n instanceof Error?n.message:String(n)}`);return}}function ll(e,t){try{return Xf(e).filter((n)=>n.endsWith(".json")).sort((n,r)=>n.localeCompare(r))}catch(n){return t?.push(`Failed to read ${e}: ${n instanceof Error?n.message:String(n)}`),[]}}function rm(e,t){if(!Hn(e))return[];let n=[];for(let r of ll(e,t)){let o=M(e,r),i=go(o,t);if(i&&mo(i))n.push(o)}return n}function mt(e,t){if(!Hn(e))return;let n=go(e,t);if(!n)return;return{path:e,config:n}}function sl(e,t,n,r){if(t){e.push(`GitHub Copilot CLI ${t} does not support ${n}; requires ${r}+`);return}e.push(`GitHub Copilot CLI version unavailable; skipping ${n} because it requires ${r}+`)}function om(e){for(let t of e){if(t?.config.disableAllHooks===!0)return t.path;if(t?.config.disableAllHooks===!1)return}return}function im(e,t,n,r){let o=Jt(e),i=M(t,".github","hooks"),s=M(o,"hooks"),a=M(t,".github","copilot"),l=M(t,".claude"),c=tm(n),d=c===!0?r:void 0,m=[mt(M(a,"settings.local.json"),d),mt(M(a,"settings.json"),d),mt(M(l,"settings.local.json"),d),mt(M(l,"settings.json"),d)],g=[mt(M(o,"settings.json"),d),mt(M(o,"config.json"),d)];if(c!==!1){let v=om([...m,...g]);if(v){if(c===null)r.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${v} as active`);return{activeConfigPaths:[],disabledBy:v}}}let u=rm(i,r),p=em(n),f=p===!0?r:void 0,b=Hn(s)?ll(s,f):[],L=[];for(let v of b){let P=M(s,v),ne=go(P,f);if(ne&&mo(ne))L.push(P)}if(p!==!0&&L.length>0)sl(r,n,`user hook files in ${s}`,"0.0.422"),L.length=0;let h=[];for(let v of[...m,...g]){if(!v)continue;if(!mo(v.config))continue;if(c===!0){h.push(v);continue}sl(r,n,"inline hook definitions in Copilot config files","1.0.8");break}let R=(v)=>v.filter((P)=>!!P&&h.includes(P)).map((P)=>P.path);return{activeConfigPaths:[...R(m),...u,...R(g),...L]}}function cl(e){let t=[],n=im(e.homeDir,e.cwd,e.copilotCliVersion,t);if(n.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:n.disabledBy,configPaths:[n.disabledBy],errors:t.length>0?t:void 0};let r=Jt(e.homeDir),o=M(r,"installed-plugins",...Fn),i=Hn(o),s=M(r,"settings.json"),a=ce(s,K);if(i&&a.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(i&&a.kind==="ok"&&k(k(a.value,"enabledPlugins"),de)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:s,errors:[`${de} is installed but not enabled in Copilot CLI`]};if(i||n.activeConfigPaths.length>0){let l=i,c=n.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:l?"plugin config":"hook config",configPath:c??(l?o:void 0),configPaths:n.activeConfigPaths.length>0?n.activeConfigPaths:void 0,errors:t.length>0?t:void 0}}return{platform:"copilot-cli",status:"n/a",errors:t.length>0?t:void 0}}import{existsSync as gm,readFileSync as hm}from"node:fs";import{existsSync as dl,mkdirSync as lm,readFileSync as cm}from"node:fs";import{dirname as dm,join as um}from"node:path";import{renameSync as sm,writeFileSync as am}from"node:fs";function O(e,t){let n=`${e}.${process.pid}.tmp`;am(n,t),sm(n,e)}var Wt="npx -y cc-safety-net hook --cursor",ul=30;function Un(e){return um(e,".cursor","hooks.json")}function Ke(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function ho(){return{command:Wt,timeout:ul,failClosed:!0}}function Mn(e){return Ke(e)&&e.command===Wt}function pm(e){return Object.keys(e).length===3&&e.command===Wt&&e.timeout===ul&&e.failClosed===!0}function fm(e){try{return JSON.parse(cm(e,"utf-8"))}catch(t){if(t instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${e}: ${t.message}`);throw t}}function pl(e){let t=fm(e);if(!Ke(t))throw Error(`Cursor hooks config ${e} must be a JSON object`);if(t.version!==1)throw Error(`Cursor hooks config ${e} must set "version": 1`);if(t.hooks!==void 0&&!Ke(t.hooks))throw Error(`Cursor hooks config ${e} "hooks" must be an object`);let n=Ke(t.hooks)?t.hooks.preToolUse:void 0;if(n!==void 0&&!Array.isArray(n))throw Error(`Cursor hooks config ${e} "hooks.preToolUse" must be an array`);return t}function fl(e){let t=Ke(e.hooks)?e.hooks.preToolUse:void 0;return Array.isArray(t)?t:[]}function mm(e){if(!e.some(Mn))return[...e,ho()];return e.reduce((t,n)=>{if(!Mn(n))return t.result.push(n),t;if(!t.inserted)t.result.push(ho()),t.inserted=!0;return t},{result:[],inserted:!1}).result}function ml(e,t,n){let r=Ke(t.hooks)?t.hooks:{},o={...t,hooks:{...r,preToolUse:n}};O(e,`${JSON.stringify(o,null,2)}
31
- `)}function gl(e){let t=Un(e);if(!dl(t))return lm(dm(t),{recursive:!0}),O(t,`${JSON.stringify({version:1,hooks:{preToolUse:[ho()]}},null,2)}
32
- `),{path:t,alreadyInstalled:!1};let n=pl(t),r=fl(n),o=r.filter(Mn);if(Ke(n.hooks)&&Array.isArray(n.hooks.preToolUse)&&o.length===1&&o[0]!==void 0&&pm(o[0]))return{path:t,alreadyInstalled:!0};return ml(t,n,mm(r)),{path:t,alreadyInstalled:!1}}function hl(e){let t=Un(e);if(!dl(t))return{path:t,alreadyInstalled:!1};let n=pl(t),r=fl(n),o=r.filter((i)=>!Mn(i));if(o.length===r.length)return{path:t,alreadyInstalled:!1};return ml(t,n,o),{path:t,alreadyInstalled:!0}}function ym(e){if(!e||typeof e!=="object"||Array.isArray(e))return[];let t=e.hooks;if(!t||typeof t!=="object"||Array.isArray(t))return[];let n=t.preToolUse;if(!Array.isArray(n))return[];return n.filter((r)=>!!r&&typeof r==="object"&&!Array.isArray(r)&&r.command===Wt)}function vm(e){let t=[];if(e.length>1)t.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let n=e[0];if(n&&n.failClosed!==!0)t.push('Managed hook is missing "failClosed": true; reinstall to repair');if(n&&n.timeout!==30)t.push('Managed hook "timeout" is not 30; reinstall to repair');return t}function yl(e){let t=Un(e.homeDir);if(!gm(t))return{platform:"cursor",status:"n/a",configPath:t};let n;try{n=JSON.parse(hm(t,"utf-8"))}catch(i){return{platform:"cursor",status:"n/a",configPath:t,errors:[`Failed to parse Cursor hooks config ${t}: ${i instanceof Error?i.message:String(i)}`]}}let r=ym(n);if(r.length===0)return{platform:"cursor",status:"n/a",configPath:t};let o=vm(r);return{platform:"cursor",status:"configured",method:"hook config",configPath:t,errors:o.length>0?o:void 0}}import{existsSync as bm}from"node:fs";import{join as yo}from"node:path";var vo="gemini-safety-net";function bo(e){let t=yo(e,".gemini","extensions"),n=yo(t,vo);if(!bm(n))return{platform:"gemini-cli",status:"n/a"};let r=yo(t,"extension-enablement.json"),o=ce(r);if(o.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let i=o.kind==="ok"?k(k(o.value,vo),"overrides"):void 0;if(Array.isArray(i)&&i.some((a)=>typeof a==="string"&&a.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:r,errors:[`${vo} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:n}}function vl(e){return bo(e.homeDir)}import{existsSync as xm,readFileSync as Cm}from"node:fs";import{existsSync as Ll,mkdirSync as Lm,readFileSync as wl,rmSync as wm}from"node:fs";import{dirname as km,join as bl}from"node:path";var Yt="npx -y cc-safety-net hook --grok-build",qn=30;function Vn(e){return bl(process.env.GROK_HOME??bl(e,".grok"),"hooks","cc-safety-net.json")}function Je(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Gn(){return{hooks:[{type:"command",command:Yt,timeout:qn}]}}function kl(e){return Je(e)&&e.command===Yt}function xl(e){return e.flatMap((t)=>{if(!Je(t)||!Array.isArray(t.hooks))return[t];let n=t.hooks.filter((r)=>!kl(r));if(n.length===t.hooks.length)return[t];return n.length===0?[]:[{...t,hooks:n}]})}function Cl(e){try{let t=JSON.parse(e);return Je(t)?t:null}catch{return null}}function Sl(e){let t=Je(e.hooks)?e.hooks.PreToolUse:void 0;return Array.isArray(t)?t:[]}function Bn(e,t,n){let r=Je(t.hooks)?t.hooks:{};O(e,`${JSON.stringify({...t,hooks:{...r,PreToolUse:n}},null,2)}
33
- `)}function Rl(e){let t=Vn(e);if(!Ll(t))return Lm(km(t),{recursive:!0}),Bn(t,{},[Gn()]),{path:t,alreadyInstalled:!1};let n=Cl(wl(t,"utf-8"));if(!n)return Bn(t,{},[Gn()]),{path:t,alreadyInstalled:!1};let r=Sl(n),o=r.filter((i)=>Je(i)&&Array.isArray(i.hooks)&&i.hooks.some(kl));if(o.length===1&&JSON.stringify(o[0])===JSON.stringify(Gn()))return{path:t,alreadyInstalled:!0};return Bn(t,n,[...xl(r),Gn()]),{path:t,alreadyInstalled:!1}}function Pl(e){let t=Vn(e);if(!Ll(t))return{path:t,alreadyInstalled:!1};let n=Cl(wl(t,"utf-8"));if(!n)return{path:t,alreadyInstalled:!1};let r=Sl(n),o=xl(r);if(JSON.stringify(o)===JSON.stringify(r))return{path:t,alreadyInstalled:!1};let i=Je(n.hooks)?n.hooks:{};if(o.length===0&&Object.keys(n).length===1&&Object.keys(i).length===1)return wm(t),{path:t,alreadyInstalled:!0};return Bn(t,n,o),{path:t,alreadyInstalled:!0}}function Zt(e){return!!e&&typeof e==="object"&&!Array.isArray(e)}function Sm(e){if(!Zt(e)||!Zt(e.hooks))return[];let t=e.hooks.PreToolUse;if(!Array.isArray(t))return[];return t.filter((n)=>Zt(n)&&Array.isArray(n.hooks)&&n.hooks.some((r)=>Zt(r)&&r.command===Yt))}function Rm(e){let n=(Array.isArray(e.hooks)?e.hooks.filter(Zt):[]).find((r)=>r.command===Yt);return[...e.matcher===void 0||e.matcher===""||e.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...n?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...n?.timeout===qn?[]:[`Managed hook "timeout" is not ${qn}; reinstall to repair`]]}function Dl(e){let t=Vn(e.homeDir);if(!xm(t))return{platform:"grok-build",status:"n/a",configPath:t};let n;try{n=JSON.parse(Cm(t,"utf-8"))}catch(i){return{platform:"grok-build",status:"n/a",configPath:t,errors:[`Failed to parse Grok Build hooks config ${t}: ${i instanceof Error?i.message:String(i)}`]}}let r=Sm(n)[0];if(!r)return{platform:"grok-build",status:"n/a",configPath:t};let o=Rm(r);return{platform:"grok-build",status:"configured",method:"hook config",configPath:t,errors:o.length>0?o:void 0}}import{readFileSync as jl}from"node:fs";import{join as Nl}from"node:path";var Q="cc-safety-net",Al="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent";function El(e){return`# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent
34
- # version: ${e}
35
- `}function Pm(e){return`${El(e)}name: cc-safety-net
36
- version: "${e}"
2
+ import{m,L,t,k,o,ue,n,v,Ce,Y,vt,bt,u,we,pe,at,G,ne,fe,b,lt,I,g,D,Ae,Ct,H,C,W,O,N,ct,s,re,i,e,oe,J,U,z,xe,R,a,ie,B,We,Ue,w,ye,dt,S,ze,Te,Ie,wt,l,r,Be,se,E,P,Le,ut,Ve,St,De,c,qe,Ke,ae,Oe,Ye,Je,Z,xt,Lt,kt,Ze,Rt,Ne,_,ke,X,pt,p,ft,mt,gt,h,ve,y,Et,Q,Pt,ht,_t,le,f,Xe,Qe,et,tt,nt,rt,be,V,M,Me,ot,Re,x,$e,Ee,d}from"../chunks/index-e7vaxtyk.js";import{je,it,A,yt,st,de,q,Pe,F,ee,K,T,te,_e,j}from"../chunks/index-zqqsva7r.js";var Lu=["-h","--help"];function Wt(ce,me){let ge=Object.entries(ce.booleans??{}),he=Object.entries(ce.values??{}),Se=Object.entries(ce.lists??{}),Fe=Object.fromEntries(ge.map(([jt])=>[jt,!1])),He={},Ge=Object.fromEntries(Se.map(([jt])=>[jt,[]])),Dt=[],At=[],Tt=!1,Ft=-1;for(let[jt,It]of me.entries()){if(jt<=Ft)continue;if(It==="--"){Dt.push(...me.slice(jt+1));break}if(Lu.includes(It)){Tt=!0;continue}let $t=ge.find(([,Gt])=>Gt.includes(It));if($t){Fe[$t[0]]=!0;continue}let Ot=he.find(([,Gt])=>Gt.includes(It));if(Ot){let Gt=me[jt+1];if(Gt===void 0||Gt.startsWith("-")){At.push(`${It} requires a value`);continue}He[Ot[0]]=Gt,Ft=jt+1;continue}let Ut=Se.find(([,Gt])=>Gt.includes(It));if(Ut){let Gt=me.slice(jt+1),Nt=Gt.findIndex((Mt)=>Mt.startsWith("-")),Vt=Gt.slice(0,Nt===-1?Gt.length:Nt);if(Vt.length===0){At.push(`${It} requires at least one value`);continue}Ge[Ut[0]]=[...Ge[Ut[0]]??[],...Vt],Ft=jt+Vt.length;continue}if(It.startsWith("-")){At.push(`Unknown option for ${ce.label}: ${It}`);continue}if(ce.positionals==="tail"){Dt.push(...me.slice(jt));break}Dt.push(It)}if(ce.positionals!=="list"&&ce.positionals!=="tail")At.push(...Dt.map((jt)=>`Unexpected argument for ${ce.label}: ${jt}`));return{flags:Fe,values:He,lists:Ge,positionals:Dt,help:Tt,errors:At}}function vn(ce){for(let me of ce)console.error(me);return ce.length>0}import{readdirSync as wp,statSync as js,unlinkSync as kp}from"node:fs";import{basename as Ns,dirname as xp,isAbsolute as Cp,join as Sp,relative as Rp,resolve as Pp,sep as Dp}from"node:path";function en(ce){return Array.from(ce,(me)=>{let ge=me.charCodeAt(0);if(ge<=31||ge>=127&&ge<=159)return`\\x${ge.toString(16).padStart(2,"0")}`;return me}).join("")}var $o=(ce)=>{let me=Date.now()-new Date(ce).getTime();if(!Number.isFinite(me))return"";let ge=Math.floor(me/60000),he=Math.floor(ge/60),Se=Math.floor(he/24);if(Se>0)return`${Se}d ago`;if(he>0)return`${he}h ago`;if(ge>0)return`${ge}m ago`;return"just now"},Gn=(ce)=>{let me=(ce??"").trim().split(/\s+/).filter((Se)=>Se&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(Se)),ge=me[0]?.split("/").pop();if(!ge)return null;let he=me[1];return he&&/^[a-z][a-z0-9-]*$/.test(he)?`${ge} ${he}`:ge};import{existsSync as wu,readdirSync as ku,readFileSync as xu}from"node:fs";import{join as Cu}from"node:path";function kn(ce,me){try{return ku(ce,{withFileTypes:!0,encoding:"utf8"}).flatMap((ge)=>{let he=Cu(ce,ge.name);if(ge.isDirectory())return kn(he,me);if(ge.name.endsWith(".jsonl"))return[he];return[]})}catch{if(me&&wu(ce))me.count++;return[]}}function Oo(ce){let me=(Se)=>`${Se.sessionId}
3
+ ${Gn(Se.segment||Se.command)}`,ge=ce.filter((Se)=>Se.decision!=="allow"),he=ge.filter((Se)=>Se.sessionId).reduce((Se,Fe)=>Se.set(me(Fe),(Se.get(me(Fe))??0)+1),new Map);return new Set(ge.filter((Se)=>Se.failureStage||(he.get(me(Se))??0)>=2))}var Su=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function Ru(ce){if(!ce||typeof ce!=="object"||Array.isArray(ce))return!1;let me=ce;if(typeof me.ts!=="string"||typeof me.command!=="string")return!1;return Su.every((ge)=>me[ge]===void 0||typeof me[ge]==="string")}function Dn(ce,me){try{return xu(ce,"utf-8").split(`
4
+ `).filter(Boolean).flatMap((ge)=>{try{let he=JSON.parse(ge);if(!Ru(he)){if(me)me.count++;return[]}return[he]}catch{if(me)me.count++;return[]}})}catch{if(me)me.count++;return[]}}import{resolve as up}from"node:path";var Pu=["AKIA","ASIA","ghp_","gho_","ghu_","ghs_","ghr_","github_pat_","glpat-","xox","npm_","pypi-","rk_","sk-","sk_","gsk_","xai-","pplx-","bastn_","tgp_v1_","flp_","wfr_","fw_","fwp_","tp-","psk-"];function fs(ce){let me=0,ge={allocateSegment(){return me++},getNextSegmentIndex(){return me},recordGlobal(he){ce.record({kind:"step",scope:"global",step:he})},recordSegment(he,Se=ge.currentSegmentIndex){if(Se===void 0)return;ce.record({kind:"step",scope:"segment",segmentIndex:Se,step:he})}};return ge}function ms(ce={}){let me=[],ge=ce.maxEvents??512,he={maxTextLength:ce.maxTextLength??2048,maxListLength:ce.maxListLength??128,maxObjectProperties:ce.maxObjectProperties??ce.maxListLength??128,maxDepth:ce.maxDepth??16},Se=0,Fe,He=new Set;return{record(Ge){if(Fe)return;try{if(!Ge||me.length>=ge){Se++;return}me.push(jo(Du(Ge,he,He)))}catch{Se++}},finish(Ge){if(Fe)return Fe;try{Fe=jo({events:Object.freeze(me),droppedEvents:Se,terminal:Au(Ge,he,He)})}catch{Se++,Fe=Object.freeze({events:Object.freeze(me),droppedEvents:Se,terminal:Object.freeze({result:"blocked",reason:"trace unavailable".slice(0,he.maxTextLength),segment:"trace unavailable".slice(0,he.maxTextLength)})})}return Fe}}}function Du(ce,me,ge){if(ce.kind!=="step")throw TypeError("invalid trace event");let{scope:he,step:Se}=ce;$r(Se,ge,me);let Fe=Bn(Se,me,ge);if(he==="global")return{kind:"step",scope:"global",step:Fe};if(he!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:ce.segmentIndex,step:Fe}}function Au(ce,me,ge){let he=ce.result;if(he==="allowed")return Object.freeze({result:"allowed"});if(he!=="blocked")throw TypeError("invalid trace terminal");let Se=ce.ruleId;return Object.freeze({result:"blocked",reason:Bn(ce.reason,me,ge),segment:Bn(ce.segment,me,ge),...Se?{ruleId:Bn(Se,me,ge)}:{}})}function $r(ce,me,ge,he=0,Se=new WeakSet){if(typeof ce==="string"){let Ge=ce.slice(0,ge.maxTextLength);if(!st(Ge))return;for(let Dt of yt(Ge))for(let At of Dt.match(/[^\s"'()$]+/g)??[])me.add(gs(At));return}if(!ce||typeof ce!=="object"||he>=ge.maxDepth||Se.has(ce))return;if(Se.add(ce),Array.isArray(ce)){let Ge=Math.min(ce.length,ge.maxListLength);for(let Dt=0;Dt<Ge;Dt++)$r(ce[Dt],me,ge,he+1,Se);return}let Fe=0,He=new Set;for(let Ge in ce){if(!Object.hasOwn(ce,Ge))continue;if(Fe>=ge.maxObjectProperties)break;Fe++,$r(Ge,me,ge);let Dt=Fo(Ge,ge,me);if(He.has(Dt))continue;He.add(Dt),$r(ce[Ge],me,ge,he+1,Se)}}function Bn(ce,me,ge,he=0,Se=new WeakSet){if(typeof ce==="string")return Fo(ce,me,ge);if(!ce||typeof ce!=="object")return ce;if(he>=me.maxDepth)return;if(Se.has(ce))return;if(Se.add(ce),Array.isArray(ce)){let Ge=[],Dt=Math.min(ce.length,me.maxListLength);for(let At=0;At<Dt;At++)Ge.push(Bn(ce[At],me,ge,he+1,Se));return Ge}let Fe={},He=0;for(let Ge in ce){if(!Object.hasOwn(ce,Ge))continue;if(He>=me.maxObjectProperties)break;He++;let Dt=Fo(Ge,me,ge);if(Object.hasOwn(Fe,Dt))continue;Object.defineProperty(Fe,Dt,{value:Bn(ce[Ge],me,ge,he+1,Se),enumerable:!0,configurable:!0,writable:!0})}return Fe}function Fo(ce,me,ge){let he=ce.slice(0,me.maxTextLength),Se=st(he)?it(he):he,Fe=ge.size>0?_u(Se,ge):Se;return(Eu(Fe)?je(Fe):Fe).slice(0,me.maxTextLength)}function Eu(ce){return ce.includes("PRIVATE KEY")||ce.includes("://")||ce.includes("eyJ")||ce.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(ce)||ce.length>=14&&Pu.some((me)=>ce.includes(me))||ce.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(ce)}function _u(ce,me){return ce.replace(/[^\s"'()$]+/g,(ge)=>me.has(gs(ge))?"<redacted>":ge)}function gs(ce){let me=2166136261,ge=2166136261;for(let he=0;he<ce.length;he++)me=Math.imul(me^ce.charCodeAt(he),16777619),ge=Math.imul(ge^ce.charCodeAt(ce.length-he-1),16777619);return`${me>>>0}:${ge>>>0}:${ce.length}`}function jo(ce){if(ce&&typeof ce==="object"&&!Object.isFrozen(ce)){for(let me of Object.values(ce))jo(me);Object.freeze(ce)}return ce}function hs(ce,me,ge){let he=ge??dt(),Se=he.getCommandProgram(ce,me.shell??"auto"),Fe=ms(),He=fs(Fe),Ge=Se.dialect==="powershell"?he.getCommandProgram(ce,"posix"):Se,Dt=wt(Ge);He.recordGlobal({type:"parse",input:ce,segments:Dt.map((Ft)=>[...Ft])});let At=De(ce,{...me,analyzePartialProgram:!0,trace:He},Se,he),Tt=He.getNextSegmentIndex();if(At&&Tt>0&&Tt<Dt.length)He.recordSegment({type:"segment-skipped",index:Tt,reason:"prior-segment-blocked"},Tt);return Object.freeze({decision:At,trace:Fe.finish(At?{result:"blocked",reason:At.reason,segment:At.evidence.find((Ft)=>Ft.kind==="command")?.segment??ce,...At.ruleId?{ruleId:At.ruleId}:{}}:{result:"allowed"})})}import{resolve as Tu}from"node:path";function No(ce){let me=Rt().safeParse(ce);return{errors:me.success?[]:ke(me.error.issues),ruleNames:new Set(Ne(ce).map((ge)=>ge.toLowerCase()))}}function Ho(ce){let me=ys(ce);if(!me.ok)return me.result;return No(me.parsed)}function ys(ce){let me=[],ge=new Set;try{let he=typeof ce==="string"?ue(ce):ce,Se=n(he);if(Se===null)return me.push(`File not found: ${he.path}`),{ok:!1,result:{errors:me,ruleNames:ge}};if(!Se.trim())return me.push("Config file is empty"),{ok:!1,result:{errors:me,ruleNames:ge}};return{ok:!0,parsed:JSON.parse(Se)}}catch(he){if(he instanceof t)return me.push(he.message),{ok:!1,result:{errors:me,ruleNames:ge}};let Se=he instanceof Error?he.message:String(he);return me.push(he instanceof SyntaxError?"Invalid JSON":Se),{ok:!1,result:{errors:me,ruleNames:ge}}}}function vs(ce){return Tu(ce??process.cwd(),".safety-net.json")}function bn(ce){let me=ys(ce);if(!me.ok)return me.result;let ge=pt(me.parsed);return{errors:ge.errors,ruleNames:ge.sources}}import{join as Bo,resolve as qu}from"node:path";import{dirname as Fr}from"node:path";var Iu="custom.";function Or(ce){if(ce.rulebook_version!==2)return[];let me=ce.rules.map((ge)=>({name:ge.name,command:ge.command,block_args:[],match:ge.match,reason:ge.reason,intent:ge.intent}));return(ce.tests??[]).flatMap((ge,he)=>{let Se=Mo(R(ge.command));if(Se.length===0)return[`tests[${he}]: could not parse fixture command: ${ge.command}`];let Fe=Se.reduce((He,Ge)=>He??l(Ge,me)?.id.slice(Iu.length),void 0);if(ge.expect==="blocked"){if(Fe===ge.rule)return[];let He=Fe?`"${Fe}" matched first`:"no rule matched";return[`tests[${he}]: expected "${ge.rule}" to block "${ge.command}" but ${He}`]}return Fe?[`tests[${he}]: expected "${ge.command}" to be allowed but "${Fe}" matched`]:[]})}function Mo(ce){return ce.nodes.flatMap((me)=>{if(me.kind==="group"||me.kind==="function")return Mo(me.body);if(me.kind!=="command")return[];let ge=xe(oe(me.dialect,me.words)).words.map(e);return[...ge.length>0?[ge]:[],...me.nested.flatMap((he)=>Mo(he))]})}var $u=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function bs(ce,me){let ge=ks(ce.rules,me);if(ge.length>0)return{ok:!0,specs:ge};return ws(ce.rules,me)}function Ls(ce,me){let ge=ks(ce,me);if(ge.length>0)return{ok:!0,specs:ge};let he=Fu(ce,me);if(he.length>0)return{ok:!0,specs:he};let Se=ju(ce,me);if(!Se.ok)return Se;if(Se.specs.length>0)return{ok:!0,specs:Se.specs};return ws(ce,me)}function ws(ce,me){let ge=ce.filter((he)=>Uo(he)?.name===me);if(ge.length===1)return{ok:!0,specs:ge};return Ou(me,ge)}function Ou(ce,me){return{ok:!1,result:{ok:!1,errors:me.length===0?[`No configured rulebook matches ${ce}`]:[`Ambiguous rulebook match ${ce}: ${me.join(", ")}`],entries:[]}}}function ks(ce,me){return ce.filter((ge)=>ge===me)}function Fu(ce,me){let ge=me.match($u),he=ge?.[1],Se=ge?.[2],Fe=ge?.[3];if(!he||!Se||!Fe||!fe(Fe))return[];return xs(ce,(He)=>He.owner===he&&He.repo===Se&&He.ref===Fe)}function ju(ce,me){if(!ne(me))return{ok:!0,specs:[]};let[ge,he]=me.split("/"),Se=xs(ce,(He)=>He.owner===ge&&He.repo===he);if(new Set(Se.map((He)=>Uo(He)?.ref).filter((He)=>!!He)).size<2)return{ok:!0,specs:Se};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${me}. Use an explicit ref:`,` cc-safety-net rule remove ${me}#<ref>`],entries:[]}}}function Uo(ce){try{return G(ce)}catch{return null}}function xs(ce,me){return ce.filter((ge)=>{let he=Uo(ge);return he?me(he):!1})}var Rs=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function Cs(ce,me,ge=k(Fr(Fr(me)),"rules policy"),he=Z()){if(b(ce))return Uu(ce,he);return Mu(ce,me,ge)}async function Ps(ce,me,ge,he,Se,Fe){if(!b(ce))return Cs(ce,me,ge,he);let He=Se?null:Nu(ce,me,ge);if(He)return He;if(!Se&&!Fe)throw Error(`${ce} is not vendored; run rule update ${ce} to vendor it`);return Cs(ce,me,ge,he)}function Nu(ce,me,ge=k(Fr(Fr(me)),"rules policy")){let he=G(ce),Se=W(me,he.name),Fe=n(o(ge,Se));if(Fe===null)return null;let He=be(Go(Fe,`Invalid rulebook ${Se}.`));if(He.name!==he.name)throw Error(`rulebook name "${He.name}" in ${Se} must match "${he.name}"`);return{spec:ce,rulebook:He,content:Fe}}async function Ds(ce,me={}){if(!ne(ce))throw Error(`Invalid GitHub repository source: ${ce}`);let[ge,he]=ce.split("/");if(!ge||!he)throw Error(`Invalid GitHub repository source: ${ce}`);if(me.ref!==void 0&&!fe(me.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${me.ref}`);let Se=me.operation??Z(),Fe=me.ref??await Hu(ge,he,ce,Se),He=await Es(ge,he,Fe,ce,Se),Ge=await jr(`https://api.github.com/repos/${ge}/${he}/git/trees/${He}?recursive=1`,"tree",Se),Dt=Ge.response;if(!Dt.ok)throw Error(`Failed to inspect ${ce}: GitHub tree returned ${Dt.status}`);let At=JSON.parse(Ge.content);if(!Array.isArray(At?.tree))throw Error(`Failed to inspect ${ce}: unexpected GitHub tree response`);let Tt=At.tree,Ft=[...new Set(Tt.flatMap((jt)=>{if(!jt||typeof jt!=="object")return[];let It=jt;if(It.type!=="blob"||typeof It.path!=="string")return[];let $t=It.path.match(at);return $t?.[1]?[$t[1]]:[]}))].sort();if(Ft.length===0)throw Error(`No rulebooks found in ${ce} under ${pe}/`);return{source:ce,owner:ge,repo:he,ref:Fe,commit:He,names:Ft}}async function Hu(ce,me,ge,he){let Se=await jr(`https://api.github.com/repos/${ce}/${me}`,"metadata",he),Fe=Se.response;if(!Fe.ok)throw Error(`Failed to inspect ${ge}: GitHub returned ${Fe.status}`);let Ge=JSON.parse(Se.content)?.default_branch;if(typeof Ge!=="string"||Ge==="")throw Error(`Failed to inspect ${ge}: missing default branch`);if(!fe(Ge))throw Error(`GitHub returned an invalid default branch: ${Ge}`);return Ge}function Mu(ce,me,ge){lt(ce);let he=W(me,ce),Se=n(o(ge,he));if(Se===null)throw Error(`Rulebook source not found: ${ce}`);let Fe=As(Go(Se,"Invalid local rulebook source."));if(Fe.name!==ce)throw Error(`rulebook name "${Fe.name}" must match local source "${ce}"`);return{spec:ce,rulebook:Fe,content:Se}}async function Uu(ce,me){let ge=G(ce),he=await Es(ge.owner,ge.repo,ge.ref,ce,me),Se=await jr(`https://raw.githubusercontent.com/${ge.owner}/${ge.repo}/${he}/${ge.path}`,"raw",me),Fe=Se.response;if(!Fe.ok)throw Error(`Failed to fetch ${ce}: GitHub raw returned ${Fe.status}`);let He=Se.content,Ge=As(Go(He,"Invalid GitHub rulebook response."));if(Ge.name!==ge.name)throw Error(`rulebook name "${Ge.name}" must match GitHub source "${ge.name}"`);return{spec:ce,rulebook:Ge,content:He}}function As(ce){let me=be(ce),ge=Or(me);if(ge.length>0)throw Error(ge.join("; "));return me}function Go(ce,me){try{return JSON.parse(ce)}catch{throw Error(me)}}async function Es(ce,me,ge,he,Se){let Fe=await jr(`https://api.github.com/repos/${ce}/${me}/commits/${encodeURIComponent(ge)}`,"commit",Se),He=Fe.response;if(!He.ok)throw Error(`Failed to resolve ${he}: GitHub returned ${He.status}`);let Ge=JSON.parse(Fe.content);if(typeof Ge?.sha!=="string"||Ge.sha==="")throw Error(`Failed to resolve commit for ${he}`);return Ge.sha}async function Gu(ce,me,ge={}){if(ge.signal?.aborted)throw ge.signal.reason;let he=ge.budget??Je(),Se=new AbortController,Fe=()=>Se.abort(ge.signal?.reason);ge.signal?.addEventListener("abort",Fe,{once:!0});let He=!1,Ge=setTimeout(()=>{if(Se.signal.aborted)return;He=!0,Se.abort()},ge.timeoutMs??Rs.timeoutMs);try{if(ge.signal?.aborted)throw ge.signal.reason;Lt(he);let Dt=await(ge.fetch??fetch)(ce,{signal:Se.signal,redirect:"error"});if(!Dt.ok)return _s(Dt),{response:Dt,content:""};return{response:Dt,content:await Bu(Dt,me,he,()=>Se.abort())}}catch(Dt){if(He)throw Error("GitHub request timed out",{cause:Dt});if(ge.signal?.aborted)throw ge.signal.reason;throw Dt}finally{clearTimeout(Ge),ge.signal?.removeEventListener("abort",Fe)}}function jr(ce,me,ge){return Gu(ge.resolveUrl?.(ce)??ce,me,{budget:ge.budget,signal:ge.controller.signal})}async function Bu(ce,me,ge=Je(),he){let Se=Rs[`${me}Bytes`],Fe=Number(ce.headers.get("content-length"));if(Number.isFinite(Fe)&&Fe>Se)throw _s(ce),Error(`GitHub ${me} response exceeds ${Se} bytes`);if(!ce.body)return"";let He=ce.body.getReader(),Ge=[],Dt=0;while(!0){let At=await He.read();if(At.done)break;try{kt(ge,At.value.byteLength)}catch(Tt){throw he?.(),Ss(He),Tt}if(Dt+=At.value.byteLength,Dt>Se)throw he?.(),Ss(He),Error(`GitHub ${me} response exceeds ${Se} bytes`);Ge.push(Buffer.from(At.value))}return Buffer.concat(Ge,Dt).toString("utf-8")}function _s(ce){if(!ce.body)return;Ts(()=>ce.body?.cancel())}function Ss(ce){Ts(()=>ce.cancel())}function Ts(ce){try{Promise.resolve(ce()).catch(()=>{})}catch{}}async function cr(ce={}){let me=Vo(ce);return Vu(me,await Nr(me,Z()))}function Vu(ce,me){if(!me.ok)return me;let ge=C(ce),he=[...new Set(M(ge.configPath,ge.filesystemScope))];if(he.length===0)return me;return{ok:!1,errors:he,entries:me.entries}}async function Nr(ce,me,ge={},he=new Set,Se=new Set){try{let Fe=C(ce),He=ft(Fe.configTarget);if(!He.ok)return He.result;let Ge=He.config;if(ce.check)return ap(Ge,Fe,ce);let Dt=ce.only?bs(Ge,ce.only):{ok:!0,specs:Ge.rules};if(!Dt.ok)return Dt.result;let At=new Set([...ce.refresh?Dt.specs:[],...he]),Tt=(Mt)=>Ps(Mt,Fe.configDir,Fe.filesystemScope,me,At.has(Mt),!ce.refresh||At.has(Mt)),Ft=await np(Ge.rules,ce.refresh?(Mt)=>Tt(Mt).then((zt)=>({ok:!0,item:zt})).catch((zt)=>{if(xt(zt))throw zt;return{ok:!1,spec:Mt,message:zt instanceof Error?zt.message:String(zt)}}):async(Mt)=>({ok:!0,item:await Tt(Mt)}),me),jt=Ft.filter((Mt)=>!Mt.ok),It=Ft.filter((Mt)=>Mt.ok).map((Mt)=>Mt.item),$t=It.flatMap((Mt)=>zu(Mt,Ge.rules)),Ot=It.flatMap((Mt)=>Ku(Mt,Se,Fe)),Ut=new Set([...$t,...Ot].map((Mt)=>Mt.spec)),Gt=[...jt,...$t,...Ot],Nt=[],Vt=Wu(Nt,()=>It.flatMap((Mt)=>Ut.has(Mt.spec)||Gt.length>0&&Se.has(Mt.spec)?[]:Ju(Mt,Fe,ge,Nt)));return{ok:Gt.length===0,errors:Gt.map((Mt)=>`Failed to update ${Mt.spec}: ${Mt.message}`),entries:It.map(Zu),changes:Vt}}catch(Fe){return lr(Fe)}}function zu(ce,me){if(!b(ce.spec))return[];let ge=ot(ce.spec),he=me.filter((Se)=>Se!==ce.spec&&ot(Se).toLowerCase()===ge.toLowerCase());if(he.length===0)return[];return[{ok:!1,spec:ce.spec,message:`rulebook name "${ge}" is also claimed by ${he.join(", ")}; rename one of them`}]}function Ku(ce,me,ge){if(!me.has(ce.spec)||!b(ce.spec))return[];let he=W(ge.configDir,ce.rulebook.name),Se=n(o(ge.filesystemScope,he));if(Se===null||Se===ce.content)return[];return[{ok:!1,spec:ce.spec,message:`${he} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Ju(ce,me,ge,he){if(!b(ce.spec))return[];let Se=W(me.configDir,ce.rulebook.name),Fe=o(me.filesystemScope,Se),He=n(Fe);if(He===ce.content)return[];return he?.push({target:Fe,previous:He}),v(Fe,ce.content,void 0,ge._testAfterPolicyRename),Yu(ce,He)}function Wu(ce,me){try{return me()}catch(ge){for(let he of[...ce].reverse()){if(he.previous===null){Y(he.target);continue}v(he.target,he.previous)}throw ge}}function Yu(ce,me){if(me===null)return[`Vendored ${ce.spec} (${ce.rulebook.version})`];let ge=Re(me),he="problem"in ge?null:ge.rulebook,Se=new Map(he?.rules.map((He)=>[He.name,JSON.stringify(He)])??[]),Fe=new Set(ce.rulebook.rules.map((He)=>He.name));return[`Updated ${ce.spec} (${he?.version??"unreadable"} -> ${ce.rulebook.version})`,...[...Fe].filter((He)=>!Se.has(He)).map((He)=>` + ${He}`),...[...Se.keys()].filter((He)=>!Fe.has(He)).map((He)=>` - ${He}`),...ce.rulebook.rules.filter((He)=>{let Ge=Se.get(He.name);return Ge!==void 0&&Ge!==JSON.stringify(He)}).map((He)=>` ~ ${He.name}`)]}function Zu(ce){return{spec:ce.spec,name:ce.rulebook.name,version:ce.rulebook.version,ruleCount:ce.rulebook.rules.length}}async function qo(ce,me={}){return Xu(ce,op(me),Z())}async function Xu(ce,me,ge,he={}){let Se=null,Fe=!1;try{let He=C(me),Ge=n(He.configTarget);Se={target:He.configTarget,content:Ge};let Dt=ft(He.configTarget);if(!Dt.ok)return Dt.result;let At=Dt.config,Tt=ne(ce);Qu(ce,me,Tt);let Ft=Tt?await Ds(ce,{ref:me.ref,operation:ge}):null,jt=Ft?ep(Ft,me.rulebooks):[],It=Ft?jt.map((Nt)=>tp(At.rules,Ft,Nt)??`${ce}#${Ft.ref}/${Nt}`):[ce],$t=It.filter((Nt)=>!At.rules.includes(Nt)),Ot=[...At.rules,...$t];if(Ot.length>ae)return rp();if(Ot.length!==At.rules.length)Fe=!0,h(He.configTarget,{version:1,rules:Ot,overrides:At.overrides??{},transparent_wrappers:At.transparent_wrappers??[]},void 0,he._testAfterPolicyRename);let Ut=await Nr(me,ge,he,new Set($t),new Set($t));if(!Ut.ok)ar(He.configTarget,Ge);if(!Ut.ok||!Ft)return Ut;let Gt=jt.filter((Nt,Vt)=>$t.includes(It[Vt]??""));return{...Ut,add:{source:ce,ref:Ft.ref,selected:jt,added:Gt,alreadyConfigured:jt.filter((Nt)=>!Gt.includes(Nt)),commits:$t.length>0?[Ft.commit]:[]}}}catch(He){if(Fe&&Se)try{ar(Se.target,Se.content)}catch(Ge){return lr(Ge)}return lr(He)}}function Qu(ce,me,ge){if(!ge&&me.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!ge&&me.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${ce}`);if(me.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let he=me.rulebooks?.filter((Se)=>!u.test(Se))??[];if(he.length>0)throw Error(`Invalid rulebook names: ${he.join(", ")}`)}function ep(ce,me){let ge=me?[...new Set(me)]:ce.names,he=ge.filter((Se)=>!ce.names.includes(Se));if(he.length>0)throw Error(`Rulebooks not found in ${ce.source} at ${ce.ref}: ${he.join(", ")}
5
+ Available rulebooks: ${ce.names.join(", ")}`);return ge}function tp(ce,me,ge){let he=`${me.source}#${me.ref}/${ge}`;if(ce.includes(he))return he;let Se=`${me.source}#${me.commit}/${ge}`;return ce.find((Fe)=>Fe===Se)}async function np(ce,me,ge=Z()){if(ce.length>ae)throw Error(Oe);let he=Array(ce.length),Se=0,Fe,He=Array.from({length:Math.min(ce.length,Ye.concurrency)},async()=>{while(!Fe){let Ge=Se;if(Ge>=ce.length)return;Se++;try{he[Ge]=await me(ce[Ge],Ge,ge.controller.signal)}catch(Dt){if(!Fe)Fe={value:Dt},Se=ce.length,ge.controller.abort(Dt);return}}});if(await Promise.all(He),Fe)throw Fe.value;return he}function rp(){return{ok:!1,errors:[Oe],entries:[]}}function Vo(ce){return{cwd:ce.cwd,userConfigDir:ce.userConfigDir,userConfigPath:ce.userConfigPath,projectConfigPath:ce.projectConfigPath,global:ce.global,check:ce.check,only:ce.only,refresh:ce.refresh}}function op(ce){return{...Vo(ce),ref:ce.ref,rulebooks:ce.rulebooks}}function ip(ce){return{...Vo(ce),deleteSource:ce.deleteSource}}async function zo(ce,me={}){try{return await sp(ce,ip(me),{})}catch(ge){return lr(ge)}}async function sp(ce,me,ge){let he=C(me),Se=p(he.configTarget);if(Se.errors.length>0)return{ok:!1,errors:Se.errors,entries:[]};if(!Se.config)return{ok:!1,errors:[`No config found at ${he.configPath}`],entries:[]};let Fe=Ls(Se.config.rules,ce);if(!Fe.ok)return Fe.result;let He=me.deleteSource?lp(he.configDir,Fe.specs,he.filesystemScope):{ok:!0,dirs:[]};if(!He.ok)return He.result;let Ge=n(he.configTarget);if(Ge===null)return lr(Error("Rules config is unavailable."));try{h(he.configTarget,{version:1,rules:Se.config.rules.filter((Tt)=>!Fe.specs.includes(Tt)),overrides:Se.config.overrides??{},transparent_wrappers:Se.config.transparent_wrappers??[]},void 0,ge._testAfterPolicyRename)}catch(Tt){throw ar(he.configTarget,Ge),Tt}let Dt=await Nr(me,Z(),ge);if(!Dt.ok)return ar(he.configTarget,Ge),Dt;let At=cp(He.dirs,ge,he.filesystemScope);if(!At.ok){ar(he.configTarget,Ge);let Tt=await Nr(me,Z(),ge);if(!Tt.ok)return{ok:!1,errors:[...At.result.errors,...Tt.errors],entries:Tt.entries};return At.result}return Dt}async function ap(ce,me,ge){let he=Me(ce,me.configDir,ge.global?"user":"project",me.filesystemScope);return{ok:he.errors.length===0&&he.warnings.length===0,errors:[...he.errors,...he.warnings],entries:he.entries}}function lp(ce,me,ge){let he=me.flatMap((Ge)=>u.test(Ge)?[]:["--delete-source can only delete local rulebook sources"]),Se=me.map((Ge)=>Bo(ce,Ge)),Fe=he.length>0?[]:Se.flatMap((Ge)=>Is(Ge,ge)),He=[...he,...Fe];return He.length>0?{ok:!1,result:{ok:!1,errors:He,entries:[]}}:{ok:!0,dirs:Se}}function Is(ce,me){let ge=qu(ce),he=o(me,ge),Se=Ce(he);if(!Se)return[`Local rulebook source directory not found: ${ce}`];let Fe=Se.find((He)=>He.name==="rulebook.json");if(!Fe)return[`Local rulebook source directory is missing rulebook.json: ${ce}`];if(Fe.kind!=="file")throw new t(me.label);if(n(o(me,Bo(ge,"rulebook.json"))),Se.length>1)return[`Local rulebook source directory contains extra files: ${ce}. delete manually if you really want to remove the directory.`];return[]}function cp(ce,me,ge){let he=ce.flatMap((Se)=>{try{if(!Ce(o(ge,Se)))return[];let Fe=Is(Se,ge);if(Fe.length>0)return Fe;return dp(Se,me,ge),[]}catch(Fe){return[`Failed to delete local rulebook source ${Se}: ${Fe instanceof Error?Fe.message:String(Fe)}`]}});return he.length>0?{ok:!1,result:{ok:!1,errors:he,entries:[]}}:{ok:!0}}function dp(ce,me,ge){if(me._testDeleteLocalSourceDir){me._testDeleteLocalSourceDir(ce);return}Y(o(ge,Bo(ce,we))),bt(o(ge,ce))}function ar(ce,me){if(me===null){Y(ce);return}v(ce,me)}function lr(ce){return{ok:!1,errors:[ce instanceof Error?ce.message:String(ce)],entries:[]}}function qn(ce,me){let ge=fp(me),he=Ve(ge),Se={effectiveLevel:he.effectiveLevel,selectedPreset:ge.policySnapshot.policy.safety.level??"standard",...ge.policySnapshot.policyScopes?{safetyPresetScope:ge.policySnapshot.policyScopes.levelScope}:{},effectiveCapabilities:he.effectiveCapabilities,destructiveCommandRuleOverrides:ge.policySnapshot.policy.destructiveCommandRuleOverrides},{configSource:Fe,configValid:He}=pp({cwd:me?.cwd,userConfigDir:me?.userConfigDir});if(!ce||!ce.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:Fe,configValid:He,...Se};let Ge=mp(ce,ge);if(Ge)return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Ge.rule,matched:!0,reason:Ge.reason}]}]},result:"blocked",reason:A(Ge.reason),segment:A(Ge.target),...Ge.ruleId?{ruleId:A(Ge.ruleId)}:{},configSource:Fe,configValid:He,...Se};let Dt=hs(ce,ge),At=Dt.decision,Tt=At?.ruleId??gp(ce,ge),Ft=J.find((It)=>It.id===Tt&&It.activationCapability),jt=Ft?he.policy.effectiveDestructiveCommandRules[Ft.id]:void 0;return{trace:yp(Dt.trace),result:At?"blocked":"allowed",reason:At?A(At.reason):void 0,segment:At?A(At.evidence.find((It)=>It.kind==="command")?.segment??ce):void 0,ruleId:At?.ruleId?A(At.ruleId):void 0,customRule:hp(vp(At?.ruleId,ge.policySnapshot)),configSource:Fe,configValid:He,...Se,...Ft&&jt?{ruleActivation:{id:Ft.id,...jt}}:{}}}function pp(ce){let me=I(ce?.cwd),ge=ce?.userConfigPath??D(ce),he=H({cwd:ce?.cwd,userConfigDir:ce?.userConfigDir,userConfigPath:ce?.userConfigPath});try{if(n(he.projectConfigTarget)!==null){if(bn(he.projectConfigTarget).errors.length===0)return{configSource:me,configValid:!0};return{configSource:me,configValid:!1}}}catch(Se){if(Se instanceof t)return{configSource:me,configValid:!1};throw Se}try{if(n(he.userConfigTarget)!==null){let Se=bn(he.userConfigTarget);return{configSource:ge,configValid:Se.errors.length===0}}return{configSource:null,configValid:!0}}catch(Se){if(Se instanceof t)return{configSource:ge,configValid:!1};throw Se}}function fp(ce){let me=up(ce?.cwd??process.cwd()),ge=ce?.policySnapshot??x({cwd:me,userConfigDir:ce?.userConfigDir}),he=E(ge.policy);return{cwd:me,effectiveCwd:me,policySnapshot:ge,environment:L(),protectedGitMetadata:Te([me]),effectiveCapabilities:he.capabilities,strict:ce?.strict??he.strict,paranoidRm:he.paranoidRm,paranoidInterpreters:he.paranoidInterpreters,worktreeMode:he.worktreeMode}}function mp(ce,me){let ge=me.cwd??process.cwd(),he=ye(c("",{command:ce},{kind:"command",shell:"posix"},{executionCwd:ge,configCwd:ge},ce)),Se=tt(he);if(Se)return{reason:et,target:Se.target,ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};let Fe=Ke(he);if(Fe)return{reason:qe,target:Fe.target,ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};let He=ze(he,me.protectedGitMetadata);if(He)return{reason:S,target:He.target,ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};let Ge=me.policySnapshot.policy,Dt=Ge.secretProtection.enabled===!1?null:rt(he,Ge.secretProtection,{strict:me.strict});if(Dt)return{reason:nt,target:Dt.target,ruleId:Dt.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"};return null}function gp(ce,me){let ge=me.policySnapshot.policy,he=Ee({...ge,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...ge.destructiveCommandRuleOverrides,...Object.fromEntries(J.flatMap((Se)=>Se.activationCapability?[[Se.id,"on"]]:[]))}},me.policySnapshot.state==="degraded"?{diagnostics:me.policySnapshot.diagnostics,reason:me.policySnapshot.reason}:void 0);return St(ce,{...me,policySnapshot:he,strict:!0,paranoidRm:!0,paranoidInterpreters:!0})?.ruleId}function hp(ce){if(!ce)return;return{id:A(ce.id),...ce.rulebook?{rulebook:{name:A(ce.rulebook.name),version:A(ce.rulebook.version)}}:{},...ce.source?{source:A(ce.source)}:{},...ce.override?{override:{type:"reason",reason:A(ce.override.reason)}}:{}}}function yp(ce){let me=ce.events.flatMap((he)=>he.kind==="step"&&he.scope==="global"?[he.step]:[]),ge=new Map;for(let he of ce.events){if(he.kind!=="step"||he.scope!=="segment")continue;let Se=ge.get(he.segmentIndex)??{index:he.segmentIndex,steps:[]};Se.steps.push(he.step),ge.set(he.segmentIndex,Se)}return{steps:me,segments:[...ge.values()]}}function vp(ce,me){let ge=ce?.replace(/^custom\./,"");if(!ge||!me.policy.rules.some((he)=>he.name===ge))return;return me.ruleMetadata[ge]??Object.freeze({id:ge})}import{existsSync as Os,readFileSync as bp}from"node:fs";function $s(ce,me){return{"safety.level":ce.safety.level,...Ko("safety.overrides",ce.safety.overrides),"workflow.worktree_mode":String(ce.workflow.worktree_mode),"destructive_command_protection.enabled":String(ce.destructive_command_protection.enabled),...Ko("destructive_command_protection.overrides",ce.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Jo(ce.destructive_command_protection.allow_paths),"secret_protection.enabled":String(ce.secret_protection.enabled),...Ko("secret_protection.overrides",ce.secret_protection.overrides),"secret_protection.deny_paths":Jo(ce.secret_protection.deny_paths),"secret_protection.allow_paths":Jo(ce.secret_protection.allow_paths),...me?{"audit.retention_days":String(ce.audit.retention_days)}:{}}}function dr(ce,me,ge){let he=$s(ce,ge),Se=$s(me,ge);return[...new Set([...Object.keys(he),...Object.keys(Se)])].flatMap((Fe)=>he[Fe]===Se[Fe]?[]:[{field:Fe,before:he[Fe],after:Se[Fe]}])}function Vn(ce){let me=y(ce);if(!Os(me))return{baseline:f(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__),diagnostics:[]};let ge=xn(me);return{baseline:f(ge.value),diagnostics:ge.errors.length>0?ge.errors:_(ge.value)}}function xn(ce){if(!Os(ce))return{errors:[`${ce}: file not found`]};try{return{value:JSON.parse(bp(ce,"utf-8")),errors:[]}}catch(me){let ge=me instanceof Error?me.message:String(me);return{errors:[`${ce}: ${me instanceof SyntaxError?`Invalid JSON: ${ge}`:ge}`]}}}function ur(ce,me){let ge=Lp(ce)?ce:{};return{version:me.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((he)=>ge[he]!==void 0).map((he)=>[he,ge[he]]))}}function Ko(ce,me){return Object.fromEntries(Object.entries(me).flatMap(([ge,he])=>he===void 0?[]:[[`${ce}.${ge}`,String(he)]]))}function Jo(ce){return ce.length===0?"(none)":ce.join(", ")}function Lp(ce){return!!ce&&typeof ce==="object"&&!Array.isArray(ce)}function Ap(ce){let me=de(),ge=Wt({label:"logs",booleans:{all:["--all"],suspect:["--suspect"],json:["--json"],pruneLegacy:["--prune-legacy"],dryRun:["--dry-run"]},values:{id:["--id"],limit:["--limit"],since:["--since"],agent:["--agent"],rule:["--rule"],session:["--session"],project:["--project"]}},ce);if(vn(ge.errors))return null;if(ge.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(ge.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let he=ge.values.limit===void 0?20:Fs(ge.values.limit);if(he===null)return console.error("--limit must be a positive number"),null;let Se=ge.values.since===void 0?Math.min(30,me):Fs(ge.values.since);if(Se===null||Se>me)return console.error(`--since must be a positive number of days no greater than ${me}`),null;let Fe={limit:he,limitExplicit:ge.values.limit!==void 0,since:Se,sinceExplicit:ge.values.since!==void 0,all:ge.flags.all,json:ge.flags.json,suspect:ge.flags.suspect,pruneLegacy:ge.flags.pruneLegacy,dryRun:ge.flags.dryRun,id:ge.values.id,agent:ge.values.agent,rule:ge.values.rule,session:ge.values.session,project:ge.values.project===void 0?void 0:Pp(ge.values.project)};if(Fe.id&&(Fe.agent!==void 0||Fe.rule!==void 0||Fe.session!==void 0||Fe.project!==void 0||Fe.suspect||Fe.sinceExplicit||Fe.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(Fe.pruneLegacy&&(Fe.id!==void 0||Fe.agent!==void 0||Fe.rule!==void 0||Fe.session!==void 0||Fe.project!==void 0||Fe.suspect||Fe.all||Fe.sinceExplicit||Fe.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(Fe.dryRun&&!Fe.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return Fe}async function Hs(ce,me={}){let ge=Ap(ce);if(!ge)return 1;let he=me.logsDir??F();if(ge.pruneLegacy)return Ep(he,ge.json,ge.dryRun);if(!he)return console.log(ge.json?"[]":ge.id?`No retained audit log entry found for id ${en(ge.id)}.`:"No audit log entries found."),0;q(he);let Se={count:0},Fe=kn(he,Se).flatMap((Tt)=>Dn(Tt,Se).map((Ft)=>({entry:Ft,file:Tt})));if(Se.count>0)console.error(`warning: ${Se.count} audit log ${Se.count===1?"source":"sources"} could not be read; these results are incomplete`);if(ge.id)return $p(Fe,ge,me.timeZone);let He=Date.now()-ge.since*24*60*60*1000,Ge=Fe.filter((Tt)=>Op(Tt,ge,he,He)),Dt=ge.suspect?Oo(Ge.map((Tt)=>Tt.entry)):null,At=(Dt?Ge.filter((Tt)=>Dt.has(Tt.entry)):Ge).sort((Tt,Ft)=>Date.parse(Ft.entry.ts)-Date.parse(Tt.entry.ts)).slice(0,ge.limit);if(ge.json)return console.log(JSON.stringify(At.map((Tt)=>Tt.entry),null,2)),0;if(At.length===0)return console.log("No audit log entries found."),0;for(let Tt of At)console.log(Np(Tt.entry,me.timeZone));return 0}function Ep(ce,me,ge){let he=ce?Tp(ce).map((Ge)=>Sp(ce,Ge)):[];if(ge)return _p(he,me);let Se=[],Fe=0,He=0;for(let Ge of he){let Dt=js(Ge,{throwIfNoEntry:!1})?.size??0,At=Ip(Ge);if(At){Se.push(`${Ns(Ge)}: ${At}`);continue}Fe++,He+=Dt}if(me)return console.log(JSON.stringify({removedFiles:Fe,removedBytes:He,failedFiles:Se.length})),Se.length===0?0:1;console.log(Fe===0&&Se.length===0?"No legacy audit log files found.":`Removed ${Fe} legacy audit log ${Fe===1?"file":"files"} (${Ms(He)}).`);for(let Ge of Se)console.error(`Could not remove ${en(Ge)}`);if(console.log("Nested v2 audit logs were not changed."),Fe>0)console.log("This deletion cannot be undone.");return Se.length===0?0:1}function _p(ce,me){let ge=ce.reduce((he,Se)=>he+(js(Se,{throwIfNoEntry:!1})?.size??0),0);if(me)return console.log(JSON.stringify({dryRun:!0,files:ce.length,bytes:ge})),0;if(console.log(ce.length===0?"No legacy audit log files found.":`Would remove ${ce.length} legacy audit log ${ce.length===1?"file":"files"} (${Ms(ge)}).`),console.log("Nested v2 audit logs are not included."),ce.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Tp(ce){try{return wp(ce,{withFileTypes:!0}).filter((me)=>me.isFile()&&me.name.endsWith(".jsonl")).map((me)=>me.name)}catch{return[]}}function Ip(ce){try{return kp(ce),null}catch(me){return me instanceof Error?me.message:String(me)}}function Ms(ce){let me=["B","KiB","MiB","GiB"],ge=Math.min(Math.floor(Math.log2(Math.max(ce,1))/10),me.length-1);return`${Math.round(ce/1024**ge*10)/10} ${me[ge]}`}function $p(ce,me,ge){let he=ce.filter((Fe)=>Fe.entry.id===me.id);if(he.length>1)return console.error(`Multiple audit log entries found for id ${en(me.id??"")}.`),1;if(me.json)return console.log(JSON.stringify(he.map((Fe)=>Fe.entry),null,2)),0;let Se=he[0];if(!Se)return console.log(`No retained audit log entry found for id ${en(me.id??"")}.`),0;return console.log(Hp(Se.entry,ge)),0}function Op(ce,me,ge,he){if(!me.all&&ce.entry.decision==="allow")return!1;if(Date.parse(ce.entry.ts)<he)return!1;if(me.agent!==void 0&&ce.entry.agent!==me.agent)return!1;if(me.rule!==void 0&&ce.entry.ruleId!==me.rule)return!1;if(me.session!==void 0&&!Fp(ce,ge,me.session))return!1;if(me.project!==void 0&&!jp(ce.entry.cwd,me.project))return!1;return!0}function Fp(ce,me,ge){if(ce.entry.sessionId===ge)return!0;return xp(ce.file)===me&&Ns(ce.file,".jsonl")===ge}function jp(ce,me){if(!ce)return!1;let ge=Rp(me,ce);return ge!==".."&&!ge.startsWith(`..${Dp}`)&&!Cp(ge)}function Np(ce,me){let ge=en(ce.id??"-"),he=en(ce.decision??"deny"),Se=ce.cwd?` [${en(ce.cwd)}]`:"",Fe=ce.segment||ce.command,He=Fe===ce.command?"":"↳ ",Ge=Fe.length>50?`${Fe.slice(0,50)}…`:Fe;return`${ge.padEnd(16)} ${en(Us(ce.ts,me))} ${he.padEnd(5)} ${en(ce.agent??"-").padEnd(15)} ${en(ce.ruleId??"-").padEnd(20)} ${He}${en(Ge)}${Se}`}function Hp(ce,me){let ge=(Se)=>en(Se===void 0||Se===null||Se===""?"-":Se),he=ce.shape?`${ce.agent??"-"} (shape: ${ce.shape})`:ce.agent??"-";return[`id: ${ge(ce.id)}`,`ts: ${ge(Us(ce.ts,me))}`,`decision: ${ge(ce.decision)}`,`agent: ${ge(he)}`,`level: ${ge(ce.level)}`,`tool: ${ge(ce.toolName)}`,`rule: ${ge(ce.ruleId)}`,`intent: ${ge(ce.intent)}`,`stage: ${ge(ce.failureStage)}`,`error: ${ge(ce.errorCode)}`,`session: ${ge(ce.sessionId)}`,`cwd: ${ge(ce.cwd)}`,`version: ${ge(ce.v)}`,`truncated: ${ge(ce.truncated===!0?"yes":void 0)}`,`reason: ${ge(ce.reason)}`,`command: ${ge(ce.command)}`,`segment: ${ge(ce.segment)}`].join(`
6
+ `)}function Us(ce,me){let ge=new Date(ce);if(Number.isNaN(ge.getTime()))return ce;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:me}).format(ge)}function Fs(ce){let me=Number(ce);return Number.isFinite(me)&&me>0?me:null}var Gs={name:"doctor",aliases:["--doctor"],description:"Run diagnostic checks to verify installation and configuration",usage:"doctor [options]",options:[{flags:"--json",description:"Output diagnostics as JSON"},{flags:"--skip-update-check",description:"Skip npm registry version check"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net doctor","cc-safety-net doctor --json","cc-safety-net doctor --skip-update-check"]};var Bs={name:"explain",description:"Show step-by-step analysis trace of how a command would be analyzed",usage:"explain [options] <command>",argument:"<command>",options:[{flags:"--json",description:"Output analysis as JSON"},{flags:"--cwd",argument:"<path>",description:"Use custom working directory"},{flags:"-h, --help",description:"Show this help"}],examples:['cc-safety-net explain "git reset --hard"','cc-safety-net explain --json "rm -rf /"','cc-safety-net explain --cwd /tmp "git status"']};var qs={name:"gui",description:"Open the local policy editor GUI",usage:"gui [options]",options:[{flags:"--no-open",description:"Print the URL without opening a browser"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net gui","cc-safety-net gui --no-open"]};import{isAbsolute as Vs,join as Yp,relative as Zp}from"node:path";var Mp=8388608;function Up(ce,me){console.log(JSON.stringify(ce(te(me))))}async function Gp(ce){let me;try{me=(await Wo(process.stdin)).trim()}catch{ce({reason:"Failed to parse hook input JSON."});return}if(!me){ce({reason:"Missing hook input JSON."});return}return Yo(me,ce,"Failed to parse hook input JSON.")}async function Wo(ce){let me=[],ge=0;for await(let he of ce){let Se=typeof he==="string"?Buffer.from(he,"utf-8"):Buffer.from(he.buffer,he.byteOffset,he.byteLength);if(ge+=Se.byteLength,ge>Mp)throw Bp(ce),Error("hook input byte limit exceeded");me.push(Se)}return Buffer.concat(me,ge).toString("utf-8")}function Bp(ce){let me=ce.destroy??ce.cancel;if(!me)return;try{Promise.resolve(me.call(ce)).catch(()=>{})}catch{}}function Yo(ce,me,ge){try{return JSON.parse(ce)}catch{me({reason:ge});return}}function tn(ce,me){let ge=me.get(ce);return ge?{kind:"command",shell:ge}:{kind:ie(ce)}}function pn(ce,me,ge,he){let Se=ce===void 0?process.cwd():ce,Fe=typeof Se==="string"&&Se.trim()!==""?N([Se]):void 0;if(Fe)return{configCwd:Fe,executionCwd:Fe};return Zt(he,me,ge,Kp(Se)),null}function Zt(ce,me,ge,he){let Se;try{Se=B(me)}catch(Fe){if(!(Fe instanceof a))throw Fe}ce(T({command:Se,segment:he,toolName:ge}))}async function qp(ce){let me=await Gp(ce.outputDeny);if(me===void 0)return;if(!me||typeof me!=="object"||Array.isArray(me)){Zt(ce.outputDeny);return}if(!ce.isSupported(me))return;let ge=ce.getAgent?.(me)??ce.agent,he=ce.agent===ge?void 0:ce.agent,Se=Wp(me),Fe=(It,$t)=>{ee(It,()=>ce.getSessionId(me),{agent:ge,shape:he,toolName:$t,cwd:Se}),ce.outputDeny(It)},He=ce.getToolName(me);if(typeof He!=="string"||He.trim()===""){Zt((It)=>Fe(It),Jp(me));return}let Ge=He,Dt=(It)=>Fe(It,Ge),At;try{At=ce.getToolInput(me,Ge,Dt)}catch(It){if(!(It instanceof a))throw It;Zt(Dt,void 0,Ge);return}if(!At.ok)return;let Tt=ce.getContext(me,At.input,Ge,Dt);if(!Tt)return;let Ft;try{Ft=B(At.input)}catch(It){if(!(It instanceof a))throw It;Zt(Dt,void 0,Ge);return}let jt=c(Ge,At.input,At.route,Tt,Ft??null);try{let It=j(jt,{guard:{auditAllowed:se(),dependencies:ce.guardDependencies},audit:{agent:ge,shape:he,getSessionId:()=>ce.getSessionId(me)}}),$t=K(It,{includeEvidence:!0,toolName:It.stage==="command-analysis"?void 0:Ge});if($t){ce.outputDeny($t);return}ce.outputAllow?.()}catch(It){if(!(It instanceof d))throw It;Vp(It);let $t=K(It.evaluation,{includeEvidence:!0,toolName:It.evaluation.stage==="command-analysis"?void 0:Ge});if($t)ce.outputDeny($t);return}}function Vp(ce){if(!P(r.debug))return;console.error(`CC Safety Net debug: ${zp(ce.stage)}: ${_e(ce.cause)}`)}function zp(ce){if(ce==="policy-protection")return"hook policy protection failed";if(ce==="config-load")return"hook config loading failed";if(ce==="secret-protection")return"hook secret protection failed";return"hook analysis failed"}function Kp(ce){return typeof ce==="string"?ce:void 0}function Jp(ce){if(!ce||typeof ce!=="object"||Array.isArray(ce))return;if(Object.hasOwn(ce,"tool_input"))return ce.tool_input;let me=ce.toolCall;if(me&&typeof me==="object"&&!Array.isArray(me))return me.args;return}function Wp(ce){if(!ce||typeof ce!=="object"||Array.isArray(ce))return null;let me=ce.cwd;if(typeof me==="string")return me;let ge=ce.toolCall;if(!ge||typeof ge!=="object"||Array.isArray(ge))return null;let he=ge.args;if(!he||typeof he!=="object"||Array.isArray(he))return null;let Se=he.Cwd;return typeof Se==="string"?Se:null}async function nn(ce){let me=(Se)=>Up(ce.createDenyOutput,Se),ge=ce.createAllowOutput;await qp({...ce,outputDeny:me,outputAllow:ge?()=>console.log(JSON.stringify(ge())):void 0})}function pr(ce){return Yp(ce,".gemini","config","hooks.json")}var Xp=new Map([["run_command","auto"]]),Qp=new Set(["absolutepath","directorypath","file_path","filepath","path","searchdirectory","searchpath","target_file","targetfile"]);function zs(ce){return tn(ce,Xp)}async function Ks(){await nn({agent:"antigravity-cli",createDenyOutput:(ce)=>({decision:"deny",reason:ce}),isSupported:()=>!0,getToolName:(ce)=>ce.toolCall?.name,getToolInput:(ce,me)=>({ok:!0,input:o2(ce.toolCall?.args,me),route:zs(me)}),getContext:e2,getSessionId:(ce)=>ce.conversationId})}function e2(ce,me,ge,he){let Fe=r2(ce).flatMap((At)=>{let Tt=N([At]);return Tt?[Tt]:[]});if(!Fe[0])return An(he,me,ge),null;if(ge!=="run_command"){let At;try{At=t2(me,ge,Fe)}catch(Tt){if(Tt instanceof a)return An(he,void 0,ge),null;if(!(Tt instanceof s))throw Tt;return An(he,me,ge),null}if(!At)return An(he,me,ge),null;return{configCwd:At,executionCwd:At}}let He=ce.toolCall?.args;if(!He||!Object.hasOwn(He,"Cwd"))return{configCwd:Fe[0],executionCwd:Fe[0]};let Ge=He.Cwd;if(typeof Ge!=="string"||Ge.trim()==="")return An(he,me,ge),null;let Dt=O(Ge,Fe);if(Dt){let At=Js(Dt,Fe);if(!At)return An(he,me,ge,Ge),null;return{configCwd:At,executionCwd:Dt}}return An(he,me,ge,Ge),null}function t2(ce,me,ge){let he=zs(me),Se=[...We(ce,Qp),...he.kind==="patch"?Ue(ce):[]].filter(Vs),Fe=re(),He=new Set(Se.flatMap((Ge)=>{let Dt=Js(i(Ge,m,Fe),ge);return Dt?[Dt]:[]}));if(He.size>1)return null;return[...He][0]??ge[0]??null}function Js(ce,me){return me.filter((ge)=>n2(ce,ge)).reduce((ge,he)=>he.length>ge.length?he:ge,"")||null}function n2(ce,me){let ge=Zp(me,ce);return ge===""||!ge.startsWith("..")&&!Vs(ge)}function An(ce,me,ge,he){let Se=me&&typeof me==="object"?me.command:void 0;ce(T({command:typeof Se==="string"?Se:void 0,segment:he,toolName:ge}))}function r2(ce){if(ce.workspacePaths===void 0)return[process.cwd()];let me=Array.isArray(ce.workspacePaths)?ce.workspacePaths.filter((ge)=>typeof ge==="string"&&ge.trim()!==""):[];return N(me)?me:[]}function o2(ce,me){if(!ce)return;if(me!=="run_command")return ce;return{...ce,command:typeof ce.CommandLine==="string"&&ce.CommandLine!==""?ce.CommandLine:void 0}}var fr=[{id:"antigravity-cli",displayName:"Antigravity CLI",doctorOrder:3,runtime:{order:1,flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:2,flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",doctorOrder:1,runtime:{order:2,displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{order:3,flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",doctorOrder:4,runtime:{order:3,flags:["-cx","--codex"],description:"Run as a Codex PreToolUse hook",legacyTopLevelFlags:[]},install:{order:4,flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",doctorOrder:7,runtime:{order:6,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:7,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:6,runtime:{order:5,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:6,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",doctorOrder:8,runtime:{order:7,flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:9,runtime:{order:8,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:9,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:10,runtime:{order:9,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:10,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:11,install:{order:11,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:12,install:{order:12,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:13,install:{order:13,flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",doctorOrder:5,runtime:{order:4,flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{order:5,flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],Hr=fr.slice().sort((ce,me)=>ce.doctorOrder-me.doctorOrder).map((ce)=>ce.id),Ws=fr.filter((ce)=>("runtime"in ce)).slice().sort((ce,me)=>ce.runtime.order-me.runtime.order).map((ce)=>({id:ce.id,displayName:"displayName"in ce.runtime?ce.runtime.displayName:ce.displayName,flags:ce.runtime.flags,legacyFlags:"legacyFlags"in ce.runtime?ce.runtime.legacyFlags:[],description:ce.runtime.description,legacyTopLevelFlags:ce.runtime.legacyTopLevelFlags})),an=fr.slice().sort((ce,me)=>ce.install.order-me.install.order).map((ce)=>({id:ce.id,...ce.install})).map(({order:ce,...me})=>me),Qv=Object.fromEntries(fr.map((ce)=>[ce.id,ce.displayName]));function Kt(ce){return fr.find((me)=>me.id===ce)?.displayName??ce}import{homedir as i2}from"node:os";import{isAbsolute as Ys,join as Zo}from"node:path";function Zs(ce){if(ce!==void 0&&ce!==null&&typeof ce!=="string")return"unknown";if(typeof ce==="string"&&!Ys(ce))return"unknown";try{let me=re(),ge=typeof ce==="string"&&ce?i(ce,m,me):void 0,he=process.env.HOME||i2(),Se=[["codex",process.env.CODEX_HOME||Zo(he,".codex")],["copilot-cli",process.env.COPILOT_HOME||Zo(he,".copilot")],["claude-code",process.env.CLAUDE_CONFIG_DIR||Zo(he,".claude")]],Fe=ge?Se.flatMap(([He,Ge])=>{if(!Ys(Ge))return[];return ct(ge,i(Ge,m,me))?[He]:[]}):[];if(Fe.length===1)return Fe[0]??"unknown";if(Fe.length>1)return"unknown"}catch(me){if(me instanceof s)return"unknown";return"unknown"}if(process.env.CLAUDECODE==="1"||Boolean(process.env.CLAUDE_CODE_ENTRYPOINT))return"claude-code";return"unknown"}var Xo="PreToolUse",Xs="BeforeTool",Qs="pre_tool_call",Qo="PreToolUse";async function Mr(ce){await nn({agent:ce.agent,...ce.getAgent?{getAgent:ce.getAgent}:{},createDenyOutput:(me)=>({hookSpecificOutput:{hookEventName:Xo,permissionDecision:"deny",permissionDecisionReason:me}}),isSupported:(me)=>me.hook_event_name===Xo,getToolName:(me)=>me.tool_name,getToolInput:(me,ge)=>({ok:!0,input:me.tool_input,route:ce.getToolRoute(ge)}),getContext:(me,ge,he,Se)=>pn(me.cwd,ge,he,Se),getSessionId:(me)=>me.session_id})}var s2=new Map([["Bash","posix"],["PowerShell","powershell"]]);function a2(ce){return tn(ce,s2)}async function ea(){await Mr({agent:"claude-code",getAgent:(ce)=>Zs(ce.transcript_path),getToolRoute:a2})}var l2=new Map([["Bash","auto"]]);async function ta(){await Mr({agent:"codex",getToolRoute:(ce)=>tn(ce,l2)})}var c2=new Map([["bash","auto"],["Bash","auto"],["powershell","powershell"],["PowerShell","powershell"]]);function d2(ce){return tn(ce,c2)}async function na(){await nn({agent:"copilot-cli",createDenyOutput:(ce)=>({permissionDecision:"deny",permissionDecisionReason:ce}),isSupported:()=>!0,getToolName:(ce)=>ce.toolName,getToolInput:(ce,me,ge)=>{if(typeof ce.toolArgs!=="string")return ge({reason:"Failed to parse toolArgs JSON."}),{ok:!1};let he=Yo(ce.toolArgs,ge,"Failed to parse toolArgs JSON.");if(he===void 0)return{ok:!1};return{ok:!0,input:he,route:d2(me)}},getContext:(ce,me,ge,he)=>pn(ce.cwd,me,ge,he),getSessionId:(ce)=>typeof ce.sessionId==="string"&&ce.sessionId.trim()?ce.sessionId:void 0})}var u2=new Map([["Shell","auto"]]);function p2(ce){return tn(ce,u2)}async function ra(){await nn({agent:"cursor",createDenyOutput:(ce)=>({permission:"deny",user_message:ce,agent_message:ce}),createAllowOutput:()=>({permission:"allow"}),isSupported:()=>!0,getToolName:(ce)=>ce.tool_name,getToolInput:(ce,me)=>({ok:!0,input:ce.tool_input,route:p2(me)}),getContext:f2,getSessionId:(ce)=>ce.conversation_id})}function f2(ce,me,ge,he){let Se=m2(ce);if(!Se[0])return Zt(he,me,ge),null;let Fe=O(h2(ce.cwd),Se);if(!Fe)return Zt(he,me,ge,typeof ce.cwd==="string"?ce.cwd:void 0),null;if(me===null||typeof me!=="object"||Array.isArray(me))return{configCwd:Fe,executionCwd:Fe};if(!Object.hasOwn(me,"working_directory"))return{configCwd:Fe,executionCwd:Fe};let He=me.working_directory;if(typeof He!=="string"||He.trim()==="")return Zt(he,me,ge),null;let Ge=O(He,Se);if(!Ge)return Zt(he,me,ge,He),null;return{configCwd:Fe,executionCwd:Ge}}function m2(ce){return g2(ce).flatMap((me)=>{let ge=N([me]);return ge?[ge]:[]})}function g2(ce){if(ce.workspace_roots===void 0)return typeof ce.cwd==="string"&&ce.cwd.trim()!==""?[ce.cwd]:[];if(!Array.isArray(ce.workspace_roots))return[];return ce.workspace_roots.filter((me)=>typeof me==="string"&&me.trim()!=="")}function h2(ce){return typeof ce==="string"&&ce.trim()!==""?ce:"."}var y2=new Map([["run_shell_command","auto"]]);function v2(ce){return tn(ce,y2)}async function oa(){await nn({agent:"gemini-cli",createDenyOutput:(ce)=>({decision:"deny",reason:ce,systemMessage:ce}),isSupported:(ce)=>ce.hook_event_name===Xs,getToolName:(ce)=>ce.tool_name,getToolInput:(ce,me)=>({ok:!0,input:ce.tool_input,route:v2(me)}),getContext:(ce,me,ge,he)=>pn(ce.cwd,me,ge,he),getSessionId:(ce)=>ce.session_id})}var b2=new Map([["run_terminal_command","auto"]]);function L2(ce){return tn(ce,b2)}async function ia(){await nn({agent:"grok-build",createDenyOutput:(ce)=>({decision:"deny",reason:ce}),createAllowOutput:()=>({decision:"allow"}),isSupported:()=>!0,getToolName:(ce)=>ce.toolName,getToolInput:(ce,me,ge)=>{if(ce.toolInputTruncated===!0)return Zt(ge,ce.toolInput,me),{ok:!1};return{ok:!0,input:ce.toolInput,route:L2(me)}},getContext:w2,getSessionId:(ce)=>ce.sessionId})}function w2(ce,me,ge,he){let Se=N(k2(ce));if(!Se)return Zt(he,me,ge),null;let Fe=O(x2(ce.cwd),[Se]);if(!Fe)return Zt(he,me,ge,typeof ce.cwd==="string"?ce.cwd:void 0),null;return{configCwd:Fe,executionCwd:Fe}}function k2(ce){let me=ce.workspaceRoot===void 0?ce.cwd:ce.workspaceRoot;return typeof me==="string"&&me.trim()!==""?[me]:[]}function x2(ce){return typeof ce==="string"&&ce.trim()!==""?ce:"."}import{resolve as C2}from"node:path";var S2=new Map([["terminal","posix"]]);async function sa(){await nn({agent:"hermes-agent",createDenyOutput:(ce)=>({action:"block",message:ce}),isSupported:(ce)=>ce.hook_event_name===Qs,getToolName:(ce)=>ce.tool_name,getToolInput:(ce,me)=>({ok:!0,input:ce.tool_input,route:tn(me,S2)}),getContext:R2,getSessionId:(ce)=>ce.session_id})}function R2(ce,me,ge,he){let Se=pn(ce.cwd,me,ge,he);if(!Se)return null;if(!me||typeof me!=="object"||Array.isArray(me))return Se;if(!Object.hasOwn(me,"workdir"))return Se;let Fe=me.workdir;if(typeof Fe!=="string"||Fe.trim()==="")return Zt(he,me,ge),null;let He=N([C2(Se.configCwd,Fe)]);if(!He)return Zt(he,me,ge,Fe),null;return{...Se,executionCwd:He}}var aa=new Map([["Bash","posix"]]);function P2(ce){return tn(ce,aa)}async function la(){await nn({agent:"kimi-code",createDenyOutput:(ce)=>({hookSpecificOutput:{hookEventName:Qo,permissionDecision:"deny",permissionDecisionReason:ce}}),isSupported:(ce)=>ce.hook_event_name===Qo,getToolName:(ce)=>ce.tool_name,getToolInput:(ce,me)=>({ok:!0,input:ce.tool_input,route:P2(me)}),getContext:(ce,me,ge,he)=>{let Se=pn(ce.cwd,me,ge,he);if(!Se)return null;let Fe=ce.tool_input;if(!aa.has(ge)||!Fe||!Object.hasOwn(Fe,"cwd"))return Se;let He=Fe.cwd;if(typeof He!=="string"||He.trim()==="")return Zt(he,me,ge),null;let Ge=O(He,[Se.configCwd]);if(!Ge)return Zt(he,me,ge,He),null;return{configCwd:Se.configCwd,executionCwd:Ge}},getSessionId:(ce)=>ce.session_id})}var D2={"antigravity-cli":Ks,"claude-code":ea,codex:ta,"copilot-cli":na,cursor:ra,"gemini-cli":oa,"grok-build":ia,"hermes-agent":sa,"kimi-code":la},zn=Ws.map((ce)=>({...ce,run:D2[ce.id]}));function ca(ce){let me=Wt({label:"hook",booleans:Object.fromEntries(zn.map((he)=>[he.id,[...he.flags,...he.legacyFlags]]))},ce);if(me.errors.length>0)return;let ge=zn.filter((he)=>me.flags[he.id]);return ge.length===1?ge[0]:void 0}function da(ce){return zn.find((me)=>me.legacyTopLevelFlags.some((ge)=>ge===ce))}var A2=zn.map((ce)=>({flags:ce.flags.join(", "),description:ce.description})),E2=zn.flatMap((ce)=>ce.flags.map((me)=>`cc-safety-net hook ${me}`)),ua={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...A2,{flags:"-h, --help",description:"Show this help"}],examples:E2};var pa={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...an.map((ce)=>({flags:ce.flag,description:`Install ${Kt(ce.id)} ${ce.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...an.map((ce)=>`cc-safety-net install ${ce.flag}`)]},fa={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...an.map((ce)=>({flags:ce.flag,description:`Uninstall ${Kt(ce.id)} ${ce.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...an.map((ce)=>`cc-safety-net uninstall ${ce.flag}`)]},ma={name:"update",description:"Update every installed CC Safety Net integration to the latest version",usage:"update",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net update"]};var ga={name:"logs",description:"Browse audit log entries recorded by hooks",usage:"logs [options]",options:[{flags:"--id",argument:"<id>",description:"Show one entry from retained history by its 16-character id (not guaranteed once it is older than the configured retention)"},{flags:"--limit",argument:"<n>",description:"Maximum entries to print",default:"20"},{flags:"--since",argument:"<days>",description:"Only include entries newer than this many days (max: the configured audit retention, 1-365)",default:"30"},{flags:"--agent",argument:"<name>",description:"Filter by agent name"},{flags:"--rule",argument:"<ruleId>",description:"Filter by rule id"},{flags:"--session",argument:"<id>",description:"Filter by session id"},{flags:"--project",argument:"<path>",description:"Filter by project path"},{flags:"--suspect",description:"Only denials that look like false positives"},{flags:"--all",description:"Include allow entries"},{flags:"--prune-legacy",description:"Permanently delete all legacy root-level logs; nested logs are untouched"},{flags:"--dry-run",description:"With --prune-legacy, report what would be deleted and delete nothing"},{flags:"--json",description:"Output entries as JSON"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net logs --id 3fa9c2d1a70e8b42","cc-safety-net logs --agent claude-code","cc-safety-net logs --project . --since 7","cc-safety-net logs --suspect --since 7","cc-safety-net logs --json","cc-safety-net logs --prune-legacy --dry-run","cc-safety-net logs --prune-legacy"]};var Ur={name:"policy",description:"Check and apply project or user policy proposals",usage:"policy <subcommand>",subcommands:[{usage:"check <file>",description:"Validate a policy proposal and print its diff"},{usage:"apply <file>",description:"Apply a proposal after confirming in a terminal"}],options:[{flags:"-g, --global",description:"Use the user-scope policy instead of the project one"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net policy check proposal.json","cc-safety-net policy apply proposal.json","cc-safety-net policy apply proposal.json --global"]};var ei=[{flags:"--ref",argument:"<ref>",description:"Use a branch, tag, or commit"},{flags:"--only",argument:"<rulebook...>",description:"Add only these repository rulebooks"},{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"-h, --help",description:"Show this help"}],ti=["cc-safety-net rule add project-rules","cc-safety-net rule add acme/safety-rules","cc-safety-net rule add acme/safety-rules --only aws gcloud","cc-safety-net rule add acme/safety-rules --ref v2 --only aws","cc-safety-net rule add --only terraform aws"],Kn={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add [source] [--ref <ref>] [--only <rulebook...>]",description:"Add rulebook sources and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Re-fetch and vendor remote rulebooks"},{usage:"sync",description:"Deprecated: migrate lock and cache leftovers"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},...ei.slice(0,2),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net rule init","cc-safety-net rule init --example","cc-safety-net rule wrapper add rtk",...ti,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var ha={name:"status",description:"Show what the runtime is enforcing right now",usage:"status",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net status"]};var ya={name:"statusline",description:"Print status line with mode indicators for shell integration",usage:"statusline --claude-code",options:[{flags:"-cc, --claude-code",description:"Print status line for Claude Code"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net statusline -cc","cc-safety-net statusline --claude-code"]};var Gr=[ha,Gs,ga,Bs,Kn,Ur,pa,ma,fa,ua,qs,ya];function _2(ce){return ce.aliases??[]}function Br(ce){let me=ce.toLowerCase();return Gr.find((ge)=>ge.name.toLowerCase()===me||_2(ge).some((he)=>he.toLowerCase()===me))}import{basename as T2}from"node:path";function qr(ce=7,me=F()){let ge=Date.now()-ce*24*60*60*1000,he=[],Se=new Set,Fe=0,He,Ge,Dt,At;if(me)q(me);let Tt={count:0},Ft=me?kn(me,Tt):[];for(let It of Ft)for(let $t of Dn(It,Tt)){if($t.decision==="allow")continue;let Ot=new Date($t.ts).getTime();if(Ot>=ge){if(Fe++,Se.add($t.sessionId??T2(It,".jsonl")),Ge===void 0||Ot<=Ge)He=$t.ts,Ge=Ot;if(At===void 0||Ot>At)Dt=$t.ts,At=Ot;I2(he,$t,Ot)}}let jt=he.map((It)=>({timestamp:It.ts,command:It.command,reason:It.reason,relativeTime:$o(new Date(It.ts))}));return{totalBlocked:Fe,sessionCount:Se.size,recentEntries:jt,oldestEntry:He,newestEntry:Dt,unreadable:Tt.count}}function I2(ce,me,ge){let he=ce.findIndex((Se)=>ge>new Date(Se.ts).getTime());if(he===-1){if(ce.length<3)ce.push(me);return}if(ce.splice(he,0,me),ce.length>3)ce.pop()}import{dirname as $2}from"node:path";function va(ce,me,ge){let he;try{if(n(me)===null)return{path:ce,exists:!1,valid:!1,ruleCount:0};he=bn(me),he.errors.push(...M(ce,ge))}catch(Se){if(!(Se instanceof t))throw Se;he={errors:[Se.message],ruleNames:new Set}}return{path:ce,exists:!0,valid:he.errors.length===0,ruleCount:he.ruleNames.size,...he.errors.length>0?{errors:he.errors}:{}}}function O2(ce,me){return{source:me,name:ce.name,command:ce.command,subcommand:ce.subcommand,blockArgs:[...ce.block_args],reason:ce.reason}}function ba(ce,me){let ge=me?.userConfigPath??D(),he=me?.projectConfigPath??I(ce),Se=$2(ge),Fe=V({cwd:ce,userConfigPath:ge,projectConfigPath:he,userConfigDir:Se}),He=H({cwd:ce,userConfigPath:ge,projectConfigPath:he,userConfigDir:Se}),Ge=new Map(Fe.rulebooks.flatMap((Dt)=>Dt.rules.map((At)=>[At,Dt.source])));return{userConfig:va(ge,He.userConfigTarget,He.userScope),projectConfig:va(he,He.projectConfigTarget,He.projectScope),effectiveRules:Fe.rules.map((Dt)=>O2(Dt,Ge.get(Dt.name)??"project")),shadowedRules:[]}}var F2=[{flag:r.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:r.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:r.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:r.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:r.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:r.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:r.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:r.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function La(){return[...F2.map((ce)=>({name:ce.flag.name,value:Le(ce.flag),isSet:ut(ce.flag),legacyName:ce.flag.legacyName,legacyValue:ce.flag.legacyName?process.env[ce.flag.legacyName]:void 0,legacyIsSet:ce.flag.legacyName?process.env[ce.flag.legacyName]!==void 0:void 0,description:ce.description,defaultBehavior:ce.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:process.env.CC_SAFETY_NET_HOME,isSet:process.env.CC_SAFETY_NET_HOME!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var wa={error:0,warning:1,info:2},j2=["policy","config","audit"];function N2(ce){return ce.map((me)=>{if(me==="ownership")return"is not owned by the current user";if(me==="permissions")return"has unsafe permissions";if(me==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var H2=[{derive:(ce)=>ce.hooks.length>0&&ce.hooks.every((me)=>!me.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(ce)=>ce.hooks.filter((me)=>me.inspectionStatus==="failed").map((me)=>{let ge=Kt(me.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${ge} inspection failed`,detail:`Doctor could not verify the ${ge} integration configuration.`,fixHint:`Correct the reported ${ge} configuration error, then run \`cc-safety-net doctor\` again.`,integration:me.platform}})},{derive:(ce)=>ce.userConfig.exists&&!ce.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:ce.userConfig.path}]:[]},{derive:(ce)=>ce.projectConfig.exists&&!ce.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:ce.projectConfig.path}]:[]},{derive:(ce)=>ce.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${ce.configState.reason}`,fixHint:"Fix the file named in the reason, or run `cc-safety-net rule update` to vendor a remote source, then rerun doctor."}]:[]},{derive:(ce)=>ce.v2Leftovers&&ce.v2Leftovers.length>0?[{checkId:"config.v2-leftovers",severity:"info",title:"Rulebook lock and cache leftovers detected",detail:`Files an earlier version left behind are no longer read: ${ce.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(ce)=>{let me=ce.environment.find((ge)=>ge.name==="CC_SAFETY_NET_AUDIT_SCOPE");return Be(me?.value)==="invalid"?[{checkId:"environment.audit-scope-invalid",severity:"warning",title:"Audit scope value is invalid",detail:"CC_SAFETY_NET_AUDIT_SCOPE is not `all` or `blocked`, so allowed command decisions are not recorded.",fixHint:"Set CC_SAFETY_NET_AUDIT_SCOPE to `all` or `blocked`, then restart the integration."}]:[]}},...j2.map((ce)=>({derive:(me)=>me.posture.directories.filter((ge)=>ge.kind===ce&&ge.status==="unsafe").map((ge)=>({checkId:`posture.${ce}-directory-unsafe`,severity:"error",title:`${ce[0]?.toUpperCase()}${ce.slice(1)} directory is unsafe`,detail:`The ${ce} directory ${N2(ge.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...ge.path?{path:ge.path}:{}}))})),{derive:(ce)=>{let me=[...ce.effectiveSafety.weakenedRuleOverrides].sort();return me.length>0?[{checkId:"posture.rule-overrides-weaken-preset",severity:"warning",title:"Rule overrides weaken the selected preset",detail:`Explicit overrides disable rules the resolved preset would enable: ${me.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${me.join(", ")}.`}]:[]}}];function ka(ce){return H2.flatMap((me,ge)=>me.derive(ce).map((he,Se)=>({finding:he,catalogOrder:ge,occurrence:Se}))).sort((me,ge)=>wa[me.finding.severity]-wa[ge.finding.severity]||me.catalogOrder-ge.catalogOrder||me.occurrence-ge.occurrence).map((me)=>me.finding)}function fn(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var M2=(ce)=>fn()?`\x1B[32m${ce}\x1B[0m`:ce,U2=(ce)=>fn()?`\x1B[33m${ce}\x1B[0m`:ce,G2=(ce)=>fn()?`\x1B[34m${ce}\x1B[0m`:ce,B2=(ce)=>fn()?`\x1B[35m${ce}\x1B[0m`:ce,q2=(ce)=>fn()?`\x1B[36m${ce}\x1B[0m`:ce,V2=(ce)=>fn()?`\x1B[31m${ce}\x1B[0m`:ce,z2=(ce)=>fn()?`\x1B[2m${ce}\x1B[0m`:ce,K2=(ce)=>fn()?`\x1B[1m${ce}\x1B[0m`:ce,Ht={green:M2,yellow:U2,blue:G2,magenta:B2,cyan:q2,red:V2,dim:z2,bold:K2},J2="\x1B[0m",W2=[39,82,198,226,208,51,196,46,201,214,93,154,220,27,49,190,200,33,129,227,45,160,63,118,123,202];function Y2(ce){let me=ce;return()=>(me=(me*1664525+1013904223)%4294967296,me/4294967296)}function Z2(ce){let me=[...W2],ge=Y2(ce);for(let he=me.length-1;he>0;he--){let Se=Math.floor(ge()*(he+1)),Fe=me[he];me[he]=me[Se],me[Se]=Fe}return me}function X2(ce,me=0){if(!fn())return"";let ge=Z2(me);return`\x1B[38;5;${ge[ce%ge.length]}m`}function xa(ce,me,ge=0){if(!fn())return`"${ce}"`;return`${X2(me,ge)}"${ce}"${J2}`}function Vr(ce){return ce==="default"?"built-in default":`${ce} policy`}var Q2=new RegExp("\x1B\\[[0-9;]*m","g"),ni=(ce)=>ce.replace(Q2,"").length;function En(ce){let me=(ce.headers??ce.rows[0]??[]).map((He,Ge)=>{let Dt=Math.max(...ce.rows.map((At)=>ni(At[Ge]??"")));return Math.max(ni(He),Dt)}),ge=(He,Ge)=>He+" ".repeat(Math.max(0,Ge-ni(He))),he=(He,Ge)=>Ge[0]+me.map((Dt)=>He.repeat(Dt+2)).join(Ge[1])+Ge[2],Se=(He)=>`│ ${He.map((Ge,Dt)=>ge(Ge,me[Dt]??0)).join(" │ ")} │`,Fe=ce.headers?[` ${Se(ce.headers)}`,` ${he("─",["├","┼","┤"])}`]:[];return[` ${he("─",["┌","┬","┐"])}`,...Fe,...ce.rows.map((He)=>` ${Se(He)}`),` ${he("─",["└","┴","┘"])}`].join(`
7
+ `)}function Ca(ce){let me=[];me.push("Hook Integration"),me.push(ef(ce));let ge=[],he=[];for(let Se of ce){let Fe=Kt(Se.platform);if(Se.errors&&Se.errors.length>0)for(let He of Se.errors)if(Se.configured)ge.push({platform:Fe,message:He});else he.push({platform:Fe,message:He})}for(let Se of ge)me.push(` Warning (${Se.platform}): ${Se.message}`);for(let Se of he)me.push(Ht.red(` Error (${Se.platform}): ${Se.message}`));return me.join(`
8
+ `)}function ef(ce){let me=["Platform","Discovery","Configuration","Inspection"],ge=ce.map((he)=>{let Se=Kt(he.platform);if(he.inspectionStatus==="not-inspected"){let Dt=Ht.dim("Not inspected");return[Se,Dt,Dt,Dt]}let Fe=he.detected?Ht.green("Detected"):he.inspectionStatus==="failed"?Ht.red("Unknown"):Ht.dim("Not detected"),He=he.configured?Ht.green("Configured"):he.detected?Ht.yellow("Not configured"):he.inspectionStatus==="failed"?Ht.red("Unknown"):Ht.dim("Not applicable"),Ge=he.inspectionStatus==="verified"?Ht.green("Verified"):he.inspectionStatus==="failed"?Ht.red("Failed"):Ht.dim("Not applicable");return[Se,Fe,He,Ge]});return En({headers:me,rows:ge})}function Sa(ce){let ge=["Guard Engine Verification",` Synthetic self-test: ${ce.failed>0?Ht.red(`${ce.passed}/${ce.total} FAIL`):Ht.green(`${ce.passed}/${ce.total} passed`)}`],he=ce.results.filter((Se)=>!Se.passed);if(he.length>0){ge.push(""),ge.push(Ht.red(" Failures:"));for(let Se of he)ge.push(Ht.red(` • ${Se.description}`)),ge.push(Ht.red(` expected ${Se.expected}, got ${Se.actual}`))}return ge.join(`
9
+ `)}function tf(ce){if(ce.length===0)return" (no custom rules)";let me=["Source","Name","Command","Block Args"],ge=ce.map((he)=>[he.source,he.name,he.subcommand?`${he.command} ${he.subcommand}`:he.command,he.blockArgs.join(", ")]);return En({headers:me,rows:ge})}function Ra(ce){let me=[];if(me.push("Configuration"),me.push(nf(ce.userConfig,ce.projectConfig)),me.push(""),ce.effectiveRules.length>0)me.push(` Effective rules (${ce.effectiveRules.length} total):`),me.push(tf(ce.effectiveRules));else me.push(" Effective rules: (none - using built-in rules only)");for(let ge of ce.shadowedRules)me.push(""),me.push(` Note: Project rule "${ge.name}" shadows user rule with same name`);return me.join(`
10
+ `)}function nf(ce,me){let ge=["Scope","Status"],he=(Fe)=>{if(!Fe.exists)return Ht.dim("N/A");if(!Fe.valid)return Ht.red(`Invalid (${Fe.errors?.[0]??"unknown error"})`);return Ht.green("Configured")},Se=[["User",he(ce)],["Project",he(me)]];return En({headers:ge,rows:Se})}function Pa(ce){let me=[];return me.push("Environment"),me.push(rf(ce)),me.join(`
11
+ `)}function Da(ce){let me=ce.effectiveSafety.policyScopes,ge=["Effective Safety",` Selected preset: ${ce.effectiveSafety.selectedPreset}${me?` (${Vr(me.levelScope)})`:""}`,` Effective: ${ce.effectiveSafety.level}`],he=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[Se,Fe]of he){let He=ce.effectiveSafety.capabilities[Se],Ge=He.enabled?Ht.green("ON"):Ht.dim("OFF"),Dt=He.sources.length>0?` (${He.sources.join(", ")})`:"";ge.push(` ${Fe}: ${Ge} via ${He.source}${Dt}`)}if(me&&me.weakenings.length>0){ge.push(" Project policy deltas:");for(let Se of me.weakenings)ge.push(` ${Se}`)}ge.push(` Stored rule customizations: ${ce.effectiveSafety.ruleCounts.stored}`),ge.push(` Effective rule customizations: ${ce.effectiveSafety.ruleCounts.effective}`);for(let[Se,Fe]of Object.entries(ce.effectiveSafety.ruleOverrides))ge.push(` ${Se}: ${Fe}`);return ge.join(`
12
+ `)}function Aa(ce){let me=["Findings"];if(ce.length===0)return me.push(" No findings from inspected doctor facts."),me.join(`
13
+ `);for(let ge of ce){let he=`[${ge.severity.toUpperCase()}] ${ge.checkId}: ${en(ge.title)}`,Se=ge.severity==="error"?Ht.red:ge.severity==="warning"?Ht.yellow:Ht.blue;if(me.push(` ${Se(he)}`),me.push(` ${en(ge.detail)}`),ge.path)me.push(` Path: ${en(ge.path)}`);if(ge.fixHint)me.push(` Fix: ${en(ge.fixHint)}`)}return me.join(`
14
+ `)}function rf(ce){let me=["Variable","Status","Legacy"],ge=ce.map((he)=>{let Se=he.isSet?Ht.green("✓"):Ht.dim("✗"),Fe=he.legacyName&&he.legacyIsSet?`${he.legacyName} ${Ht.green("✓")}`:he.legacyName??"";return[he.name,Se,Fe]});return En({headers:me,rows:ge})}function Ea(ce){let me=[];if(ce.totalBlocked===0)me.push("Recent Activity"),me.push(" No blocked commands in the last 7 days"),me.push(" Tip: This is normal for new installations");else me.push(`Recent Activity · last 7 days (${ce.totalBlocked} blocked / ${ce.sessionCount} sessions)`),me.push(of(ce.recentEntries));if(ce.unreadable>0)me.push(` Warning: ${ce.unreadable} audit log ${ce.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return me.join(`
15
+ `)}function of(ce){let me=["Time","Command"],ge=ce.map((he)=>{let Se=en(he.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),Fe=Se.length>40?`${Se.slice(0,37)}...`:Se;return[he.relativeTime,Fe]});return En({headers:me,rows:ge})}function _a(ce){let me=[];if(me.push("Update Check"),ce.latestVersion===null&&!ce.error)return me.push(zr([["Status",Ht.dim("Skipped")],["Installed",ce.currentVersion]])),me.join(`
16
+ `);if(ce.error)return me.push(zr([["Status",`${Ht.yellow("⚠")} Error`],["Installed",ce.currentVersion],["Error",Ht.dim(ce.error)]])),me.join(`
17
+ `);if(ce.updateAvailable)return me.push(zr([["Status",`${Ht.yellow("⚠")} Update Available`],["Current",ce.currentVersion],["Latest",Ht.green(ce.latestVersion??"")]])),me.push(""),me.push(" Run: bunx cc-safety-net@latest doctor"),me.push(" Or: npx cc-safety-net@latest doctor"),me.join(`
18
+ `);return me.push(zr([["Status",`${Ht.green("✓")} Up to date`],["Version",ce.currentVersion]])),me.join(`
19
+ `)}function zr(ce){return En({rows:ce})}function Ta(ce){let me=[];return me.push("System Info"),me.push(sf(ce)),me.join(`
20
+ `)}function sf(ce){let me=["Component","Version"],ge=(Fe)=>{if(Fe===null)return Ht.dim("not found");return Fe},Se=[{label:"cc-safety-net",value:ce.version},...Hr.map((Fe)=>({label:Kt(Fe),value:ce.versions[Fe]??null})),{label:"Node.js",value:ce.nodeVersion},{label:"npm",value:ce.npmVersion},{label:"Bun",value:ce.bunVersion},{label:"Platform",value:ce.platform}].map((Fe)=>[Fe.label,ge(Fe.value)]);return En({headers:me,rows:Se})}function Ia(ce){if(ce.findings.length===0)return Ht.green(`
21
+ No findings from inspected doctor facts.`);let me={error:ce.findings.filter((Fe)=>Fe.severity==="error").length,warning:ce.findings.filter((Fe)=>Fe.severity==="warning").length,info:ce.findings.filter((Fe)=>Fe.severity==="info").length},ge=["error","warning","info"].filter((Fe)=>me[Fe]>0).map((Fe)=>`${me[Fe]} ${Fe}`),he=ce.findings.length===1?"finding":"findings",Se=`
22
+ ${ce.findings.length} ${he}: ${ge.join(", ")}.`;if(me.error>0)return Ht.red(Se);if(me.warning>0)return Ht.yellow(Se);return Ht.blue(Se)}import{lstatSync as af}from"node:fs";import{dirname as ri}from"node:path";function oi(ce,me){try{let ge=af(me);if(ge.isSymbolicLink())return{kind:ce,path:me,status:"unsafe",issues:["symlink"]};if(!ge.isDirectory())return{kind:ce,path:me,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:ce,path:me,status:"unknown",issues:[]};let he=[...ge.uid!==process.getuid()?["ownership"]:[],...(ge.mode&18)!==0?["permissions"]:[]];return{kind:ce,path:me,status:he.length>0?"unsafe":"safe",issues:he}}catch(ge){if(typeof ge==="object"&&ge!==null&&"code"in ge&&ge.code==="ENOENT")return{kind:ce,path:me,status:"not-applicable",issues:[]};return{kind:ce,path:me,status:"unknown",issues:[]}}}function $a(ce){let me=F();return{directories:[oi("policy",ri(ri(ce))),oi("config",ri(ce)),...me?[oi("audit",me)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as lf}from"node:child_process";import{existsSync as Oa}from"node:fs";import{delimiter as cf,extname as df,join as uf}from"node:path";import{stripVTControlCharacters as Fa}from"node:util";var Na="2.3.4",pf=5000,ff="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function Xt(){return Na}function ii(ce,me){let ge=ce[me];if(ge)return ge;let he=Object.keys(ce).find((Se)=>Se.toLowerCase()===me.toLowerCase()&&!!ce[Se]);return he?ce[he]:ge}function mf(ce){return(ii(ce,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((me)=>me.length>0)}function gf(ce,me){let ge=df(ce)?[ce]:[...mf(me).map((he)=>`${ce}${he}`),ce];if(ce.includes("/")||ce.includes("\\"))return ge.find((he)=>Oa(he))??ce;return(ii(me,"PATH")??"").split(cf).flatMap((he)=>ge.map((Se)=>uf(he,Se))).find((he)=>Oa(he))??ce}function ja(ce){if(!/[\s"&|<>^]/.test(ce))return ce;return`"${ce.replace(/"/g,'""')}"`}function _n(ce,me){let[ge,...he]=ce,Se=me[ff]==="win32"?"win32":process.platform;if(!ge||Se!=="win32")return{cmd:ge??"",args:he};let Fe=gf(ge,me);if(!/\.(?:bat|cmd)$/i.test(Fe))return{cmd:Fe,args:he};return{cmd:ii(me,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",ja(Fe),...he.map(ja)].join(" ")]}}var Jn=async(ce,me=pf)=>{let ge=await hf(ce,{timeoutMs:me});if(ge.code!==0)return null;return Fa(ge.stdout).trim()||Fa(ge.stderr).trim()||null};function hf(ce,me){let[ge,...he]=ce;if(!ge)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((Se)=>{try{let Fe=_n([ge,...he],process.env),He=lf(Fe.cmd,Fe.args,{stdio:["ignore","pipe","pipe"]}),Ge=!1,Dt="",At="";He.stdout.on("data",(jt)=>{Dt+=jt.toString()}),He.stderr.on("data",(jt)=>{At+=jt.toString()});let Tt=(jt)=>{if(Ge)return;Ge=!0,clearTimeout(Ft),Se(jt)},Ft=setTimeout(()=>{He.kill(),Tt({code:null,stdout:Dt,stderr:At})},me.timeoutMs);He.on("close",(jt)=>{Tt({code:jt,stdout:Dt,stderr:At})}),He.on("error",()=>{Tt({code:null,stdout:Dt,stderr:At})})}catch{Se({code:null,stdout:"",stderr:""})}})}function Kr(ce){if(!ce)return null;let me=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(ce);if(me)return me[1]??null;let ge=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(ce);if(ge)return ge[1]??null;return ce.split(`
23
+ `)[0]?.trim()||null}async function mr(ce=Jn){let[me,ge,he,Se,Fe,He]=await Promise.all([Promise.all(an.map(async(Ge)=>[Ge.id,Kr(await ce([...Ge.probeCommand]))])),ce(["codex","plugin","list"],30000),ce(["amp","plugins","list"],30000),ce(["node","--version"]),ce(["npm","--version"]),ce(["bun","--version"])]);return{version:Na,versions:Object.fromEntries(me),codexPluginListOutput:ge,ampPluginListOutput:he,nodeVersion:Kr(Se),npmVersion:Kr(Fe),bunVersion:Kr(He),platform:`${process.platform} ${process.arch}`}}function si(ce,me){if(me==="dev")return!1;let ge=ce.split(".").map(Number),he=me.split(".").map(Number),[Se=0,Fe=0,He=0]=ge,[Ge=0,Dt=0,At=0]=he;if(Se!==Ge)return Se>Ge;if(Fe!==Dt)return Fe>Dt;return He>At}async function Cn(){let ce=Xt(),me=new AbortController,ge=setTimeout(()=>me.abort(),3000);try{let he=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:me.signal});if(!he.ok)return{currentVersion:ce,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${he.status}`};let Se=await he.json(),Fe=si(Se.version,ce);return{currentVersion:ce,latestVersion:Se.version,updateAvailable:Fe}}catch(he){return{currentVersion:ce,latestVersion:null,updateAvailable:!1,error:he instanceof Error?he.message:"Network error"}}finally{clearTimeout(ge)}}import*as za from"node:readline";var Ga=(ce)=>`\x1B[${ce}B`,yf=(ce)=>`\x1B[${ce}A`;var Ha=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function vf(ce){return new Promise((me)=>setTimeout(me,ce))}function bf(ce,me,ge){if(!ge)return me(ce);if(ge.aborted)return Promise.resolve();return new Promise((he,Se)=>{let Fe=()=>ge.removeEventListener("abort",He),He=()=>{Fe(),he()};ge.addEventListener("abort",He,{once:!0}),me(ce).then(()=>{Fe(),he()},(Ge)=>{Fe(),Se(Ge)})})}function gr(ce,me){return ce&&ce>0?ce:me}function Jr(ce){return Math.max(0,Math.min(1,ce))}function Wn(ce){return Math.max(0,Math.min(255,Math.round(ce)))}function ai(ce){return ce<=0.0031308?12.92*ce:1.055*ce**0.4166666666666667-0.055}function Lf(ce,me,ge){let he=ge*Math.PI/180,Se=me*Math.cos(he),Fe=me*Math.sin(he),He=(ce+0.3963377774*Se+0.2158037573*Fe)**3,Ge=(ce-0.1055613458*Se-0.0638541728*Fe)**3,Dt=(ce-0.0894841775*Se-1.291485548*Fe)**3;return{blue:Wn(ai(Jr(-0.0041960863*He-0.7034186147*Ge+1.707614701*Dt))*255),green:Wn(ai(Jr(-1.2684380046*He+2.6097574011*Ge-0.3413193965*Dt))*255),red:Wn(ai(Jr(4.0767416621*He-3.3077115913*Ge+0.2309699292*Dt))*255)}}function li(ce,me){let ge=(me*ce*180/Math.PI%360+360)%360;return Lf(0.72,0.15,ge)}function Ba(ce,me=0.1){let ge=li(me,ce);return`\x1B[38;2;${ge.red};${ge.green};${ge.blue}m`}function wf(ce,me){return{blue:Wn(ce.blue+(255-ce.blue)*me),green:Wn(ce.green+(255-ce.green)*me),red:Wn(ce.red+(255-ce.red)*me)}}function qa(ce,me,ge){let he=Math.imul(ce+2654435769,2246822507)^Math.imul(me+3266489909,668265263)^Math.imul(ge+374761393,2654435761),Se=he^he>>>15,Fe=Math.imul(Se,739982445),He=Fe^Fe>>>12,Ge=Math.imul(He,695872825);return((Ge^Ge>>>15)>>>0)/4294967296}function kf(ce,me,ge){let he=Math.floor(qa(ce,me,ge)*Ha.length);return Ha[he]??"░"}function Ma(ce){let me=Jr(ce);return me*me*me*(me*(me*6-15)+10)}function xf(ce){if(ce.length===0)return"";let me=[],ge=!1,he="";for(let Se of ce){let Fe=`${Se.red};${Se.green};${Se.blue}`;if(Se.bold!==ge)me.push(Se.bold?"\x1B[1m":"\x1B[22m"),ge=Se.bold;if(Fe!==he)me.push(`\x1B[38;2;${Fe}m`),he=Fe;me.push(Se.character)}return`${me.join("")}\x1B[22m\x1B[39m`}function Cf(ce,me,ge,he,Se){return ce.map((Fe,He)=>({...li(ge,he+me+He/Se),bold:!1,character:Fe}))}function Sf(ce,me,ge,he,Se,Fe,He,Ge){let Dt=Math.max(1,he*0.75),At=Math.min(1,ge/Dt),Tt=Se*Ma(At),Ft=Math.max(0,(ge-Dt)/Math.max(1,he-Dt)),jt=(1-Ma(ge/he))*Ge*2,It=0.35*Math.max(0,1-Ft*2),$t=At>=1,Ot=Math.min(ce.length,Math.ceil(Tt+2+1));return ce.slice(0,Ot).map((Ut,Gt)=>{let Nt=li(Fe,He+me+Gt/Ge+jt),Vt=Gt+qa(me,Gt,7919)*2-1;if(Vt>Tt+2)return{...Nt,bold:!1,character:" "};let Mt=Tt-Vt,zt=0.8*Math.exp(-(Mt*Mt)/12.5),un=Math.min(0.9,zt+It),Ir=!$t&&Vt>Tt-4;return{...wf(Nt,un),bold:un>0.3,character:Ir?kf(me,Gt,ge):Ut}})}function Ua(ce){return`\x1B[?2026h${ce.map((me,ge)=>`\x1B8${ge>0?Ga(ge):""}${xf(me)}`).join("")}\x1B[?2026l`}async function ci(ce,me={}){if(!ce)return;let ge=me.output??process.stdout,he=me.sleep??vf,Se=gr(me.frequency,0.1),Fe=me.seed??0,He=gr(me.speed,40),Ge=gr(me.spread,3),Dt=gr(me.frameRate,60),At=Math.max(1,Math.floor(gr(me.duration,12))),Tt=ce.split(`
24
+ `).map((Ot)=>Array.from(Ot)),Ft=Math.max(...Tt.map((Ot)=>Ot.length)),jt=1000*At*Tt.filter((Ot)=>Ot.length>0).length/He,It=Ft>0?Math.max(1,Math.ceil(jt/(1000/Dt))):0,$t=It>0?jt/It:0;ge.write(`\x1B[?25l${Tt.length>1?`${`
25
+ `.repeat(Tt.length-1)}${yf(Tt.length-1)}`:""}\x1B7`);try{for(let Ot=1;Ot<=It;Ot+=1){if(me.signal?.aborted)break;ge.write(Ua(Tt.map((Ut,Gt)=>Sf(Ut,Gt,Ot,It,Ft,Se,Fe,Ge)))),await bf($t,he,me.signal)}}finally{if(ge.write(Ua(Tt.map((Ot,Ut)=>Cf(Ot,Ut,Se,Fe,Ge)))),ge.write("\x1B8"),Tt.length>1)ge.write(Ga(Tt.length-1));ge.write(`
26
+ \x1B[0m\x1B[?25h`)}}var Va=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
27
+ `);function Rf(ce){return Boolean(ce.isTTY)}async function hr(ce={}){let me=ce.output??process.stdout;if(!Rf(me))return;let ge=ce.input??process.stdin,he={duration:ce.duration,frequency:ce.frequency,output:me,seed:ce.seed??Math.random()*8192,sleep:ce.sleep,speed:ce.speed,spread:ce.spread};if(!ge.isTTY||typeof ge.setRawMode!=="function"){await ci(Va,he);return}let Se=new AbortController,Fe=ge.readableFlowing===!0,He=ge.isRaw===!0,Ge=!1,Dt=(At,Tt)=>{if(Tt.ctrl&&Tt.name==="c")Ge=!0;if(Ge||Tt.name==="return"||Tt.name==="enter")Se.abort()};za.emitKeypressEvents(ge),ge.on("keypress",Dt),ge.setRawMode(!0),ge.resume();try{await ci(Va,{...he,signal:Se.signal})}finally{if(ge.off("keypress",Dt),ge.setRawMode(He),!Fe)ge.pause()}if(!Ge)return;if(ce.onInterrupt){ce.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as Pf}from"node:crypto";import{existsSync as Ka}from"node:fs";import{dirname as Wr,join as Ja}from"node:path";var Df="`cc-safety-net rule sync` is deprecated: rulebooks are live files that need no synchronization. This run only migrates the lock and cache an earlier version left behind.",Af="cache",Ef="rulebooks";function Wa(ce={}){let me=C(ce),ge=o(me.filesystemScope,Za(me.configDir)),he=n(me.lockTarget);if(console.log(Df),he===null&&!Ka(ge.path))return console.log(`No v2 lock or cache leftovers found in ${Wr(me.configDir)}; nothing to migrate.`),0;let Se=Of(he),Fe=p(me.configTarget);if(!Fe.config&&(n(me.configTarget)!==null||Se.size>0))return console.error(`Cannot migrate: the rules config in ${Wr(me.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let He=Fe.config?.rules??[];for(let Ge of He.flatMap((Dt)=>_f(Dt,Se,me,ge,ce.global===!0)))console.log(Ge);return Y(me.lockTarget),vt(ge),console.log(`Removed the v2 lock and cache under ${Wr(me.configDir)}.`),0}function Ya(ce){return[...new Set([{cwd:ce},{cwd:ce,global:!0}].flatMap((me)=>{let ge=C(me);return[ge.lockPath,Za(ge.configDir)]}))].filter((me)=>Ka(me))}function _f(ce,me,ge,he,Se){if(!b(ce))return[];let Fe=G(ce).name,He=o(ge.filesystemScope,W(ge.configDir,Fe)),Ge=n(He);if(Ge!==null&&Tf(Ge,Fe))return[];let Dt=me.get(ce),At=Dt?If(Dt,Fe,he.path,ge.filesystemScope):null;if(At===null)return[`Could not migrate ${ce} from the v2 cache. Run \`cc-safety-net rule update ${ce}${Se?" --global":""}\` to vendor it.`];if(v(He,At),Ge!==null)return[`Restored ${ce} from the v2 cache over an invalid file.`];return[`Vendored ${ce} from the v2 cache.`]}function Tf(ce,me){let ge=Re(ce);return!("problem"in ge)&&ge.rulebook.name===me}function If(ce,me,ge,he){let Se=Ja(ge,Ef,`${$f(ce)}--${ce.digest.replace("sha256:","").slice(0,12)}`,we),Fe=n(o(he,Se));if(Fe===null||Nf(Fe)!==ce.digest)return null;let He=Re(Fe);if("problem"in He||He.rulebook.name!==me)return null;return Fe}function Za(ce){return Ja(Wr(ce),Af)}function $f(ce){return([ce.owner,ce.repo,ce.display_ref,ce.name].every((he)=>typeof he==="string"&&he!=="")?`${ce.owner}/${ce.repo}#${ce.display_ref}/${ce.name}`:ce.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function Of(ce){let me=ce===null?null:jf(ce),ge=Xa(me)&&Array.isArray(me.rulebooks)?me.rulebooks:[];return new Map(ge.filter(Ff).map((he)=>[he.spec,he]))}function Ff(ce){return Xa(ce)&&typeof ce.spec==="string"&&typeof ce.digest==="string"}function Xa(ce){return!!ce&&typeof ce==="object"}function jf(ce){try{return JSON.parse(ce)}catch{return null}}function Nf(ce){return`sha256:${Pf("sha256").update(ce).digest("hex")}`}var Qa="\r\x1B[2K",Hf="\x1B[?25l",Mf="\x1B[39m",Uf="\x1B[?25h",Gf=100,Bf=0.55,qf=80,el=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function Vf(ce){return new Promise((me)=>setTimeout(me,ce))}async function Yr(ce,me={}){let ge=me.output??process.stdout;if(!ge.isTTY)return ce;let he=me.sleep??Vf,Se=!1,Fe=ce.then((Ge)=>(Se=!0,Ge),(Ge)=>{throw Se=!0,Ge});if(await Promise.race([Fe.then(()=>!0),he(Gf).then(()=>!1)]))return Fe;ge.write(Hf);try{for(let Ge=0;!Se;Ge+=1)ge.write(`${Qa}${Ba(Ge*Bf)}${el[Ge%el.length]}${Mf} ${me.loadingMessage??"Loading…"}`),await Promise.race([Fe,he(qf)]);return await Fe}finally{ge.write(`${Qa}${Uf}`)}}async function yr(ce,me,ge,he={}){let Se=me();if(ce)await ge();if(ce&&Se.ready)await Yr(Se.ready,he);return Se.finish()}import{homedir as Lg}from"node:os";import{stripVTControlCharacters as zf}from"node:util";var Zr="amp plugins list",Kf=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function tl(ce){if(!ce.ampPluginListOutput)return{platform:"amp",status:"n/a"};let me=zf(ce.ampPluginListOutput).split(`
28
+ `).map((ge)=>Kf.exec(ge)?.[1]).find((ge)=>ge!==void 0);if(!me)return{platform:"amp",status:"n/a"};if(me!=="active")return{platform:"amp",status:"disabled",method:Zr,configPath:Zr,errors:[`Amp personal plugin cc-safety-net is ${me}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:Zr,configPath:Zr}}import{existsSync as Jf,readFileSync as Wf}from"node:fs";var Yf=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Zf(ce){if(!ce||typeof ce!=="object"||Array.isArray(ce))return[];return Object.values(ce).flatMap((me)=>{if(!me||typeof me!=="object"||Array.isArray(me))return[];let ge=me,he=ge.PreToolUse;if(!Array.isArray(he))return[];return he.flatMap((Se)=>{if(!Se||typeof Se!=="object"||Array.isArray(Se))return[];let Fe=Se.hooks;if(!Array.isArray(Fe))return[];return Fe.flatMap((He)=>{if(!He||typeof He!=="object"||Array.isArray(He))return[];let Ge=He.command;if(typeof Ge!=="string"||!Yf.test(Ge))return[];return[{command:Ge,enabled:ge.enabled!==!1}]})})})}function nl(ce){let me=pr(ce.homeDir);if(!Jf(me))return{platform:"antigravity-cli",status:"n/a",configPath:me};let ge;try{ge=Zf(JSON.parse(Wf(me,"utf-8")))}catch(he){return{platform:"antigravity-cli",status:"n/a",configPath:me,errors:[`Failed to parse Antigravity hooks config ${me}: ${he instanceof Error?he.message:String(he)}`]}}if(ge.some((he)=>he.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:me};if(ge.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:me};return{platform:"antigravity-cli",status:"n/a",configPath:me}}import{join as rl}from"node:path";import{existsSync as Xf,lstatSync as Qf,readFileSync as em}from"node:fs";function mn(ce,me=(ge)=>ge){if(!Xf(ce))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(me(em(ce,"utf-8")))}}catch{return{kind:"unreadable"}}}function Yt(ce){try{return Qf(ce)}catch{return}}function Xr(ce,me){let ge=Yt(me);if(!ge)return{platform:ce,status:"n/a",configPath:me};if(!ge.isSymbolicLink()&&ge.isDirectory())return;return{platform:ce,status:"n/a",configPath:me,errors:[`${me} is a symlink or not a directory; move or remove it before installing`]}}function Bt(ce,me){return typeof ce==="object"&&ce!==null?ce[me]:void 0}var di="cc-safety-net@cc-marketplace";function ol(ce){return rl(ce,".claude","plugins","installed_plugins.json")}function il(ce,me){let ge=Bt(Bt(ce,"plugins"),me);return Array.isArray(ge)&&ge.length>0}function Qr(ce,me){let ge=mn(ol(ce));return ge.kind==="ok"&&il(ge.value,me)}function ui(ce){let me=ol(ce),ge=mn(me);if(ge.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(ge.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!il(ge.value,di))return{platform:"claude-code",status:"n/a"};let he=rl(ce,".claude","settings.json"),Se=mn(he);if(Se.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(Se.kind==="ok"&&Bt(Bt(Se.value,"enabledPlugins"),di)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:he,errors:[`${di} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:me}}function sl(ce){return ui(ce.homeDir)}function al(ce){if(!ce.codexPluginListOutput)return{platform:"codex",status:"n/a"};let me=ce.codexPluginListOutput.split(`
29
+ `).find((ge)=>ge.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!me)return{platform:"codex",status:"n/a"};if(!me.includes("installed,"))return{platform:"codex",status:"n/a"};if(!me.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list"}}import{existsSync as ro,readdirSync as tm,readFileSync as nm}from"node:fs";import{join as rn}from"node:path";var gn="cc-safety-net@cc-marketplace",eo=["cc-marketplace","cc-safety-net"],ll=["_direct","copilot-safety-net"],cl=["cc-marketplace","safety-net"],dl="safety-net@cc-marketplace";function to(ce,me){let ge=me.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${ge}([^a-z0-9-]|$)`,"m").test(ce??"")}function ul(ce){return to(ce,"cc-safety-net@cc-marketplace")}function pl(ce){return to(ce,"cc-marketplace")}function fl(ce){return to(ce,"copilot-safety-net")}function ml(ce){return to(ce,"safety-net@cc-marketplace")}function sn(ce){let me="",ge=0,he=!1,Se=!1,Fe=-1;while(ge<ce.length){let He=ce[ge],Ge=ce[ge+1];if(Se){me+=He,Se=!1,ge++;continue}if(He==='"'&&!he){he=!0,Fe=-1,me+=He,ge++;continue}if(He==='"'&&he){he=!1,me+=He,ge++;continue}if(He==="\\"&&he){Se=!0,me+=He,ge++;continue}if(he){me+=He,ge++;continue}if(He==="/"&&Ge==="/"){while(ge<ce.length&&ce[ge]!==`
30
+ `)ge++;continue}if(He==="/"&&Ge==="*"){ge+=2;while(ge<ce.length-1){if(ce[ge]==="*"&&ce[ge+1]==="/"){ge+=2;break}ge++}continue}if(He===","){Fe=me.length,me+=He,ge++;continue}if(He==="}"||He==="]"){if(Fe!==-1){let Dt=me.slice(Fe+1);if(/^\s*$/.test(Dt))me=me.slice(0,Fe)+Dt}Fe=-1,me+=He,ge++;continue}if(!/\s/.test(He))Fe=-1;me+=He,ge++}return me}function pi(ce){if(!ce?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(ce)}function hl(ce,me){if(!ce)return null;let ge=ce.match(/(\d+)\.(\d+)\.(\d+)/);if(!ge)return null;let he=[Number(ge[1]),Number(ge[2]),Number(ge[3])];for(let Se=0;Se<me.length;Se++){let Fe=he[Se]??0,He=me[Se]??0;if(Fe!==He)return Fe>He}return!0}function rm(ce){return hl(ce,[0,0,422])}function om(ce){return hl(ce,[1,0,8])}function vr(ce){return process.env.COPILOT_HOME||rn(ce,".copilot")}function fi(ce){return(ce.hooks?.preToolUse??[]).some((ge)=>{if(ge.type!=="command")return!1;return pi(ge.command)||pi(ge.bash)||pi(ge.powershell)})}function no(ce){return ce===void 0||typeof ce==="string"}function im(ce){if(!ce||typeof ce!=="object"||Array.isArray(ce))return!1;let me=ce;if(me.disableAllHooks!==void 0&&typeof me.disableAllHooks!=="boolean")return!1;if(me.hooks===void 0)return!0;if(!me.hooks||typeof me.hooks!=="object"||Array.isArray(me.hooks))return!1;let ge=me.hooks.preToolUse;if(ge===void 0)return!0;return Array.isArray(ge)&&ge.every((he)=>he!==null&&typeof he==="object"&&!Array.isArray(he)&&no(he.type)&&no(he.command)&&no(he.bash)&&no(he.powershell))}function mi(ce,me){try{let ge=JSON.parse(sn(nm(ce,"utf-8")));if(!im(ge)){me?.push(`Invalid hook config ${ce}: hooks.preToolUse must be an array of hook objects`);return}return ge}catch(ge){me?.push(`Failed to parse ${ce}: ${ge instanceof Error?ge.message:String(ge)}`);return}}function yl(ce,me){try{return tm(ce).filter((ge)=>ge.endsWith(".json")).sort((ge,he)=>ge.localeCompare(he))}catch(ge){return me?.push(`Failed to read ${ce}: ${ge instanceof Error?ge.message:String(ge)}`),[]}}function sm(ce,me){if(!ro(ce))return[];let ge=[];for(let he of yl(ce,me)){let Se=rn(ce,he),Fe=mi(Se,me);if(Fe&&fi(Fe))ge.push(Se)}return ge}function Yn(ce,me){if(!ro(ce))return;let ge=mi(ce,me);if(!ge)return;return{path:ce,config:ge}}function gl(ce,me,ge,he){if(me){ce.push(`GitHub Copilot CLI ${me} does not support ${ge}; requires ${he}+`);return}ce.push(`GitHub Copilot CLI version unavailable; skipping ${ge} because it requires ${he}+`)}function am(ce){for(let me of ce){if(me?.config.disableAllHooks===!0)return me.path;if(me?.config.disableAllHooks===!1)return}return}function lm(ce,me,ge,he){let Se=vr(ce),Fe=rn(me,".github","hooks"),He=rn(Se,"hooks"),Ge=rn(me,".github","copilot"),Dt=rn(me,".claude"),At=om(ge),Tt=At===!0?he:void 0,Ft=[Yn(rn(Ge,"settings.local.json"),Tt),Yn(rn(Ge,"settings.json"),Tt),Yn(rn(Dt,"settings.local.json"),Tt),Yn(rn(Dt,"settings.json"),Tt)],jt=[Yn(rn(Se,"settings.json"),Tt),Yn(rn(Se,"config.json"),Tt)];if(At!==!1){let Mt=am([...Ft,...jt]);if(Mt){if(At===null)he.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${Mt} as active`);return{activeConfigPaths:[],disabledBy:Mt}}}let It=sm(Fe,he),$t=rm(ge),Ot=$t===!0?he:void 0,Ut=ro(He)?yl(He,Ot):[],Gt=[];for(let Mt of Ut){let zt=rn(He,Mt),un=mi(zt,Ot);if(un&&fi(un))Gt.push(zt)}if($t!==!0&&Gt.length>0)gl(he,ge,`user hook files in ${He}`,"0.0.422"),Gt.length=0;let Nt=[];for(let Mt of[...Ft,...jt]){if(!Mt)continue;if(!fi(Mt.config))continue;if(At===!0){Nt.push(Mt);continue}gl(he,ge,"inline hook definitions in Copilot config files","1.0.8");break}let Vt=(Mt)=>Mt.filter((zt)=>!!zt&&Nt.includes(zt)).map((zt)=>zt.path);return{activeConfigPaths:[...Vt(Ft),...It,...Vt(jt),...Gt]}}function vl(ce){let me=[],ge=lm(ce.homeDir,ce.cwd,ce.copilotCliVersion,me);if(ge.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:ge.disabledBy,configPaths:[ge.disabledBy],errors:me.length>0?me:void 0};let he=vr(ce.homeDir),Se=rn(he,"installed-plugins",...eo),Fe=ro(Se),He=rn(he,"settings.json"),Ge=mn(He,sn);if(Fe&&Ge.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(Fe&&Ge.kind==="ok"&&Bt(Bt(Ge.value,"enabledPlugins"),gn)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:He,errors:[`${gn} is installed but not enabled in Copilot CLI`]};if(Fe||ge.activeConfigPaths.length>0){let Dt=Fe,At=ge.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:Dt?"plugin config":"hook config",configPath:At??(Dt?Se:void 0),configPaths:ge.activeConfigPaths.length>0?ge.activeConfigPaths:void 0,errors:me.length>0?me:void 0}}return{platform:"copilot-cli",status:"n/a",errors:me.length>0?me:void 0}}import{existsSync as vm,readFileSync as bm}from"node:fs";import{existsSync as bl,mkdirSync as um,readFileSync as pm}from"node:fs";import{dirname as fm,join as mm}from"node:path";import{renameSync as cm,writeFileSync as dm}from"node:fs";function Qt(ce,me){let ge=`${ce}.${process.pid}.tmp`;dm(ge,me),cm(ge,ce)}var br="npx -y cc-safety-net hook --cursor",Ll=30;function io(ce){return mm(ce,".cursor","hooks.json")}function Tn(ce){return typeof ce==="object"&&ce!==null&&!Array.isArray(ce)}function gi(){return{command:br,timeout:Ll,failClosed:!0}}function oo(ce){return Tn(ce)&&ce.command===br}function gm(ce){return Object.keys(ce).length===3&&ce.command===br&&ce.timeout===Ll&&ce.failClosed===!0}function hm(ce){try{return JSON.parse(pm(ce,"utf-8"))}catch(me){if(me instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${ce}: ${me.message}`);throw me}}function wl(ce){let me=hm(ce);if(!Tn(me))throw Error(`Cursor hooks config ${ce} must be a JSON object`);if(me.version!==1)throw Error(`Cursor hooks config ${ce} must set "version": 1`);if(me.hooks!==void 0&&!Tn(me.hooks))throw Error(`Cursor hooks config ${ce} "hooks" must be an object`);let ge=Tn(me.hooks)?me.hooks.preToolUse:void 0;if(ge!==void 0&&!Array.isArray(ge))throw Error(`Cursor hooks config ${ce} "hooks.preToolUse" must be an array`);return me}function kl(ce){let me=Tn(ce.hooks)?ce.hooks.preToolUse:void 0;return Array.isArray(me)?me:[]}function ym(ce){if(!ce.some(oo))return[...ce,gi()];return ce.reduce((me,ge)=>{if(!oo(ge))return me.result.push(ge),me;if(!me.inserted)me.result.push(gi()),me.inserted=!0;return me},{result:[],inserted:!1}).result}function xl(ce,me,ge){let he=Tn(me.hooks)?me.hooks:{},Se={...me,hooks:{...he,preToolUse:ge}};Qt(ce,`${JSON.stringify(Se,null,2)}
31
+ `)}function Cl(ce){let me=io(ce);if(!bl(me))return um(fm(me),{recursive:!0}),Qt(me,`${JSON.stringify({version:1,hooks:{preToolUse:[gi()]}},null,2)}
32
+ `),{path:me,alreadyInstalled:!1};let ge=wl(me),he=kl(ge),Se=he.filter(oo);if(Tn(ge.hooks)&&Array.isArray(ge.hooks.preToolUse)&&Se.length===1&&Se[0]!==void 0&&gm(Se[0]))return{path:me,alreadyInstalled:!0};return xl(me,ge,ym(he)),{path:me,alreadyInstalled:!1}}function Sl(ce){let me=io(ce);if(!bl(me))return{path:me,alreadyInstalled:!1};let ge=wl(me),he=kl(ge),Se=he.filter((Fe)=>!oo(Fe));if(Se.length===he.length)return{path:me,alreadyInstalled:!1};return xl(me,ge,Se),{path:me,alreadyInstalled:!0}}function Lm(ce){if(!ce||typeof ce!=="object"||Array.isArray(ce))return[];let me=ce.hooks;if(!me||typeof me!=="object"||Array.isArray(me))return[];let ge=me.preToolUse;if(!Array.isArray(ge))return[];return ge.filter((he)=>!!he&&typeof he==="object"&&!Array.isArray(he)&&he.command===br)}function wm(ce){let me=[];if(ce.length>1)me.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let ge=ce[0];if(ge&&ge.failClosed!==!0)me.push('Managed hook is missing "failClosed": true; reinstall to repair');if(ge&&ge.timeout!==30)me.push('Managed hook "timeout" is not 30; reinstall to repair');return me}function Rl(ce){let me=io(ce.homeDir);if(!vm(me))return{platform:"cursor",status:"n/a",configPath:me};let ge;try{ge=JSON.parse(bm(me,"utf-8"))}catch(Fe){return{platform:"cursor",status:"n/a",configPath:me,errors:[`Failed to parse Cursor hooks config ${me}: ${Fe instanceof Error?Fe.message:String(Fe)}`]}}let he=Lm(ge);if(he.length===0)return{platform:"cursor",status:"n/a",configPath:me};let Se=wm(he);return{platform:"cursor",status:"configured",method:"hook config",configPath:me,errors:Se.length>0?Se:void 0}}import{existsSync as km}from"node:fs";import{join as hi}from"node:path";var yi="gemini-safety-net";function vi(ce){let me=hi(ce,".gemini","extensions"),ge=hi(me,yi);if(!km(ge))return{platform:"gemini-cli",status:"n/a"};let he=hi(me,"extension-enablement.json"),Se=mn(he);if(Se.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let Fe=Se.kind==="ok"?Bt(Bt(Se.value,yi),"overrides"):void 0;if(Array.isArray(Fe)&&Fe.some((Ge)=>typeof Ge==="string"&&Ge.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:he,errors:[`${yi} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:ge}}function Pl(ce){return vi(ce.homeDir)}import{existsSync as Rm,readFileSync as Pm}from"node:fs";import{existsSync as Al,mkdirSync as xm,readFileSync as El,rmSync as Cm}from"node:fs";import{dirname as Sm,join as Dl}from"node:path";var Lr="npx -y cc-safety-net hook --grok-build",lo=30;function co(ce){return Dl(process.env.GROK_HOME??Dl(ce,".grok"),"hooks","cc-safety-net.json")}function In(ce){return typeof ce==="object"&&ce!==null&&!Array.isArray(ce)}function so(){return{hooks:[{type:"command",command:Lr,timeout:lo}]}}function _l(ce){return In(ce)&&ce.command===Lr}function Tl(ce){return ce.flatMap((me)=>{if(!In(me)||!Array.isArray(me.hooks))return[me];let ge=me.hooks.filter((he)=>!_l(he));if(ge.length===me.hooks.length)return[me];return ge.length===0?[]:[{...me,hooks:ge}]})}function Il(ce){try{let me=JSON.parse(ce);return In(me)?me:null}catch{return null}}function $l(ce){let me=In(ce.hooks)?ce.hooks.PreToolUse:void 0;return Array.isArray(me)?me:[]}function ao(ce,me,ge){let he=In(me.hooks)?me.hooks:{};Qt(ce,`${JSON.stringify({...me,hooks:{...he,PreToolUse:ge}},null,2)}
33
+ `)}function Ol(ce){let me=co(ce);if(!Al(me))return xm(Sm(me),{recursive:!0}),ao(me,{},[so()]),{path:me,alreadyInstalled:!1};let ge=Il(El(me,"utf-8"));if(!ge)return ao(me,{},[so()]),{path:me,alreadyInstalled:!1};let he=$l(ge),Se=he.filter((Fe)=>In(Fe)&&Array.isArray(Fe.hooks)&&Fe.hooks.some(_l));if(Se.length===1&&JSON.stringify(Se[0])===JSON.stringify(so()))return{path:me,alreadyInstalled:!0};return ao(me,ge,[...Tl(he),so()]),{path:me,alreadyInstalled:!1}}function Fl(ce){let me=co(ce);if(!Al(me))return{path:me,alreadyInstalled:!1};let ge=Il(El(me,"utf-8"));if(!ge)return{path:me,alreadyInstalled:!1};let he=$l(ge),Se=Tl(he);if(JSON.stringify(Se)===JSON.stringify(he))return{path:me,alreadyInstalled:!1};let Fe=In(ge.hooks)?ge.hooks:{};if(Se.length===0&&Object.keys(ge).length===1&&Object.keys(Fe).length===1)return Cm(me),{path:me,alreadyInstalled:!0};return ao(me,ge,Se),{path:me,alreadyInstalled:!0}}function wr(ce){return!!ce&&typeof ce==="object"&&!Array.isArray(ce)}function Dm(ce){if(!wr(ce)||!wr(ce.hooks))return[];let me=ce.hooks.PreToolUse;if(!Array.isArray(me))return[];return me.filter((ge)=>wr(ge)&&Array.isArray(ge.hooks)&&ge.hooks.some((he)=>wr(he)&&he.command===Lr))}function Am(ce){let ge=(Array.isArray(ce.hooks)?ce.hooks.filter(wr):[]).find((he)=>he.command===Lr);return[...ce.matcher===void 0||ce.matcher===""||ce.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...ge?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...ge?.timeout===lo?[]:[`Managed hook "timeout" is not ${lo}; reinstall to repair`]]}function jl(ce){let me=co(ce.homeDir);if(!Rm(me))return{platform:"grok-build",status:"n/a",configPath:me};let ge;try{ge=JSON.parse(Pm(me,"utf-8"))}catch(Fe){return{platform:"grok-build",status:"n/a",configPath:me,errors:[`Failed to parse Grok Build hooks config ${me}: ${Fe instanceof Error?Fe.message:String(Fe)}`]}}let he=Dm(ge)[0];if(!he)return{platform:"grok-build",status:"n/a",configPath:me};let Se=Am(he);return{platform:"grok-build",status:"configured",method:"hook config",configPath:me,errors:Se.length>0?Se:void 0}}import{readFileSync as zl}from"node:fs";import{join as Kl}from"node:path";var ln="cc-safety-net",Nl="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent";function Hl(ce){return`# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent
34
+ # version: ${ce}
35
+ `}function Em(ce){return`${Hl(ce)}name: cc-safety-net
36
+ version: "${ce}"
37
37
  description: "Block destructive commands and secret-file access before Hermes runs a tool."
38
38
  author: "cc-safety-net"
39
39
  provides_hooks:
40
40
  - pre_tool_call
41
- `}function Dm(e){return`${El(e)}"""CC Safety Net guard for Hermes Agent.
41
+ `}function _m(ce){return`${Hl(ce)}"""CC Safety Net guard for Hermes Agent.
42
42
 
43
43
  Registers pre_tool_call and forwards the tool call to the packaged CC Safety Net
44
44
  adapter (cc-safety-net hook --hermes-agent) over JSON stdin. The adapter prints nothing
@@ -120,6 +120,10 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
120
120
  )
121
121
 
122
122
  try:
123
+ if os.name == "nt":
124
+ launch_options = {}
125
+ else:
126
+ launch_options = {"start_new_session": True}
123
127
  process = subprocess.Popen(
124
128
  [executable] + ANALYZER[1:],
125
129
  stdin=subprocess.PIPE,
@@ -136,8 +140,9 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
136
140
  # still the real Hermes working directory, which the analysis needs.
137
141
  cwd=os.path.expanduser("~"),
138
142
  # Own process group so the timeout below can kill the whole tree: npx's descendants
139
- # outlive a kill aimed at npx alone and keep holding the pipes captured here.
140
- start_new_session=True,
143
+ # outlive a kill aimed at npx alone and keep holding the pipes captured here. Windows
144
+ # uses taskkill's process-tree traversal instead because sessions are POSIX-only.
145
+ **launch_options,
141
146
  )
142
147
  except OSError as error:
143
148
  return _block("analysis could not start (%s)." % error)
@@ -146,12 +151,31 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
146
151
  stdout, _ = process.communicate(payload, timeout=TIMEOUT_SECONDS)
147
152
  except subprocess.TimeoutExpired:
148
153
  try:
149
- os.killpg(process.pid, signal.SIGKILL)
150
- except OSError:
154
+ if os.name == "nt":
155
+ system_root = os.environ.get("SystemRoot")
156
+ if not system_root:
157
+ raise OSError("SystemRoot is unavailable")
158
+ subprocess.run(
159
+ [
160
+ os.path.join(system_root, "System32", "taskkill.exe"),
161
+ "/PID",
162
+ str(process.pid),
163
+ "/T",
164
+ "/F",
165
+ ],
166
+ stdin=subprocess.DEVNULL,
167
+ stdout=subprocess.DEVNULL,
168
+ stderr=subprocess.DEVNULL,
169
+ timeout=1,
170
+ check=False,
171
+ )
172
+ else:
173
+ os.killpg(process.pid, signal.SIGKILL)
174
+ except (OSError, subprocess.SubprocessError):
151
175
  pass
152
176
  try:
153
- process.communicate(timeout=TIMEOUT_SECONDS)
154
- except subprocess.TimeoutExpired:
177
+ process.communicate(timeout=1)
178
+ except (OSError, subprocess.SubprocessError):
155
179
  pass
156
180
  return _block("analysis timed out after %ss." % TIMEOUT_SECONDS)
157
181
 
@@ -176,86 +200,86 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
176
200
 
177
201
  def register(ctx):
178
202
  ctx.register_hook("pre_tool_call", _pre_tool_call)
179
- `}function Xt(e){return[{name:"__init__.py",content:Dm(e)},{name:"plugin.yaml",content:Pm(e)}]}import{mkdirSync as Am,readdirSync as Em,readFileSync as _m,rmSync as Lo}from"node:fs";import{join as We}from"node:path";var Tm="__pycache__";function wo(e){let t=process.env.HERMES_HOME?.trim();return t?t:We(e,".hermes")}function ko(e){return We(wo(e),"plugins",Q)}function xo(e){return e.startsWith(Al)}function Co(e,t){let n=ko(e),r=_(n);if(r&&(r.isSymbolicLink()||!r.isDirectory()))throw Error(`Refusing to ${t} ${n}: not a regular directory. Move or remove it and rerun ${t==="install"?"install":"uninstall"} --hermes-agent.`);return n}function _l(e,t){let n=_(e);if(!n)return;if(n.isSymbolicLink()||!n.isFile())throw Error(`Refusing to ${t} ${e}: not a regular file. Move or remove it.`);let r=_m(e,"utf-8");if(!xo(r))throw Error(`Refusing to ${t} unmanaged file at ${e}. Move or remove it.`);return r}function Tl(e){let t=Co(e,"install"),n=Xt(I());if(n.map((o)=>_l(We(t,o.name),"overwrite")).every((o,i)=>o===n[i]?.content))return{path:t,alreadyInstalled:!0};return Am(t,{recursive:!0}),n.forEach((o)=>{O(We(t,o.name),o.content)}),{path:t,alreadyInstalled:!1}}function So(e){let t=Co(e,"remove");if(!_(t))return[];return Xt(I()).filter((n)=>_l(We(t,n.name),"remove")!==void 0)}function Il(e){let t=Co(e,"remove");if(!_(t))return{path:t,alreadyInstalled:!1};let n=So(e);if(n.forEach((r)=>{Lo(We(t,r.name))}),Lo(We(t,Tm),{recursive:!0,force:!0}),Em(t).length===0)Lo(t,{recursive:!0});return{path:t,alreadyInstalled:n.length>0}}var zn="hermes-agent",$l=/^([^\s#][^:]*):/,Im=/^\s+([A-Za-z_][\w-]*):/,Ol=/^\s+-\s*(.*)$/;function $m(e){return e.trim().replace(/^(["'])(.*)\1$/,"$2")}function Om(e){let t=e.split(/\r?\n/),n=t.findIndex((i)=>$l.exec(i)?.[1]?.trim()==="plugins");if(n===-1)return[];let r=t.slice(n+1),o=r.findIndex((i)=>$l.test(i));return o===-1?r:r.slice(0,o)}function Fl(e,t){let n=Om(e),r=n.findIndex((s)=>Im.exec(s)?.[1]===t);if(r===-1)return[];let o=n.slice(r+1),i=o.findIndex((s)=>!Ol.test(s));return(i===-1?o:o.slice(0,i)).map((s)=>$m(Ol.exec(s)?.[1]??""))}function Fm(e){try{return jl(Nl(wo(e),"config.yaml"),"utf-8")}catch{return}}function Ro(e){let t=Fm(e)??"";return Fl(t,"enabled").includes(Q)&&!Fl(t,"disabled").includes(Q)}function Hl(e){return/^# version:\s*(.+)$/m.exec(e)?.[1]?.trim()}function jm(e,t){let n=_(e);if(!n)return{error:`${t.name} is missing from ${e}; run install --hermes-agent`};if(n.isSymbolicLink()||!n.isFile())return{error:`${e} is a symlink or not a regular file; move or remove it`};try{let r=jl(e,"utf-8");if(!xo(r))return{error:`Unmanaged ${t.name} occupies ${e}; move or remove it`};if(Hl(r)===I()&&r!==t.content)return{error:`Modified ${t.name} occupies ${e}; run install --hermes-agent to restore it`};return{content:r}}catch(r){return{error:`Failed to read ${e}: ${r instanceof Error?r.message:String(r)}`}}}function Ml(e){let t=ko(e.homeDir),n=$n(zn,t);if(n)return n;let r=Xt(I()).map((a)=>jm(Nl(t,a.name),a)),o=r.flatMap((a)=>("error"in a)?[a.error]:[]);if(o.length>0)return{platform:zn,status:"n/a",configPath:t,errors:o};let i=r.some((a)=>("content"in a)&&Hl(a.content)!==I()),s=i?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!Ro(e.homeDir))return{platform:zn,status:"disabled",method:"plugin directory",configPath:t,errors:[`${Q} is not enabled in Hermes; run \`hermes plugins enable ${Q}\``,...s]};return{platform:zn,status:"configured",method:"plugin directory",configPath:t,errors:i?s:void 0}}import{existsSync as Nm,readFileSync as Hm}from"node:fs";import{join as Ul}from"node:path";var Mm=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function Um(e){return Ul(process.env.KIMI_CODE_HOME||Ul(e,".kimi-code"),"config.toml")}function Qt(e){let t=Um(e.homeDir);if(!Nm(t))return{platform:"kimi-code",status:"n/a",configPath:t};try{if(!Mm.test(Hm(t,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:t}}catch(n){return{platform:"kimi-code",status:"n/a",configPath:t,errors:[`Failed to read ${t}: ${n instanceof Error?n.message:String(n)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:t}}import{readFileSync as Zl}from"node:fs";import{join as tn}from"node:path";var A="cc-safety-net",ee="index.js",gt="openclaw.plugin.json",ht="package.json";var Kn="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as qm,lstatSync as Vm,readdirSync as zm,readFileSync as Km}from"node:fs";import{dirname as ql,join as Ie}from"node:path";import{fileURLToPath as Jm}from"node:url";import{spawn as Gm}from"node:child_process";function Bm(e){return e.join(" ")}function Po(e,t,n){return[`Failed to run ${Bm(e)}${t===null?"":` (exit ${t})`}.`,n.trim()].filter(Boolean).join(`
180
- `)}function Do(e){let t={stdout:"",stderr:""};return e.stdout.setEncoding("utf-8"),e.stderr.setEncoding("utf-8"),e.stdout.on("data",(n)=>{t.stdout+=n}),e.stderr.on("data",(n)=>{t.stderr+=n}),t}function ue(e,t){return new Promise((n,r)=>{let o=ze([...e],process.env),i=Gm(o.cmd,o.args,{stdio:["ignore","pipe","pipe"]}),s=Do(i),a=()=>[s.stdout,s.stderr].filter(Boolean).join(`
181
- `),l=t?.timeoutMs??120000,c=setTimeout(()=>{i.kill(),r(Error(Po(e,null,`Timed out after ${l}ms.
182
- ${a()}`.trim())))},l);i.on("error",(d)=>{clearTimeout(c),r(Error(Po(e,null,`${d.message}
183
- ${a()}`.trim())))}),i.on("close",(d)=>{if(clearTimeout(c),d!==0){r(Error(Po(e,d,a())));return}n(t?.stdoutOnly?s.stdout:a())})})}async function Ao(e){for(let t of e)await ue(t)}async function Gl(e){for(let t of e)try{await ue(t)}catch(n){console.warn(n instanceof Error?n.message:String(n))}}var Bl=Ie("openclaw",A),Wm=[ee,gt,ht];function Eo(e,t){if(e==="~")return t;if(e.startsWith("~/")||e.startsWith("~\\"))return Ie(t,e.slice(2));return e}function Vl(e){let t=process.env.OPENCLAW_STATE_DIR?.trim();if(t)return Eo(t,e);let n=process.env.OPENCLAW_CONFIG_PATH?.trim();return n?ql(Eo(n,e)):Ie(e,".openclaw")}function zl(e){let t=process.env.OPENCLAW_CONFIG_PATH?.trim();return t?Eo(t,e):Ie(Vl(e),"openclaw.json")}function _o(e){return Ie(Vl(e),"extensions",A)}function Ym(e){let t=zm(e);if(t.length===0)return!0;if(t.some((o)=>!Wm.includes(o)))return!1;let n=Ie(e,ee),r=_(n);return r!==void 0&&!r.isSymbolicLink()&&r.isFile()&&Km(n,"utf-8").startsWith(Kn)}function To(e){let t=_o(e),n=_(t);if(!n)return;if(!n.isSymbolicLink()&&n.isDirectory()&&Ym(t))return;throw Error(`Refusing to modify ${t}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function Kl(){let e=ql(Jm(import.meta.url));return[Ie(e,"..",Bl),Ie(e,"..","..","..","dist",Bl)]}function Io(e=Kl()){return e.find((t)=>qm(t)&&Vm(t).isDirectory())}function Zm(e=Kl()){let t=Io(e);if(!t)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return t}function Jl(e=Zm()){return[["openclaw","plugins","install",e,"--force"],["openclaw","plugins","enable",A]]}function Xm(e){let t=(()=>{try{return JSON.parse(e)}catch{return}})(),n=k(k(t,"plugin"),"status");return typeof n==="string"?n:void 0}async function Wl(){let e=Xm(await ue(["openclaw","plugins","inspect",A,"--runtime","--json"],{stdoutOnly:!0}));if(e==="loaded")return;throw Error(`${e===void 0?`The ${A} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${A} plugin with status "${e}".`} Run \`openclaw plugins inspect ${A} --runtime\` for details.`)}var Jn="openclaw",en=`run \`openclaw plugins enable ${A}\``;function yt(e,t){let n=tn(e,t),r=_(n);if(!r)return{error:`${t} is missing from ${n}; run install --openclaw`};if(r.isSymbolicLink()||!r.isFile())return{error:`${n} is a symlink or not a regular file; move or remove it`};try{return{content:Zl(n,"utf-8")}}catch(o){return{error:`Failed to read ${n}: ${o instanceof Error?o.message:String(o)}`}}}function Xl(e){try{return JSON.parse(K(e))}catch{return}}function Qm(e){let t=yt(e,gt);if("error"in t)return t.error;if(k(Xl(t.content),"id")===A)return;return`${tn(e,gt)} is not a valid ${A} manifest; run install --openclaw`}function eg(e){let t=yt(e,ht);if("error"in t)return t.error;let n=k(k(Xl(t.content),"openclaw"),"extensions");if(Array.isArray(n)&&n.includes(`./${ee}`))return;return`${tn(e,ht)} does not point OpenClaw at ${ee}; run install --openclaw`}function Yl(e){return Array.isArray(e)?e.filter((t)=>typeof t==="string"):[]}function tg(e){let t=zl(e);if(!_(t))return`${A} is not enabled; ${en}`;let n=(()=>{try{return JSON.parse(K(Zl(t,"utf-8")))}catch{return}})();if(n===void 0)return`Failed to read ${t}; fix it, then ${en}`;let r=k(n,"plugins");if(k(r,"enabled")===!1)return`plugins.enabled is false in ${t}; no OpenClaw plugin loads`;let o=k(k(k(r,"entries"),A),"enabled");if(Yl(k(r,"deny")).includes(A)||o===!1)return`${A} is disabled in ${t}; ${en}`;let i=Yl(k(r,"allow"));if(i.length>0&&!i.includes(A))return`plugins.allow in ${t} does not list ${A}; add it, then ${en}`;if(i.includes(A)||o===!0)return;return`${A} is not enabled; ${en}`}function Ql(e){return/^\/\/ version:\s*(.+)$/m.exec(e)?.[1]?.trim()}function ng(e,t,n){if(n===void 0)return[];let r=yt(n,ee);if("error"in r||Ql(r.content)!==t)return[];return[ee,gt,ht].flatMap((o)=>{let i=yt(e,o),s=yt(n,o);if("error"in i||"error"in s||i.content===s.content)return[];return[`Modified ${o} occupies ${tn(e,o)}; run install --openclaw to restore it`]})}function ec(e){let t=_o(e.homeDir),n=$n(Jn,t);if(n)return n;let r=yt(t,ee),i=["error"in r?r.error:r.content.startsWith(Kn)?void 0:`Unmanaged ${ee} occupies ${tn(t,ee)}; move or remove it`,Qm(t),eg(t)].filter((d)=>d!==void 0),s="content"in r?Ql(r.content):void 0,a=i.length>0?i:ng(t,s,Io());if(a.length>0)return{platform:Jn,status:"n/a",configPath:t,errors:a};let l=s===I()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],c=tg(e.homeDir);if(c)return{platform:Jn,status:"disabled",method:"plugin directory",configPath:t,errors:[c,...l]};return{platform:Jn,status:"configured",method:"plugin directory",configPath:t,errors:l.length>0?l:void 0}}import{existsSync as fg,readFileSync as mg}from"node:fs";import{join as gg}from"node:path";import{existsSync as $o,readFileSync as ic,rmSync as og}from"node:fs";import{join as ke}from"node:path";import{pathToFileURL as ig}from"node:url";function tc(e){return e!==void 0&&/\s/.test(e)}function rg(e,t,n){let r=t+1,o=!1;while(r<e.length){let i=e[r];if(o){o=!1,r++;continue}if(i==="\\"){o=!0,r++;continue}if(i==='"')return r+1;r++}throw Error(n)}function Wn(e,t,n){let r=e[t],o=r==="["?"]":"}",i=0,s=t;while(s<e.length){let a=n.skipComment?.(e,s)??s;if(a!==s){s=a;continue}if(e[s]==='"'){s=rg(e,s,n.stringError);continue}if(e[s]===r)i++;if(e[s]===o){if(i--,i===0)return s}s++}throw Error(n.bracketError)}function nc(e,t){let n=e.lastIndexOf(`
184
- `,t)+1;return/^[ \t]*/.exec(e.slice(n))?.[0]??""}function Yn(e,t){let{start:n,end:r,end:o}=t;while(tc(e[o]))o++;if(e[o]===","){if(r=o+1,e[r]===`
185
- `)r++;return`${e.slice(0,n)}${e.slice(r)}`}o=t.start-1;while(tc(e[o]))o--;if(e[o]===","){n=o;let i=e.lastIndexOf(`
186
- `,n-1);if(i!==-1&&/^\s*$/.test(e.slice(i+1,n)))n=i}return`${e.slice(0,n)}${e.slice(r)}`}var Zn="cc-safety-net",sc=`${Zn}@latest`,ac=["opencode.json","opencode.jsonc"],rc="CCSafetyNetPlugin";function Xn(e){return ke(process.env.XDG_CONFIG_HOME||ke(e,".config"),"opencode")}function sg(e){return ke(Xn(e),ac[0])}function ag(e){return ac.map((t)=>ke(Xn(e),t))}function lc(e){return ke(process.env.XDG_CACHE_HOME||ke(e,".cache"),"opencode","packages",sc)}function Oo(e){og(lc(e),{recursive:!0,force:!0})}async function cc(e){let t=ke(lc(e),"node_modules",Zn),n=ke(t,"package.json");if(!$o(n))throw Error(`The OpenCode plugin cache at ${t} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${sc}\` for details.`);let r=k(JSON.parse(ic(n,"utf-8")),"main");if(typeof r!=="string")throw Error(`The cached OpenCode plugin at ${t} declares no "main" entry.`);let o=ke(t,r);if(typeof(await import(ig(o).href))[rc]==="function")return;throw Error(`The cached OpenCode plugin at ${o} does not export a callable ${rc}, so OpenCode would load nothing and fail open.`)}function Qn(e,t){if(e[t]==="/"&&e[t+1]==="/"){let n=e.indexOf(`
187
- `,t+2);return n===-1?e.length:n+1}if(e[t]==="/"&&e[t+1]==="*"){let n=e.indexOf("*/",t+2);return n===-1?e.length:n+2}return t}function oc(e,t){let n=t;while(n<e.length){if(/\s/.test(e[n]??"")){n++;continue}let r=Qn(e,n);if(r===n)return n;n=r}return n}function dc(e,t){let n=t+1,r=!1;while(n<e.length){if(r){r=!1,n++;continue}if(e[n]==="\\"){r=!0,n++;continue}if(e[n]==='"')return n+1;n++}throw Error("Unterminated string in OpenCode config")}function uc(e,t,n){return JSON.parse(e.slice(t,n))}function lg(e,t){return Wn(e,t,{skipComment:Qn,stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"})}function cg(e){let t=0,n=0;while(n<e.length){let r=Qn(e,n);if(r!==n){n=r;continue}if(e[n]==='"'){let o=dc(e,n);if(t===1&&uc(e,n,o)==="plugin"){let i=oc(e,o),s=oc(e,i+1);if(e[i]===":"&&e[s]==="[")return{start:s,end:lg(e,s)}}n=o;continue}if(e[n]==="{"||e[n]==="[")t++;if(e[n]==="}"||e[n]==="]")t--;n++}return}function dg(e,t){let n=[],r=t.start+1;while(r<t.end){let o=Qn(e,r);if(o!==r){r=o;continue}if(e[r]==='"'){let i=dc(e,r),s=uc(e,r,i);if(typeof s==="string"&&s.includes(Zn))n.push({start:r,end:i});r=i;continue}r++}return n}function pc(e,t){try{return JSON.parse(K(e))}catch(n){if(n instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${t}: ${n.message}`);throw n}}function ug(e){if(!e||typeof e!=="object"||Array.isArray(e))return!1;let t=e.plugin;if(!Array.isArray(t))return!1;return t.some((n)=>typeof n==="string"&&n.includes(Zn))}function pg(e,t){let n=cg(e);if(!n)throw Error(`Failed to locate OpenCode plugin array in ${t}`);let r=[...dg(e,n)].reverse().reduce(Yn,e);return pc(r,t),r}function fc(e){Oo(e);let t=ag(e),n=t.find((o)=>$o(o)),r=[];for(let o of t){if(!$o(o))continue;try{let i=ic(o,"utf-8");if(!ug(pc(i,o)))continue;return O(o,pg(i,o)),{path:o,alreadyInstalled:!0}}catch(i){r.push(i instanceof Error?i.message:String(i))}}if(r.length>0)throw Error(r.join(`
188
- `));return{path:n??sg(e),alreadyInstalled:!1}}function mc(e){let t=[],n=Xn(e.homeDir),r=["opencode.json","opencode.jsonc"];for(let o of r){let i=gg(n,o);if(fg(i))try{let s=mg(i,"utf-8"),a=K(s);if((JSON.parse(a).plugin??[]).some((m)=>m.includes("cc-safety-net")))return{platform:"opencode",status:"configured",method:"plugin array",configPath:i,errors:t.length>0?t:void 0}}catch(s){t.push(`Failed to parse ${o}: ${s instanceof Error?s.message:String(s)}`)}}return{platform:"opencode",status:"n/a",errors:t.length>0?t:void 0}}import{join as hg}from"node:path";function Fo(e){return hg(e,".pi","agent","settings.json")}function jo(e){if(typeof e!=="string")return!1;return e==="npm:cc-safety-net"||e.startsWith("npm:cc-safety-net@")}function gc(e){let t=Fo(e.homeDir),n=ce(t);if(n.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(n.kind==="missing")return{platform:"pi",status:"n/a"};let r=k(n.value,"packages");if(!Array.isArray(r))return{platform:"pi",status:"n/a"};let o=r.find((a)=>jo(typeof a==="string"?a:k(a,"source")));if(o===void 0)return{platform:"pi",status:"n/a"};let i=k(o,"extensions");if(Array.isArray(i)&&i.some((a)=>typeof a==="string"&&a.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:t,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:t}}var vg={amp:za,"antigravity-cli":Ka,"claude-code":Za,codex:Xa,"copilot-cli":cl,cursor:yl,"gemini-cli":vl,"grok-build":Dl,"hermes-agent":Ml,"kimi-code":Qt,openclaw:ec,opencode:mc,pi:gc};function vt(e,t){let n={...t,cwd:e,homeDir:t?.homeDir??yg()};return wn.map((r)=>bg(vg[r](n)))}function bg(e){if(e.status==="not-inspected")return{platform:e.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:e.platform,detected:e.status!=="n/a",configured:e.status==="configured",inspectionStatus:e.status!=="n/a"?"verified":e.errors&&e.errors.length>0?"failed":"not-applicable",method:e.method,configPath:e.configPath,configPaths:e.configPaths,errors:e.errors}}import{tmpdir as Lg}from"node:os";import{join as wg}from"node:path";var kg=Object.freeze([{command:"git reset --hard",description:"git reset --hard",expectBlocked:!0},{command:"rm -rf /",description:"rm -rf /",expectBlocked:!0},{command:"rm -rf ./node_modules",description:"rm in cwd (safe)",expectBlocked:!1}]),xg=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),safety:Object.freeze({}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),Cg={strict:!1,paranoidRm:!1,paranoidInterpreters:!1,worktreeMode:!1,effectiveLevel:"standard",capabilities:{fail_closed:{enabled:!1,source:"preset",sources:[]},paranoid_rm:{enabled:!1,source:"preset",sources:[]},paranoid_interpreters:{enabled:!1,source:"preset",sources:[]}}};function hc(){let e=wg(Lg(),"cc-safety-net-self-test"),t=kg.map((n)=>{let r=bn(st("self-test",{command:n.command},{kind:"command",shell:"auto"},{configCwd:e,executionCwd:e},n.command),{guard:{dependencies:{loadPolicySnapshot:()=>xg,getModes:()=>Cg,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),o=n.expectBlocked?"blocked":"allowed",i=r.decision.kind==="deny"?"blocked":"allowed";return{command:n.command,description:n.description,expected:o,actual:i,passed:o===i,reason:r.decision.kind==="deny"?r.decision.reason:void 0,ruleId:r.decision.kind==="deny"?r.decision.ruleId:void 0}});return{passed:t.filter((n)=>n.passed).length,failed:t.filter((n)=>!n.passed).length,total:t.length,results:t}}function No(e){let t=E({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},e);if(fe(t.errors))return null;return{json:t.flags.json,skipUpdateCheck:t.flags.skipUpdateCheck}}async function yc(e={}){let t=await Kt(!e.json,()=>{let n=Sg(e);return{ready:n,finish:()=>n}},()=>zt(),{loadingMessage:"Checking system status…"});if(e.json)console.log(JSON.stringify(t,null,2));else Rg(t);return t.engineSelfTest.failed>0||t.findings.some((n)=>n.severity==="error")?1:0}async function Sg(e){let t=e.cwd??process.cwd(),n=await qt(),r=vt(t,{ampPluginListOutput:n.ampPluginListOutput,codexPluginListOutput:n.codexPluginListOutput,copilotCliVersion:n.versions["copilot-cli"]}),o=ca(t),i=da(),s=z({cwd:t}),a=s.policy,l=ye(a),c=Ue(a,l.capabilities),d=Rn(7),m=Ua(t),g=e.skipUpdateCheck?{currentVersion:I(),latestVersion:null,updateAvailable:!1}:await Te(),u={hooks:r,engineSelfTest:hc(),userConfig:o.userConfig,projectConfig:o.projectConfig,configState:Ht(s),effectiveRules:o.effectiveRules,shadowedRules:o.shadowedRules,environment:i,effectiveSafety:{selectedPreset:a.safety.level??"standard",level:l.effectiveLevel,capabilities:l.capabilities,ruleOverrides:a.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(c).filter(([,p])=>p.source==="rule_override"&&p.override==="off"&&p.inheritedEnabled&&p.changesInherited).map(([p])=>p),ruleCounts:{stored:Object.keys(a.destructiveCommandRuleOverrides).length,effective:Object.values(c).filter((p)=>p.changesInherited).length},...s.policyScopes?{policyScopes:s.policyScopes}:{}},...m.length>0?{v2Leftovers:m}:{},posture:Ca(o.userConfig.path),activity:d,update:g,system:n};return{...u,findings:pa(u)}}function Rg(e){console.log(),console.log(ma(e.hooks)),console.log(),console.log(ga(e.engineSelfTest)),console.log(),console.log(ha(e)),console.log(),console.log(ya(e.environment)),console.log(),console.log(va(e)),console.log(),console.log(ba(e.findings)),console.log(),console.log(La(e.activity)),console.log(),console.log(ka(e.system)),console.log(),console.log(wa(e.update)),console.log(xa(e))}import{existsSync as Pg}from"node:fs";var Dg=/^[A-Za-z0-9_@%+=:,./-]+$/,vc="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Ho(e){let t=E({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},e);if(fe(t.errors))return console.error(vc),console.error("Pass -- before a command that starts with dashes."),null;if(t.values.cwd!==void 0&&!Pg(t.values.cwd))return console.error(`Error: --cwd path does not exist: ${t.values.cwd}`),null;let n=t.positionals.length===1?t.positionals[0]:t.positionals.map((r)=>Dg.test(r)?r:`'${r.replaceAll("'","'\\''")}'`).join(" ");if(!n)return console.error("Error: No command provided"),console.error(vc),null;return{json:t.flags.json,cwd:t.values.cwd,command:n}}function bc(e){if(e)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function Lc(e,t){let r=t-18;return[`${e.dtl}${e.dh.repeat(t)}${e.dtr}`,`${e.dv} Command Analysis${" ".repeat(r)}${e.dv}`,`${e.dbl}${e.dh.repeat(t)}${e.dbr}`]}function Mo(e){return JSON.stringify(e)}function wc(e,t=0){return`[${e.map((r,o)=>fa(r,o,t)).join(",")}]`}function nn(e,t,n=70){let r=e.split(" "),o=[],i="";for(let s of r)if(i&&i.length+s.length+1>n)o.push(i),i=s;else i=i?`${i} ${s}`:s;if(i)o.push(i);return o.map((s,a)=>a===0?s:`${t}${s}`)}function kc(e,t,n){let r=[];switch(e.type){case"parse":return null;case"env-strip":return r.push(""),r.push(`STEP ${t} ${n.h} Strip environment variables`),r.push(` Removed: ${e.envVars.map((o)=>`${o}=<redacted>`).join(", ")}`),r.push(` Tokens: ${Mo(e.output)}`),{lines:r,incrementStep:!0};case"leading-tokens-stripped":return r.push(""),r.push(`STEP ${t} ${n.h} Strip wrappers`),r.push(` Removed: ${e.removed.join(", ")}`),r.push(` Tokens: ${Mo(e.output)}`),{lines:r,incrementStep:!0};case"shell-wrapper":return r.push(""),r.push(`STEP ${t} ${n.h} Detect shell wrapper`),r.push(` Wrapper: ${e.wrapper} -c`),r.push(` Inner: ${e.innerCommand}`),{lines:r,incrementStep:!0};case"interpreter":{if(r.push(""),r.push(`STEP ${t} ${n.h} Detect interpreter`),r.push(` Interpreter: ${e.interpreter}`),r.push(` Code: ${e.codeArg}`),e.paranoidBlocked)r.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:r,incrementStep:!0}}case"busybox":return r.push(""),r.push(`STEP ${t} ${n.h} Busybox wrapper`),r.push(` Subcommand: ${e.subcommand}`),{lines:r,incrementStep:!0};case"transparent-wrapper":return r.push(""),r.push(`STEP ${t} ${n.h} Transparent wrapper`),r.push(` Wrapper: ${e.wrapper}`),r.push(` Tokens: ${Mo(e.output)}`),{lines:r,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(r.push(""),r.push(`STEP ${t} ${n.h} Match rules`),r.push(` Rule: ${e.rule}()`),e.matched)r.push(" Result: MATCHED");else r.push(" Result: No match");return{lines:r,incrementStep:!0}}case"worktree-relaxation":return r.push(""),r.push(`STEP ${t} ${n.h} Worktree relaxation`),r.push(` Mode: ${S.worktree.name}`),r.push(` Git cwd: ${e.gitCwd}`),r.push(" Result: Allowed local discard in linked worktree"),{lines:r,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(e.embeddedCommandFound)return r.push(""),r.push(`STEP ${t} ${n.h} Fallback scan`),r.push(` Found: ${e.embeddedCommandFound}`),{lines:r,incrementStep:!0};return null}case"custom-rules-check":{if(e.rulesChecked){if(r.push(""),r.push(`STEP ${t} ${n.h} Custom rules`),e.matched)r.push(" Result: MATCHED");else r.push(" Result: No match");return{lines:r,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(e.matched)return r.push(""),r.push(`STEP ${t} ${n.h} Dangerous text check`),r.push(` Token: ${e.token}`),r.push(" Result: MATCHED"),{lines:r,incrementStep:!0};return null}case"strict-unparseable":return r.push(""),r.push(`STEP ${t} ${n.h} Strict mode check`),r.push(` Command: ${e.rawCommand}`),r.push(" Result: ✗ UNPARSEABLE"),{lines:r,incrementStep:!0};case"segment-skipped":return null;case"error":return r.push(""),r.push(`ERROR: ${e.message}`),{lines:r,incrementStep:!1};default:return e}}function Uo(e,t){let n=bc(t?.asciiOnly??!1),r=58,o=[],i=1;o.push(...Lc(n,58)),o.push("");let s=e.trace.steps.find((p)=>p.type==="error");if(s&&s.type==="error"){o.push("ERROR"),o.push(` ${s.message}`),o.push(""),o.push("RESULT"),o.push(` Status: ${e.result==="blocked"?y.red("BLOCKED"):y.green("ALLOWED")}`),o.push(""),o.push("CONFIG");let p=e.configSource??"none";return o.push(` Path: ${p}`),o.join(`
189
- `)}let a=e.trace.steps.find((p)=>p.type==="parse");if(a&&a.type==="parse"){o.push("INPUT"),o.push(` ${a.input}`),o.push(""),o.push(`STEP ${i} ${n.h} Split shell commands`),i++;for(let p=0;p<a.segments.length;p++){let f=a.segments[p];if(f){let b=Math.random();o.push(` Segment ${p+1}: ${wc(f,b)}`)}}}let l=e.trace.segments,c=l.length>1;for(let p of l){if(c){o.push("");let h="";if(a&&a.type==="parse"){let mr=a.segments[p.index];if(mr)h=mr.join(" ")}let R=54,v=h,P=` Segment ${p.index+1}: `,ne=" ";if(h){if(P.length+h.length+ne.length>R){let bu=R-P.length-ne.length;v=`${h.substring(0,bu-1)}…`}}let un=h?`${P}${v}${ne}`:` Segment ${p.index+1} `,yu=h?`${P}${y.cyan(v)}${ne}`:un,pi=58-un.length,fi=Math.floor(pi/2),vu=pi-fi;o.push(`${n.sh.repeat(fi)}${yu}${n.sh.repeat(vu)}`)}if(p.steps.find((h)=>h.type==="segment-skipped")){o.push(""),o.push(" (skipped — prior segment blocked)");continue}let b=!1,L=!1;for(let h of p.steps){let R=kc(h,i,n);if(R){if(L=!0,h.type==="recurse"){o.push("");let v=" RECURSING ",P=58-v.length-4;o.push(` ${n.tl}${n.h}${v}${n.h.repeat(P)}`),o.push(` ${n.v}`),b=!0;continue}for(let v of R.lines)if(b)o.push(` ${n.v} ${v}`);else o.push(v);if(R.incrementStep)i++}}if(b)o.push(` ${n.v}`),o.push(` ${n.bl}${n.h.repeat(56)}`),b=!1;if(!L)o.push(""),o.push(` ${y.green("✓")} Allowed (no matching rules)`)}if(o.push(""),o.push("RESULT"),e.result==="blocked"){if(o.push(` Status: ${y.red("BLOCKED")}`),e.customRule){if(o.push(` Rule: ${e.customRule.id}`),e.customRule.rulebook)o.push(` Rulebook: ${e.customRule.rulebook.name} ${e.customRule.rulebook.version}`);if(e.customRule.source)o.push(` Source: ${e.customRule.source}`);if(e.customRule.override)o.push(` Override: reason ${e.customRule.override.reason}`)}if(e.reason){let p=nn(e.reason," ");o.push(` Reason: ${p[0]}`);for(let f=1;f<p.length;f++)o.push(p[f]??"")}}else o.push(` Status: ${y.green("ALLOWED")}`);o.push(""),o.push("CONFIG");let d=e.configSource??"none",m=e.configValid?"":" (invalid)";o.push(` Path: ${d}${m}`);let g=e.safetyPresetScope;o.push(` Safety preset: ${e.selectedPreset??"standard"}${g?` (${Pn(g)})`:""}`),o.push(` Effective capabilities: ${e.effectiveLevel}`);let u=Object.entries(e.destructiveCommandRuleOverrides??{});if(o.push(` Rule customizations: ${u.length}`),e.ruleActivation)o.push(` Rule activation: ${e.ruleActivation.id} — ${e.ruleActivation.enabled?"on":"off"} via ${e.ruleActivation.source}`);return o.join(`
190
- `)}function Go(e){return JSON.stringify(e,null,2)}function xc(e){return new Promise((t)=>{process.stdout.write(`${e}
191
- `,()=>t())})}async function Cc(e){let t=Ho(e);if(!t)return 1;try{let n=at(t.command,{cwd:t.cwd}),r=!!process.env.NO_COLOR||!process.stdout.isTTY;return await xc(t.json?Go(n):Uo(n,{asciiOnly:r})),0}catch(n){if(!(n instanceof Gr)&&!(n instanceof Me)&&!(n instanceof Le))throw n;if(t.json)return await xc(JSON.stringify({error:n.message})),1;return console.error(n.message),1}}var Sc="2.3.2",te=" ",Ye="cc-safety-net";function Rc(e){return e.argument?`${e.flags} ${e.argument}`:e.flags}function Ag(e){return Math.max(...e.map((t)=>Rc(t).length))}function Eg(e){return Math.max(...e.map((t)=>t.usage.length))}function _g(e){return Math.max(...e.map((t)=>`${Ye} ${t.usage}`.length))}function Tg(e,t){let n=`${Ye} ${e.usage}`;return`${te}${n.padEnd(t+2)}${e.description}`}function xe(e,t){return`${te}${e.padEnd(Math.max(40,e.length+2))}${t}`}function bt(e,t=console.log){let n=[];if(n.push(`${Ye} ${e.name}`),n.push(""),n.push(`${te}${e.description}`),n.push(""),n.push("USAGE:"),n.push(`${te}${Ye} ${e.usage}`),n.push(""),e.subcommands&&e.subcommands.length>0){n.push("SUBCOMMANDS:");let r=Eg(e.subcommands);for(let o of e.subcommands)n.push(`${te}${o.usage.padEnd(r+2)}${o.description}`);n.push("")}if(e.options.length>0){n.push("OPTIONS:");let r=Ag(e.options);for(let o of e.options){let i=Rc(o),s=o.default?`${o.description} (default: ${o.default})`:o.description;n.push(`${te}${i.padEnd(r+2)}${s}`)}n.push("")}if(e.examples&&e.examples.length>0){n.push("EXAMPLES:");for(let r of e.examples)n.push(`${te}${r}`)}t(n.join(`
192
- `))}function Bo(){let e=_g(Cn),t=[];t.push(`${Ye} v${Sc}`),t.push(""),t.push("Blocks destructive commands and secret access."),t.push(""),t.push("COMMANDS:");for(let n of Cn)t.push(Tg(n,e));t.push(""),t.push("GLOBAL OPTIONS:"),t.push(`${te}-h, --help Show help (use with command for command-specific help)`),t.push(`${te}-V, --version Show version`),t.push(""),t.push("HELP:"),t.push(`${te}${Ye} help <command> Show help for a specific command`),t.push(`${te}${Ye} <command> --help Show help for a specific command`),t.push(""),t.push("ENVIRONMENT VARIABLES:"),t.push(xe(`${S.level.name}=standard|strict|paranoid`,"Set session safety level")),t.push(xe(`${S.worktree.name}=1`,"Allow local git discards in linked worktrees")),t.push(xe(`${S.debug.name}=1`,"Print diagnostic messages to stderr")),t.push(xe(`${S.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),t.push(xe("CC_SAFETY_NET_HOME","Override rule config home directory")),t.push(""),t.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),t.push(xe(`${S.strict.name}=1`,"Force safety.overrides.fail_closed on")),t.push(xe(`${S.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),t.push(xe(`${S.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),t.push(xe(`${S.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),t.push(""),t.push("Documentation: https://ccsafetynet.com/docs"),console.log(t.join(`
193
- `))}function Pc(){console.log(Sc)}function rn(e,t=console.log){let n=Sn(e);if(!n)return!1;if(n.name.toLowerCase()!==e.toLowerCase())return!1;return bt(n,t),!0}import{existsSync as ti,readFileSync as bd}from"node:fs";import{homedir as Ah,tmpdir as Eh}from"node:os";import{join as Qo}from"node:path";import*as $e from"node:readline";function Ig(e){return e==="install"?"Install":"Uninstall"}function $g(e){return e==="install"?"Installing":"Uninstalling"}function Og(e){return e==="install"?"into":"from"}function Ec(e){return e?.available===!0}function Fg(e,t){let n=new Set(t);return e.filter((r)=>n.has(r.target)).map((r)=>r.target)}function Dc(e,t,n){if(e.length===0||e.every((r)=>!r.available))return t;return Array.from({length:e.length},(r,o)=>o+1).map((r)=>(t+r*n+e.length)%e.length).find((r)=>Ec(e[r]))}function jg(e,t,n){if(n.ctrl&&n.name==="c")return"interrupt";if(n.name==="escape"||t==="q")return"abort";if(e==="install"&&(t==="u"||t==="U"))return"update";if(n.name==="up"||t==="k")return"up";if(n.name==="down"||t==="j")return"down";if(n.name==="space"||t===" ")return"toggle";if(n.name==="return"||n.name==="enter")return"confirm";return null}function Ng(e){return{cursor:e.findIndex((t)=>t.available),selected:[]}}function Hg(e,t,n){if(n==="confirm"||n==="update"||n==="abort"||n==="interrupt")return{state:e,done:n};if(n==="up")return{state:{...e,cursor:Dc(t,e.cursor,-1)}};if(n==="down")return{state:{...e,cursor:Dc(t,e.cursor,1)}};let r=t[e.cursor];if(!Ec(r))return{state:e};let o=e.selected.includes(r.target)?e.selected.filter((i)=>i!==r.target):Fg(t,[...e.selected,r.target]);return{state:{...e,selected:o}}}var _c="◉",Tc="◯",Ic=">",$c=" ";function Mg(e,t,n,r={}){let o=r.color!==!1,i=o?y.dim:(l)=>l,s=o?y.green:(l)=>l,a=o?y.bold:(l)=>l;return["",`${Ig(e)} CC Safety Net ${Og(e)}:`,"",...t.map((l,c)=>{let d=n.selected.includes(l.target),m=c===n.cursor,g=d?_c:Tc,u=m?Ic:$c,p=l.available?"":` (${l.unavailableReason??"not installed"})`,f=`${g} ${l.label}${p}`,b=!l.available?i(f):d?s(f):m?a(f):f;return`${u} ${b}`}),"",e==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":t.some((l)=>l.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${e}. q/Esc: close`].join(`
194
- `)}var Ac=["global-hook","plugin"];function Ug(e,t,n={}){let r=n.color!==!1?y.bold:(i)=>i;return["","Install the Kimi Code integration as:","",...[`Global hook — ${t?"already installed; selecting it reports the current state":"write the hook into ~/.kimi-code/config.toml now"}`,"Native Kimi plugin — print the steps to run inside Kimi Code"].map((i,s)=>{let a=s===e,l=`${a?_c:Tc} ${i}`;return`${a?Ic:$c} ${a?r(l):l}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
195
- `)}function Oc(e){let{input:t,output:n}=e;$e.emitKeypressEvents(t);let r=t.isRaw===!0;t.setRawMode(!0),t.resume();let o=0,i=()=>{if(o===0)return;$e.moveCursor(n,0,-o),$e.cursorTo(n,0),$e.clearScreenDown(n)},s=()=>{i();let a=e.render();n.write(`${a}
196
- `),o=a.split(`
197
- `).length};return new Promise((a)=>{let l=(d)=>{t.off("keypress",c),t.setRawMode(r),t.pause(),i(),a(d)};function c(d,m){e.onKey(d,m,{finish:l,draw:s})}t.on("keypress",c),s()})}function Fc(e={}){let t=0;return Oc({input:e.input??process.stdin,output:e.output??process.stdout,render:()=>Ug(t,e.globalHookInstalled===!0),onKey:(n,r,o)=>{if(r.ctrl&&r.name==="c"){o.finish(null),(e.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(r.name==="escape"||n==="q")return o.finish(null);if(r.name==="return"||r.name==="enter")return o.finish(Ac[t]);if(r.name==="up"||r.name==="down"||n==="k"||n==="j")t=(t+1)%Ac.length,o.draw()}})}function qo(e=process.stdin,t=process.stdout){return Boolean(e.isTTY&&t.isTTY&&typeof e.setRawMode==="function")}function jc(e,t,n={}){let r=n.output??process.stdout,o=Ng(t);return Oc({input:n.input??process.stdin,output:r,render:()=>Mg(e,t,o),onKey:(i,s,a)=>{let l=jg(e,i,s);if(!l)return;let c=Hg(o,t,l);if(o=c.state,c.done==="interrupt"){a.finish(null),(n.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(c.done==="abort")return a.finish(null);if(c.done==="update")return a.finish("update");if(c.done==="confirm"){if(o.selected.length===0){r.write("\x07"),a.draw();return}a.finish([...o.selected]),r.write(`${$g(e)} selected integrations...
198
- `);return}a.draw()}})}import{existsSync as Hc,lstatSync as Bg,mkdirSync as qg,mkdtempSync as Vg,readdirSync as zg,readFileSync as wt,rmSync as tr}from"node:fs";import{tmpdir as Kg}from"node:os";import{basename as Jg,dirname as Wg,join as G}from"node:path";import{fileURLToPath as Yg}from"node:url";var Vo="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",Ze="cc-safety-net",Xe="cc-safety-net/index.ts";import{spawn as Gg}from"node:child_process";var zo=(e,t)=>{let n=ze([...e],process.env);return new Promise((r)=>{let o=Gg(n.cmd,n.args,{cwd:t,stdio:["ignore","pipe","pipe"]}),i=Do(o),s=!1,a=setTimeout(()=>{s=!0,o.kill()},120000);o.on("error",(l)=>{clearTimeout(a),r({status:null,errorCode:l.code,stdout:i.stdout,stderr:[l.message,i.stderr].filter(Boolean).join(`
199
- `)})}),o.on("close",(l)=>{clearTimeout(a),r({status:s?null:l,errorCode:s?"ETIMEDOUT":void 0,stdout:i.stdout,stderr:i.stderr})})})};var Lt="cc-safety-net.ts",Nc=G("amp",Xe);function Zg(e){return G(e,".config","amp","plugins","cc-safety-net.ts")}function Xg(){let e=Wg(Yg(import.meta.url));return[G(e,"..",Nc),G(e,"..","..","..","dist",Nc)]}function Qg(e=Xg()){let t=e.find((n)=>Hc(n)&&Bg(n).isFile());if(!t)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return t}function Mc(e){try{return JSON.parse(e)}catch{return}}function nr(e){return e.subarray(0,Buffer.byteLength(Vo)).toString("utf-8")===Vo}async function on(e,t,n){let r=await e(t,n);if(r.status===0)return r;throw Error([`Failed to run ${t.join(" ")}${r.status===null?"":` (exit ${r.status})`}.`,[r.stdout,r.stderr].filter(Boolean).join(`
203
+ `}function kr(ce){return[{name:"__init__.py",content:_m(ce)},{name:"plugin.yaml",content:Em(ce)}]}import{mkdirSync as Tm,readdirSync as Im,readFileSync as $m,rmSync as bi}from"node:fs";import{join as $n}from"node:path";var Om="__pycache__";function Li(ce){let me=process.env.HERMES_HOME?.trim();return me?me:$n(ce,".hermes")}function wi(ce){return $n(Li(ce),"plugins",ln)}function ki(ce){return ce.startsWith(Nl)}function xi(ce,me){let ge=wi(ce),he=Yt(ge);if(he&&(he.isSymbolicLink()||!he.isDirectory()))throw Error(`Refusing to ${me} ${ge}: not a regular directory. Move or remove it and rerun ${me==="install"?"install":"uninstall"} --hermes-agent.`);return ge}function Ml(ce,me){let ge=Yt(ce);if(!ge)return;if(ge.isSymbolicLink()||!ge.isFile())throw Error(`Refusing to ${me} ${ce}: not a regular file. Move or remove it.`);let he=$m(ce,"utf-8");if(!ki(he))throw Error(`Refusing to ${me} unmanaged file at ${ce}. Move or remove it.`);return he}function Ul(ce){let me=xi(ce,"install"),ge=kr(Xt());if(ge.map((Se)=>Ml($n(me,Se.name),"overwrite")).every((Se,Fe)=>Se===ge[Fe]?.content))return{path:me,alreadyInstalled:!0};return Tm(me,{recursive:!0}),ge.forEach((Se)=>{Qt($n(me,Se.name),Se.content)}),{path:me,alreadyInstalled:!1}}function Ci(ce){let me=xi(ce,"remove");if(!Yt(me))return[];return kr(Xt()).filter((ge)=>Ml($n(me,ge.name),"remove")!==void 0)}function Gl(ce){let me=xi(ce,"remove");if(!Yt(me))return{path:me,alreadyInstalled:!1};let ge=Ci(ce);if(ge.forEach((he)=>{bi($n(me,he.name))}),bi($n(me,Om),{recursive:!0,force:!0}),Im(me).length===0)bi(me,{recursive:!0});return{path:me,alreadyInstalled:ge.length>0}}var uo="hermes-agent",Bl=/^([^\s#][^:]*):/,Fm=/^\s+([A-Za-z_][\w-]*):/,ql=/^\s+-\s*(.*)$/;function jm(ce){return ce.trim().replace(/^(["'])(.*)\1$/,"$2")}function Nm(ce){let me=ce.split(/\r?\n/),ge=me.findIndex((Fe)=>Bl.exec(Fe)?.[1]?.trim()==="plugins");if(ge===-1)return[];let he=me.slice(ge+1),Se=he.findIndex((Fe)=>Bl.test(Fe));return Se===-1?he:he.slice(0,Se)}function Vl(ce,me){let ge=Nm(ce),he=ge.findIndex((He)=>Fm.exec(He)?.[1]===me);if(he===-1)return[];let Se=ge.slice(he+1),Fe=Se.findIndex((He)=>!ql.test(He));return(Fe===-1?Se:Se.slice(0,Fe)).map((He)=>jm(ql.exec(He)?.[1]??""))}function Hm(ce){try{return zl(Kl(Li(ce),"config.yaml"),"utf-8")}catch{return}}function Si(ce){let me=Hm(ce)??"";return Vl(me,"enabled").includes(ln)&&!Vl(me,"disabled").includes(ln)}function Jl(ce){return/^# version:\s*(.+)$/m.exec(ce)?.[1]?.trim()}function Mm(ce,me){let ge=Yt(ce);if(!ge)return{error:`${me.name} is missing from ${ce}; run install --hermes-agent`};if(ge.isSymbolicLink()||!ge.isFile())return{error:`${ce} is a symlink or not a regular file; move or remove it`};try{let he=zl(ce,"utf-8");if(!ki(he))return{error:`Unmanaged ${me.name} occupies ${ce}; move or remove it`};if(Jl(he)===Xt()&&he!==me.content)return{error:`Modified ${me.name} occupies ${ce}; run install --hermes-agent to restore it`};return{content:he}}catch(he){return{error:`Failed to read ${ce}: ${he instanceof Error?he.message:String(he)}`}}}function Wl(ce){let me=wi(ce.homeDir),ge=Xr(uo,me);if(ge)return ge;let he=kr(Xt()).map((Ge)=>Mm(Kl(me,Ge.name),Ge)),Se=he.flatMap((Ge)=>("error"in Ge)?[Ge.error]:[]);if(Se.length>0)return{platform:uo,status:"n/a",configPath:me,errors:Se};let Fe=he.some((Ge)=>("content"in Ge)&&Jl(Ge.content)!==Xt()),He=Fe?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!Si(ce.homeDir))return{platform:uo,status:"disabled",method:"plugin directory",configPath:me,errors:[`${ln} is not enabled in Hermes; run \`hermes plugins enable ${ln}\``,...He]};return{platform:uo,status:"configured",method:"plugin directory",configPath:me,errors:Fe?He:void 0}}import{existsSync as Um,readFileSync as Gm}from"node:fs";import{join as Yl}from"node:path";var Bm=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function qm(ce){return Yl(process.env.KIMI_CODE_HOME||Yl(ce,".kimi-code"),"config.toml")}function xr(ce){let me=qm(ce.homeDir);if(!Um(me))return{platform:"kimi-code",status:"n/a",configPath:me};try{if(!Bm.test(Gm(me,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:me}}catch(ge){return{platform:"kimi-code",status:"n/a",configPath:me,errors:[`Failed to read ${me}: ${ge instanceof Error?ge.message:String(ge)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:me}}import{readFileSync as sc}from"node:fs";import{join as Sr}from"node:path";var Jt="cc-safety-net",cn="index.js",Zn="openclaw.plugin.json",Xn="package.json";var po="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as Km,lstatSync as Jm,readdirSync as Wm,readFileSync as Ym}from"node:fs";import{dirname as Ql,join as Sn}from"node:path";import{fileURLToPath as Zm}from"node:url";import{spawn as Vm}from"node:child_process";function zm(ce){return ce.join(" ")}function Ri(ce,me,ge){return[`Failed to run ${zm(ce)}${me===null?"":` (exit ${me})`}.`,ge.trim()].filter(Boolean).join(`
204
+ `)}function Pi(ce){let me={stdout:"",stderr:""};return ce.stdout.setEncoding("utf-8"),ce.stderr.setEncoding("utf-8"),ce.stdout.on("data",(ge)=>{me.stdout+=ge}),ce.stderr.on("data",(ge)=>{me.stderr+=ge}),me}function hn(ce,me){return new Promise((ge,he)=>{let Se=_n([...ce],process.env),Fe=Vm(Se.cmd,Se.args,{stdio:["ignore","pipe","pipe"]}),He=Pi(Fe),Ge=()=>[He.stdout,He.stderr].filter(Boolean).join(`
205
+ `),Dt=me?.timeoutMs??120000,At=setTimeout(()=>{Fe.kill(),he(Error(Ri(ce,null,`Timed out after ${Dt}ms.
206
+ ${Ge()}`.trim())))},Dt);Fe.on("error",(Tt)=>{clearTimeout(At),he(Error(Ri(ce,null,`${Tt.message}
207
+ ${Ge()}`.trim())))}),Fe.on("close",(Tt)=>{if(clearTimeout(At),Tt!==0){he(Error(Ri(ce,Tt,Ge())));return}ge(me?.stdoutOnly?He.stdout:Ge())})})}async function Di(ce){for(let me of ce)await hn(me)}async function Zl(ce){for(let me of ce)try{await hn(me)}catch(ge){console.warn(ge instanceof Error?ge.message:String(ge))}}var Xl=Sn("openclaw",Jt),Xm=[cn,Zn,Xn];function Ai(ce,me){if(ce==="~")return me;if(ce.startsWith("~/")||ce.startsWith("~\\"))return Sn(me,ce.slice(2));return ce}function ec(ce){let me=process.env.OPENCLAW_STATE_DIR?.trim();if(me)return Ai(me,ce);let ge=process.env.OPENCLAW_CONFIG_PATH?.trim();return ge?Ql(Ai(ge,ce)):Sn(ce,".openclaw")}function tc(ce){let me=process.env.OPENCLAW_CONFIG_PATH?.trim();return me?Ai(me,ce):Sn(ec(ce),"openclaw.json")}function Ei(ce){return Sn(ec(ce),"extensions",Jt)}function Qm(ce){let me=Wm(ce);if(me.length===0)return!0;if(me.some((Se)=>!Xm.includes(Se)))return!1;let ge=Sn(ce,cn),he=Yt(ge);return he!==void 0&&!he.isSymbolicLink()&&he.isFile()&&Ym(ge,"utf-8").startsWith(po)}function _i(ce){let me=Ei(ce),ge=Yt(me);if(!ge)return;if(!ge.isSymbolicLink()&&ge.isDirectory()&&Qm(me))return;throw Error(`Refusing to modify ${me}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function nc(){let ce=Ql(Zm(import.meta.url));return[Sn(ce,"..",Xl),Sn(ce,"..","..","..","dist",Xl)]}function Ti(ce=nc()){return ce.find((me)=>Km(me)&&Jm(me).isDirectory())}function eg(ce=nc()){let me=Ti(ce);if(!me)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return me}function rc(ce=eg()){return[["openclaw","plugins","install",ce,"--force"],["openclaw","plugins","enable",Jt]]}function tg(ce){let me=(()=>{try{return JSON.parse(ce)}catch{return}})(),ge=Bt(Bt(me,"plugin"),"status");return typeof ge==="string"?ge:void 0}async function oc(){let ce=tg(await hn(["openclaw","plugins","inspect",Jt,"--runtime","--json"],{stdoutOnly:!0}));if(ce==="loaded")return;throw Error(`${ce===void 0?`The ${Jt} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${Jt} plugin with status "${ce}".`} Run \`openclaw plugins inspect ${Jt} --runtime\` for details.`)}var fo="openclaw",Cr=`run \`openclaw plugins enable ${Jt}\``;function Qn(ce,me){let ge=Sr(ce,me),he=Yt(ge);if(!he)return{error:`${me} is missing from ${ge}; run install --openclaw`};if(he.isSymbolicLink()||!he.isFile())return{error:`${ge} is a symlink or not a regular file; move or remove it`};try{return{content:sc(ge,"utf-8")}}catch(Se){return{error:`Failed to read ${ge}: ${Se instanceof Error?Se.message:String(Se)}`}}}function ac(ce){try{return JSON.parse(sn(ce))}catch{return}}function ng(ce){let me=Qn(ce,Zn);if("error"in me)return me.error;if(Bt(ac(me.content),"id")===Jt)return;return`${Sr(ce,Zn)} is not a valid ${Jt} manifest; run install --openclaw`}function rg(ce){let me=Qn(ce,Xn);if("error"in me)return me.error;let ge=Bt(Bt(ac(me.content),"openclaw"),"extensions");if(Array.isArray(ge)&&ge.includes(`./${cn}`))return;return`${Sr(ce,Xn)} does not point OpenClaw at ${cn}; run install --openclaw`}function ic(ce){return Array.isArray(ce)?ce.filter((me)=>typeof me==="string"):[]}function og(ce){let me=tc(ce);if(!Yt(me))return`${Jt} is not enabled; ${Cr}`;let ge=(()=>{try{return JSON.parse(sn(sc(me,"utf-8")))}catch{return}})();if(ge===void 0)return`Failed to read ${me}; fix it, then ${Cr}`;let he=Bt(ge,"plugins");if(Bt(he,"enabled")===!1)return`plugins.enabled is false in ${me}; no OpenClaw plugin loads`;let Se=Bt(Bt(Bt(he,"entries"),Jt),"enabled");if(ic(Bt(he,"deny")).includes(Jt)||Se===!1)return`${Jt} is disabled in ${me}; ${Cr}`;let Fe=ic(Bt(he,"allow"));if(Fe.length>0&&!Fe.includes(Jt))return`plugins.allow in ${me} does not list ${Jt}; add it, then ${Cr}`;if(Fe.includes(Jt)||Se===!0)return;return`${Jt} is not enabled; ${Cr}`}function lc(ce){return/^\/\/ version:\s*(.+)$/m.exec(ce)?.[1]?.trim()}function ig(ce,me,ge){if(ge===void 0)return[];let he=Qn(ge,cn);if("error"in he||lc(he.content)!==me)return[];return[cn,Zn,Xn].flatMap((Se)=>{let Fe=Qn(ce,Se),He=Qn(ge,Se);if("error"in Fe||"error"in He||Fe.content===He.content)return[];return[`Modified ${Se} occupies ${Sr(ce,Se)}; run install --openclaw to restore it`]})}function cc(ce){let me=Ei(ce.homeDir),ge=Xr(fo,me);if(ge)return ge;let he=Qn(me,cn),Fe=["error"in he?he.error:he.content.startsWith(po)?void 0:`Unmanaged ${cn} occupies ${Sr(me,cn)}; move or remove it`,ng(me),rg(me)].filter((Tt)=>Tt!==void 0),He="content"in he?lc(he.content):void 0,Ge=Fe.length>0?Fe:ig(me,He,Ti());if(Ge.length>0)return{platform:fo,status:"n/a",configPath:me,errors:Ge};let Dt=He===Xt()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],At=og(ce.homeDir);if(At)return{platform:fo,status:"disabled",method:"plugin directory",configPath:me,errors:[At,...Dt]};return{platform:fo,status:"configured",method:"plugin directory",configPath:me,errors:Dt.length>0?Dt:void 0}}import{existsSync as hg,readFileSync as yg}from"node:fs";import{join as vg}from"node:path";import{existsSync as Ii,readFileSync as mc,rmSync as ag}from"node:fs";import{join as Ln}from"node:path";import{pathToFileURL as lg}from"node:url";function dc(ce){return ce!==void 0&&/\s/.test(ce)}function sg(ce,me,ge){let he=me+1,Se=!1;while(he<ce.length){let Fe=ce[he];if(Se){Se=!1,he++;continue}if(Fe==="\\"){Se=!0,he++;continue}if(Fe==='"')return he+1;he++}throw Error(ge)}function mo(ce,me,ge){let he=ce[me],Se=he==="["?"]":"}",Fe=0,He=me;while(He<ce.length){let Ge=ge.skipComment?.(ce,He)??He;if(Ge!==He){He=Ge;continue}if(ce[He]==='"'){He=sg(ce,He,ge.stringError);continue}if(ce[He]===he)Fe++;if(ce[He]===Se){if(Fe--,Fe===0)return He}He++}throw Error(ge.bracketError)}function uc(ce,me){let ge=ce.lastIndexOf(`
208
+ `,me)+1;return/^[ \t]*/.exec(ce.slice(ge))?.[0]??""}function go(ce,me){let{start:ge,end:he,end:Se}=me;while(dc(ce[Se]))Se++;if(ce[Se]===","){if(he=Se+1,ce[he]===`
209
+ `)he++;return`${ce.slice(0,ge)}${ce.slice(he)}`}Se=me.start-1;while(dc(ce[Se]))Se--;if(ce[Se]===","){ge=Se;let Fe=ce.lastIndexOf(`
210
+ `,ge-1);if(Fe!==-1&&/^\s*$/.test(ce.slice(Fe+1,ge)))ge=Fe}return`${ce.slice(0,ge)}${ce.slice(he)}`}var ho="cc-safety-net",gc=`${ho}@latest`,hc=["opencode.json","opencode.jsonc"],pc="CCSafetyNetPlugin";function yo(ce){return Ln(process.env.XDG_CONFIG_HOME||Ln(ce,".config"),"opencode")}function cg(ce){return Ln(yo(ce),hc[0])}function dg(ce){return hc.map((me)=>Ln(yo(ce),me))}function yc(ce){return Ln(process.env.XDG_CACHE_HOME||Ln(ce,".cache"),"opencode","packages",gc)}function $i(ce){ag(yc(ce),{recursive:!0,force:!0})}async function vc(ce){let me=Ln(yc(ce),"node_modules",ho),ge=Ln(me,"package.json");if(!Ii(ge))throw Error(`The OpenCode plugin cache at ${me} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${gc}\` for details.`);let he=Bt(JSON.parse(mc(ge,"utf-8")),"main");if(typeof he!=="string")throw Error(`The cached OpenCode plugin at ${me} declares no "main" entry.`);let Se=Ln(me,he);if(typeof(await import(lg(Se).href))[pc]==="function")return;throw Error(`The cached OpenCode plugin at ${Se} does not export a callable ${pc}, so OpenCode would load nothing and fail open.`)}function vo(ce,me){if(ce[me]==="/"&&ce[me+1]==="/"){let ge=ce.indexOf(`
211
+ `,me+2);return ge===-1?ce.length:ge+1}if(ce[me]==="/"&&ce[me+1]==="*"){let ge=ce.indexOf("*/",me+2);return ge===-1?ce.length:ge+2}return me}function fc(ce,me){let ge=me;while(ge<ce.length){if(/\s/.test(ce[ge]??"")){ge++;continue}let he=vo(ce,ge);if(he===ge)return ge;ge=he}return ge}function bc(ce,me){let ge=me+1,he=!1;while(ge<ce.length){if(he){he=!1,ge++;continue}if(ce[ge]==="\\"){he=!0,ge++;continue}if(ce[ge]==='"')return ge+1;ge++}throw Error("Unterminated string in OpenCode config")}function Lc(ce,me,ge){return JSON.parse(ce.slice(me,ge))}function ug(ce,me){return mo(ce,me,{skipComment:vo,stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"})}function pg(ce){let me=0,ge=0;while(ge<ce.length){let he=vo(ce,ge);if(he!==ge){ge=he;continue}if(ce[ge]==='"'){let Se=bc(ce,ge);if(me===1&&Lc(ce,ge,Se)==="plugin"){let Fe=fc(ce,Se),He=fc(ce,Fe+1);if(ce[Fe]===":"&&ce[He]==="[")return{start:He,end:ug(ce,He)}}ge=Se;continue}if(ce[ge]==="{"||ce[ge]==="[")me++;if(ce[ge]==="}"||ce[ge]==="]")me--;ge++}return}function fg(ce,me){let ge=[],he=me.start+1;while(he<me.end){let Se=vo(ce,he);if(Se!==he){he=Se;continue}if(ce[he]==='"'){let Fe=bc(ce,he),He=Lc(ce,he,Fe);if(typeof He==="string"&&He.includes(ho))ge.push({start:he,end:Fe});he=Fe;continue}he++}return ge}function wc(ce,me){try{return JSON.parse(sn(ce))}catch(ge){if(ge instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${me}: ${ge.message}`);throw ge}}function mg(ce){if(!ce||typeof ce!=="object"||Array.isArray(ce))return!1;let me=ce.plugin;if(!Array.isArray(me))return!1;return me.some((ge)=>typeof ge==="string"&&ge.includes(ho))}function gg(ce,me){let ge=pg(ce);if(!ge)throw Error(`Failed to locate OpenCode plugin array in ${me}`);let he=[...fg(ce,ge)].reverse().reduce(go,ce);return wc(he,me),he}function kc(ce){$i(ce);let me=dg(ce),ge=me.find((Se)=>Ii(Se)),he=[];for(let Se of me){if(!Ii(Se))continue;try{let Fe=mc(Se,"utf-8");if(!mg(wc(Fe,Se)))continue;return Qt(Se,gg(Fe,Se)),{path:Se,alreadyInstalled:!0}}catch(Fe){he.push(Fe instanceof Error?Fe.message:String(Fe))}}if(he.length>0)throw Error(he.join(`
212
+ `));return{path:ge??cg(ce),alreadyInstalled:!1}}function xc(ce){let me=[],ge=yo(ce.homeDir),he=["opencode.json","opencode.jsonc"];for(let Se of he){let Fe=vg(ge,Se);if(hg(Fe))try{let He=yg(Fe,"utf-8"),Ge=sn(He);if((JSON.parse(Ge).plugin??[]).some((Ft)=>Ft.includes("cc-safety-net")))return{platform:"opencode",status:"configured",method:"plugin array",configPath:Fe,errors:me.length>0?me:void 0}}catch(He){me.push(`Failed to parse ${Se}: ${He instanceof Error?He.message:String(He)}`)}}return{platform:"opencode",status:"n/a",errors:me.length>0?me:void 0}}import{join as bg}from"node:path";function Oi(ce){return bg(ce,".pi","agent","settings.json")}function Fi(ce){if(typeof ce!=="string")return!1;return ce==="npm:cc-safety-net"||ce.startsWith("npm:cc-safety-net@")}function Cc(ce){let me=Oi(ce.homeDir),ge=mn(me);if(ge.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(ge.kind==="missing")return{platform:"pi",status:"n/a"};let he=Bt(ge.value,"packages");if(!Array.isArray(he))return{platform:"pi",status:"n/a"};let Se=he.find((Ge)=>Fi(typeof Ge==="string"?Ge:Bt(Ge,"source")));if(Se===void 0)return{platform:"pi",status:"n/a"};let Fe=Bt(Se,"extensions");if(Array.isArray(Fe)&&Fe.some((Ge)=>typeof Ge==="string"&&Ge.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:me,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:me}}var wg={amp:tl,"antigravity-cli":nl,"claude-code":sl,codex:al,"copilot-cli":vl,cursor:Rl,"gemini-cli":Pl,"grok-build":jl,"hermes-agent":Wl,"kimi-code":xr,openclaw:cc,opencode:xc,pi:Cc};function er(ce,me){let ge={...me,cwd:ce,homeDir:me?.homeDir??Lg()};return Hr.map((he)=>kg(wg[he](ge)))}function kg(ce){if(ce.status==="not-inspected")return{platform:ce.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:ce.platform,detected:ce.status!=="n/a",configured:ce.status==="configured",inspectionStatus:ce.status!=="n/a"?"verified":ce.errors&&ce.errors.length>0?"failed":"not-applicable",method:ce.method,configPath:ce.configPath,configPaths:ce.configPaths,errors:ce.errors}}import{tmpdir as xg}from"node:os";import{join as Cg}from"node:path";var Sg=Object.freeze([{command:"git reset --hard",description:"git reset --hard",expectBlocked:!0},{command:"rm -rf /",description:"rm -rf /",expectBlocked:!0},{command:"rm -rf ./node_modules",description:"rm in cwd (safe)",expectBlocked:!1}]),Rg=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),safety:Object.freeze({}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),Pg={strict:!1,paranoidRm:!1,paranoidInterpreters:!1,worktreeMode:!1,effectiveLevel:"standard",capabilities:{fail_closed:{enabled:!1,source:"preset",sources:[]},paranoid_rm:{enabled:!1,source:"preset",sources:[]},paranoid_interpreters:{enabled:!1,source:"preset",sources:[]}}};function Sc(){let ce=Cg(xg(),"cc-safety-net-self-test"),me=Sg.map((ge)=>{let he=j(c("self-test",{command:ge.command},{kind:"command",shell:"auto"},{configCwd:ce,executionCwd:ce},ge.command),{guard:{dependencies:{loadPolicySnapshot:()=>Rg,getModes:()=>Pg,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),Se=ge.expectBlocked?"blocked":"allowed",Fe=he.decision.kind==="deny"?"blocked":"allowed";return{command:ge.command,description:ge.description,expected:Se,actual:Fe,passed:Se===Fe,reason:he.decision.kind==="deny"?he.decision.reason:void 0,ruleId:he.decision.kind==="deny"?he.decision.ruleId:void 0}});return{passed:me.filter((ge)=>ge.passed).length,failed:me.filter((ge)=>!ge.passed).length,total:me.length,results:me}}function ji(ce){let me=Wt({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},ce);if(vn(me.errors))return null;return{json:me.flags.json,skipUpdateCheck:me.flags.skipUpdateCheck}}async function Rc(ce={}){let me=await yr(!ce.json,()=>{let ge=Dg(ce);return{ready:ge,finish:()=>ge}},()=>hr(),{loadingMessage:"Checking system status…"});if(ce.json)console.log(JSON.stringify(me,null,2));else Ag(me);return me.engineSelfTest.failed>0||me.findings.some((ge)=>ge.severity==="error")?1:0}async function Dg(ce){let me=ce.cwd??process.cwd(),ge=await mr(),he=er(me,{ampPluginListOutput:ge.ampPluginListOutput,codexPluginListOutput:ge.codexPluginListOutput,copilotCliVersion:ge.versions["copilot-cli"]}),Se=ba(me),Fe=La(),He=x({cwd:me}),Ge=He.policy,Dt=E(Ge),At=U(Ge,Dt.capabilities),Tt=qr(7),Ft=Ya(me),jt=ce.skipUpdateCheck?{currentVersion:Xt(),latestVersion:null,updateAvailable:!1}:await Cn(),It={hooks:he,engineSelfTest:Sc(),userConfig:Se.userConfig,projectConfig:Se.projectConfig,configState:$e(He),effectiveRules:Se.effectiveRules,shadowedRules:Se.shadowedRules,environment:Fe,effectiveSafety:{selectedPreset:Ge.safety.level??"standard",level:Dt.effectiveLevel,capabilities:Dt.capabilities,ruleOverrides:Ge.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(At).filter(([,$t])=>$t.source==="rule_override"&&$t.override==="off"&&$t.inheritedEnabled&&$t.changesInherited).map(([$t])=>$t),ruleCounts:{stored:Object.keys(Ge.destructiveCommandRuleOverrides).length,effective:Object.values(At).filter(($t)=>$t.changesInherited).length},...He.policyScopes?{policyScopes:He.policyScopes}:{}},...Ft.length>0?{v2Leftovers:Ft}:{},posture:$a(Se.userConfig.path),activity:Tt,update:jt,system:ge};return{...It,findings:ka(It)}}function Ag(ce){console.log(),console.log(Ca(ce.hooks)),console.log(),console.log(Sa(ce.engineSelfTest)),console.log(),console.log(Ra(ce)),console.log(),console.log(Pa(ce.environment)),console.log(),console.log(Da(ce)),console.log(),console.log(Aa(ce.findings)),console.log(),console.log(Ea(ce.activity)),console.log(),console.log(Ta(ce.system)),console.log(),console.log(_a(ce.update)),console.log(Ia(ce))}import{existsSync as Eg}from"node:fs";var _g=/^[A-Za-z0-9_@%+=:,./-]+$/,Pc="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Ni(ce){let me=Wt({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},ce);if(vn(me.errors))return console.error(Pc),console.error("Pass -- before a command that starts with dashes."),null;if(me.values.cwd!==void 0&&!Eg(me.values.cwd))return console.error(`Error: --cwd path does not exist: ${me.values.cwd}`),null;let ge=me.positionals.length===1?me.positionals[0]:me.positionals.map((he)=>_g.test(he)?he:`'${he.replaceAll("'","'\\''")}'`).join(" ");if(!ge)return console.error("Error: No command provided"),console.error(Pc),null;return{json:me.flags.json,cwd:me.values.cwd,command:ge}}function Dc(ce){if(ce)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function Ac(ce,me){let he=me-18;return[`${ce.dtl}${ce.dh.repeat(me)}${ce.dtr}`,`${ce.dv} Command Analysis${" ".repeat(he)}${ce.dv}`,`${ce.dbl}${ce.dh.repeat(me)}${ce.dbr}`]}function Hi(ce){return JSON.stringify(ce)}function Ec(ce,me=0){return`[${ce.map((he,Se)=>xa(he,Se,me)).join(",")}]`}function Rr(ce,me,ge=70){let he=ce.split(" "),Se=[],Fe="";for(let He of he)if(Fe&&Fe.length+He.length+1>ge)Se.push(Fe),Fe=He;else Fe=Fe?`${Fe} ${He}`:He;if(Fe)Se.push(Fe);return Se.map((He,Ge)=>Ge===0?He:`${me}${He}`)}function _c(ce,me,ge){let he=[];switch(ce.type){case"parse":return null;case"env-strip":return he.push(""),he.push(`STEP ${me} ${ge.h} Strip environment variables`),he.push(` Removed: ${ce.envVars.map((Se)=>`${Se}=<redacted>`).join(", ")}`),he.push(` Tokens: ${Hi(ce.output)}`),{lines:he,incrementStep:!0};case"leading-tokens-stripped":return he.push(""),he.push(`STEP ${me} ${ge.h} Strip wrappers`),he.push(` Removed: ${ce.removed.join(", ")}`),he.push(` Tokens: ${Hi(ce.output)}`),{lines:he,incrementStep:!0};case"shell-wrapper":return he.push(""),he.push(`STEP ${me} ${ge.h} Detect shell wrapper`),he.push(` Wrapper: ${ce.wrapper} -c`),he.push(` Inner: ${ce.innerCommand}`),{lines:he,incrementStep:!0};case"interpreter":{if(he.push(""),he.push(`STEP ${me} ${ge.h} Detect interpreter`),he.push(` Interpreter: ${ce.interpreter}`),he.push(` Code: ${ce.codeArg}`),ce.paranoidBlocked)he.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:he,incrementStep:!0}}case"busybox":return he.push(""),he.push(`STEP ${me} ${ge.h} Busybox wrapper`),he.push(` Subcommand: ${ce.subcommand}`),{lines:he,incrementStep:!0};case"transparent-wrapper":return he.push(""),he.push(`STEP ${me} ${ge.h} Transparent wrapper`),he.push(` Wrapper: ${ce.wrapper}`),he.push(` Tokens: ${Hi(ce.output)}`),{lines:he,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(he.push(""),he.push(`STEP ${me} ${ge.h} Match rules`),he.push(` Rule: ${ce.rule}()`),ce.matched)he.push(" Result: MATCHED");else he.push(" Result: No match");return{lines:he,incrementStep:!0}}case"worktree-relaxation":return he.push(""),he.push(`STEP ${me} ${ge.h} Worktree relaxation`),he.push(` Mode: ${r.worktree.name}`),he.push(` Git cwd: ${ce.gitCwd}`),he.push(" Result: Allowed local discard in linked worktree"),{lines:he,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(ce.embeddedCommandFound)return he.push(""),he.push(`STEP ${me} ${ge.h} Fallback scan`),he.push(` Found: ${ce.embeddedCommandFound}`),{lines:he,incrementStep:!0};return null}case"custom-rules-check":{if(ce.rulesChecked){if(he.push(""),he.push(`STEP ${me} ${ge.h} Custom rules`),ce.matched)he.push(" Result: MATCHED");else he.push(" Result: No match");return{lines:he,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(ce.matched)return he.push(""),he.push(`STEP ${me} ${ge.h} Dangerous text check`),he.push(` Token: ${ce.token}`),he.push(" Result: MATCHED"),{lines:he,incrementStep:!0};return null}case"strict-unparseable":return he.push(""),he.push(`STEP ${me} ${ge.h} Strict mode check`),he.push(` Command: ${ce.rawCommand}`),he.push(" Result: ✗ UNPARSEABLE"),{lines:he,incrementStep:!0};case"segment-skipped":return null;case"error":return he.push(""),he.push(`ERROR: ${ce.message}`),{lines:he,incrementStep:!1};default:return ce}}function Mi(ce,me){let ge=Dc(me?.asciiOnly??!1),he=58,Se=[],Fe=1;Se.push(...Ac(ge,58)),Se.push("");let He=ce.trace.steps.find(($t)=>$t.type==="error");if(He&&He.type==="error"){Se.push("ERROR"),Se.push(` ${He.message}`),Se.push(""),Se.push("RESULT"),Se.push(` Status: ${ce.result==="blocked"?Ht.red("BLOCKED"):Ht.green("ALLOWED")}`),Se.push(""),Se.push("CONFIG");let $t=ce.configSource??"none";return Se.push(` Path: ${$t}`),Se.join(`
213
+ `)}let Ge=ce.trace.steps.find(($t)=>$t.type==="parse");if(Ge&&Ge.type==="parse"){Se.push("INPUT"),Se.push(` ${Ge.input}`),Se.push(""),Se.push(`STEP ${Fe} ${ge.h} Split shell commands`),Fe++;for(let $t=0;$t<Ge.segments.length;$t++){let Ot=Ge.segments[$t];if(Ot){let Ut=Math.random();Se.push(` Segment ${$t+1}: ${Ec(Ot,Ut)}`)}}}let Dt=ce.trace.segments,At=Dt.length>1;for(let $t of Dt){if(At){Se.push("");let Nt="";if(Ge&&Ge.type==="parse"){let Io=Ge.segments[$t.index];if(Io)Nt=Io.join(" ")}let Vt=54,Mt=Nt,zt=` Segment ${$t.index+1}: `,un=" ";if(Nt){if(zt.length+Nt.length+un.length>Vt){let bu=Vt-zt.length-un.length;Mt=`${Nt.substring(0,bu-1)}…`}}let Ir=Nt?`${zt}${Mt}${un}`:` Segment ${$t.index+1} `,yu=Nt?`${zt}${Ht.cyan(Mt)}${un}`:Ir,us=58-Ir.length,ps=Math.floor(us/2),vu=us-ps;Se.push(`${ge.sh.repeat(ps)}${yu}${ge.sh.repeat(vu)}`)}if($t.steps.find((Nt)=>Nt.type==="segment-skipped")){Se.push(""),Se.push(" (skipped — prior segment blocked)");continue}let Ut=!1,Gt=!1;for(let Nt of $t.steps){let Vt=_c(Nt,Fe,ge);if(Vt){if(Gt=!0,Nt.type==="recurse"){Se.push("");let Mt=" RECURSING ",zt=58-Mt.length-4;Se.push(` ${ge.tl}${ge.h}${Mt}${ge.h.repeat(zt)}`),Se.push(` ${ge.v}`),Ut=!0;continue}for(let Mt of Vt.lines)if(Ut)Se.push(` ${ge.v} ${Mt}`);else Se.push(Mt);if(Vt.incrementStep)Fe++}}if(Ut)Se.push(` ${ge.v}`),Se.push(` ${ge.bl}${ge.h.repeat(56)}`),Ut=!1;if(!Gt)Se.push(""),Se.push(` ${Ht.green("✓")} Allowed (no matching rules)`)}if(Se.push(""),Se.push("RESULT"),ce.result==="blocked"){if(Se.push(` Status: ${Ht.red("BLOCKED")}`),ce.customRule){if(Se.push(` Rule: ${ce.customRule.id}`),ce.customRule.rulebook)Se.push(` Rulebook: ${ce.customRule.rulebook.name} ${ce.customRule.rulebook.version}`);if(ce.customRule.source)Se.push(` Source: ${ce.customRule.source}`);if(ce.customRule.override)Se.push(` Override: reason ${ce.customRule.override.reason}`)}if(ce.reason){let $t=Rr(ce.reason," ");Se.push(` Reason: ${$t[0]}`);for(let Ot=1;Ot<$t.length;Ot++)Se.push($t[Ot]??"")}}else Se.push(` Status: ${Ht.green("ALLOWED")}`);Se.push(""),Se.push("CONFIG");let Tt=ce.configSource??"none",Ft=ce.configValid?"":" (invalid)";Se.push(` Path: ${Tt}${Ft}`);let jt=ce.safetyPresetScope;Se.push(` Safety preset: ${ce.selectedPreset??"standard"}${jt?` (${Vr(jt)})`:""}`),Se.push(` Effective capabilities: ${ce.effectiveLevel}`);let It=Object.entries(ce.destructiveCommandRuleOverrides??{});if(Se.push(` Rule customizations: ${It.length}`),ce.ruleActivation)Se.push(` Rule activation: ${ce.ruleActivation.id} — ${ce.ruleActivation.enabled?"on":"off"} via ${ce.ruleActivation.source}`);return Se.join(`
214
+ `)}function Ui(ce){return JSON.stringify(ce,null,2)}function Tc(ce){return new Promise((me)=>{process.stdout.write(`${ce}
215
+ `,()=>me())})}async function Ic(ce){let me=Ni(ce);if(!me)return 1;try{let ge=qn(me.command,{cwd:me.cwd}),he=!!process.env.NO_COLOR||!process.stdout.isTTY;return await Tc(me.json?Ui(ge):Mi(ge,{asciiOnly:he})),0}catch(ge){if(!(ge instanceof w)&&!(ge instanceof s)&&!(ge instanceof a))throw ge;if(me.json)return await Tc(JSON.stringify({error:ge.message})),1;return console.error(ge.message),1}}var $c="2.3.4",dn=" ",On="cc-safety-net";function Oc(ce){return ce.argument?`${ce.flags} ${ce.argument}`:ce.flags}function Tg(ce){return Math.max(...ce.map((me)=>Oc(me).length))}function Ig(ce){return Math.max(...ce.map((me)=>me.usage.length))}function $g(ce){return Math.max(...ce.map((me)=>`${On} ${me.usage}`.length))}function Og(ce,me){let ge=`${On} ${ce.usage}`;return`${dn}${ge.padEnd(me+2)}${ce.description}`}function wn(ce,me){return`${dn}${ce.padEnd(Math.max(40,ce.length+2))}${me}`}function tr(ce,me=console.log){let ge=[];if(ge.push(`${On} ${ce.name}`),ge.push(""),ge.push(`${dn}${ce.description}`),ge.push(""),ge.push("USAGE:"),ge.push(`${dn}${On} ${ce.usage}`),ge.push(""),ce.subcommands&&ce.subcommands.length>0){ge.push("SUBCOMMANDS:");let he=Ig(ce.subcommands);for(let Se of ce.subcommands)ge.push(`${dn}${Se.usage.padEnd(he+2)}${Se.description}`);ge.push("")}if(ce.options.length>0){ge.push("OPTIONS:");let he=Tg(ce.options);for(let Se of ce.options){let Fe=Oc(Se),He=Se.default?`${Se.description} (default: ${Se.default})`:Se.description;ge.push(`${dn}${Fe.padEnd(he+2)}${He}`)}ge.push("")}if(ce.examples&&ce.examples.length>0){ge.push("EXAMPLES:");for(let he of ce.examples)ge.push(`${dn}${he}`)}me(ge.join(`
216
+ `))}function Gi(){let ce=$g(Gr),me=[];me.push(`${On} v${$c}`),me.push(""),me.push("Blocks destructive commands and secret access."),me.push(""),me.push("COMMANDS:");for(let ge of Gr)me.push(Og(ge,ce));me.push(""),me.push("GLOBAL OPTIONS:"),me.push(`${dn}-h, --help Show help (use with command for command-specific help)`),me.push(`${dn}-V, --version Show version`),me.push(""),me.push("HELP:"),me.push(`${dn}${On} help <command> Show help for a specific command`),me.push(`${dn}${On} <command> --help Show help for a specific command`),me.push(""),me.push("ENVIRONMENT VARIABLES:"),me.push(wn(`${r.level.name}=standard|strict|paranoid`,"Set session safety level")),me.push(wn(`${r.worktree.name}=1`,"Allow local git discards in linked worktrees")),me.push(wn(`${r.debug.name}=1`,"Print diagnostic messages to stderr")),me.push(wn(`${r.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),me.push(wn("CC_SAFETY_NET_HOME","Override rule config home directory")),me.push(""),me.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),me.push(wn(`${r.strict.name}=1`,"Force safety.overrides.fail_closed on")),me.push(wn(`${r.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),me.push(wn(`${r.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),me.push(wn(`${r.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),me.push(""),me.push("Documentation: https://ccsafetynet.com/docs"),console.log(me.join(`
217
+ `))}function Fc(){console.log($c)}function Pr(ce,me=console.log){let ge=Br(ce);if(!ge)return!1;if(ge.name.toLowerCase()!==ce.toLowerCase())return!1;return tr(ge,me),!0}import{existsSync as es,readFileSync as Dd}from"node:fs";import{homedir as Th,tmpdir as Ih}from"node:os";import{join as Xi}from"node:path";import*as Rn from"node:readline";function Fg(ce){return ce==="install"?"Install":"Uninstall"}function jg(ce){return ce==="install"?"Installing":"Uninstalling"}function Ng(ce){return ce==="install"?"into":"from"}function Hc(ce){return ce?.available===!0}function Hg(ce,me){let ge=new Set(me);return ce.filter((he)=>ge.has(he.target)).map((he)=>he.target)}function jc(ce,me,ge){if(ce.length===0||ce.every((he)=>!he.available))return me;return Array.from({length:ce.length},(he,Se)=>Se+1).map((he)=>(me+he*ge+ce.length)%ce.length).find((he)=>Hc(ce[he]))}function Mg(ce,me,ge){if(ge.ctrl&&ge.name==="c")return"interrupt";if(ge.name==="escape"||me==="q")return"abort";if(ce==="install"&&(me==="u"||me==="U"))return"update";if(ge.name==="up"||me==="k")return"up";if(ge.name==="down"||me==="j")return"down";if(ge.name==="space"||me===" ")return"toggle";if(ge.name==="return"||ge.name==="enter")return"confirm";return null}function Ug(ce){return{cursor:ce.findIndex((me)=>me.available),selected:[]}}function Gg(ce,me,ge){if(ge==="confirm"||ge==="update"||ge==="abort"||ge==="interrupt")return{state:ce,done:ge};if(ge==="up")return{state:{...ce,cursor:jc(me,ce.cursor,-1)}};if(ge==="down")return{state:{...ce,cursor:jc(me,ce.cursor,1)}};let he=me[ce.cursor];if(!Hc(he))return{state:ce};let Se=ce.selected.includes(he.target)?ce.selected.filter((Fe)=>Fe!==he.target):Hg(me,[...ce.selected,he.target]);return{state:{...ce,selected:Se}}}var Mc="◉",Uc="◯",Gc=">",Bc=" ";function Bg(ce,me,ge,he={}){let Se=he.color!==!1,Fe=Se?Ht.dim:(Dt)=>Dt,He=Se?Ht.green:(Dt)=>Dt,Ge=Se?Ht.bold:(Dt)=>Dt;return["",`${Fg(ce)} CC Safety Net ${Ng(ce)}:`,"",...me.map((Dt,At)=>{let Tt=ge.selected.includes(Dt.target),Ft=At===ge.cursor,jt=Tt?Mc:Uc,It=Ft?Gc:Bc,$t=Dt.available?"":` (${Dt.unavailableReason??"not installed"})`,Ot=`${jt} ${Dt.label}${$t}`,Ut=!Dt.available?Fe(Ot):Tt?He(Ot):Ft?Ge(Ot):Ot;return`${It} ${Ut}`}),"",ce==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":me.some((Dt)=>Dt.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${ce}. q/Esc: close`].join(`
218
+ `)}var Nc=["global-hook","plugin"];function qg(ce,me,ge={}){let he=ge.color!==!1?Ht.bold:(Fe)=>Fe;return["","Install the Kimi Code integration as:","",...[`Global hook — ${me?"already installed; selecting it reports the current state":"write the hook into ~/.kimi-code/config.toml now"}`,"Native Kimi plugin — print the steps to run inside Kimi Code"].map((Fe,He)=>{let Ge=He===ce,Dt=`${Ge?Mc:Uc} ${Fe}`;return`${Ge?Gc:Bc} ${Ge?he(Dt):Dt}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
219
+ `)}function qc(ce){let{input:me,output:ge}=ce;Rn.emitKeypressEvents(me);let he=me.isRaw===!0;me.setRawMode(!0),me.resume();let Se=0,Fe=()=>{if(Se===0)return;Rn.moveCursor(ge,0,-Se),Rn.cursorTo(ge,0),Rn.clearScreenDown(ge)},He=()=>{Fe();let Ge=ce.render();ge.write(`${Ge}
220
+ `),Se=Ge.split(`
221
+ `).length};return new Promise((Ge)=>{let Dt=(Tt)=>{me.off("keypress",At),me.setRawMode(he),me.pause(),Fe(),Ge(Tt)};function At(Tt,Ft){ce.onKey(Tt,Ft,{finish:Dt,draw:He})}me.on("keypress",At),He()})}function Vc(ce={}){let me=0;return qc({input:ce.input??process.stdin,output:ce.output??process.stdout,render:()=>qg(me,ce.globalHookInstalled===!0),onKey:(ge,he,Se)=>{if(he.ctrl&&he.name==="c"){Se.finish(null),(ce.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(he.name==="escape"||ge==="q")return Se.finish(null);if(he.name==="return"||he.name==="enter")return Se.finish(Nc[me]);if(he.name==="up"||he.name==="down"||ge==="k"||ge==="j")me=(me+1)%Nc.length,Se.draw()}})}function Bi(ce=process.stdin,me=process.stdout){return Boolean(ce.isTTY&&me.isTTY&&typeof ce.setRawMode==="function")}function zc(ce,me,ge={}){let he=ge.output??process.stdout,Se=Ug(me);return qc({input:ge.input??process.stdin,output:he,render:()=>Bg(ce,me,Se),onKey:(Fe,He,Ge)=>{let Dt=Mg(ce,Fe,He);if(!Dt)return;let At=Gg(Se,me,Dt);if(Se=At.state,At.done==="interrupt"){Ge.finish(null),(ge.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(At.done==="abort")return Ge.finish(null);if(At.done==="update")return Ge.finish("update");if(At.done==="confirm"){if(Se.selected.length===0){he.write("\x07"),Ge.draw();return}Ge.finish([...Se.selected]),he.write(`${jg(ce)} selected integrations...
222
+ `);return}Ge.draw()}})}import{existsSync as Jc,lstatSync as zg,mkdirSync as Kg,mkdtempSync as Jg,readdirSync as Wg,readFileSync as rr,rmSync as Lo}from"node:fs";import{tmpdir as Yg}from"node:os";import{basename as Zg,dirname as Xg,join as on}from"node:path";import{fileURLToPath as Qg}from"node:url";var qi="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",Fn="cc-safety-net",jn="cc-safety-net/index.ts";import{spawn as Vg}from"node:child_process";var Vi=(ce,me)=>{let ge=_n([...ce],process.env);return new Promise((he)=>{let Se=Vg(ge.cmd,ge.args,{cwd:me,stdio:["ignore","pipe","pipe"]}),Fe=Pi(Se),He=!1,Ge=setTimeout(()=>{He=!0,Se.kill()},120000);Se.on("error",(Dt)=>{clearTimeout(Ge),he({status:null,errorCode:Dt.code,stdout:Fe.stdout,stderr:[Dt.message,Fe.stderr].filter(Boolean).join(`
223
+ `)})}),Se.on("close",(Dt)=>{clearTimeout(Ge),he({status:He?null:Dt,errorCode:He?"ETIMEDOUT":void 0,stdout:Fe.stdout,stderr:Fe.stderr})})})};var nr="cc-safety-net.ts",Kc=on("amp",jn);function eh(ce){return on(ce,".config","amp","plugins","cc-safety-net.ts")}function th(){let ce=Xg(Qg(import.meta.url));return[on(ce,"..",Kc),on(ce,"..","..","..","dist",Kc)]}function nh(ce=th()){let me=ce.find((ge)=>Jc(ge)&&zg(ge).isFile());if(!me)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return me}function Wc(ce){try{return JSON.parse(ce)}catch{return}}function wo(ce){return ce.subarray(0,Buffer.byteLength(qi)).toString("utf-8")===qi}async function Dr(ce,me,ge){let he=await ce(me,ge);if(he.status===0)return he;throw Error([`Failed to run ${me.join(" ")}${he.status===null?"":` (exit ${he.status})`}.`,[he.stdout,he.stderr].filter(Boolean).join(`
200
224
  `).trim()].filter(Boolean).join(`
201
- `))}async function Uc(e){let t=await e(["amp","plugins","repositories","--json"]);if(t.status===null)throw Error(`${t.errorCode==="ENOENT"?'Amp CLI not found. Install the amp CLI, sign in with "amp login", and rerun install --amp.':`amp plugins repositories --json did not finish (${t.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
202
- ${t.stderr}`.trim());if(t.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${t.status}). Sign in with "amp login" and rerun install --amp.
203
- ${[t.stdout,t.stderr].filter(Boolean).join(`
204
- `)}`.trim());let n=Mc(t.stdout),r=(Array.isArray(n)?n:[]).filter((o)=>k(o,"scope")==="user"&&k(o,"exists")===!0&&k(o,"viewerCanWrite")===!0).map((o)=>k(o,"cloneRef")).find((o)=>typeof o==="string"&&o.length>0);if(!r)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return r}async function Gc(e,t){let n=Vg(G(Kg(),"cc-safety-net-amp-"));try{return await on(e,["amp","clone","user-plugins",n]),await t(n)}finally{tr(n,{recursive:!0,force:!0})}}function Ko(e){return`rerun ${e==="overwrite"?"install":"uninstall"} --amp`}function Bc(e,t,n){let r=G(e,t),o=_(r);if(!o)return;if(o.isSymbolicLink()||!o.isFile())throw Error(`Refusing to ${n} ${t} in your Amp personal plugins repository: not a regular file. Remove it there and ${Ko(n)}.`);let i=wt(r);if(nr(i))return i;throw Error(`Refusing to ${n} unmanaged file ${t} in your Amp personal plugins repository. Remove it there and ${Ko(n)}.`)}function qc(e,t){let n=G(e,Ze),r=_(n);if(!r)return;if(r.isSymbolicLink()||!r.isDirectory())throw Error(`Refusing to ${t} ${Ze} in your Amp personal plugins repository: not a regular directory. Remove it there and ${Ko(t)}.`);return Bc(e,Xe,t)}function eh(e){let t=G(e,Lt),n=_(t);if(!n||n.isSymbolicLink()||!n.isFile())return;let r=wt(t);return nr(r)?r:void 0}async function Vc(e,t,n,r){if(await on(e,n,t),(await on(e,["git","status","--porcelain"],t)).stdout.trim()==="")return!1;return await on(e,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",r],t),await on(e,["git","push","origin","HEAD"],t),!0}function er(e,t){th(e,t),nh(e,t)}function zc(e,t){if(t==="keep")return;throw Error(`Local Amp plugin ${e} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function th(e,t){let n=Zg(e),r=_(n);if(!r)return;if(!r.isSymbolicLink()&&r.isFile()&&nr(wt(n))){tr(n);return}zc(n,t)}function nh(e,t){let n=G(e,".config","amp","plugins",Ze),r=_(n);if(!r)return;if(!r.isSymbolicLink()&&r.isDirectory()&&rh(n)){tr(n,{recursive:!0});return}zc(n,t)}function rh(e){let t=Jg(Xe);if(zg(e).join("\x00")!==t)return!1;let n=G(e,t),r=_(n);return!!r&&!r.isSymbolicLink()&&r.isFile()&&nr(wt(n))}function oh(){let e=ve();if(!Hc(e))return"";let t=Mc(wt(e,"utf-8"));if(!t||typeof t!=="object"||Array.isArray(t))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(Y(t))};
205
- `}async function Kc(e,t=Qg(),n=zo){let r=Buffer.concat([wt(t),Buffer.from(oh(),"utf-8")]),o=await Uc(n);return Gc(n,async(i)=>{let s=`${o}/${Ze}`,a=qc(i,"overwrite"),l=Bc(i,Lt,"overwrite");if(a?.equals(r)&&!l)return er(e,"fail"),{path:s,alreadyInstalled:!0};if(qg(G(i,Ze),{recursive:!0}),O(G(i,Xe),r),l)tr(G(i,Lt));let c=await Vc(n,i,["git","add","--",Xe,...l?[Lt]:[]],`chore: update cc-safety-net plugin to v${I()}`);return er(e,"fail"),{path:s,alreadyInstalled:!c}})}async function Jc(e,t=zo){let n=await Uc(t);return Gc(t,async(r)=>{let o=qc(r,"remove"),i=eh(r),s=`${n}/${i&&!o?Lt:Ze}`;if(!o&&!i)return er(e,"keep"),{path:s,alreadyInstalled:!1};return await Vc(t,r,["git","rm","--",...o?[Xe]:[],...i?[Lt]:[]],`chore: remove cc-safety-net plugin v${I()}`),er(e,"keep"),{path:s,alreadyInstalled:!0}})}import{existsSync as Wc,mkdirSync as ih,readFileSync as sh}from"node:fs";import{dirname as ah}from"node:path";var Jo="npx -y cc-safety-net hook --agy-cli",Qe="cc-safety-net";function et(e){return Boolean(e)&&typeof e==="object"&&!Array.isArray(e)}function or(){return{PreToolUse:[{hooks:[{type:"command",command:Jo,timeout:30}]}]}}function Yc(e){try{let t=JSON.parse(sh(e,"utf-8"));if(!t||typeof t!=="object"||Array.isArray(t))throw Error("Antigravity hooks config must be a JSON object");return t}catch(t){if(t instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${e}: ${t.message}`);throw t}}function Zc(e){let t=e[Qe];if(t===void 0){let r=or();return e[Qe]=r,{definition:r,preToolUse:r.PreToolUse??[]}}if(!et(t))throw Error(`Antigravity hooks config entry "${Qe}" must be an object`);let n=Array.isArray(t.PreToolUse)?t.PreToolUse:[];return t.PreToolUse=n,{definition:t,preToolUse:n}}function Xc(e){if(!Array.isArray(e.PreToolUse))return!1;return e.PreToolUse.some((t)=>et(t)&&Array.isArray(t.hooks)&&t.hooks.some((n)=>et(n)&&n.command===Jo))}function lh(e){return Object.values(e).some((t)=>et(t)&&t.enabled!==!1&&Xc(t))}function ch(e){if(e[Qe]===void 0)return!1;let t=Zc(e);if(t.definition.enabled!==!1||!Xc(t.definition))return!1;return t.definition.enabled=!0,!0}function dh(e){if(e[Qe]===void 0){e[Qe]=or();return}let t=Zc(e);t.definition.enabled=!0,t.preToolUse.push(or().PreToolUse?.[0]??{hooks:[]})}function uh(e){let t=!1;for(let n of Object.values(e)){if(!et(n)||!Array.isArray(n.PreToolUse))continue;n.PreToolUse=n.PreToolUse.flatMap((r)=>{if(!et(r)||!Array.isArray(r.hooks))return[r];let o=r.hooks.filter((i)=>!et(i)||i.command!==Jo);if(o.length!==r.hooks.length)t=!0;return o.length===0?[]:[{...r,hooks:o}]})}return t}function rr(e,t){O(e,`${JSON.stringify(t,null,2)}
206
- `)}function Qc(e){let t=Gt(e);if(ih(ah(t),{recursive:!0}),!Wc(t))return rr(t,{[Qe]:or()}),{path:t,alreadyInstalled:!1};let n=Yc(t);if(lh(n))return{path:t,alreadyInstalled:!0};if(ch(n))return rr(t,n),{path:t,alreadyInstalled:!1};return dh(n),rr(t,n),{path:t,alreadyInstalled:!1}}function ed(e){let t=Gt(e);if(!Wc(t))return{path:t,alreadyInstalled:!1};let n=Yc(t);if(!uh(n))return{path:t,alreadyInstalled:!1};return rr(t,n),{path:t,alreadyInstalled:!0}}import{existsSync as ph,readdirSync as fh,rmSync as mh}from"node:fs";import{join as gh}from"node:path";function td(e,t=process.platform,n){if(!ph(e))return;let r=t==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);fh(e).filter((o)=>o!==n&&r.test(o)).forEach((o)=>{mh(gh(e,o),{recursive:!0,force:!0})})}import{spawn as hh}from"node:child_process";var pe=X.map((e)=>({target:e.id,flag:e.flag,label:D(e.id),probeCommand:e.probeCommand}));function Wo(e){let t=new Set(e);return pe.map((n)=>n.target).filter((n)=>t.has(n))}async function nd(e,t){for(let n of e)await t(n)}var yh=5000;function Yo(e){return new Promise((t)=>{let n=ze([...e],process.env),r=hh(n.cmd,n.args,{env:process.env,stdio:"ignore"}),o=!1,i=(a)=>{if(o)return;o=!0,clearTimeout(s),t(a)},s=setTimeout(()=>{r.kill(),i(!1)},yh);r.on("error",()=>i(!1)),r.on("close",(a)=>i(a===0))})}function rd(e=Yo,t={}){let n=new Set(t.configuredTargets??[]);return Promise.all(pe.map(async(r)=>({target:r.target,flag:r.flag,label:r.label,...id(t.action,await e(r.probeCommand),n.has(r.target))})))}function od(e,t){let n=new Set(t.configuredTargets??[]);return e.map((r)=>({...r,...id(t.action,r.available,n.has(r.target))}))}function id(e,t,n){if(e==="uninstall")return n?{available:!0}:{available:!1,unavailableReason:"not installed"};if(e==="install"&&n)return{available:!1,unavailableReason:"already installed"};if(!t)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}import{existsSync as sd,readdirSync as vh,rmSync as bh}from"node:fs";import{join as kt}from"node:path";function ir(e,t=process.platform){let n=kt(process.env.npm_config_cache||(t==="win32"?kt(process.env.LOCALAPPDATA||kt(e,"AppData","Local"),"npm-cache"):kt(e,".npm")),"_npx");if(!sd(n))return;vh(n).filter((r)=>sd(kt(n,r,"node_modules","cc-safety-net"))).forEach((r)=>{bh(kt(n,r),{recursive:!0,force:!0})})}import{existsSync as ld,mkdirSync as Lh,readFileSync as cd}from"node:fs";import{dirname as wh,join as ad}from"node:path";var sn="npx -y cc-safety-net hook --kimi-code",Zo=`[[hooks]]
225
+ `))}async function Yc(ce){let me=await ce(["amp","plugins","repositories","--json"]);if(me.status===null)throw Error(`${me.errorCode==="ENOENT"?'Amp CLI not found. Install the amp CLI, sign in with "amp login", and rerun install --amp.':`amp plugins repositories --json did not finish (${me.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
226
+ ${me.stderr}`.trim());if(me.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${me.status}). Sign in with "amp login" and rerun install --amp.
227
+ ${[me.stdout,me.stderr].filter(Boolean).join(`
228
+ `)}`.trim());let ge=Wc(me.stdout),he=(Array.isArray(ge)?ge:[]).filter((Se)=>Bt(Se,"scope")==="user"&&Bt(Se,"exists")===!0&&Bt(Se,"viewerCanWrite")===!0).map((Se)=>Bt(Se,"cloneRef")).find((Se)=>typeof Se==="string"&&Se.length>0);if(!he)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return he}async function Zc(ce,me){let ge=Jg(on(Yg(),"cc-safety-net-amp-"));try{return await Dr(ce,["amp","clone","user-plugins",ge]),await me(ge)}finally{Lo(ge,{recursive:!0,force:!0})}}function zi(ce){return`rerun ${ce==="overwrite"?"install":"uninstall"} --amp`}function Xc(ce,me,ge){let he=on(ce,me),Se=Yt(he);if(!Se)return;if(Se.isSymbolicLink()||!Se.isFile())throw Error(`Refusing to ${ge} ${me} in your Amp personal plugins repository: not a regular file. Remove it there and ${zi(ge)}.`);let Fe=rr(he);if(wo(Fe))return Fe;throw Error(`Refusing to ${ge} unmanaged file ${me} in your Amp personal plugins repository. Remove it there and ${zi(ge)}.`)}function Qc(ce,me){let ge=on(ce,Fn),he=Yt(ge);if(!he)return;if(he.isSymbolicLink()||!he.isDirectory())throw Error(`Refusing to ${me} ${Fn} in your Amp personal plugins repository: not a regular directory. Remove it there and ${zi(me)}.`);return Xc(ce,jn,me)}function rh(ce){let me=on(ce,nr),ge=Yt(me);if(!ge||ge.isSymbolicLink()||!ge.isFile())return;let he=rr(me);return wo(he)?he:void 0}async function ed(ce,me,ge,he){if(await Dr(ce,ge,me),(await Dr(ce,["git","status","--porcelain"],me)).stdout.trim()==="")return!1;return await Dr(ce,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",he],me),await Dr(ce,["git","push","origin","HEAD"],me),!0}function bo(ce,me){oh(ce,me),ih(ce,me)}function td(ce,me){if(me==="keep")return;throw Error(`Local Amp plugin ${ce} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function oh(ce,me){let ge=eh(ce),he=Yt(ge);if(!he)return;if(!he.isSymbolicLink()&&he.isFile()&&wo(rr(ge))){Lo(ge);return}td(ge,me)}function ih(ce,me){let ge=on(ce,".config","amp","plugins",Fn),he=Yt(ge);if(!he)return;if(!he.isSymbolicLink()&&he.isDirectory()&&sh(ge)){Lo(ge,{recursive:!0});return}td(ge,me)}function sh(ce){let me=Zg(jn);if(Wg(ce).join("\x00")!==me)return!1;let ge=on(ce,me),he=Yt(ge);return!!he&&!he.isSymbolicLink()&&he.isFile()&&wo(rr(ge))}function ah(){let ce=y();if(!Jc(ce))return"";let me=Wc(rr(ce,"utf-8"));if(!me||typeof me!=="object"||Array.isArray(me))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(f(me))};
229
+ `}async function nd(ce,me=nh(),ge=Vi){let he=Buffer.concat([rr(me),Buffer.from(ah(),"utf-8")]),Se=await Yc(ge);return Zc(ge,async(Fe)=>{let He=`${Se}/${Fn}`,Ge=Qc(Fe,"overwrite"),Dt=Xc(Fe,nr,"overwrite");if(Ge?.equals(he)&&!Dt)return bo(ce,"fail"),{path:He,alreadyInstalled:!0};if(Kg(on(Fe,Fn),{recursive:!0}),Qt(on(Fe,jn),he),Dt)Lo(on(Fe,nr));let At=await ed(ge,Fe,["git","add","--",jn,...Dt?[nr]:[]],`chore: update cc-safety-net plugin to v${Xt()}`);return bo(ce,"fail"),{path:He,alreadyInstalled:!At}})}async function rd(ce,me=Vi){let ge=await Yc(me);return Zc(me,async(he)=>{let Se=Qc(he,"remove"),Fe=rh(he),He=`${ge}/${Fe&&!Se?nr:Fn}`;if(!Se&&!Fe)return bo(ce,"keep"),{path:He,alreadyInstalled:!1};return await ed(me,he,["git","rm","--",...Se?[jn]:[],...Fe?[nr]:[]],`chore: remove cc-safety-net plugin v${Xt()}`),bo(ce,"keep"),{path:He,alreadyInstalled:!0}})}import{existsSync as od,mkdirSync as lh,readFileSync as ch}from"node:fs";import{dirname as dh}from"node:path";var Ki="npx -y cc-safety-net hook --agy-cli",Nn="cc-safety-net";function Hn(ce){return Boolean(ce)&&typeof ce==="object"&&!Array.isArray(ce)}function xo(){return{PreToolUse:[{hooks:[{type:"command",command:Ki,timeout:30}]}]}}function id(ce){try{let me=JSON.parse(ch(ce,"utf-8"));if(!me||typeof me!=="object"||Array.isArray(me))throw Error("Antigravity hooks config must be a JSON object");return me}catch(me){if(me instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${ce}: ${me.message}`);throw me}}function sd(ce){let me=ce[Nn];if(me===void 0){let he=xo();return ce[Nn]=he,{definition:he,preToolUse:he.PreToolUse??[]}}if(!Hn(me))throw Error(`Antigravity hooks config entry "${Nn}" must be an object`);let ge=Array.isArray(me.PreToolUse)?me.PreToolUse:[];return me.PreToolUse=ge,{definition:me,preToolUse:ge}}function ad(ce){if(!Array.isArray(ce.PreToolUse))return!1;return ce.PreToolUse.some((me)=>Hn(me)&&Array.isArray(me.hooks)&&me.hooks.some((ge)=>Hn(ge)&&ge.command===Ki))}function uh(ce){return Object.values(ce).some((me)=>Hn(me)&&me.enabled!==!1&&ad(me))}function ph(ce){if(ce[Nn]===void 0)return!1;let me=sd(ce);if(me.definition.enabled!==!1||!ad(me.definition))return!1;return me.definition.enabled=!0,!0}function fh(ce){if(ce[Nn]===void 0){ce[Nn]=xo();return}let me=sd(ce);me.definition.enabled=!0,me.preToolUse.push(xo().PreToolUse?.[0]??{hooks:[]})}function mh(ce){let me=!1;for(let ge of Object.values(ce)){if(!Hn(ge)||!Array.isArray(ge.PreToolUse))continue;ge.PreToolUse=ge.PreToolUse.flatMap((he)=>{if(!Hn(he)||!Array.isArray(he.hooks))return[he];let Se=he.hooks.filter((Fe)=>!Hn(Fe)||Fe.command!==Ki);if(Se.length!==he.hooks.length)me=!0;return Se.length===0?[]:[{...he,hooks:Se}]})}return me}function ko(ce,me){Qt(ce,`${JSON.stringify(me,null,2)}
230
+ `)}function ld(ce){let me=pr(ce);if(lh(dh(me),{recursive:!0}),!od(me))return ko(me,{[Nn]:xo()}),{path:me,alreadyInstalled:!1};let ge=id(me);if(uh(ge))return{path:me,alreadyInstalled:!0};if(ph(ge))return ko(me,ge),{path:me,alreadyInstalled:!1};return fh(ge),ko(me,ge),{path:me,alreadyInstalled:!1}}function cd(ce){let me=pr(ce);if(!od(me))return{path:me,alreadyInstalled:!1};let ge=id(me);if(!mh(ge))return{path:me,alreadyInstalled:!1};return ko(me,ge),{path:me,alreadyInstalled:!0}}import{existsSync as gh,readdirSync as hh,rmSync as yh}from"node:fs";import{join as vh}from"node:path";function dd(ce,me=process.platform,ge){if(!gh(ce))return;let he=me==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);hh(ce).filter((Se)=>Se!==ge&&he.test(Se)).forEach((Se)=>{yh(vh(ce,Se),{recursive:!0,force:!0})})}import{spawn as bh}from"node:child_process";var yn=an.map((ce)=>({target:ce.id,flag:ce.flag,label:Kt(ce.id),probeCommand:ce.probeCommand}));function Ji(ce){let me=new Set(ce);return yn.map((ge)=>ge.target).filter((ge)=>me.has(ge))}async function ud(ce,me){for(let ge of ce)await me(ge)}var Lh=5000;function Wi(ce){return new Promise((me)=>{let ge=_n([...ce],process.env),he=bh(ge.cmd,ge.args,{env:process.env,stdio:"ignore"}),Se=!1,Fe=(Ge)=>{if(Se)return;Se=!0,clearTimeout(He),me(Ge)},He=setTimeout(()=>{he.kill(),Fe(!1)},Lh);he.on("error",()=>Fe(!1)),he.on("close",(Ge)=>Fe(Ge===0))})}function pd(ce=Wi,me={}){let ge=new Set(me.configuredTargets??[]);return Promise.all(yn.map(async(he)=>({target:he.target,flag:he.flag,label:he.label,...md(me.action,await ce(he.probeCommand),ge.has(he.target))})))}function fd(ce,me){let ge=new Set(me.configuredTargets??[]);return ce.map((he)=>({...he,...md(me.action,he.available,ge.has(he.target))}))}function md(ce,me,ge){if(ce==="uninstall")return ge?{available:!0}:{available:!1,unavailableReason:"not installed"};if(ce==="install"&&ge)return{available:!1,unavailableReason:"already installed"};if(!me)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}import{existsSync as gd,readdirSync as wh,rmSync as kh}from"node:fs";import{join as or}from"node:path";function Co(ce,me=process.platform){let ge=or(process.env.npm_config_cache||(me==="win32"?or(process.env.LOCALAPPDATA||or(ce,"AppData","Local"),"npm-cache"):or(ce,".npm")),"_npx");if(!gd(ge))return;wh(ge).filter((he)=>gd(or(ge,he,"node_modules","cc-safety-net"))).forEach((he)=>{kh(or(ge,he),{recursive:!0,force:!0})})}import{existsSync as yd,mkdirSync as xh,readFileSync as vd}from"node:fs";import{dirname as Ch,join as hd}from"node:path";var Ar="npx -y cc-safety-net hook --kimi-code",Yi=`[[hooks]]
207
231
  event = "PreToolUse"
208
- command = "${sn}"`,Xo=`{ event = "PreToolUse", command = "${sn}" }`;function dd(e){return ad(process.env.KIMI_CODE_HOME??ad(e,".kimi-code"),"config.toml")}function kh(e){return e.split(`
209
- `).reduce((n,r)=>{if(/^\s*\[/.test(r))return n.activeTable=!0,n.lines.push(r),n;if(!n.activeTable&&/^\s*hooks\s*=\s*\[\s*]\s*(?:#.*)?$/.test(r))return n;return n.lines.push(r),n},{activeTable:!1,lines:[]}).lines.join(`
210
- `)}function xh(e,t){if(e[t]!=="#")return t;let n=e.indexOf(`
211
- `,t+1);return n===-1?e.length:n+1}function Ch(e,t){return Wn(e,t,{skipComment:xh,stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"})}function ud(e){let t=!1,n=0;while(n<e.length){let r=e.indexOf(`
212
- `,n),o=r===-1?e.length:r,i=e.slice(n,o);if(/^\s*\[/.test(i))t=!0;if(!t){let s=/^(\s*)hooks\s*=\s*\[/.exec(i);if(s){let a=n+s[0].lastIndexOf("[");return{start:a,end:Ch(e,a)}}}n=r===-1?e.length:r+1}return}function Sh(e,t){let n=e.slice(0,t.end).trimEnd(),r=nc(e,t.end),o=r===""?" ":`${r} `,i=!n.endsWith("[")&&!n.endsWith(",");return`${n}${i?",":""}
213
- ${o}${Xo}${e.slice(t.end)}`}function Rh(e){let t=ud(e);if(t&&e.slice(t.start+1,t.end).trim())return Sh(e,t);let n=kh(e).trimEnd();if(n==="")return`${Zo}
214
- `;return`${n}
215
-
216
- ${Zo}
217
- `}function Ph(e){return e.split(/(?=^\s*\[)/m).filter((n)=>!/^\s*\[\[hooks]]\s*$/m.test(n)||!n.includes(sn)).join("").trimEnd()}function Dh(e,t){let n=e.indexOf(Xo,t.start);if(n===-1||n>t.end)return e;return Yn(e,{start:n,end:n+Xo.length})}function pd(e){let t=dd(e);if(Lh(wh(t),{recursive:!0}),!ld(t))return O(t,`${Zo}
218
- `),{path:t,alreadyInstalled:!1};let n=cd(t,"utf-8");if(n.includes(sn))return{path:t,alreadyInstalled:!0};return O(t,Rh(n)),{path:t,alreadyInstalled:!1}}function fd(e){let t=dd(e);if(!ld(t))return{path:t,alreadyInstalled:!1};let n=cd(t,"utf-8");if(!n.includes(sn))return{path:t,alreadyInstalled:!1};let r=ud(n),o=r?Dh(n,r):`${Ph(n)}
219
- `;return O(t,o),{path:t,alreadyInstalled:!0}}var ei="safety-net@cc-marketplace",md=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),gd=new Set(["antigravity-cli","cursor","grok-build","hermes-agent","kimi-code"]);function ni(e){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(e??"")}function Ld(e){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(e??"")}function _h(e){return/^Marketplace `cc-marketplace`\s*$/m.test(e??"")}var wd={"claude-code":{installCommands:(e)=>{let t=On(e,"cc-safety-net@cc-marketplace");return{commands:[...t?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...po(e).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:On(e,ei)?[["claude","plugin","uninstall",ei]]:[],update:t}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(e,t)=>{let n=t??await ue(["codex","plugin","list"]),r=Ld(n);return{commands:[r||_h(n)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:ni(n)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:r}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:"Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."},"copilot-cli":{installCommands:async()=>{let e=await ue(["copilot","plugin","list"]),t=[...ol(e)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...il(e)?[["copilot","plugin","uninstall",tl]]:[]];if(nl(e))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",de]],cleanupCommands:t,update:!0};return{commands:[rl(await ue(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",de]],cleanupCommands:t}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(e)=>{let t=bo(e);if(t.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(t.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:To,installCommands:()=>({commands:Jl()}),uninstallCommands:[["openclaw","plugins","uninstall",A,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
220
- `)},opencode:{beforeInstall:Oo,installCommands:[["opencode","plugin","-g","-f","cc-safety-net@latest"]]},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]}};function ar(){return process.env.HOME??Ah()}function kd(e,t=(n)=>n){try{let n=JSON.parse(t(bd(e,"utf-8")));if(!n||typeof n!=="object"||Array.isArray(n))throw Error(`Settings file ${e} must be a JSON object`);return n}catch(n){if(n instanceof SyntaxError)throw Error(`Failed to parse ${e}: ${n.message}`);throw n}}function Th(e){let t=Qo(Jt(e),"settings.json");if(!ti(t))return;let n=kd(t,K),r=n.enabledPlugins;if(!r||typeof r!=="object"||Array.isArray(r))return;if(r[de]!==!1)return;let o=bd(t,"utf-8"),i=o.replace(new RegExp(`("${de}"\\s*:\\s*)false`),"$1true");return r[de]=!0,O(t,i!==o?i:`${JSON.stringify(n,null,2)}
221
- `),`Enabled ${de} plugin in ${t}`}function Ih(e){let t=Fo(e);if(!ti(t))return;let n=kd(t);if(!Array.isArray(n.packages))return;let r=n.packages.find((o)=>!!o&&typeof o==="object"&&!Array.isArray(o)&&jo(o.source)&&("extensions"in o));if(!r)return;return delete r.extensions,O(t,`${JSON.stringify(n,null,2)}
222
- `),`Enabled npm:cc-safety-net extensions in ${t}`}function hd(e,t){let n=E({label:t,booleans:Object.fromEntries(pe.map((i)=>[i.target,[i.flag]]))},e),r=n.errors[0];if(r)throw Error(r);let o=pe.filter((i)=>n.flags[i.target]).map((i)=>i.target);if(o.length!==1)throw Error(`Choose exactly one ${t} target: ${pe.map((i)=>i.flag).join(", ")}`);return o[0]}async function xd(e=ar(),t=pt){let[n,r,o]=await Promise.all([t(["amp","plugins","list"],30000),t(["codex","plugin","list"],30000),t(["copilot","--binary-version"])]);return{codexPluginListOutput:r,hooks:vt(process.cwd(),{homeDir:e,ampPluginListOutput:n,codexPluginListOutput:r,copilotCliVersion:o})}}async function $h(e,t=pt){let n=await xd(ar(),t);return n.hooks.filter((r)=>e==="install"?r.configured:r.detected||r.inspectionStatus==="not-inspected").filter((r)=>r.platform!=="codex"||!ni(n.codexPluginListOutput)||Ld(n.codexPluginListOutput)).map((r)=>r.platform)}function Oh(e,t,n){if(t.length>0)return{finish:async()=>[hd(t,e)]};if(!n.selectTargets&&!qo(n.input,n.output))return{finish:async()=>[hd(t,e)]};let r=n.detectConfiguredTargets??(()=>$h(e,n.fetchVersion)),o=Promise.all([rd(n.probeTargets),r()]);return{ready:o,finish:async()=>{let[i,s]=await o,a=od(i,{action:e,configuredTargets:s}),l=n.selectTargets?await n.selectTargets(e,vd(e,a)):await jc(e,vd(e,a),{input:n.input,output:n.output});if(l==="update")return l;if(!l||l.length===0)return null;return Wo(l)}}}async function tt(e,t,n=!1,r){let o=wd[e];o.beforeInstall?.(t);let i=typeof o.installCommands==="function"?await o.installCommands(t,r):{commands:o.installCommands};return await Ao(i.commands),await Gl(i.cleanupCommands??[]),[`${i.update||n?"Updated":"Installed"} ${D(e)} integration`,o.postInstallMessage].filter(Boolean).join(`
223
- `)}async function xt(e){let t=wd[e];if(!t.uninstallCommands)throw Error(`${D(e)} uninstall is not supported`);return await Ao(t.uninstallCommands),`Uninstalled ${D(e)} integration`}function Fh(e){let t=fc(e);return t.alreadyInstalled?`Uninstalled OpenCode plugin from ${t.path}`:`OpenCode plugin not installed in ${t.path}`}var jh={"antigravity-cli":{install:Qc,uninstall:ed},cursor:{install:gl,uninstall:hl},"grok-build":{install:Rl,uninstall:Pl},"kimi-code":{install:pd,uninstall:fd}};function Oe(e,t,n,r=!1){if(e==="install"&&!r)ir(n);let o=jh[t][e](n),i=D(t),s=e!=="install"?"Uninstalled":r?"Updated":"Installed";return e==="install"&&o.alreadyInstalled?r?`${i} hook up to date in ${o.path}`:`${i} hook already installed in ${o.path}`:e==="uninstall"&&!o.alreadyInstalled?`${i} hook not installed in ${o.path}`:`${s} ${i} hook ${e==="install"?"in":"from"} ${o.path}`}var Nh={amp:{install:Kc,uninstall:Jc,restartNote:'Amp personal plugins apply to every Amp session, including Orb threads. Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:Tl,uninstall:Il,afterInstall:async(e)=>{let t=Ro(e);return await ue(["hermes","plugins","enable",Q,"--no-allow-tool-override"]),!t},beforeUninstall:async(e)=>{So(e);try{await ue(["hermes","plugins","disable",Q])}catch(t){console.warn(`${t instanceof Error?t.message:String(t)}
224
- Removing the plugin files anyway; ${Q} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function sr(e,t,n,r=!1){let o=Nh[t];if(e==="uninstall")await o.beforeUninstall?.(n);let i=e==="install"?await o.install(n):await o.uninstall(n),s=e==="install"&&await o.afterInstall?.(n),a=D(t),l=!s&&(e==="install"&&i.alreadyInstalled||e==="uninstall"&&!i.alreadyInstalled);return[l?e==="install"?`${a} plugin ${r?"up to date":"already installed"} at ${i.path}`:`${a} plugin not installed at ${i.path}`:`${e!=="install"?"Uninstalled":r?"Updated":"Installed"} ${a} plugin ${e==="install"?"at":"from"} ${i.path}`,l?void 0:o.restartNote].filter(Boolean).join(`
225
- `)}var Hh={amp:{install:(e,t)=>sr("install","amp",e,t),uninstall:(e)=>sr("uninstall","amp",e)},"antigravity-cli":{install:(e,t)=>Oe("install","antigravity-cli",e,t),uninstall:(e)=>Oe("uninstall","antigravity-cli",e)},"claude-code":{install:(e,t)=>tt("claude-code",e,t),uninstall:()=>xt("claude-code")},codex:{install:(e,t,n)=>tt("codex",e,t,n),uninstall:()=>xt("codex")},"copilot-cli":{install:async(e,t)=>[await tt("copilot-cli",e,t),Th(e)].filter(Boolean).join(`
226
- `),uninstall:()=>xt("copilot-cli")},cursor:{install:(e,t)=>Oe("install","cursor",e,t),uninstall:(e)=>Oe("uninstall","cursor",e)},"gemini-cli":{install:(e,t)=>tt("gemini-cli",e,t),uninstall:()=>xt("gemini-cli")},"grok-build":{install:(e,t)=>Oe("install","grok-build",e,t),uninstall:(e)=>Oe("uninstall","grok-build",e)},"hermes-agent":{install:(e,t)=>{if(!t)ir(e);return sr("install","hermes-agent",e,t)},uninstall:(e)=>sr("uninstall","hermes-agent",e)},"kimi-code":{install:(e,t)=>Oe("install","kimi-code",e,t),uninstall:(e)=>Oe("uninstall","kimi-code",e)},openclaw:{install:async(e,t)=>{let n=await tt("openclaw",e,t);return await Wl(),n},uninstall:(e)=>(To(e),xt("openclaw"))},opencode:{install:async(e,t)=>{let n=await tt("opencode",e,t);return await cc(e),n},uninstall:(e)=>Fh(e)},pi:{install:async(e,t)=>[await tt("pi",e,t),Ih(e)].filter(Boolean).join(`
227
- `),uninstall:()=>xt("pi")}},yd=["Install CC Safety Net as a native Kimi Code plugin:",""," 1. Start Kimi Code and run: /plugins install https://github.com/kenryu42/cc-safety-net"," Confirm the trust prompt; it defaults to cancel."," 2. Run /reload, or start a new session.","","Note: Kimi Code hooks are fail-open. When the hook process cannot start, crashes, or times","out, Kimi Code allows the tool call."].join(`
228
- `);function Mh(e){if(Qt({homeDir:e,cwd:process.cwd()}).status!=="configured")return yd;return[yd,"",y.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
232
+ command = "${Ar}"`,Zi=`{ event = "PreToolUse", command = "${Ar}" }`;function bd(ce){return hd(process.env.KIMI_CODE_HOME??hd(ce,".kimi-code"),"config.toml")}function Sh(ce){return ce.split(`
233
+ `).reduce((ge,he)=>{if(/^\s*\[/.test(he))return ge.activeTable=!0,ge.lines.push(he),ge;if(!ge.activeTable&&/^\s*hooks\s*=\s*\[\s*]\s*(?:#.*)?$/.test(he))return ge;return ge.lines.push(he),ge},{activeTable:!1,lines:[]}).lines.join(`
234
+ `)}function Rh(ce,me){if(ce[me]!=="#")return me;let ge=ce.indexOf(`
235
+ `,me+1);return ge===-1?ce.length:ge+1}function Ph(ce,me){return mo(ce,me,{skipComment:Rh,stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"})}function Ld(ce){let me=!1,ge=0;while(ge<ce.length){let he=ce.indexOf(`
236
+ `,ge),Se=he===-1?ce.length:he,Fe=ce.slice(ge,Se);if(/^\s*\[/.test(Fe))me=!0;if(!me){let He=/^(\s*)hooks\s*=\s*\[/.exec(Fe);if(He){let Ge=ge+He[0].lastIndexOf("[");return{start:Ge,end:Ph(ce,Ge)}}}ge=he===-1?ce.length:he+1}return}function Dh(ce,me){let ge=ce.slice(0,me.end).trimEnd(),he=uc(ce,me.end),Se=he===""?" ":`${he} `,Fe=!ge.endsWith("[")&&!ge.endsWith(",");return`${ge}${Fe?",":""}
237
+ ${Se}${Zi}${ce.slice(me.end)}`}function Ah(ce){let me=Ld(ce);if(me&&ce.slice(me.start+1,me.end).trim())return Dh(ce,me);let ge=Sh(ce).trimEnd();if(ge==="")return`${Yi}
238
+ `;return`${ge}
239
+
240
+ ${Yi}
241
+ `}function Eh(ce){return ce.split(/(?=^\s*\[)/m).filter((ge)=>!/^\s*\[\[hooks]]\s*$/m.test(ge)||!ge.includes(Ar)).join("").trimEnd()}function _h(ce,me){let ge=ce.indexOf(Zi,me.start);if(ge===-1||ge>me.end)return ce;return go(ce,{start:ge,end:ge+Zi.length})}function wd(ce){let me=bd(ce);if(xh(Ch(me),{recursive:!0}),!yd(me))return Qt(me,`${Yi}
242
+ `),{path:me,alreadyInstalled:!1};let ge=vd(me,"utf-8");if(ge.includes(Ar))return{path:me,alreadyInstalled:!0};return Qt(me,Ah(ge)),{path:me,alreadyInstalled:!1}}function kd(ce){let me=bd(ce);if(!yd(me))return{path:me,alreadyInstalled:!1};let ge=vd(me,"utf-8");if(!ge.includes(Ar))return{path:me,alreadyInstalled:!1};let he=Ld(ge),Se=he?_h(ge,he):`${Eh(ge)}
243
+ `;return Qt(me,Se),{path:me,alreadyInstalled:!0}}var Qi="safety-net@cc-marketplace",xd=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),Cd=new Set(["antigravity-cli","cursor","grok-build","hermes-agent","kimi-code"]);function ts(ce){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(ce??"")}function Ad(ce){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(ce??"")}function $h(ce){return/^Marketplace `cc-marketplace`\s*$/m.test(ce??"")}var Ed={"claude-code":{installCommands:(ce)=>{let me=Qr(ce,"cc-safety-net@cc-marketplace");return{commands:[...me?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...ui(ce).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Qr(ce,Qi)?[["claude","plugin","uninstall",Qi]]:[],update:me}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(ce,me)=>{let ge=me??await hn(["codex","plugin","list"]),he=Ad(ge);return{commands:[he||$h(ge)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:ts(ge)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:he}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:"Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."},"copilot-cli":{installCommands:async()=>{let ce=await hn(["copilot","plugin","list"]),me=[...fl(ce)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...ml(ce)?[["copilot","plugin","uninstall",dl]]:[]];if(ul(ce))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",gn]],cleanupCommands:me,update:!0};return{commands:[pl(await hn(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",gn]],cleanupCommands:me}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(ce)=>{let me=vi(ce);if(me.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(me.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:_i,installCommands:()=>({commands:rc()}),uninstallCommands:[["openclaw","plugins","uninstall",Jt,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
244
+ `)},opencode:{beforeInstall:$i,installCommands:[["opencode","plugin","-g","-f","cc-safety-net@latest"]]},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]}};function Ro(){return process.env.HOME??Th()}function _d(ce,me=(ge)=>ge){try{let ge=JSON.parse(me(Dd(ce,"utf-8")));if(!ge||typeof ge!=="object"||Array.isArray(ge))throw Error(`Settings file ${ce} must be a JSON object`);return ge}catch(ge){if(ge instanceof SyntaxError)throw Error(`Failed to parse ${ce}: ${ge.message}`);throw ge}}function Oh(ce){let me=Xi(vr(ce),"settings.json");if(!es(me))return;let ge=_d(me,sn),he=ge.enabledPlugins;if(!he||typeof he!=="object"||Array.isArray(he))return;if(he[gn]!==!1)return;let Se=Dd(me,"utf-8"),Fe=Se.replace(new RegExp(`("${gn}"\\s*:\\s*)false`),"$1true");return he[gn]=!0,Qt(me,Fe!==Se?Fe:`${JSON.stringify(ge,null,2)}
245
+ `),`Enabled ${gn} plugin in ${me}`}function Fh(ce){let me=Oi(ce);if(!es(me))return;let ge=_d(me);if(!Array.isArray(ge.packages))return;let he=ge.packages.find((Se)=>!!Se&&typeof Se==="object"&&!Array.isArray(Se)&&Fi(Se.source)&&("extensions"in Se));if(!he)return;return delete he.extensions,Qt(me,`${JSON.stringify(ge,null,2)}
246
+ `),`Enabled npm:cc-safety-net extensions in ${me}`}function Sd(ce,me){let ge=Wt({label:me,booleans:Object.fromEntries(yn.map((Fe)=>[Fe.target,[Fe.flag]]))},ce),he=ge.errors[0];if(he)throw Error(he);let Se=yn.filter((Fe)=>ge.flags[Fe.target]).map((Fe)=>Fe.target);if(Se.length!==1)throw Error(`Choose exactly one ${me} target: ${yn.map((Fe)=>Fe.flag).join(", ")}`);return Se[0]}async function Td(ce=Ro(),me=Jn){let[ge,he,Se]=await Promise.all([me(["amp","plugins","list"],30000),me(["codex","plugin","list"],30000),me(["copilot","--binary-version"])]);return{codexPluginListOutput:he,hooks:er(process.cwd(),{homeDir:ce,ampPluginListOutput:ge,codexPluginListOutput:he,copilotCliVersion:Se})}}async function jh(ce,me=Jn){let ge=await Td(Ro(),me);return ge.hooks.filter((he)=>ce==="install"?he.configured:he.detected||he.inspectionStatus==="not-inspected").filter((he)=>he.platform!=="codex"||!ts(ge.codexPluginListOutput)||Ad(ge.codexPluginListOutput)).map((he)=>he.platform)}function Nh(ce,me,ge){if(me.length>0)return{finish:async()=>[Sd(me,ce)]};if(!ge.selectTargets&&!Bi(ge.input,ge.output))return{finish:async()=>[Sd(me,ce)]};let he=ge.detectConfiguredTargets??(()=>jh(ce,ge.fetchVersion)),Se=Promise.all([pd(ge.probeTargets),he()]);return{ready:Se,finish:async()=>{let[Fe,He]=await Se,Ge=fd(Fe,{action:ce,configuredTargets:He}),Dt=ge.selectTargets?await ge.selectTargets(ce,Pd(ce,Ge)):await zc(ce,Pd(ce,Ge),{input:ge.input,output:ge.output});if(Dt==="update")return Dt;if(!Dt||Dt.length===0)return null;return Ji(Dt)}}}async function Mn(ce,me,ge=!1,he){let Se=Ed[ce];Se.beforeInstall?.(me);let Fe=typeof Se.installCommands==="function"?await Se.installCommands(me,he):{commands:Se.installCommands};return await Di(Fe.commands),await Zl(Fe.cleanupCommands??[]),[`${Fe.update||ge?"Updated":"Installed"} ${Kt(ce)} integration`,Se.postInstallMessage].filter(Boolean).join(`
247
+ `)}async function ir(ce){let me=Ed[ce];if(!me.uninstallCommands)throw Error(`${Kt(ce)} uninstall is not supported`);return await Di(me.uninstallCommands),`Uninstalled ${Kt(ce)} integration`}function Hh(ce){let me=kc(ce);return me.alreadyInstalled?`Uninstalled OpenCode plugin from ${me.path}`:`OpenCode plugin not installed in ${me.path}`}var Mh={"antigravity-cli":{install:ld,uninstall:cd},cursor:{install:Cl,uninstall:Sl},"grok-build":{install:Ol,uninstall:Fl},"kimi-code":{install:wd,uninstall:kd}};function Pn(ce,me,ge,he=!1){if(ce==="install"&&!he)Co(ge);let Se=Mh[me][ce](ge),Fe=Kt(me),He=ce!=="install"?"Uninstalled":he?"Updated":"Installed";return ce==="install"&&Se.alreadyInstalled?he?`${Fe} hook up to date in ${Se.path}`:`${Fe} hook already installed in ${Se.path}`:ce==="uninstall"&&!Se.alreadyInstalled?`${Fe} hook not installed in ${Se.path}`:`${He} ${Fe} hook ${ce==="install"?"in":"from"} ${Se.path}`}var Uh={amp:{install:nd,uninstall:rd,restartNote:'Amp personal plugins apply to every Amp session, including Orb threads. Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:Ul,uninstall:Gl,afterInstall:async(ce)=>{let me=Si(ce);return await hn(["hermes","plugins","enable",ln,"--no-allow-tool-override"]),!me},beforeUninstall:async(ce)=>{Ci(ce);try{await hn(["hermes","plugins","disable",ln])}catch(me){console.warn(`${me instanceof Error?me.message:String(me)}
248
+ Removing the plugin files anyway; ${ln} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function So(ce,me,ge,he=!1){let Se=Uh[me];if(ce==="uninstall")await Se.beforeUninstall?.(ge);let Fe=ce==="install"?await Se.install(ge):await Se.uninstall(ge),He=ce==="install"&&await Se.afterInstall?.(ge),Ge=Kt(me),Dt=!He&&(ce==="install"&&Fe.alreadyInstalled||ce==="uninstall"&&!Fe.alreadyInstalled);return[Dt?ce==="install"?`${Ge} plugin ${he?"up to date":"already installed"} at ${Fe.path}`:`${Ge} plugin not installed at ${Fe.path}`:`${ce!=="install"?"Uninstalled":he?"Updated":"Installed"} ${Ge} plugin ${ce==="install"?"at":"from"} ${Fe.path}`,Dt?void 0:Se.restartNote].filter(Boolean).join(`
249
+ `)}var Gh={amp:{install:(ce,me)=>So("install","amp",ce,me),uninstall:(ce)=>So("uninstall","amp",ce)},"antigravity-cli":{install:(ce,me)=>Pn("install","antigravity-cli",ce,me),uninstall:(ce)=>Pn("uninstall","antigravity-cli",ce)},"claude-code":{install:(ce,me)=>Mn("claude-code",ce,me),uninstall:()=>ir("claude-code")},codex:{install:(ce,me,ge)=>Mn("codex",ce,me,ge),uninstall:()=>ir("codex")},"copilot-cli":{install:async(ce,me)=>[await Mn("copilot-cli",ce,me),Oh(ce)].filter(Boolean).join(`
250
+ `),uninstall:()=>ir("copilot-cli")},cursor:{install:(ce,me)=>Pn("install","cursor",ce,me),uninstall:(ce)=>Pn("uninstall","cursor",ce)},"gemini-cli":{install:(ce,me)=>Mn("gemini-cli",ce,me),uninstall:()=>ir("gemini-cli")},"grok-build":{install:(ce,me)=>Pn("install","grok-build",ce,me),uninstall:(ce)=>Pn("uninstall","grok-build",ce)},"hermes-agent":{install:(ce,me)=>{if(!me)Co(ce);return So("install","hermes-agent",ce,me)},uninstall:(ce)=>So("uninstall","hermes-agent",ce)},"kimi-code":{install:(ce,me)=>Pn("install","kimi-code",ce,me),uninstall:(ce)=>Pn("uninstall","kimi-code",ce)},openclaw:{install:async(ce,me)=>{let ge=await Mn("openclaw",ce,me);return await oc(),ge},uninstall:(ce)=>(_i(ce),ir("openclaw"))},opencode:{install:async(ce,me)=>{let ge=await Mn("opencode",ce,me);return await vc(ce),ge},uninstall:(ce)=>Hh(ce)},pi:{install:async(ce,me)=>[await Mn("pi",ce,me),Fh(ce)].filter(Boolean).join(`
251
+ `),uninstall:()=>ir("pi")}},Rd=["Install CC Safety Net as a native Kimi Code plugin:",""," 1. Start Kimi Code and run: /plugins install https://github.com/kenryu42/cc-safety-net"," Confirm the trust prompt; it defaults to cancel."," 2. Run /reload, or start a new session.","","Note: Kimi Code hooks are fail-open. When the hook process cannot start, crashes, or times","out, Kimi Code allows the tool call."].join(`
252
+ `);function Bh(ce){if(xr({homeDir:ce,cwd:process.cwd()}).status!=="configured")return Rd;return[Rd,"",Ht.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
229
253
  `))].join(`
230
- `)}function vd(e,t){return t.map((n)=>e==="install"&&n.target==="kimi-code"&&n.unavailableReason==="already installed"?{...n,available:!0,unavailableReason:void 0,label:`${n.label} (global hook installed)`}:n)}function Uh(e,t){if(e.selectKimiInstallMethod)return e.selectKimiInstallMethod();if(!qo(e.input,e.output))return Promise.resolve("global-hook");return Fc({input:e.input,output:e.output,globalHookInstalled:Qt({homeDir:t,cwd:process.cwd()}).status==="configured"})}async function Cd(e,t,n,r=!1,o){return Hh[t][e](n,r,o)}function Gh(e){let t=E({label:"update"},e).errors[0];if(t)throw Error(t)}async function Bh(e,t=pt){let n=await xd(e,t),r=Qo(Jt(e),"installed-plugins");return{targets:Wo([...n.hooks.filter((i)=>i.platform!=="copilot-cli"&&i.detected).map((i)=>i.platform),...[Fn,el,Qa].flatMap((i)=>ti(Qo(r,...i))?["copilot-cli"]:[]),...On(e,ei)?["claude-code"]:[],...ni(n.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:n.codexPluginListOutput}}async function qh(e){let t=ar(),n=e.output??process.stdout,r=(e.scriptPath??process.argv[1]??"").split(/[\\/]/),o=r.find((u)=>/^bunx-\d+-/.test(u)),i=o!==void 0||r.includes("_npx")?null:(e.checkLatestVersion??Te)(),s=async()=>{let u=i&&await i;if(u?.updateAvailable)n.write(`
231
- Update available: cc-safety-net ${u.currentVersion} → ${u.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
232
- `)},a=Bh(t,e.fetchVersion??pt).then(async(u)=>{let p=new Set(u.targets);return{targets:u.targets,codexPluginListOutput:u.codexPluginListOutput,available:new Map(await Promise.all(pe.filter((f)=>p.has(f.target)&&md.has(f.target)).map(async(f)=>[f.target,await Yo(f.probeCommand)])))}}),l=await Kt(e.showBanner??!0,()=>({ready:a,finish:()=>a}),()=>zt({input:e.input??process.stdin,output:n}),{loadingMessage:"Checking installed integrations…",output:n}),c=await Promise.resolve().then(()=>(td(Eh(),process.platform,o),null)).catch((u)=>an(u));if(l.targets.length===0){if(n.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),c!==null)console.error(c);return await s(),c===null?0:1}let d=l.targets.some((u)=>gd.has(u))?await Promise.resolve().then(()=>(ir(t),null)).catch((u)=>an(u)):null,m=await Tn(Promise.all(l.targets.map((u)=>{if(md.has(u)&&!l.available.get(u))return Promise.resolve({message:`${D(u)} not found; skipped`,failed:!1});if(d!==null&&gd.has(u))return Promise.resolve({message:d,failed:!0});return Cd("install",u,t,!0,l.codexPluginListOutput).then((p)=>({message:p,failed:!1}),(p)=>({message:an(p),failed:!0}))})),{loadingMessage:`Updating ${l.targets.length} integration${l.targets.length===1?"":"s"}…`,output:n}),g=c===null?m:[...m,{message:c,failed:!0}];return g.forEach((u)=>{u.failed?console.error(u.message):n.write(`${u.message}
233
- `)}),await s(),g.some((u)=>u.failed)?1:0}function ri(e,t={}){return Promise.resolve().then(()=>Gh(e)).then(()=>qh(t)).catch((n)=>(console.error(an(n)),1))}async function ln(e,t,n={}){try{let r=await Kt(!0,()=>Oh(e,t,n),()=>zt({input:n.input??process.stdin,output:n.output??process.stdout}),{loadingMessage:e==="install"?"Checking available integrations…":"Checking installed integrations…",output:n.output??process.stdout});if(!r)return(n.output??process.stdout).write(`Cancelled: nothing was ${e}ed.
234
- `),0;if(r==="update")return(n.runUpdate??(()=>ri([],{fetchVersion:n.fetchVersion,input:n.input,output:n.output,showBanner:!1})))();let o=ar(),i=n.output??process.stdout;return await nd(r,async(s)=>{if(s==="kimi-code"&&e==="install"){let l=await Uh(n,o);if(l===null){i.write(`Cancelled: Kimi Code integration was not installed.
235
- `);return}if(l==="plugin"){i.write(`${Mh(o)}
236
- `);return}}let a=await Tn(Cd(e,s,o),{loadingMessage:`${e==="install"?"Installing":"Uninstalling"} ${D(s)} integration…`,output:i});i.write(`${a}
237
- `)}),0}catch(r){return console.error(an(r)),1}}function an(e){let t=e instanceof Error?e.message:String(e),n=typeof e==="object"&&e!==null&&"code"in e?e.code:null;if(n==="EACCES"||n==="EPERM")return`${t}
238
- Check file permissions for the target config file and parent directory.`;if(n==="ENOENT")return`${t}
239
- Check that the target config path and parent directory exist.`;if(n==="ENOTDIR")return`${t}
240
- Check that every parent path component is a directory.`;return t}import{mkdirSync as Vh}from"node:fs";import{dirname as zh}from"node:path";import{createInterface as Kh}from"node:readline";var Sd=new Set(["check","apply"]),Rd="(unset)";async function Dd(e,t={}){let n=E({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},e),r=n.positionals[0],o=[...n.errors,...r&&!Sd.has(r)?[`Unknown policy subcommand: ${r}`]:[],...r&&Sd.has(r)&&!n.positionals[1]?[`policy ${r} requires a file`]:[],...n.positionals.slice(2).map((u)=>`Unexpected policy argument: ${u}`)];if(o.length>0){for(let u of o)console.error(u);return 1}let i=n.positionals[1];if(!r||!i)return bt(xn,console.error),1;let s=n.flags.global?ve():se(t.cwd??process.cwd()),a=_e(i),l=[...a.errors,...Ee(a.value).map((u)=>`${i}: ${u}`),...!n.flags.global&&Yh(a.value)&&a.value.audit!==void 0?[`${i}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(l.length>0){for(let u of l)console.error(u);return 1}let c=Y(a.value);if(console.log(`Scope: ${n.flags.global?"user":"project"} (${s})`),console.log(`Proposal: ${i}`),n.flags.global)Pd(Y(_e(s).value),c,!0);if(!n.flags.global){let u=lt().baseline;console.log("Effective policy (user + project merged):"),Pd(Ge(u,Be(_e(s).value).policy).policy,Ge(u,Be(a.value).policy).policy,!1)}if(r==="check")return 0;let d=t.input??process.stdin,m=t.output??process.stdout;if(!d.isTTY||!m.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${i}${n.flags.global?" --global":""}`),1;if(!await Jh(`Apply this policy to ${s}? [y/N] `,d,m))return console.log("Cancelled; nothing was written."),0;return Wh(s,a.value,c,n.flags.global),console.log(`Policy applied: ${s}`),0}function Jh(e,t,n){let r=Kh({input:t,output:n,terminal:!1});return new Promise((o)=>{r.once("close",()=>o(!1)),r.question(e,(i)=>{o(/^y(es)?$/i.test(i.trim())),r.close()})})}function Wh(e,t,n,r){if(r){cn(n);return}Vh(zh(e),{recursive:!0}),J(e,jt(t,n))}function Pd(e,t,n){let r=Ft(e,t,n);if(r.length===0){console.log("No changes.");return}console.log(`Changes (${r.length}):`);for(let o of r)console.log(` ${o.field}: ${o.before??Rd} -> ${o.after??Rd}`)}function Yh(e){return!!e&&typeof e==="object"&&!Array.isArray(e)}import{join as Ty}from"node:path";var Ad="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Priority |\n|-------|-------------|---------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | Second |\n| GitHub source | Listed in a local `rule.json` | Vendored into the consumer's `<rulebook-name>/rulebook.json` by `rule add` | Source order |\n\nEvery rulebook is a live file: the runtime reads it on each tool call, so an edit applies to the next command with no publishing step.\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule verify` reports the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- Transparent wrappers have no built-in defaults. Configure only wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n\n## Rulebook Sources\n\n- Local sources are bare rulebook names such as `project-rules`; the rulebook file is `.cc-safety-net/rules/project-rules/rulebook.json`.\n- Run `cc-safety-net rule add owner/repo` to add every rulebook currently present on the repository's default branch.\n- Use `--only` to select one or more rulebooks while preserving their order: `cc-safety-net rule add owner/repo --only aws gcloud`.\n- Use `--ref` to select a branch, tag, or commit instead of the default branch: `cc-safety-net rule add owner/repo --ref v2 --only aws`.\n- GitHub sources are stored in canonical form as `owner/repo#ref/<rulebook-name>`. That form remains valid in `rule.json` and as direct CLI input.\n- GitHub refs may contain `/`-separated path segments, such as `feature/rulebook-v2`.\n- The GitHub source name, the repository directory name, and the rulebook `name` must match exactly.\n- Rulebook source strings must be unique in a config.\n\n## rulebook.json Schema\n\n```json\n{\n \"rulebook_version\": 1,\n \"name\": \"project-rules\",\n \"version\": \"1.0.0\",\n \"description\": \"Project-specific CC Safety Net rules.\",\n \"author\": \"project\",\n \"allowed_commands\": [\"docker\"],\n \"rules\": [\n {\n \"name\": \"block-docker-system-prune\",\n \"command\": \"docker\",\n \"subcommand\": \"system\",\n \"block_args\": [\"prune\"],\n \"reason\": \"Use targeted cleanup instead.\"\n }\n ],\n \"tests\": [\n {\n \"command\": \"docker system prune\",\n \"expect\": \"blocked\",\n \"rule\": \"block-docker-system-prune\"\n },\n {\n \"command\": \"docker ps\",\n \"expect\": \"allowed\"\n }\n ]\n}\n```\n\n### Rulebook Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `rulebook_version` | Yes | Must be `1` or `2` |\n| `name` | Yes | `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` |\n| `version` | Yes | Non-empty string |\n| `description` | No | Free text; not type-checked at runtime |\n| `author` | No | Free text; not type-checked at runtime |\n| `allowed_commands` | Yes | Unique command names matching `^[a-zA-Z][a-zA-Z0-9_-]*$` |\n| `rules` | Yes | Array of rule objects |\n| `tests` | No | Array of fixtures |\n\n### Rule Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Unique within the rulebook (case-insensitive); same pattern as rulebook `name` |\n| `command` | Yes | Must be listed in `allowed_commands`; basename only, not path |\n| `subcommand` | No | Same pattern as `command`; omit to match any subcommand |\n| `intent` | No | One of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain` |\n| `block_args` | Yes | Non-empty array of non-empty strings |\n| `reason` | Yes | Non-empty string, max 256 chars |\n\n### Rule Fields (`rulebook_version` 2)\n\nVersion 2 replaces `subcommand` and `block_args` with an exact-token `match` object. Version 1 rulebooks keep their fields and their behavior; a client that does not support version 2 rejects the rulebook instead of applying broader version 1 semantics.\n\n```json\n{\n \"name\": \"block-terraform-apply-destroy\",\n \"command\": \"terraform\",\n \"match\": {\n \"command_path\": [\"apply\"],\n \"any_args\": [\"-destroy\", \"--destroy\"]\n },\n \"reason\": \"Review a destroy plan first with 'terraform plan -destroy'.\",\n \"intent\": \"use_alternative\"\n}\n```\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Same as version 1 |\n| `command` | Yes | Same as version 1 |\n| `match.command_path` | Yes | Non-empty array of non-empty command words |\n| `match.any_args` | No | Non-empty array of unique non-empty argument tokens |\n| `match.exclude_args` | No | Non-empty array of unique non-empty argument tokens |\n| `intent` | No | Same as version 1 |\n| `reason` | Yes | Same as version 1 |\n\n### Matching Behavior (`rulebook_version` 2)\n\n- **Command**: Normalized to lowercase basename, as in version 1.\n- **Command path**: After recognized global options and their values are skipped, the next command words must equal `command_path` exactly. AWS, gcloud, and Azure CLI value-taking global options are built in; Terraform's `-chdir=dir` is `=`-joined and is skipped with its own token.\n- **Unrecognized options**: A token starting with `-` that is not a recognized global option is skipped without consuming a value, so an unlisted value-taking option with a separate value (`--newflag value`) makes the rule miss. This fails open deliberately; document such gaps in the rulebook.\n- **`any_args`**: At least one listed token must appear literally among the arguments.\n- **`exclude_args`**: Any listed token appearing literally among the arguments prevents the match, which is how a safe preview such as `aws s3 rm --dryrun` stays allowed.\n- **No short-option expansion**: Arguments compare as exact tokens, so list every accepted spelling (`\"-destroy\"` and `\"--destroy\"`).\n- **Literal and case-sensitive**: No regex, glob, or substring matching. The first matching rule wins.\n- Release channels are separate rules: `gcloud beta compute instances delete` needs its own `command_path`.\n\n### Test Fixture Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `command` | Yes | Non-empty shell command string |\n| `expect` | Yes | `\"blocked\"` or `\"allowed\"` |\n| `rule` | Required for blocked fixtures | Rule name expected to block the command |\n\nFixtures are optional documentation of intended behavior. Version 1 fixtures are shape-validated only. Version 2 fixtures are evaluated against the rulebook's own rules when a source is fetched by `rule add` or `rule update`, and by `rule verify`; a failing fixture rejects that source before it is written. Loading a rulebook does not re-evaluate fixtures. CC Safety Net never executes fixture commands; they are analyzer inputs only.\n\n## Matching Behavior\n\nThe subcommand, argument, and option rules below describe `rulebook_version` 1 rules; version 2 rules match as described in Matching Behavior (`rulebook_version` 2). Execution order and transparent wrappers apply to both.\n\n- **Command**: Normalized to lowercase basename with any trailing `.exe` removed (`/usr/bin/git` → `git`).\n- **Subcommand**: The first command token after recognized Git and Docker global options and their values; `--` ends option parsing. An unrecognized option without `=` may consume the following token as its value.\n- **Arguments**: Each `block_args` value is compared literally against every command token, including expanded short options. The command is blocked if **any** item matches.\n- **Short options**: Expanded (`-Ap` matches `-A`).\n- **Long options**: Exact match (`--all-files` does not match `--all`).\n- **Execution order**: Built-in rules first, then custom rulebooks. Custom rules only add restrictions.\n- **Transparent wrappers**: A configured wrapper such as `rtk` lets `rtk git commit` be analyzed as `git commit` only when `git` is protected by built-in analyzers or active custom rules. `rtk -- git commit` is also supported.\n\n## Workflow\n\n1. Run `cc-safety-net rule init` or create `rule.json` manually.\n2. Optionally run `cc-safety-net rule init --example` to create an inactive example rulebook.\n3. Use `cc-safety-net rule wrapper add rtk` for trusted transparent wrappers.\n4. Run `cc-safety-net rule add <source>` after creating or choosing a rulebook source; add `--only <rulebook...>` or `--ref <ref>` for repository selection. The command adds the selected sources and syncs them.\n5. Edit a local rulebook whenever you like: the edit is enforced on the next command, so there is nothing to run afterwards.\n6. Run `cc-safety-net rule update [source]` to re-fetch remote sources and rewrite the vendored copies; the command prints what changed. A source with an ordinary update failure keeps its vendored copy while the other selected sources still update. Resource-limit failures remain fatal for the whole update.\n7. Run `cc-safety-net rule verify` to validate config, local rulebooks, and shareable GitHub-source rulebook directories in the current repository (it does not fetch remote content).\n8. Run `cc-safety-net rule list` to inspect active rulebooks and transparent wrappers.\n\nA missing or invalid rulebook file makes that source inactive, and an unreadable or invalid `rule.json` makes every source in its scope inactive. Inactive sources stop applying their rules while other custom rules and all built-in protections stay active. Fix the file named in the diagnostic, or run `cc-safety-net rule update` when a remote source has not been vendored yet. Run `cc-safety-net status` to see degraded sources.\n";function lr(e,t){if(!e.ok){$d(e);return}Td(e,t)}function _d(e,t,n){if(e.ok)console.log(n);if(!e.add){lr(e,`Added rulebook source: ${t}`);return}if(!e.ok){$d(e);return}if(e.add.added.length>0)console.log(`Added ${e.add.added.length} ${e.add.added.length===1?"rulebook":"rulebooks"} from ${e.add.source} at ${e.add.ref}:`),e.add.added.forEach((r)=>{console.log(` - ${r}`)});if(e.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${e.add.source} at ${e.add.ref}: ${e.add.alreadyConfigured.join(", ")}`);if(e.add.commits.length>0)console.log(`Vendored at ${e.add.commits.map((r)=>r.slice(0,7)).join(", ")}.`);Td(e,"Rule config updated.")}function Td(e,t){for(let n of e.changes??[])console.log(n);console.log(t),console.log(""),Zh(e.entries)}function Zh(e){if(e.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${e.length}):`);for(let t of e)console.log(` - ${t.name} ${t.version} (${Xh(t.ruleCount)})`),console.log(` Source: ${t.spec}`)}function Xh(e){return`${e} ${e===1?"rule":"rules"}`}function Id(e){nt("Active sources",e.rulebooks,(t)=>[`[${t.source}] ${t.name} ${t.version}`,` Source: ${t.spec}`]),nt("Active rules",e.rules,(t)=>[`[${ey(e,t.name)}] ${t.name}`,...Qh(t),` Reason: ${t.reason}`]),nt("Disabled rules",Ed(e,"off"),(t)=>[t.key]),nt("Reason overrides",Ed(e,"reason"),(t)=>[t.key,` Reason: ${t.value.reason}`]),nt("Transparent wrappers",e.transparent_wrappers,(t)=>[t]),nt("Issues",e.errors,(t)=>[t]),nt("Warnings",e.warnings,(t)=>[t])}function nt(e,t,n){if(t.length===0){console.log(`${e}: (none)`);return}console.log(`${e} (${t.length}):`);for(let r of t){let[o,...i]=n(r);console.log(` - ${o}`);for(let s of i)console.log(` ${s}`)}}function Qh(e){if(!e.match)return[` Command: ${e.subcommand?`${e.command} ${e.subcommand}`:e.command}`,` Block args: ${e.block_args.join(", ")}`];return[` Command: ${[e.command,...e.match.command_path].join(" ")}`,...e.match.any_args?[` Any args: ${e.match.any_args.join(", ")}`]:[],...e.match.exclude_args?[` Exclude args: ${e.match.exclude_args.join(", ")}`]:[]]}function ey(e,t){return e.rulebooks.find((n)=>n.rules.includes(t))?.source??"project"}function Ed(e,t){return Object.entries({...e.userConfig?.overrides??{},...e.projectConfig?.overrides??{}}).filter((n)=>{if(t==="off")return n[1]==="off";return!!n[1]&&typeof n[1]==="object"}).map(([n,r])=>({key:n,value:r}))}function $d(e){for(let t of e.errors)console.error(t)}import{dirname as Od,join as cr}from"node:path";var ty=".safety-net.json",ny="~/.cc-safety-net/config.json";async function Hd(e){return[await Fd({legacyPath:Nd({cwd:e.cwd}),configPath:oe(e.cwd),defaultRulebookName:"project-rules",migratedFrom:ty,cleanup:e.cleanup,syncOptions:{cwd:e.cwd}}),await Fd({legacyPath:It(),configPath:ie(),defaultRulebookName:"user-rules",migratedFrom:ny,cleanup:e.cleanup,syncOptions:{cwd:e.cwd,global:!0}})].every((n)=>n)?0:1}async function Fd(e){let t=U(e.syncOptions),n=x(t.filesystemScope,e.legacyPath),r=w(n);if(r===null)return console.log(`No legacy config found at ${e.legacyPath}`),!0;let o=oy(r);if(!o.ok){for(let g of o.errors)console.error(g);return!1}let i=q(t.configTarget);if(i.errors.length>0){for(let g of i.errors)console.error(g);return!1}let s=i.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},a=iy(Od(e.configPath),s.rules,e.defaultRulebookName,e.migratedFrom,t.filesystemScope),l=cr(Od(e.configPath),a,"rulebook.json"),c=x(t.filesystemScope,l),d=[jd(t.configTarget),jd(c)],m=await ry(e,t.configTarget,c,a,o.config.rules,s.rules.includes(a)?s.rules:[...s.rules,a],s.overrides??{},s.transparent_wrappers??[]);if(!m.ok){ly(d);for(let g of m.errors)console.error(g);return!1}if(!e.cleanup)return console.log(`Migrated legacy config at ${e.legacyPath}. Legacy file is no longer used.`),!0;if(!ay(t.configTarget,c,a,e.migratedFrom,o.config.rules))return console.error(`Migration cleanup verification failed for ${e.legacyPath}`),!1;return he(n),console.log(`Deleted legacy config at ${e.legacyPath}`),!0}async function ry(e,t,n,r,o,i,s,a){try{return J(t,{version:1,rules:i,overrides:s,transparent_wrappers:a}),J(n,sy(r,e.migratedFrom,o)),await Tt(e.syncOptions)}catch(l){return{ok:!1,errors:[l instanceof Error?l.message:String(l)]}}}function oy(e){try{let t=JSON.parse(e),n=Lr(t);if(n.errors.length>0)return{ok:!1,errors:n.errors};return{ok:!0,config:{version:1,rules:t.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function iy(e,t,n,r,o){let i=t.find((s)=>cy(x(o,cr(e,s,"rulebook.json")))===r);if(i)return i;if(w(x(o,cr(e,n,"rulebook.json")))===null)return n;for(let s=2;;s++){let a=`${n}-${s}`;if(w(x(o,cr(e,a,"rulebook.json")))===null)return a}}function sy(e,t,n){return{rulebook_version:1,name:e,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:t,allowed_commands:[...new Set(n.map((r)=>r.command))],rules:n,tests:n.map((r)=>({command:[r.command,r.subcommand,r.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:r.name}))}}function ay(e,t,n,r,o){if(!q(e).config?.rules.includes(n))return!1;try{let s=w(t);if(s===null)return!1;let a=JSON.parse(s);return a.migrated_from===r&&JSON.stringify(a.rules)===JSON.stringify(o)}catch{return!1}}function jd(e){return{target:e,content:w(e)}}function ly(e){for(let t of e){if(t.content===null){he(t.target);continue}B(t.target,t.content)}}function cy(e){let t=w(e);if(t===null)return null;try{let n=JSON.parse(t);return typeof n.migrated_from==="string"?n.migrated_from:null}catch{return null}}import{mkdir as dy,readFile as uy,writeFile as py}from"node:fs/promises";import{dirname as fy,join as my}from"node:path";var gy=86400000,hy=604800000;async function Ud(e=Date.now()){if(process.env.CC_SAFETY_NET_NO_UPDATE_CHECK)return null;let t=Mr();if(!t)return null;let n=my(t,".cc-safety-net","update-check.json"),r=await yy(n,e);if(!r.lastCheck||e-r.lastCheck>gy){let s=await Te();if(r.lastCheck=e,s.latestVersion)r.latestVersion=s.latestVersion;if(!await Md(n,r))return null;if(s.error)return null}let o=r.latestVersion,i=I();if(!o||!so(o,i))return null;if(r.notifiedVersion===o&&r.notifiedAt!==void 0&&e-r.notifiedAt<hy)return null;if(r.notifiedVersion=o,r.notifiedAt=e,!await Md(n,r))return null;return`UPDATE_AVAILABLE: cc-safety-net v${o} is available (running v${i}). Ask the user once whether to run \`npx -y cc-safety-net@latest update\`; continue the current task either way and do not raise this again.`}async function yy(e,t){let n=await uy(e,"utf8").then((i)=>JSON.parse(i)).catch(()=>{return});if(!n||typeof n!=="object"||Array.isArray(n))return{};let r=n,o=(i)=>typeof i==="number"&&Number.isFinite(i)&&i<=t?i:void 0;return{lastCheck:o(r.lastCheck),latestVersion:typeof r.latestVersion==="string"?r.latestVersion:void 0,notifiedVersion:typeof r.notifiedVersion==="string"?r.notifiedVersion:void 0,notifiedAt:o(r.notifiedAt)}}async function Md(e,t){return dy(fy(e),{recursive:!0,mode:448}).then(()=>py(e,JSON.stringify(t),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as vy,resolve as oi}from"node:path";var Gd="CC Safety Net Config",by="═".repeat(Gd.length),Ly="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",wy=new Set(["rule.json","rule.lock","cache"]);function Bd(e={}){try{return ky(e)}catch(t){if(t instanceof H)return console.error(t.message),1;throw t}}function ky(e){let t=e.cwd??process.cwd(),n=e.userConfigPath??ie(),r=e.projectConfigPath??oe(t),o=e.legacyUserConfigPath??It(),i=e.legacyProjectConfigPath??Ai(t),s=oi(t,Pt),a=Ae({cwd:t,userConfigPath:n,projectConfigPath:r}),l=Ae({cwd:t}),c=x(a.userScope,n),d=x(a.projectScope,r),m=e.legacyUserConfigPath?St(e.legacyUserConfigPath,"user policy"):x(l.userScope,o),g=e.legacyProjectConfigPath?St(e.legacyProjectConfigPath,"project policy"):x(l.projectScope,i),u=!1,p=!1,f=[],b=[],L=xy(x(l.projectScope,s));if(Sy(),w(c)!==null){let h=me(c);if(h.errors.push(...W(n,a.userScope)),f.push({scope:"User",path:n,result:h,schema:"rules",target:c}),h.errors.length>0)u=!0}if(w(m)!==null)if(p=!0,w(c)!==null)b.push(dr("user","cleanup"));else{let h=wr(m);if(f.push({scope:"User",path:o,result:h,schema:"legacy",inactive:!0,target:m}),b.push(dr("user",h.errors.length>0?"fix-or-delete":"migrate")),h.errors.length>0)u=!0}if(w(d)!==null){let h=me(d);if(h.errors.push(...W(r,a.projectScope)),f.push({scope:"Project",path:oi(r),result:h,schema:"rules",target:d}),h.errors.length>0)u=!0;if(w(g)!==null)p=!0,b.push(dr("project","cleanup"))}else if(w(g)!==null){p=!0,u=!0;let h=wr(g);f.push({scope:"Project",path:oi(i),result:h,schema:"legacy",inactive:!0,target:g}),b.push(dr("project",h.errors.length>0?"fix-or-delete":"migrate"))}if(L?.result.errors.length)u=!0;if(f.length===0&&!L)return console.log(`
241
- No config files found. Using built-in rules only.`),0;for(let h of f)if(h.inactive)Py(h.scope,h.path,h.result);else if(h.result.errors.length>0)Dy(h.scope,h.path,h.result.errors);else{if(h.schema==="rules"&&_y(h.target))console.log(`
242
- Added $schema to ${h.scope.toLowerCase()} config.`);Ry(h.scope,h.path,h.result,h.schema)}for(let h of b)console.error(`
243
- ${y.red(h)}`);if(L)if(L.result.errors.length>0)Ey(L.path,L.result.errors);else Ay(L.path,L.result);if(u)return console.error(`
244
- Config validation failed.`),1;return console.log(p?`
254
+ `)}function Pd(ce,me){return me.map((ge)=>ce==="install"&&ge.target==="kimi-code"&&ge.unavailableReason==="already installed"?{...ge,available:!0,unavailableReason:void 0,label:`${ge.label} (global hook installed)`}:ge)}function qh(ce,me){if(ce.selectKimiInstallMethod)return ce.selectKimiInstallMethod();if(!Bi(ce.input,ce.output))return Promise.resolve("global-hook");return Vc({input:ce.input,output:ce.output,globalHookInstalled:xr({homeDir:me,cwd:process.cwd()}).status==="configured"})}async function Id(ce,me,ge,he=!1,Se){return Gh[me][ce](ge,he,Se)}function Vh(ce){let me=Wt({label:"update"},ce).errors[0];if(me)throw Error(me)}async function zh(ce,me=Jn){let ge=await Td(ce,me),he=Xi(vr(ce),"installed-plugins");return{targets:Ji([...ge.hooks.filter((Fe)=>Fe.platform!=="copilot-cli"&&Fe.detected).map((Fe)=>Fe.platform),...[eo,cl,ll].flatMap((Fe)=>es(Xi(he,...Fe))?["copilot-cli"]:[]),...Qr(ce,Qi)?["claude-code"]:[],...ts(ge.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:ge.codexPluginListOutput}}async function Kh(ce){let me=Ro(),ge=ce.output??process.stdout,he=(ce.scriptPath??process.argv[1]??"").split(/[\\/]/),Se=he.find((It)=>/^bunx-\d+-/.test(It)),Fe=Se!==void 0||he.includes("_npx")?null:(ce.checkLatestVersion??Cn)(),He=async()=>{let It=Fe&&await Fe;if(It?.updateAvailable)ge.write(`
255
+ Update available: cc-safety-net ${It.currentVersion} → ${It.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
256
+ `)},Ge=zh(me,ce.fetchVersion??Jn).then(async(It)=>{let $t=new Set(It.targets);return{targets:It.targets,codexPluginListOutput:It.codexPluginListOutput,available:new Map(await Promise.all(yn.filter((Ot)=>$t.has(Ot.target)&&xd.has(Ot.target)).map(async(Ot)=>[Ot.target,await Wi(Ot.probeCommand)])))}}),Dt=await yr(ce.showBanner??!0,()=>({ready:Ge,finish:()=>Ge}),()=>hr({input:ce.input??process.stdin,output:ge}),{loadingMessage:"Checking installed integrations…",output:ge}),At=await Promise.resolve().then(()=>(dd(Ih(),process.platform,Se),null)).catch((It)=>Er(It));if(Dt.targets.length===0){if(ge.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),At!==null)console.error(At);return await He(),At===null?0:1}let Tt=Dt.targets.some((It)=>Cd.has(It))?await Promise.resolve().then(()=>(Co(me),null)).catch((It)=>Er(It)):null,Ft=await Yr(Promise.all(Dt.targets.map((It)=>{if(xd.has(It)&&!Dt.available.get(It))return Promise.resolve({message:`${Kt(It)} not found; skipped`,failed:!1});if(Tt!==null&&Cd.has(It))return Promise.resolve({message:Tt,failed:!0});return Id("install",It,me,!0,Dt.codexPluginListOutput).then(($t)=>({message:$t,failed:!1}),($t)=>({message:Er($t),failed:!0}))})),{loadingMessage:`Updating ${Dt.targets.length} integration${Dt.targets.length===1?"":"s"}…`,output:ge}),jt=At===null?Ft:[...Ft,{message:At,failed:!0}];return jt.forEach((It)=>{It.failed?console.error(It.message):ge.write(`${It.message}
257
+ `)}),await He(),jt.some((It)=>It.failed)?1:0}function ns(ce,me={}){return Promise.resolve().then(()=>Vh(ce)).then(()=>Kh(me)).catch((ge)=>(console.error(Er(ge)),1))}async function _r(ce,me,ge={}){try{let he=await yr(!0,()=>Nh(ce,me,ge),()=>hr({input:ge.input??process.stdin,output:ge.output??process.stdout}),{loadingMessage:ce==="install"?"Checking available integrations…":"Checking installed integrations…",output:ge.output??process.stdout});if(!he)return(ge.output??process.stdout).write(`Cancelled: nothing was ${ce}ed.
258
+ `),0;if(he==="update")return(ge.runUpdate??(()=>ns([],{fetchVersion:ge.fetchVersion,input:ge.input,output:ge.output,showBanner:!1})))();let Se=Ro(),Fe=ge.output??process.stdout;return await ud(he,async(He)=>{if(He==="kimi-code"&&ce==="install"){let Dt=await qh(ge,Se);if(Dt===null){Fe.write(`Cancelled: Kimi Code integration was not installed.
259
+ `);return}if(Dt==="plugin"){Fe.write(`${Bh(Se)}
260
+ `);return}}let Ge=await Yr(Id(ce,He,Se),{loadingMessage:`${ce==="install"?"Installing":"Uninstalling"} ${Kt(He)} integration…`,output:Fe});Fe.write(`${Ge}
261
+ `)}),0}catch(he){return console.error(Er(he)),1}}function Er(ce){let me=ce instanceof Error?ce.message:String(ce),ge=typeof ce==="object"&&ce!==null&&"code"in ce?ce.code:null;if(ge==="EACCES"||ge==="EPERM")return`${me}
262
+ Check file permissions for the target config file and parent directory.`;if(ge==="ENOENT")return`${me}
263
+ Check that the target config path and parent directory exist.`;if(ge==="ENOTDIR")return`${me}
264
+ Check that every parent path component is a directory.`;return me}import{mkdirSync as Jh}from"node:fs";import{dirname as Wh}from"node:path";import{createInterface as Yh}from"node:readline";var $d=new Set(["check","apply"]),Od="(unset)";async function jd(ce,me={}){let ge=Wt({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},ce),he=ge.positionals[0],Se=[...ge.errors,...he&&!$d.has(he)?[`Unknown policy subcommand: ${he}`]:[],...he&&$d.has(he)&&!ge.positionals[1]?[`policy ${he} requires a file`]:[],...ge.positionals.slice(2).map((It)=>`Unexpected policy argument: ${It}`)];if(Se.length>0){for(let It of Se)console.error(It);return 1}let Fe=ge.positionals[1];if(!he||!Fe)return tr(Ur,console.error),1;let He=ge.flags.global?y():g(me.cwd??process.cwd()),Ge=xn(Fe),Dt=[...Ge.errors,..._(Ge.value).map((It)=>`${Fe}: ${It}`),...!ge.flags.global&&Qh(Ge.value)&&Ge.value.audit!==void 0?[`${Fe}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(Dt.length>0){for(let It of Dt)console.error(It);return 1}let At=f(Ge.value);if(console.log(`Scope: ${ge.flags.global?"user":"project"} (${He})`),console.log(`Proposal: ${Fe}`),ge.flags.global)Fd(f(xn(He).value),At,!0);if(!ge.flags.global){let It=Vn().baseline;console.log("Effective policy (user + project merged):"),Fd(X(It,le(xn(He).value).policy).policy,X(It,le(Ge.value).policy).policy,!1)}if(he==="check")return 0;let Tt=me.input??process.stdin,Ft=me.output??process.stdout;if(!Tt.isTTY||!Ft.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${Fe}${ge.flags.global?" --global":""}`),1;if(!await Zh(`Apply this policy to ${He}? [y/N] `,Tt,Ft))return console.log("Cancelled; nothing was written."),0;return Xh(He,Ge.value,At,ge.flags.global),console.log(`Policy applied: ${He}`),0}function Zh(ce,me,ge){let he=Yh({input:me,output:ge,terminal:!1});return new Promise((Se)=>{he.once("close",()=>Se(!1)),he.question(ce,(Fe)=>{Se(/^y(es)?$/i.test(Fe.trim())),he.close()})})}function Xh(ce,me,ge,he){if(he){Q(ge);return}Jh(Wh(ce),{recursive:!0}),h(ce,ur(me,ge))}function Fd(ce,me,ge){let he=dr(ce,me,ge);if(he.length===0){console.log("No changes.");return}console.log(`Changes (${he.length}):`);for(let Se of he)console.log(` ${Se.field}: ${Se.before??Od} -> ${Se.after??Od}`)}function Qh(ce){return!!ce&&typeof ce==="object"&&!Array.isArray(ce)}import{join as Oy}from"node:path";var Nd="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Priority |\n|-------|-------------|---------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | Second |\n| GitHub source | Listed in a local `rule.json` | Vendored into the consumer's `<rulebook-name>/rulebook.json` by `rule add` | Source order |\n\nEvery rulebook is a live file: the runtime reads it on each tool call, so an edit applies to the next command with no publishing step.\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule verify` reports the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- Transparent wrappers have no built-in defaults. Configure only wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n\n## Rulebook Sources\n\n- Local sources are bare rulebook names such as `project-rules`; the rulebook file is `.cc-safety-net/rules/project-rules/rulebook.json`.\n- Run `cc-safety-net rule add owner/repo` to add every rulebook currently present on the repository's default branch.\n- Use `--only` to select one or more rulebooks while preserving their order: `cc-safety-net rule add owner/repo --only aws gcloud`.\n- Use `--ref` to select a branch, tag, or commit instead of the default branch: `cc-safety-net rule add owner/repo --ref v2 --only aws`.\n- GitHub sources are stored in canonical form as `owner/repo#ref/<rulebook-name>`. That form remains valid in `rule.json` and as direct CLI input.\n- GitHub refs may contain `/`-separated path segments, such as `feature/rulebook-v2`.\n- The GitHub source name, the repository directory name, and the rulebook `name` must match exactly.\n- Rulebook source strings must be unique in a config.\n\n## rulebook.json Schema\n\n```json\n{\n \"rulebook_version\": 1,\n \"name\": \"project-rules\",\n \"version\": \"1.0.0\",\n \"description\": \"Project-specific CC Safety Net rules.\",\n \"author\": \"project\",\n \"allowed_commands\": [\"docker\"],\n \"rules\": [\n {\n \"name\": \"block-docker-system-prune\",\n \"command\": \"docker\",\n \"subcommand\": \"system\",\n \"block_args\": [\"prune\"],\n \"reason\": \"Use targeted cleanup instead.\"\n }\n ],\n \"tests\": [\n {\n \"command\": \"docker system prune\",\n \"expect\": \"blocked\",\n \"rule\": \"block-docker-system-prune\"\n },\n {\n \"command\": \"docker ps\",\n \"expect\": \"allowed\"\n }\n ]\n}\n```\n\n### Rulebook Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `rulebook_version` | Yes | Must be `1` or `2` |\n| `name` | Yes | `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` |\n| `version` | Yes | Non-empty string |\n| `description` | No | Free text; not type-checked at runtime |\n| `author` | No | Free text; not type-checked at runtime |\n| `allowed_commands` | Yes | Unique command names matching `^[a-zA-Z][a-zA-Z0-9_-]*$` |\n| `rules` | Yes | Array of rule objects |\n| `tests` | No | Array of fixtures |\n\n### Rule Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Unique within the rulebook (case-insensitive); same pattern as rulebook `name` |\n| `command` | Yes | Must be listed in `allowed_commands`; basename only, not path |\n| `subcommand` | No | Same pattern as `command`; omit to match any subcommand |\n| `intent` | No | One of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain` |\n| `block_args` | Yes | Non-empty array of non-empty strings |\n| `reason` | Yes | Non-empty string, max 256 chars |\n\n### Rule Fields (`rulebook_version` 2)\n\nVersion 2 replaces `subcommand` and `block_args` with an exact-token `match` object. Version 1 rulebooks keep their fields and their behavior; a client that does not support version 2 rejects the rulebook instead of applying broader version 1 semantics.\n\n```json\n{\n \"name\": \"block-terraform-apply-destroy\",\n \"command\": \"terraform\",\n \"match\": {\n \"command_path\": [\"apply\"],\n \"any_args\": [\"-destroy\", \"--destroy\"]\n },\n \"reason\": \"Review a destroy plan first with 'terraform plan -destroy'.\",\n \"intent\": \"use_alternative\"\n}\n```\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Same as version 1 |\n| `command` | Yes | Same as version 1 |\n| `match.command_path` | Yes | Non-empty array of non-empty command words |\n| `match.any_args` | No | Non-empty array of unique non-empty argument tokens |\n| `match.exclude_args` | No | Non-empty array of unique non-empty argument tokens |\n| `intent` | No | Same as version 1 |\n| `reason` | Yes | Same as version 1 |\n\n### Matching Behavior (`rulebook_version` 2)\n\n- **Command**: Normalized to lowercase basename, as in version 1.\n- **Command path**: After recognized global options and their values are skipped, the next command words must equal `command_path` exactly. AWS, gcloud, and Azure CLI value-taking global options are built in; Terraform's `-chdir=dir` is `=`-joined and is skipped with its own token.\n- **Unrecognized options**: A token starting with `-` that is not a recognized global option is skipped without consuming a value, so an unlisted value-taking option with a separate value (`--newflag value`) makes the rule miss. This fails open deliberately; document such gaps in the rulebook.\n- **`any_args`**: At least one listed token must appear literally among the arguments.\n- **`exclude_args`**: Any listed token appearing literally among the arguments prevents the match, which is how a safe preview such as `aws s3 rm --dryrun` stays allowed.\n- **No short-option expansion**: Arguments compare as exact tokens, so list every accepted spelling (`\"-destroy\"` and `\"--destroy\"`).\n- **Literal and case-sensitive**: No regex, glob, or substring matching. The first matching rule wins.\n- Release channels are separate rules: `gcloud beta compute instances delete` needs its own `command_path`.\n\n### Test Fixture Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `command` | Yes | Non-empty shell command string |\n| `expect` | Yes | `\"blocked\"` or `\"allowed\"` |\n| `rule` | Required for blocked fixtures | Rule name expected to block the command |\n\nFixtures are optional documentation of intended behavior. Version 1 fixtures are shape-validated only. Version 2 fixtures are evaluated against the rulebook's own rules when a source is fetched by `rule add` or `rule update`, and by `rule verify`; a failing fixture rejects that source before it is written. Loading a rulebook does not re-evaluate fixtures. CC Safety Net never executes fixture commands; they are analyzer inputs only.\n\n## Matching Behavior\n\nThe subcommand, argument, and option rules below describe `rulebook_version` 1 rules; version 2 rules match as described in Matching Behavior (`rulebook_version` 2). Execution order and transparent wrappers apply to both.\n\n- **Command**: Normalized to lowercase basename with any trailing `.exe` removed (`/usr/bin/git` → `git`).\n- **Subcommand**: The first command token after recognized Git and Docker global options and their values; `--` ends option parsing. An unrecognized option without `=` may consume the following token as its value.\n- **Arguments**: Each `block_args` value is compared literally against every command token, including expanded short options. The command is blocked if **any** item matches.\n- **Short options**: Expanded (`-Ap` matches `-A`).\n- **Long options**: Exact match (`--all-files` does not match `--all`).\n- **Execution order**: Built-in rules first, then custom rulebooks. Custom rules only add restrictions.\n- **Transparent wrappers**: A configured wrapper such as `rtk` lets `rtk git commit` be analyzed as `git commit` only when `git` is protected by built-in analyzers or active custom rules. `rtk -- git commit` is also supported.\n\n## Workflow\n\n1. Run `cc-safety-net rule init` or create `rule.json` manually.\n2. Optionally run `cc-safety-net rule init --example` to create an inactive example rulebook.\n3. Use `cc-safety-net rule wrapper add rtk` for trusted transparent wrappers.\n4. Run `cc-safety-net rule add <source>` after creating or choosing a rulebook source; add `--only <rulebook...>` or `--ref <ref>` for repository selection. The command adds the selected sources and syncs them.\n5. Edit a local rulebook whenever you like: the edit is enforced on the next command, so there is nothing to run afterwards.\n6. Run `cc-safety-net rule update [source]` to re-fetch remote sources and rewrite the vendored copies; the command prints what changed. A source with an ordinary update failure keeps its vendored copy while the other selected sources still update. Resource-limit failures remain fatal for the whole update.\n7. Run `cc-safety-net rule verify` to validate config, local rulebooks, and shareable GitHub-source rulebook directories in the current repository (it does not fetch remote content).\n8. Run `cc-safety-net rule list` to inspect active rulebooks and transparent wrappers.\n\nA missing or invalid rulebook file makes that source inactive, and an unreadable or invalid `rule.json` makes every source in its scope inactive. Inactive sources stop applying their rules while other custom rules and all built-in protections stay active. Fix the file named in the diagnostic, or run `cc-safety-net rule update` when a remote source has not been vendored yet. Run `cc-safety-net status` to see degraded sources.\n";function Po(ce,me){if(!ce.ok){Bd(ce);return}Ud(ce,me)}function Md(ce,me,ge){if(ce.ok)console.log(ge);if(!ce.add){Po(ce,`Added rulebook source: ${me}`);return}if(!ce.ok){Bd(ce);return}if(ce.add.added.length>0)console.log(`Added ${ce.add.added.length} ${ce.add.added.length===1?"rulebook":"rulebooks"} from ${ce.add.source} at ${ce.add.ref}:`),ce.add.added.forEach((he)=>{console.log(` - ${he}`)});if(ce.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${ce.add.source} at ${ce.add.ref}: ${ce.add.alreadyConfigured.join(", ")}`);if(ce.add.commits.length>0)console.log(`Vendored at ${ce.add.commits.map((he)=>he.slice(0,7)).join(", ")}.`);Ud(ce,"Rule config updated.")}function Ud(ce,me){for(let ge of ce.changes??[])console.log(ge);console.log(me),console.log(""),ey(ce.entries)}function ey(ce){if(ce.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${ce.length}):`);for(let me of ce)console.log(` - ${me.name} ${me.version} (${ty(me.ruleCount)})`),console.log(` Source: ${me.spec}`)}function ty(ce){return`${ce} ${ce===1?"rule":"rules"}`}function Gd(ce){Un("Active sources",ce.rulebooks,(me)=>[`[${me.source}] ${me.name} ${me.version}`,` Source: ${me.spec}`]),Un("Active rules",ce.rules,(me)=>[`[${ry(ce,me.name)}] ${me.name}`,...ny(me),` Reason: ${me.reason}`]),Un("Disabled rules",Hd(ce,"off"),(me)=>[me.key]),Un("Reason overrides",Hd(ce,"reason"),(me)=>[me.key,` Reason: ${me.value.reason}`]),Un("Transparent wrappers",ce.transparent_wrappers,(me)=>[me]),Un("Issues",ce.errors,(me)=>[me]),Un("Warnings",ce.warnings,(me)=>[me])}function Un(ce,me,ge){if(me.length===0){console.log(`${ce}: (none)`);return}console.log(`${ce} (${me.length}):`);for(let he of me){let[Se,...Fe]=ge(he);console.log(` - ${Se}`);for(let He of Fe)console.log(` ${He}`)}}function ny(ce){if(!ce.match)return[` Command: ${ce.subcommand?`${ce.command} ${ce.subcommand}`:ce.command}`,` Block args: ${ce.block_args.join(", ")}`];return[` Command: ${[ce.command,...ce.match.command_path].join(" ")}`,...ce.match.any_args?[` Any args: ${ce.match.any_args.join(", ")}`]:[],...ce.match.exclude_args?[` Exclude args: ${ce.match.exclude_args.join(", ")}`]:[]]}function ry(ce,me){return ce.rulebooks.find((ge)=>ge.rules.includes(me))?.source??"project"}function Hd(ce,me){return Object.entries({...ce.userConfig?.overrides??{},...ce.projectConfig?.overrides??{}}).filter((ge)=>{if(me==="off")return ge[1]==="off";return!!ge[1]&&typeof ge[1]==="object"}).map(([ge,he])=>({key:ge,value:he}))}function Bd(ce){for(let me of ce.errors)console.error(me)}import{dirname as qd,join as Do}from"node:path";var oy=".safety-net.json",iy="~/.cc-safety-net/config.json";async function Kd(ce){return[await Vd({legacyPath:Ct({cwd:ce.cwd}),configPath:I(ce.cwd),defaultRulebookName:"project-rules",migratedFrom:oy,cleanup:ce.cleanup,syncOptions:{cwd:ce.cwd}}),await Vd({legacyPath:Ae(),configPath:D(),defaultRulebookName:"user-rules",migratedFrom:iy,cleanup:ce.cleanup,syncOptions:{cwd:ce.cwd,global:!0}})].every((ge)=>ge)?0:1}async function Vd(ce){let me=C(ce.syncOptions),ge=o(me.filesystemScope,ce.legacyPath),he=n(ge);if(he===null)return console.log(`No legacy config found at ${ce.legacyPath}`),!0;let Se=ay(he);if(!Se.ok){for(let jt of Se.errors)console.error(jt);return!1}let Fe=p(me.configTarget);if(Fe.errors.length>0){for(let jt of Fe.errors)console.error(jt);return!1}let He=Fe.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},Ge=ly(qd(ce.configPath),He.rules,ce.defaultRulebookName,ce.migratedFrom,me.filesystemScope),Dt=Do(qd(ce.configPath),Ge,"rulebook.json"),At=o(me.filesystemScope,Dt),Tt=[zd(me.configTarget),zd(At)],Ft=await sy(ce,me.configTarget,At,Ge,Se.config.rules,He.rules.includes(Ge)?He.rules:[...He.rules,Ge],He.overrides??{},He.transparent_wrappers??[]);if(!Ft.ok){uy(Tt);for(let jt of Ft.errors)console.error(jt);return!1}if(!ce.cleanup)return console.log(`Migrated legacy config at ${ce.legacyPath}. Legacy file is no longer used.`),!0;if(!dy(me.configTarget,At,Ge,ce.migratedFrom,Se.config.rules))return console.error(`Migration cleanup verification failed for ${ce.legacyPath}`),!1;return Y(ge),console.log(`Deleted legacy config at ${ce.legacyPath}`),!0}async function sy(ce,me,ge,he,Se,Fe,He,Ge){try{return h(me,{version:1,rules:Fe,overrides:He,transparent_wrappers:Ge}),h(ge,cy(he,ce.migratedFrom,Se)),await cr(ce.syncOptions)}catch(Dt){return{ok:!1,errors:[Dt instanceof Error?Dt.message:String(Dt)]}}}function ay(ce){try{let me=JSON.parse(ce),ge=No(me);if(ge.errors.length>0)return{ok:!1,errors:ge.errors};return{ok:!0,config:{version:1,rules:me.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function ly(ce,me,ge,he,Se){let Fe=me.find((He)=>py(o(Se,Do(ce,He,"rulebook.json")))===he);if(Fe)return Fe;if(n(o(Se,Do(ce,ge,"rulebook.json")))===null)return ge;for(let He=2;;He++){let Ge=`${ge}-${He}`;if(n(o(Se,Do(ce,Ge,"rulebook.json")))===null)return Ge}}function cy(ce,me,ge){return{rulebook_version:1,name:ce,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:me,allowed_commands:[...new Set(ge.map((he)=>he.command))],rules:ge,tests:ge.map((he)=>({command:[he.command,he.subcommand,he.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:he.name}))}}function dy(ce,me,ge,he,Se){if(!p(ce).config?.rules.includes(ge))return!1;try{let He=n(me);if(He===null)return!1;let Ge=JSON.parse(He);return Ge.migrated_from===he&&JSON.stringify(Ge.rules)===JSON.stringify(Se)}catch{return!1}}function zd(ce){return{target:ce,content:n(ce)}}function uy(ce){for(let me of ce){if(me.content===null){Y(me.target);continue}v(me.target,me.content)}}function py(ce){let me=n(ce);if(me===null)return null;try{let ge=JSON.parse(me);return typeof ge.migrated_from==="string"?ge.migrated_from:null}catch{return null}}import{mkdir as fy,readFile as my,writeFile as gy}from"node:fs/promises";import{dirname as hy,join as yy}from"node:path";var vy=86400000,by=604800000;async function Wd(ce=Date.now()){if(process.env.CC_SAFETY_NET_NO_UPDATE_CHECK)return null;let me=Pe();if(!me)return null;let ge=yy(me,".cc-safety-net","update-check.json"),he=await Ly(ge,ce);if(!he.lastCheck||ce-he.lastCheck>vy){let He=await Cn();if(he.lastCheck=ce,He.latestVersion)he.latestVersion=He.latestVersion;if(!await Jd(ge,he))return null;if(He.error)return null}let Se=he.latestVersion,Fe=Xt();if(!Se||!si(Se,Fe))return null;if(he.notifiedVersion===Se&&he.notifiedAt!==void 0&&ce-he.notifiedAt<by)return null;if(he.notifiedVersion=Se,he.notifiedAt=ce,!await Jd(ge,he))return null;return`UPDATE_AVAILABLE: cc-safety-net v${Se} is available (running v${Fe}). Ask the user once whether to run \`npx -y cc-safety-net@latest update\`; continue the current task either way and do not raise this again.`}async function Ly(ce,me){let ge=await my(ce,"utf8").then((Fe)=>JSON.parse(Fe)).catch(()=>{return});if(!ge||typeof ge!=="object"||Array.isArray(ge))return{};let he=ge,Se=(Fe)=>typeof Fe==="number"&&Number.isFinite(Fe)&&Fe<=me?Fe:void 0;return{lastCheck:Se(he.lastCheck),latestVersion:typeof he.latestVersion==="string"?he.latestVersion:void 0,notifiedVersion:typeof he.notifiedVersion==="string"?he.notifiedVersion:void 0,notifiedAt:Se(he.notifiedAt)}}async function Jd(ce,me){return fy(hy(ce),{recursive:!0,mode:448}).then(()=>gy(ce,JSON.stringify(me),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as wy,resolve as rs}from"node:path";var Yd="CC Safety Net Config",ky="═".repeat(Yd.length),xy="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",Cy=new Set(["rule.json","rule.lock","cache"]);function Zd(ce={}){try{return Sy(ce)}catch(me){if(me instanceof t)return console.error(me.message),1;throw me}}function Sy(ce){let me=ce.cwd??process.cwd(),ge=ce.userConfigPath??D(),he=ce.projectConfigPath??I(me),Se=ce.legacyUserConfigPath??Ae(),Fe=ce.legacyProjectConfigPath??vs(me),He=rs(me,pe),Ge=H({cwd:me,userConfigPath:ge,projectConfigPath:he}),Dt=H({cwd:me}),At=o(Ge.userScope,ge),Tt=o(Ge.projectScope,he),Ft=ce.legacyUserConfigPath?ue(ce.legacyUserConfigPath,"user policy"):o(Dt.userScope,Se),jt=ce.legacyProjectConfigPath?ue(ce.legacyProjectConfigPath,"project policy"):o(Dt.projectScope,Fe),It=!1,$t=!1,Ot=[],Ut=[],Gt=Ry(o(Dt.projectScope,He));if(Dy(),n(At)!==null){let Nt=bn(At);if(Nt.errors.push(...M(ge,Ge.userScope)),Ot.push({scope:"User",path:ge,result:Nt,schema:"rules",target:At}),Nt.errors.length>0)It=!0}if(n(Ft)!==null)if($t=!0,n(At)!==null)Ut.push(Ao("user","cleanup"));else{let Nt=Ho(Ft);if(Ot.push({scope:"User",path:Se,result:Nt,schema:"legacy",inactive:!0,target:Ft}),Ut.push(Ao("user",Nt.errors.length>0?"fix-or-delete":"migrate")),Nt.errors.length>0)It=!0}if(n(Tt)!==null){let Nt=bn(Tt);if(Nt.errors.push(...M(he,Ge.projectScope)),Ot.push({scope:"Project",path:rs(he),result:Nt,schema:"rules",target:Tt}),Nt.errors.length>0)It=!0;if(n(jt)!==null)$t=!0,Ut.push(Ao("project","cleanup"))}else if(n(jt)!==null){$t=!0,It=!0;let Nt=Ho(jt);Ot.push({scope:"Project",path:rs(Fe),result:Nt,schema:"legacy",inactive:!0,target:jt}),Ut.push(Ao("project",Nt.errors.length>0?"fix-or-delete":"migrate"))}if(Gt?.result.errors.length)It=!0;if(Ot.length===0&&!Gt)return console.log(`
265
+ No config files found. Using built-in rules only.`),0;for(let Nt of Ot)if(Nt.inactive)Ey(Nt.scope,Nt.path,Nt.result);else if(Nt.result.errors.length>0)_y(Nt.scope,Nt.path,Nt.result.errors);else{if(Nt.schema==="rules"&&$y(Nt.target))console.log(`
266
+ Added $schema to ${Nt.scope.toLowerCase()} config.`);Ay(Nt.scope,Nt.path,Nt.result,Nt.schema)}for(let Nt of Ut)console.error(`
267
+ ${Ht.red(Nt)}`);if(Gt)if(Gt.result.errors.length>0)Iy(Gt.path,Gt.result.errors);else Ty(Gt.path,Gt.result);if(It)return console.error(`
268
+ Config validation failed.`),1;return console.log($t?`
245
269
  Configs valid with warnings.`:`
246
- All configs valid.`),0}function dr(e,t){let n=`legacy ${e} config`;if(t==="cleanup")return`Warning: Legacy ${e} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(t==="migrate")return`Warning: Legacy ${e} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${e} config is no longer supported. Fix or delete the ${n}, then run \`npx -y cc-safety-net rule migrate\`.`}function xy(e){if(it(e)===null)return null;let t=Cy(e);if(t.ruleNames.size===0&&t.errors.length===0)return null;return{path:e.path,result:t}}function Cy(e){let t=[],n=new Set,r=(it(e)??[]).filter((o)=>!wy.has(o.name)).sort((o,i)=>o.name.localeCompare(i.name));if(r.length===0)return{errors:t,ruleNames:n};for(let o of r){if(!Pe.test(o.name)){t.push(`rulebook directory names must match ${Pe}: ${o.name}`);continue}if(o.kind!=="directory"){t.push(`${o.name} must be a rulebook directory`);continue}let i=x(e.scope,vy(e.path,o.name,"rulebook.json")),s=w(i);if(s===null){t.push(`${o.name}/rulebook.json is required`);continue}try{let a;try{a=JSON.parse(s)}catch{t.push(`${o.name}/rulebook.json: invalid JSON`);continue}let l=Dt(a);if(l.name!==o.name){t.push(`rulebook name "${l.name}" must match folder "${o.name}"`);continue}let c=fn(l);if(c.length>0){t.push(...c.map((d)=>`${o.name}/rulebook.json: ${d}`));continue}n.add(o.name)}catch(a){t.push(a instanceof Error?`${o.name}/rulebook.json: ${a.message}`:`${o.name}/rulebook.json: ${String(a)}`)}}return{errors:t,ruleNames:n}}function Sy(){console.log(Gd),console.log(by)}function Ry(e,t,n,r){if(console.log(`
247
- ✓ ${e} config: ${t}`),console.log(` Schema: ${r==="rules"?"rulebook sources":"legacy inline rules"}`),n.ruleNames.size>0){console.log(` ${r==="rules"?"Sources":"Rules"}:`);let o=1;for(let i of n.ruleNames)console.log(` ${o}. ${i}`),o++}else console.log(` ${r==="rules"?"Sources":"Rules"}: (none)`)}function Py(e,t,n){if(console.error(`
248
- ✗ Legacy ${e.toLowerCase()} config: ${t}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),n.errors.length>0){console.error(" Errors:");let r=1;for(let o of n.errors)for(let i of o.split("; "))console.error(` ${r}. ${i}`),r++;return}if(n.ruleNames.size>0){console.error(" Rules:");let r=1;for(let o of n.ruleNames)console.error(` ${r}. ${o}`),r++;return}console.error(" Rules: (none)")}function Dy(e,t,n){qd(`${e} config`,t,n)}function Ay(e,t){console.log(`
249
- ✓ GitHub source rules: ${e}`),console.log(" Rulebooks:");let n=1;for(let r of t.ruleNames)console.log(` ${n}. ${r}`),n++}function Ey(e,t){qd("GitHub source rules",e,t)}function qd(e,t,n){console.error(`
250
- ✗ ${e}: ${t}`),console.error(" Errors:");let r=1;for(let o of n)for(let i of o.split("; "))console.error(` ${r}. ${i}`),r++}function _y(e){try{let t=w(e);if(t===null)return!1;let n=JSON.parse(t);if(n.$schema)return!1;return B(e,JSON.stringify({$schema:Ly,...n},null,2)),!0}catch(t){if(t instanceof H)throw t;return!1}}var Vd=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),Iy=new Set(["add","remove","list"]),$y="cc-safety-net/rulebooks";async function zd(e){try{return await Oy(e)}catch(t){if(t instanceof H)return console.error(t.message),1;throw t}}async function Oy(e){let t=jy(e),n=t.help?Fy(t.positionals):null;if(n)return bt(n),0;if(t.errors.length>0){for(let s of t.errors)console.error(s);return 1}let r=t.positionals[0];if(!r)return bt(ut,console.error),1;let o=t.positionals[1],i={global:t.global};if(r==="init"){let s=U(i);Uy(s.configTarget);let a=Ty(s.configDir,"example-rules","rulebook.json"),l=x(s.filesystemScope,a);if(t.example&&w(l)===null)jr(l,"example-rules");let c=W(s.configPath,s.filesystemScope);for(let d of c)console.error(d);if(c.length>0)return 1;return console.log("Rule config initialized."),0}if(r==="add"){let s=Kd(t);if(!s)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let a=U(i),l=await Ir(s,{...i,ref:t.ref,rulebooks:t.only.length>0?t.only:void 0});return _d(l,s,`Scope: ${t.global?"user":"project"} (${a.configDir})`),l.ok?0:1}if(r==="remove"){if(!o)return console.error("rule remove requires a source"),1;let s=await Or(o,{...i,deleteSource:t.deleteSource});return lr(s,`Removed rulebook source: ${o}`),s.ok?0:1}if(r==="update"){let s=await Tt({...i,only:o,refresh:!0});return lr(s,"Rule config updated."),s.ok?0:1}if(r==="sync")return Ma({global:t.global});if(r==="list"){let s=De();return Id(s),s.errors.length>0?1:0}if(r==="wrapper")return Gy(t);if(r==="migrate")return Hd({cleanup:t.cleanup,cwd:process.cwd()});if(r==="doc"){console.log(Ad);let s=await Ud();if(s)console.error(s);return 0}if(r==="verify")return Bd();return 1}function Fy(e){if(e.length===0)return ut;let t=ut.subcommands.filter((r)=>r.usage.split(" ")[0]===e[0]);if(t.length===0)return null;if(e.length===1&&t.length>1)return{name:`rule ${e[0]}`,description:`Subcommands of rule ${e[0]}`,usage:`rule ${e[0]} <subcommand>`,subcommands:t,options:[]};let n=e.length===1?t[0]:t.find((r)=>r.usage.split(" ")[1]===e[1]);if(!n)return null;return{name:`rule ${e[0]}`,description:n.description,usage:`rule ${n.usage}`,options:e[0]==="add"?eo:[],examples:e[0]==="add"?to:void 0}}function jy(e){let t=E({label:"rule",booleans:{global:["-g","--global"],check:["--check"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},e),n={...t.flags,ref:t.values.ref,only:t.lists.only??[],help:t.help,positionals:t.positionals,errors:t.errors};return Ny(n),n}function Ny(e){let[t]=e.positionals;if(t&&!Vd.has(t))e.errors.push(`Unknown rule subcommand: ${t}`);if(e.deleteSource&&t!=="remove")if(t&&Vd.has(t))e.errors.push(`Unknown option for rule ${t}: --delete-source`);else e.errors.push("--delete-source is only valid with 'rule remove'");if(e.check&&t)e.errors.push(Ct(t,"--check"));if(e.cleanup&&t!=="migrate")e.errors.push(Ct(t,"--cleanup"));if(e.example&&t!=="init")e.errors.push(Ct(t,"--example"));if(e.ref&&t!=="add")e.errors.push(Ct(t,"--ref"));if(e.only.length>0&&t!=="add")e.errors.push(Ct(t,"--only"));if(t==="add")Hy(e);if(t==="migrate"){if(e.global)e.errors.push(Ct(t,"--global"));if(e.positionals.length>1)e.errors.push(`Unexpected rule migrate argument: ${e.positionals[1]}`)}else if(t==="wrapper")My(e);else if(e.positionals.length>2)e.errors.push(`Unexpected rule argument: ${e.positionals[2]}`);if(t==="list"&&e.global)e.errors.push("Unknown option for rule list: --global")}function Kd(e){if(e.positionals[1])return e.positionals[1];if(e.ref||e.only.length>0)return $y;return}function Hy(e){let t=Kd(e);if(!t)return;if((e.ref||e.only.length>0)&&!Se(t)){if(e.ref)e.errors.push(`--ref can only select a ref for an owner/repo source: ${t}`);if(e.only.length>0)e.errors.push("--only can only select rulebooks from an owner/repo source");return}if(e.ref&&!Ne(e.ref))e.errors.push(`--ref must use valid path segments: ${e.ref}`);let n=e.only.filter((r)=>!Pe.test(r));if(n.length>0)e.errors.push(`Invalid rulebook names: ${n.join(", ")}`)}function Ct(e,t){return e?`Unknown option for rule ${e}: ${t}`:`Unknown option for rule: ${t}`}function My(e){let t=e.positionals[1],n=e.positionals[2];if(!t){e.errors.push("rule wrapper requires add, remove, or list");return}if(!Iy.has(t)){e.errors.push(`Unknown rule wrapper action: ${t}`);return}if(t==="list"){if(n)e.errors.push(`Unexpected rule wrapper argument: ${n}`);return}if(!n){e.errors.push(`rule wrapper ${t} requires a command`);return}if(e.positionals.length>3)e.errors.push(`Unexpected rule wrapper argument: ${e.positionals[3]}`)}function Uy(e){if(w(e)===null){Fr(e);return}let t=q(e);if(!t.config)return;J(e,{version:1,rules:t.config.rules,overrides:t.config.overrides??{},transparent_wrappers:t.config.transparent_wrappers??[]})}async function Gy(e){let t=e.positionals[1],n=e.positionals[2],r=U({global:e.global}).configTarget;if(t==="list"){let a=q(r);if(a.errors.length>0){for(let l of a.errors)console.error(l);return 1}return By(a.config?.transparent_wrappers??[]),0}if(!n||!Ur.test(n))return console.error("transparent wrapper must match command pattern"),1;if(Br(n))return console.error(`reserved command "${n}" cannot be a wrapper`),1;let o=q(r);if(o.errors.length>0){for(let a of o.errors)console.error(a);return 1}let i=o.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},s=t==="add"?[...new Set([...i.transparent_wrappers??[],n])]:(i.transparent_wrappers??[]).filter((a)=>a!==n);return J(r,{version:1,rules:i.rules,overrides:i.overrides??{},transparent_wrappers:s}),console.log(t==="add"?`Added transparent wrapper: ${n}`:`Removed transparent wrapper: ${n}`),0}function By(e){if(e.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${e.length}):`);for(let t of e)console.log(` - ${t}`)}import{homedir as ai}from"node:os";import{sep as Yy}from"node:path";import{existsSync as qy,readFileSync as Vy}from"node:fs";import{homedir as zy}from"node:os";import{join as Ky}from"node:path";async function Jy(e){if(e.isTTY)return null;return(await Wr(e).catch(()=>null))?.trim()||null}function Wy(){if(process.env.CLAUDE_SETTINGS_PATH)return process.env.CLAUDE_SETTINGS_PATH;return Ky(zy(),".claude","settings.json")}function ii(){let e=Wy();if(!qy(e))return!1;try{let t=Vy(e,"utf-8"),n=JSON.parse(t);if(!n.enabledPlugins)return!1;let r="cc-safety-net@cc-marketplace";if(!(r in n.enabledPlugins))return!1;return n.enabledPlugins[r]===!0}catch(t){if(Nt(S.debug))console.error(`CC Safety Net debug: failed to read Claude settings: ${e}: ${t instanceof Error?t.message:String(t)}`);return!1}}async function si(e=process.stdin){let t=ii(),n;if(!t)n="\uD83D\uDEE1️ CC Safety Net ❌";else{let o=z({cwd:process.cwd()}),i=o.policy,s=ye(i),a=Object.values(Ue(i,s.capabilities)).some((d)=>d.changesInherited),l={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[a?"custom":s.effectiveLevel],c=(o.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";n=`\uD83D\uDEE1️ CC Safety Net ${l}${s.worktreeMode?"\uD83C\uDF33":""}${c}${o.state==="degraded"?"⚠️":""}`}let r=await Jy(e);if(r&&!r.startsWith("{"))console.log(`${r} | ${n}`);else console.log(n)}function Jd(){let e=z({cwd:process.cwd()}),t=e.policy,n=ye(t),r=!!process.env.NO_COLOR||!process.stdout.isTTY,o=Math.min(process.stdout.columns||80,100),i=r?"ok":"✔",s=r?"OFF":"✘",a=(p,f)=>{let b=` ${p.padEnd(13)}${f}`;return(b.length>o?`${b.slice(0,o-1)}…`:b).replaceAll(s,y.red(s))},l=Object.values(Ue(t,n.capabilities)).some((p)=>p.changesInherited),c=(p)=>p===ai()||p.startsWith(`${ai()}${Yy}`)?`~${p.slice(ai().length)}`:p,d={ready:y.green,degraded:y.yellow}[e.state],m=e.policyScopes?.weakenings??[],g=[...ii()?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...e.diagnostics],u=r?"-":"·";console.log([`${r?"":"\uD83D\uDEE1️ "}CC Safety Net — ${d(e.state)}`,"",a("Protection",`destructive ${t.destructiveCommandProtectionEnabled?i:s} secrets ${t.secretProtection.enabled?i:s}`),a("Level",l?`${n.effectiveLevel} (customised)`:n.effectiveLevel),a("Rules",t.rules.length===0?"none active":`${t.rules.length} active`),a("Policy",c(ve())),...e.policyScopes?[a("Project",c(se()))]:[],...n.worktreeMode?[a("Worktree","relaxations active")]:[],"",...m.length===0?[]:[" Project policy",...m.flatMap((p)=>nn(p," ",o-6).map((f,b)=>b===0?` ${f}`:f)),""],...g.length===0?[" Everything configured is active."]:[" Not active",...g.flatMap((p)=>nn(p," ",o-6).map((f,b)=>b===0?` ${u} ${f}`:f)),""," Full report: cc-safety-net doctor"]].join(`
251
- `))}import{spawn as fu}from"node:child_process";import{randomBytes as a0}from"node:crypto";import{existsSync as l0}from"node:fs";import{createServer as c0}from"node:http";import{Writable as d0}from"node:stream";import{homedir as Zy}from"node:os";var ur=500;function Xy(e){let t=e.filter((o)=>o.decision!=="allow"),n=e.filter((o)=>o.decision==="allow"),r=Math.min(t.length,Math.max(ur-n.length,Math.ceil(ur/2)));return[...t.slice(0,r),...n.slice(0,ur-r)]}function Wd(e,t=be()){if(t)He(t);let n=(f)=>new Date(f.getFullYear(),f.getMonth(),f.getDate()).getTime(),r=n(new Date),o=new Date(r);o.setDate(o.getDate()-(e-1));let i=o.getTime(),s=[],a={count:0};for(let f of t?Ce(t,a):[])for(let b of Fe(f,a)){if(!b||typeof b.ts!=="string"||typeof b.command!=="string")continue;let L=new Date(b.ts).getTime();if(!Number.isFinite(L))continue;if(L>=i)s.push(b)}s.sort((f,b)=>new Date(b.ts).getTime()-new Date(f.ts).getTime());let l=Array.from({length:e},()=>0),c=Array.from({length:e},()=>0),d={},m={},g={},u=0,p=0;for(let f of s){let b=f.agent||"unknown";d[b]=(d[b]??0)+1;let L=Math.round((r-n(new Date(f.ts)))/86400000),h=e-1-L,R=L>=0&&L<e;if(R)c[h]=(c[h]??0)+1;if(f.decision!=="allow"){if(u++,f.ruleId)m[f.ruleId]=(m[f.ruleId]??0)+1;let v=rt(f.segment||f.command);if(v)g[v]=(g[v]??0)+1;if(f.failureStage)p++;if(R)l[h]=(l[h]??0)+1}}return{days:e,logsDir:t,homeDir:Zy(),totalInWindow:s.length,truncated:s.length>ur,unreadable:a.count,counts:{blocked:u,allowed:s.length-u,agents:d,blockedByDay:l,analyzedByDay:c,rules:m,commands:g,errors:p},entries:Xy(s).sort((f,b)=>new Date(b.ts).getTime()-new Date(f.ts).getTime())}}import{spawn as Qy}from"node:child_process";import{existsSync as e0,statSync as Yd}from"node:fs";import{delimiter as t0,join as n0}from"node:path";var r0=120000,pr="Choose the project folder",o0=`try
252
- return POSIX path of (choose folder with prompt "${pr}")
270
+ All configs valid.`),0}function Ao(ce,me){let ge=`legacy ${ce} config`;if(me==="cleanup")return`Warning: Legacy ${ce} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(me==="migrate")return`Warning: Legacy ${ce} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${ce} config is no longer supported. Fix or delete the ${ge}, then run \`npx -y cc-safety-net rule migrate\`.`}function Ry(ce){if(Ce(ce)===null)return null;let me=Py(ce);if(me.ruleNames.size===0&&me.errors.length===0)return null;return{path:ce.path,result:me}}function Py(ce){let me=[],ge=new Set,he=(Ce(ce)??[]).filter((Se)=>!Cy.has(Se.name)).sort((Se,Fe)=>Se.name.localeCompare(Fe.name));if(he.length===0)return{errors:me,ruleNames:ge};for(let Se of he){if(!u.test(Se.name)){me.push(`rulebook directory names must match ${u}: ${Se.name}`);continue}if(Se.kind!=="directory"){me.push(`${Se.name} must be a rulebook directory`);continue}let Fe=o(ce.scope,wy(ce.path,Se.name,"rulebook.json")),He=n(Fe);if(He===null){me.push(`${Se.name}/rulebook.json is required`);continue}try{let Ge;try{Ge=JSON.parse(He)}catch{me.push(`${Se.name}/rulebook.json: invalid JSON`);continue}let Dt=be(Ge);if(Dt.name!==Se.name){me.push(`rulebook name "${Dt.name}" must match folder "${Se.name}"`);continue}let At=Or(Dt);if(At.length>0){me.push(...At.map((Tt)=>`${Se.name}/rulebook.json: ${Tt}`));continue}ge.add(Se.name)}catch(Ge){me.push(Ge instanceof Error?`${Se.name}/rulebook.json: ${Ge.message}`:`${Se.name}/rulebook.json: ${String(Ge)}`)}}return{errors:me,ruleNames:ge}}function Dy(){console.log(Yd),console.log(ky)}function Ay(ce,me,ge,he){if(console.log(`
271
+ ✓ ${ce} config: ${me}`),console.log(` Schema: ${he==="rules"?"rulebook sources":"legacy inline rules"}`),ge.ruleNames.size>0){console.log(` ${he==="rules"?"Sources":"Rules"}:`);let Se=1;for(let Fe of ge.ruleNames)console.log(` ${Se}. ${Fe}`),Se++}else console.log(` ${he==="rules"?"Sources":"Rules"}: (none)`)}function Ey(ce,me,ge){if(console.error(`
272
+ ✗ Legacy ${ce.toLowerCase()} config: ${me}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),ge.errors.length>0){console.error(" Errors:");let he=1;for(let Se of ge.errors)for(let Fe of Se.split("; "))console.error(` ${he}. ${Fe}`),he++;return}if(ge.ruleNames.size>0){console.error(" Rules:");let he=1;for(let Se of ge.ruleNames)console.error(` ${he}. ${Se}`),he++;return}console.error(" Rules: (none)")}function _y(ce,me,ge){Xd(`${ce} config`,me,ge)}function Ty(ce,me){console.log(`
273
+ ✓ GitHub source rules: ${ce}`),console.log(" Rulebooks:");let ge=1;for(let he of me.ruleNames)console.log(` ${ge}. ${he}`),ge++}function Iy(ce,me){Xd("GitHub source rules",ce,me)}function Xd(ce,me,ge){console.error(`
274
+ ✗ ${ce}: ${me}`),console.error(" Errors:");let he=1;for(let Se of ge)for(let Fe of Se.split("; "))console.error(` ${he}. ${Fe}`),he++}function $y(ce){try{let me=n(ce);if(me===null)return!1;let ge=JSON.parse(me);if(ge.$schema)return!1;return v(ce,JSON.stringify({$schema:xy,...ge},null,2)),!0}catch(me){if(me instanceof t)throw me;return!1}}var Qd=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),Fy=new Set(["add","remove","list"]),jy="cc-safety-net/rulebooks";async function eu(ce){try{return await Ny(ce)}catch(me){if(me instanceof t)return console.error(me.message),1;throw me}}async function Ny(ce){let me=My(ce),ge=me.help?Hy(me.positionals):null;if(ge)return tr(ge),0;if(me.errors.length>0){for(let He of me.errors)console.error(He);return 1}let he=me.positionals[0];if(!he)return tr(Kn,console.error),1;let Se=me.positionals[1],Fe={global:me.global};if(he==="init"){let He=C(Fe);qy(He.configTarget);let Ge=Oy(He.configDir,"example-rules","rulebook.json"),Dt=o(He.filesystemScope,Ge);if(me.example&&n(Dt)===null)gt(Dt,"example-rules");let At=M(He.configPath,He.filesystemScope);for(let Tt of At)console.error(Tt);if(At.length>0)return 1;return console.log("Rule config initialized."),0}if(he==="add"){let He=tu(me);if(!He)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let Ge=C(Fe),Dt=await qo(He,{...Fe,ref:me.ref,rulebooks:me.only.length>0?me.only:void 0});return Md(Dt,He,`Scope: ${me.global?"user":"project"} (${Ge.configDir})`),Dt.ok?0:1}if(he==="remove"){if(!Se)return console.error("rule remove requires a source"),1;let He=await zo(Se,{...Fe,deleteSource:me.deleteSource});return Po(He,`Removed rulebook source: ${Se}`),He.ok?0:1}if(he==="update"){let He=await cr({...Fe,only:Se,refresh:!0});return Po(He,"Rule config updated."),He.ok?0:1}if(he==="sync")return Wa({global:me.global});if(he==="list"){let He=V();return Gd(He),He.errors.length>0?1:0}if(he==="wrapper")return Vy(me);if(he==="migrate")return Kd({cleanup:me.cleanup,cwd:process.cwd()});if(he==="doc"){console.log(Nd);let He=await Wd();if(He)console.error(He);return 0}if(he==="verify")return Zd();return 1}function Hy(ce){if(ce.length===0)return Kn;let me=Kn.subcommands.filter((he)=>he.usage.split(" ")[0]===ce[0]);if(me.length===0)return null;if(ce.length===1&&me.length>1)return{name:`rule ${ce[0]}`,description:`Subcommands of rule ${ce[0]}`,usage:`rule ${ce[0]} <subcommand>`,subcommands:me,options:[]};let ge=ce.length===1?me[0]:me.find((he)=>he.usage.split(" ")[1]===ce[1]);if(!ge)return null;return{name:`rule ${ce[0]}`,description:ge.description,usage:`rule ${ge.usage}`,options:ce[0]==="add"?ei:[],examples:ce[0]==="add"?ti:void 0}}function My(ce){let me=Wt({label:"rule",booleans:{global:["-g","--global"],check:["--check"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},ce),ge={...me.flags,ref:me.values.ref,only:me.lists.only??[],help:me.help,positionals:me.positionals,errors:me.errors};return Uy(ge),ge}function Uy(ce){let[me]=ce.positionals;if(me&&!Qd.has(me))ce.errors.push(`Unknown rule subcommand: ${me}`);if(ce.deleteSource&&me!=="remove")if(me&&Qd.has(me))ce.errors.push(`Unknown option for rule ${me}: --delete-source`);else ce.errors.push("--delete-source is only valid with 'rule remove'");if(ce.check&&me)ce.errors.push(sr(me,"--check"));if(ce.cleanup&&me!=="migrate")ce.errors.push(sr(me,"--cleanup"));if(ce.example&&me!=="init")ce.errors.push(sr(me,"--example"));if(ce.ref&&me!=="add")ce.errors.push(sr(me,"--ref"));if(ce.only.length>0&&me!=="add")ce.errors.push(sr(me,"--only"));if(me==="add")Gy(ce);if(me==="migrate"){if(ce.global)ce.errors.push(sr(me,"--global"));if(ce.positionals.length>1)ce.errors.push(`Unexpected rule migrate argument: ${ce.positionals[1]}`)}else if(me==="wrapper")By(ce);else if(ce.positionals.length>2)ce.errors.push(`Unexpected rule argument: ${ce.positionals[2]}`);if(me==="list"&&ce.global)ce.errors.push("Unknown option for rule list: --global")}function tu(ce){if(ce.positionals[1])return ce.positionals[1];if(ce.ref||ce.only.length>0)return jy;return}function Gy(ce){let me=tu(ce);if(!me)return;if((ce.ref||ce.only.length>0)&&!ne(me)){if(ce.ref)ce.errors.push(`--ref can only select a ref for an owner/repo source: ${me}`);if(ce.only.length>0)ce.errors.push("--only can only select rulebooks from an owner/repo source");return}if(ce.ref&&!fe(ce.ref))ce.errors.push(`--ref must use valid path segments: ${ce.ref}`);let ge=ce.only.filter((he)=>!u.test(he));if(ge.length>0)ce.errors.push(`Invalid rulebook names: ${ge.join(", ")}`)}function sr(ce,me){return ce?`Unknown option for rule ${ce}: ${me}`:`Unknown option for rule: ${me}`}function By(ce){let me=ce.positionals[1],ge=ce.positionals[2];if(!me){ce.errors.push("rule wrapper requires add, remove, or list");return}if(!Fy.has(me)){ce.errors.push(`Unknown rule wrapper action: ${me}`);return}if(me==="list"){if(ge)ce.errors.push(`Unexpected rule wrapper argument: ${ge}`);return}if(!ge){ce.errors.push(`rule wrapper ${me} requires a command`);return}if(ce.positionals.length>3)ce.errors.push(`Unexpected rule wrapper argument: ${ce.positionals[3]}`)}function qy(ce){if(n(ce)===null){mt(ce);return}let me=p(ce);if(!me.config)return;h(ce,{version:1,rules:me.config.rules,overrides:me.config.overrides??{},transparent_wrappers:me.config.transparent_wrappers??[]})}async function Vy(ce){let me=ce.positionals[1],ge=ce.positionals[2],he=C({global:ce.global}).configTarget;if(me==="list"){let Ge=p(he);if(Ge.errors.length>0){for(let Dt of Ge.errors)console.error(Dt);return 1}return zy(Ge.config?.transparent_wrappers??[]),0}if(!ge||!z.test(ge))return console.error("transparent wrapper must match command pattern"),1;if(Ie(ge))return console.error(`reserved command "${ge}" cannot be a wrapper`),1;let Se=p(he);if(Se.errors.length>0){for(let Ge of Se.errors)console.error(Ge);return 1}let Fe=Se.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},He=me==="add"?[...new Set([...Fe.transparent_wrappers??[],ge])]:(Fe.transparent_wrappers??[]).filter((Ge)=>Ge!==ge);return h(he,{version:1,rules:Fe.rules,overrides:Fe.overrides??{},transparent_wrappers:He}),console.log(me==="add"?`Added transparent wrapper: ${ge}`:`Removed transparent wrapper: ${ge}`),0}function zy(ce){if(ce.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${ce.length}):`);for(let me of ce)console.log(` - ${me}`)}import{homedir as ss}from"node:os";import{sep as Qy}from"node:path";import{existsSync as Ky,readFileSync as Jy}from"node:fs";import{homedir as Wy}from"node:os";import{join as Yy}from"node:path";async function Zy(ce){if(ce.isTTY)return null;return(await Wo(ce).catch(()=>null))?.trim()||null}function Xy(){if(process.env.CLAUDE_SETTINGS_PATH)return process.env.CLAUDE_SETTINGS_PATH;return Yy(Wy(),".claude","settings.json")}function os(){let ce=Xy();if(!Ky(ce))return!1;try{let me=Jy(ce,"utf-8"),ge=JSON.parse(me);if(!ge.enabledPlugins)return!1;let he="cc-safety-net@cc-marketplace";if(!(he in ge.enabledPlugins))return!1;return ge.enabledPlugins[he]===!0}catch(me){if(P(r.debug))console.error(`CC Safety Net debug: failed to read Claude settings: ${ce}: ${me instanceof Error?me.message:String(me)}`);return!1}}async function is(ce=process.stdin){let me=os(),ge;if(!me)ge="\uD83D\uDEE1️ CC Safety Net ❌";else{let Se=x({cwd:process.cwd()}),Fe=Se.policy,He=E(Fe),Ge=Object.values(U(Fe,He.capabilities)).some((Tt)=>Tt.changesInherited),Dt={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[Ge?"custom":He.effectiveLevel],At=(Se.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";ge=`\uD83D\uDEE1️ CC Safety Net ${Dt}${He.worktreeMode?"\uD83C\uDF33":""}${At}${Se.state==="degraded"?"⚠️":""}`}let he=await Zy(ce);if(he&&!he.startsWith("{"))console.log(`${he} | ${ge}`);else console.log(ge)}function nu(){let ce=x({cwd:process.cwd()}),me=ce.policy,ge=E(me),he=!!process.env.NO_COLOR||!process.stdout.isTTY,Se=Math.min(process.stdout.columns||80,100),Fe=he?"ok":"✔",He=he?"OFF":"✘",Ge=($t,Ot)=>{let Ut=` ${$t.padEnd(13)}${Ot}`;return(Ut.length>Se?`${Ut.slice(0,Se-1)}…`:Ut).replaceAll(He,Ht.red(He))},Dt=Object.values(U(me,ge.capabilities)).some(($t)=>$t.changesInherited),At=($t)=>$t===ss()||$t.startsWith(`${ss()}${Qy}`)?`~${$t.slice(ss().length)}`:$t,Tt={ready:Ht.green,degraded:Ht.yellow}[ce.state],Ft=ce.policyScopes?.weakenings??[],jt=[...os()?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...ce.diagnostics],It=he?"-":"·";console.log([`${he?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Tt(ce.state)}`,"",Ge("Protection",`destructive ${me.destructiveCommandProtectionEnabled?Fe:He} secrets ${me.secretProtection.enabled?Fe:He}`),Ge("Level",Dt?`${ge.effectiveLevel} (customised)`:ge.effectiveLevel),Ge("Rules",me.rules.length===0?"none active":`${me.rules.length} active`),Ge("Policy",At(y())),...ce.policyScopes?[Ge("Project",At(g()))]:[],...ge.worktreeMode?[Ge("Worktree","relaxations active")]:[],"",...Ft.length===0?[]:[" Project policy",...Ft.flatMap(($t)=>Rr($t," ",Se-6).map((Ot,Ut)=>Ut===0?` ${Ot}`:Ot)),""],...jt.length===0?[" Everything configured is active."]:[" Not active",...jt.flatMap(($t)=>Rr($t," ",Se-6).map((Ot,Ut)=>Ut===0?` ${It} ${Ot}`:Ot)),""," Full report: cc-safety-net doctor"]].join(`
275
+ `))}import{spawn as fu}from"node:child_process";import{randomBytes as d0}from"node:crypto";import{existsSync as u0}from"node:fs";import{createServer as p0}from"node:http";import{Writable as f0}from"node:stream";import{homedir as e0}from"node:os";var Eo=500;function t0(ce){let me=ce.filter((Se)=>Se.decision!=="allow"),ge=ce.filter((Se)=>Se.decision==="allow"),he=Math.min(me.length,Math.max(Eo-ge.length,Math.ceil(Eo/2)));return[...me.slice(0,he),...ge.slice(0,Eo-he)]}function ru(ce,me=F()){if(me)q(me);let ge=(Ot)=>new Date(Ot.getFullYear(),Ot.getMonth(),Ot.getDate()).getTime(),he=ge(new Date),Se=new Date(he);Se.setDate(Se.getDate()-(ce-1));let Fe=Se.getTime(),He=[],Ge={count:0};for(let Ot of me?kn(me,Ge):[])for(let Ut of Dn(Ot,Ge)){if(!Ut||typeof Ut.ts!=="string"||typeof Ut.command!=="string")continue;let Gt=new Date(Ut.ts).getTime();if(!Number.isFinite(Gt))continue;if(Gt>=Fe)He.push(Ut)}He.sort((Ot,Ut)=>new Date(Ut.ts).getTime()-new Date(Ot.ts).getTime());let Dt=Array.from({length:ce},()=>0),At=Array.from({length:ce},()=>0),Tt={},Ft={},jt={},It=0,$t=0;for(let Ot of He){let Ut=Ot.agent||"unknown";Tt[Ut]=(Tt[Ut]??0)+1;let Gt=Math.round((he-ge(new Date(Ot.ts)))/86400000),Nt=ce-1-Gt,Vt=Gt>=0&&Gt<ce;if(Vt)At[Nt]=(At[Nt]??0)+1;if(Ot.decision!=="allow"){if(It++,Ot.ruleId)Ft[Ot.ruleId]=(Ft[Ot.ruleId]??0)+1;let Mt=Gn(Ot.segment||Ot.command);if(Mt)jt[Mt]=(jt[Mt]??0)+1;if(Ot.failureStage)$t++;if(Vt)Dt[Nt]=(Dt[Nt]??0)+1}}return{days:ce,logsDir:me,homeDir:e0(),totalInWindow:He.length,truncated:He.length>Eo,unreadable:Ge.count,counts:{blocked:It,allowed:He.length-It,agents:Tt,blockedByDay:Dt,analyzedByDay:At,rules:Ft,commands:jt,errors:$t},entries:t0(He).sort((Ot,Ut)=>new Date(Ut.ts).getTime()-new Date(Ot.ts).getTime())}}import{spawn as n0}from"node:child_process";import{existsSync as r0,statSync as ou}from"node:fs";import{delimiter as o0,join as i0}from"node:path";var s0=120000,_o="Choose the project folder",a0=`try
276
+ return POSIX path of (choose folder with prompt "${_o}")
253
277
  on error number -128
254
278
  return ""
255
- end try`,i0=`Add-Type -AssemblyName System.Windows.Forms
279
+ end try`,l0=`Add-Type -AssemblyName System.Windows.Forms
256
280
  $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
257
- $dialog.Description = '${pr}'
258
- if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,Zd=[{binary:"zenity",args:["--file-selection","--directory",`--title=${pr}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",pr]}],Xd=(e,t)=>(t.PATH??"").split(t0).some((n)=>{if(n.length===0)return!1;try{let r=Yd(n0(n,e));return r.isFile()&&(r.mode&73)!==0}catch{return!1}});function li(e,t){if(e==="darwin"||e==="win32")return!0;if(e!=="linux")return!1;if(!t.DISPLAY&&!t.WAYLAND_DISPLAY)return!1;return Zd.some((n)=>Xd(n.binary,t))}function s0(e,t){if(e==="darwin")return{cmd:"osascript",args:["-e",o0]};if(e==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",i0]};let n=Zd.find((r)=>Xd(r.binary,t));return n?{cmd:n.binary,args:n.args}:null}function ci(e=process.platform,t=process.env){let n=s0(e,t);if(!n)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((r)=>{let o=Qy(n.cmd,n.args,{env:t,stdio:["ignore","pipe","pipe"]}),i="",s=!1,a=(c)=>{if(s)return;s=!0,clearTimeout(l),r(c)},l=setTimeout(()=>{o.kill(),a({error:"The folder dialog timed out"})},r0);o.stdout.on("data",(c)=>{i+=c.toString()}),o.on("error",()=>a({error:`Could not open the folder dialog (${n.cmd})`})),o.on("close",()=>{let c=i.trim().replace(/\/+$/,"");if(!c)return a({cancelled:!0});if(!e0(c)||!Yd(c).isDirectory())return a({error:"That selection is not a folder on disk"});a({path:c})})})}var Qd=`<!doctype html>
281
+ $dialog.Description = '${_o}'
282
+ if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,iu=[{binary:"zenity",args:["--file-selection","--directory",`--title=${_o}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",_o]}],su=(ce,me)=>(me.PATH??"").split(o0).some((ge)=>{if(ge.length===0)return!1;try{let he=ou(i0(ge,ce));return he.isFile()&&(he.mode&73)!==0}catch{return!1}});function as(ce,me){if(ce==="darwin"||ce==="win32")return!0;if(ce!=="linux")return!1;if(!me.DISPLAY&&!me.WAYLAND_DISPLAY)return!1;return iu.some((ge)=>su(ge.binary,me))}function c0(ce,me){if(ce==="darwin")return{cmd:"osascript",args:["-e",a0]};if(ce==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",l0]};let ge=iu.find((he)=>su(he.binary,me));return ge?{cmd:ge.binary,args:ge.args}:null}function ls(ce=process.platform,me=process.env){let ge=c0(ce,me);if(!ge)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((he)=>{let Se=n0(ge.cmd,ge.args,{env:me,stdio:["ignore","pipe","pipe"]}),Fe="",He=!1,Ge=(At)=>{if(He)return;He=!0,clearTimeout(Dt),he(At)},Dt=setTimeout(()=>{Se.kill(),Ge({error:"The folder dialog timed out"})},s0);Se.stdout.on("data",(At)=>{Fe+=At.toString()}),Se.on("error",()=>Ge({error:`Could not open the folder dialog (${ge.cmd})`})),Se.on("close",()=>{let At=Fe.trim().replace(/\/+$/,"");if(!At)return Ge({cancelled:!0});if(!r0(At)||!ou(At).isDirectory())return Ge({error:"That selection is not a folder on disk"});Ge({path:At})})})}var au=`<!doctype html>
259
283
  <html lang="en">
260
284
  <head>
261
285
  <meta charset="utf-8">
@@ -4070,12 +4094,12 @@ var renderIntegrations = () => {
4070
4094
  if (!loaded)
4071
4095
  return;
4072
4096
  qs("integrations-list").innerHTML = loaded.targets.map((row) => {
4073
- const busy2 = integrationBusy.has(row.target);
4097
+ const busy = integrationBusy.has(row.target);
4074
4098
  const version = row.version === null ? '<span class="muted">not detected</span>' : \`<span class="agent-badge">v\${escapeHtml(row.version)}</span>\`;
4075
4099
  const status = row.status === "active" ? '<span class="state-active">Installed</span>' : row.status === "disabled" ? '<span class="state-disabled">Disabled</span>' : row.status === "not-inspected" ? \`<span class="muted" title="This runtime's state file could not be read, so its status is unknown.">Not inspected</span>\` : '<span class="muted">Not installed</span>';
4076
4100
  const uninstall = row.status === "active";
4077
4101
  const busyLabel = uninstall ? "Uninstalling…" : "Installing…";
4078
- const action = row.version === null ? "" : \`<button type="button" class="\${uninstall ? "danger" : "primary"}" data-integration-action="\${uninstall ? "uninstall" : "install"}" data-integration-target="\${escapeHtml(row.target)}"\${busy2 ? " disabled" : ""}>\${busy2 ? busyLabel : uninstall ? "Uninstall" : row.status === "disabled" ? "Enable" : "Install"}</button>\`;
4102
+ const action = row.version === null ? "" : \`<button type="button" class="\${uninstall ? "danger" : "primary"}" data-integration-action="\${uninstall ? "uninstall" : "install"}" data-integration-target="\${escapeHtml(row.target)}"\${busy ? " disabled" : ""}>\${busy ? busyLabel : uninstall ? "Uninstall" : row.status === "disabled" ? "Enable" : "Install"}</button>\`;
4079
4103
  const note = row.note ? \`<div class="status \${row.note.kind}">\${escapeHtml(row.note.text)}</div>\` : "";
4080
4104
  return \`<div class="integration-row">
4081
4105
  <span class="integration-info"><strong>\${escapeHtml(row.label)}</strong> \${version} \${status}</span>
@@ -5951,6 +5975,6 @@ load().then((loaded) => {
5951
5975
  </script>
5952
5976
  </body>
5953
5977
  </html>
5954
- `;var eu='<script id="ccsn-data" type="application/json">';function tu(e){return Qd.replace(eu,()=>eu+JSON.stringify({token:e}).replaceAll("<","\\u003c"))}var fr="kenryu42/cc-safety-net",u0=`https://github.com/${fr}`,ui=1e4,p0=7,f0="The project draft directory changed; reload the draft before applying.",m0="audit settings are user scope only; remove the audit section from a project proposal";async function mu(e,t={}){let n=E({label:"gui",booleans:{noOpen:["--no-open"]}},e),r=t.log??console.log,o=t.error??console.error;if(n.errors.length>0){for(let s of n.errors)o(s);return o("Usage: cc-safety-net gui [--no-open]"),1}let i=await g0(t);if(r(`CC Safety Net policy GUI: ${i.url}`),!n.flags.noOpen)try{await(t.openBrowser??R0)(i.url)}catch(s){o(`Failed to open browser: ${s instanceof Error?s.message:String(s)}`),o(`Open this URL manually: ${i.url}`)}if(t.keepAlive===!1)return await i.close(),0;return await S0(i),0}async function g0(e={}){let t=a0(24).toString("base64url"),n={dir:null,revision:0},r=c0((s,a)=>{h0(s,a,t,e,n)});await new Promise((s,a)=>{r.once("error",a),r.listen(0,"127.0.0.1",()=>{r.off("error",a),s()})});let i=`http://127.0.0.1:${r.address().port}`;return{origin:i,token:t,url:`${i}/?token=${encodeURIComponent(t)}`,close:()=>C0(r)}}async function h0(e,t,n,r,o){let i=new URL(e.url??"/","http://127.0.0.1");if(e.method==="GET"&&i.pathname==="/favicon.ico"){t.writeHead(204,{"cache-control":"no-store"}),t.end();return}if(!w0(e,i,n)){C(t,403,{error:"Forbidden"});return}if(e.method==="GET"&&i.pathname==="/"){x0(t,tu(n));return}if(e.method==="GET"&&i.pathname==="/api/policy"){let s=au(r),a=z(r);C(t,200,{...s,configState:Ht(a),...a.policyScopes?{projectPolicy:{path:se(r.cwd),weakenings:a.policyScopes.weakenings}}:{},destructiveCommandRules:$t,secretPatterns:iu,version:I(),preview:s.errors.length>0?null:cu(s.policy)});return}if(e.method==="POST"&&i.pathname==="/api/policy/preview"){let s=await dn(e);if(!s.ok){C(t,s.status,{errors:[s.error]});return}let a=lu(s.value);C(t,a.errors.length>0?400:200,a);return}if(e.method==="POST"&&i.pathname==="/api/policy/explain"){let s=await dn(e);if(!s.ok){C(t,s.status,{errors:[s.error]});return}let a=s.value;if(a===null||typeof a.command!=="string"){C(t,400,{errors:["command must be a string"]});return}let l=Ee(a.policy);if(l.length>0){C(t,400,{errors:l});return}C(t,200,b0(a.command,a.policy,r));return}if(e.method==="POST"&&i.pathname==="/api/policy"){let s=await dn(e);if(!s.ok){C(t,s.status,{errors:[s.error]});return}let a=cn(s.value,r);C(t,a.errors.length>0?400:200,a);return}if(e.method==="POST"&&i.pathname==="/api/reset"){C(t,200,cn(su,r));return}if(e.method==="POST"&&i.pathname==="/api/repair"){C(t,200,du(r));return}if(e.method==="POST"&&i.pathname==="/api/policy/project/choose-directory"){let s=await(r.chooseDirectory??ci)();if("path"in s)o.dir=s.path,o.revision+=1;C(t,200,{cancelled:"cancelled"in s,..."error"in s?{error:s.error}:{}});return}if(e.method==="GET"&&i.pathname==="/api/policy/project"){let s=gu(o,r),a=nu(s),l=lt(r);C(t,200,{dir:s,path:se(s),revision:o.revision,baseline:l.baseline,userPolicyDiagnostics:l.diagnostics,projection:a.projection,projectionDiagnostics:a.diagnostics,canPickDirectory:li(process.platform,process.env)});return}if(e.method==="POST"&&i.pathname==="/api/policy/project/diff"){let s=await ru(e,t,o,r);if(!s)return;let a=nu(s.dir),l=lt(r).baseline,c=Ge(l,Be(s.proposal).policy);C(t,200,{rows:Ft(Ge(l,a.projection).policy,c.policy,!1),weakenings:c.weakenings,existingFileDiagnostics:a.diagnostics,errors:[]});return}if(e.method==="POST"&&i.pathname==="/api/policy/project/apply"){let s=await ru(e,t,o,r);if(!s)return;let a=v0(s.dir,s.proposal);C(t,a.errors.length>0?500:200,a);return}if(e.method==="GET"&&i.pathname==="/api/activity"){let s=ct(r),a=L0(i.searchParams.get("days"),s);if(a===null){C(t,400,{error:`days must be an integer between 1 and ${s}`});return}C(t,200,Wd(a,r.activityLogsDir));return}if(e.method==="POST"&&i.pathname==="/api/rules/choose-directory"){C(t,200,await ci());return}if(e.method==="GET"&&i.pathname==="/api/rules"){let s=De(r),a=new Map(s.rules.map((l)=>[l.name,l]));C(t,200,{projectPath:r.cwd??process.cwd(),canPickDirectory:li(process.platform,process.env),rulebooks:s.rulebooks.map((l)=>({source:l.source,spec:l.spec,name:l.name,version:l.version,rules:l.rules.flatMap((c)=>{let d=a.get(c);if(!d)return[];return[{name:d.name,command:d.command,subcommand:d.subcommand,block_args:d.block_args,reason:d.reason}]})})),errors:s.errors,warnings:s.warnings});return}if(e.method==="GET"&&i.pathname==="/api/star/context"){C(t,200,await(r.fetchStarContext??(()=>_0({logsDir:r.activityLogsDir})))());return}if(e.method==="POST"&&i.pathname==="/api/star"){let s=await(r.starRepo??P0)();C(t,200,s.ok?{ok:!0}:{ok:!1,fallbackUrl:u0});return}if(e.method==="GET"&&i.pathname==="/api/integrations"){C(t,200,await(r.fetchIntegrations??D0)());return}if(e.method==="GET"&&i.pathname==="/api/health"){C(t,200,await(r.fetchHealth??A0)());return}if(e.method==="POST"&&(i.pathname==="/api/install"||i.pathname==="/api/uninstall")){let s=await dn(e);if(!s.ok){C(t,s.status,{errors:[s.error]});return}let a=s.value?.target;if(typeof a!=="string"||!pe.some((c)=>c.target===a)){C(t,400,{error:"unknown target"});return}let l=i.pathname==="/api/install"?"install":"uninstall";C(t,200,await(r.runIntegration??E0)(l,a));return}C(t,404,{error:"Not found"})}function gu(e,t){return e.dir??t.cwd??process.cwd()}function nu(e){let t=se(e),n=l0(t)?_e(t):{value:void 0,errors:[]},r=Be(n.value);return{projection:r.policy,diagnostics:[...n.errors,...r.diagnostics]}}async function ru(e,t,n,r){let o=gu(n,r),i=n.revision,s=await dn(e);if(!s.ok)return C(t,s.status,{errors:[s.error]}),null;let a=s.value;if(typeof a?.revision!=="number")return C(t,400,{errors:["revision must be a number"]}),null;if(a.revision!==i)return C(t,409,{errors:[f0]}),null;let l=y0(a.proposal);if(l.length>0)return C(t,400,{errors:l}),null;return{dir:o,proposal:a.proposal}}function y0(e){let t=Ee(e);if(t.length>0)return t;return e?.audit===void 0?[]:[m0]}function v0(e,t){let n=se(e),r=jt(t,Y(t));try{return B(x(Rt(e,"project policy"),n),`${JSON.stringify(r,null,2)}
5955
- `),{path:n,errors:[]}}catch(o){return{path:n,errors:[o instanceof Error?o.message:String(o)]}}}function b0(e,t,n){let r=Y(t),o=z(n),i=Ot({rules:o.policy.rules,transparentWrappers:o.policy.transparentWrappers,safety:pu(r.safety),worktreeMode:r.workflow.worktree_mode,destructiveCommandProtectionEnabled:r.destructive_command_protection.enabled,destructiveCommandRuleOverrides:r.destructive_command_protection.overrides,destructiveCommandAllowPaths:r.destructive_command_protection.allow_paths,secretProtection:{enabled:r.secret_protection.enabled,disabledRules:uu(r.secret_protection.overrides),denyPaths:r.secret_protection.deny_paths,allowPaths:r.secret_protection.allow_paths}});return at(e,{policySnapshot:i,cwd:n.cwd,userConfigDir:n.userConfigDir})}function L0(e,t){if(e===null)return Math.min(p0,t);let n=Number(e);if(!Number.isInteger(n)||n<1||n>t)return null;return n}function w0(e,t,n){if(t.searchParams.get("token")!==n)return!1;if(e.method!=="POST")return!0;return e.headers["x-cc-safety-net-token"]===n}var k0=1048576;async function dn(e){let t=[],n=0;for await(let r of e){let o=r;if(n+=o.byteLength,n>k0)return{ok:!1,status:413,error:"Request body is too large"};t.push(o)}try{return{ok:!0,value:JSON.parse(Buffer.concat(t).toString("utf-8")||"{}")}}catch(r){return{ok:!1,status:400,error:`Invalid JSON: ${r instanceof Error?r.message:String(r)}`}}}function x0(e,t){e.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),e.end(t)}function C(e,t,n){e.writeHead(t,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),e.end(JSON.stringify(n))}function C0(e){return new Promise((t,n)=>{e.close((r)=>r?n(r):t())})}function S0(e){return new Promise((t)=>{let n=()=>{process.off("SIGINT",r),process.off("SIGTERM",r)},r=()=>{n(),e.close().then(t)};process.once("SIGINT",r),process.once("SIGTERM",r)})}function R0(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",n=process.platform==="win32"?["/c","start","",e]:[e];return new Promise((r,o)=>{let i=fu(t,n,{detached:!0,stdio:"ignore"}),s=(l)=>{i.off("spawn",a),o(l)},a=()=>{i.off("error",s),i.unref(),r()};i.once("error",s),i.once("spawn",a)})}async function P0(e="gh",t=ui){return{ok:await di(e,["api","-X","PUT",`/user/starred/${fr}`],t)===0}}async function D0(e={}){let t=await qt(e.fetcher),n=hu(t,e.homeDir);return{targets:X.map((r)=>{let o=n.find((i)=>i.platform===r.id);return{target:r.id,label:D(r.id),version:t.versions[r.id]??null,status:o?.configured?"active":o?.detected?"disabled":o?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:t.version,nodeVersion:t.nodeVersion,platform:t.platform}}}function hu(e,t){return vt(process.cwd(),{homeDir:t,ampPluginListOutput:e.ampPluginListOutput,codexPluginListOutput:e.codexPluginListOutput,copilotCliVersion:e.versions["copilot-cli"]})}async function A0(e={}){let[t,n]=await Promise.all([qt(e.fetcher),(e.checkUpdates??Te)()]);return{hooks:hu(t,e.homeDir).filter((r)=>r.detected).map((r)=>({platform:r.platform,label:D(r.platform),configured:r.configured})),update:{currentVersion:n.currentVersion,latestVersion:n.latestVersion??null,updateAvailable:n.updateAvailable}}}var ou=Promise.resolve();function E0(e,t,n={}){let r=async()=>{let i=[],s=console.log,a=console.error;console.log=(...l)=>i.push(l.map(String).join(" ")),console.error=console.log;try{return{ok:await ln(e,[],{selectTargets:async()=>[t],output:new d0({write(c,d,m){i.push(String(c).replace(/\n$/,"")),m()}}),...n})===0,output:i.join(`
5956
- `)}}finally{console.log=s,console.error=a}},o=ou.then(r);return ou=o.then(()=>{return},()=>{return}),o}async function _0(e={}){let[t,n,r]=await Promise.all([T0(e.command),I0(e.fetchRepo),Promise.resolve(Rn(ct(),e.logsDir).totalBlocked)]);return{starred:t,starCount:n,blockedTotal:r}}async function T0(e="gh",t=ui){if(await di(e,["auth","status"],t)!==0)return null;let n=await di(e,["api",`/user/starred/${fr}`],t);if(n===0)return!0;if(n===null)return null;return!1}function di(e,t,n){return new Promise((r)=>{let o=fu(e,t,{stdio:"ignore",windowsHide:!0}),i=!1,s,a=(l)=>{if(i)return;if(i=!0,s)clearTimeout(s);r(l)};o.once("error",()=>a(null)),o.once("close",a),s=setTimeout(()=>{o.kill(),a(null)},n)})}async function I0(e=fetch){try{let t=await e(`https://api.github.com/repos/${fr}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(ui)});if(!t.ok)return null;let n=await t.json();return typeof n.stargazers_count==="number"?n.stargazers_count:null}catch{return null}}function $0(e){if(e[0]!=="help")return!1;let t=e[1];if(!t)Bo(),process.exit(0);if(rn(t))process.exit(0);console.error(`Unknown command: ${t}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var O0={hook:async(e)=>{let t=Qs(e);if(t){await t.run();return}console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),rn("hook",console.error),process.exit(1)},install:async(e)=>{process.exit(await ln("install",e))},update:async(e)=>{process.exit(await ri(e))},uninstall:async(e)=>{process.exit(await ln("uninstall",e))},rule:async(e)=>{process.exit(await zd(e))},policy:async(e)=>{process.exit(await Dd(e))},status:async(e)=>{if(fe(E({label:"status"},e).errors))process.exit(1);Jd()},statusline:async(e)=>{let t=E({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},e);if(t.errors.length===0&&t.flags.claudeCode){await si();return}if(fe(t.errors),!t.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");rn("statusline",console.error),process.exit(1)},doctor:async(e)=>{let t=No(e);if(!t)process.exit(1);let n=await yc({json:t.json,skipUpdateCheck:t.skipUpdateCheck});process.exit(n)},logs:async(e)=>{process.exit(await Ls(e))},gui:async(e)=>{process.exit(await mu(e))},explain:async(e)=>{process.exit(await Cc(e))}};async function F0(){let e=process.argv.slice(2),t=E({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},e);if($0(e))return;let n=e[0],r=n?Sn(n):void 0;if(t.help&&r&&r.name!=="rule")rn(r.name),process.exit(0);if(!n||t.help&&!r)Bo(),process.exit(0);if(t.flags.version)Pc(),process.exit(0);if(r){await O0[r.name](e.slice(1));return}let o=ea(n);if(o){await o.run();return}if(n==="--statusline"){await si();return}console.error(n.startsWith("-")?`Unknown option: ${n}`:`Unknown command: ${n}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}F0().catch((e)=>{console.error("CC Safety Net error:",e),process.exit(1)});
5978
+ `;var lu='<script id="ccsn-data" type="application/json">';function cu(ce){return au.replace(lu,()=>lu+JSON.stringify({token:ce}).replaceAll("<","\\u003c"))}var To="kenryu42/cc-safety-net",m0=`https://github.com/${To}`,ds=1e4,g0=7,h0="The project draft directory changed; reload the draft before applying.",y0="audit settings are user scope only; remove the audit section from a project proposal";async function mu(ce,me={}){let ge=Wt({label:"gui",booleans:{noOpen:["--no-open"]}},ce),he=me.log??console.log,Se=me.error??console.error;if(ge.errors.length>0){for(let He of ge.errors)Se(He);return Se("Usage: cc-safety-net gui [--no-open]"),1}let Fe=await v0(me);if(he(`CC Safety Net policy GUI: ${Fe.url}`),!ge.flags.noOpen)try{await(me.openBrowser??A0)(Fe.url)}catch(He){Se(`Failed to open browser: ${He instanceof Error?He.message:String(He)}`),Se(`Open this URL manually: ${Fe.url}`)}if(me.keepAlive===!1)return await Fe.close(),0;return await D0(Fe),0}async function v0(ce={}){let me=d0(24).toString("base64url"),ge={dir:null,revision:0},he=p0((He,Ge)=>{b0(He,Ge,me,ce,ge)});await new Promise((He,Ge)=>{he.once("error",Ge),he.listen(0,"127.0.0.1",()=>{he.off("error",Ge),He()})});let Fe=`http://127.0.0.1:${he.address().port}`;return{origin:Fe,token:me,url:`${Fe}/?token=${encodeURIComponent(me)}`,close:()=>P0(he)}}async function b0(ce,me,ge,he,Se){let Fe=new URL(ce.url??"/","http://127.0.0.1");if(ce.method==="GET"&&Fe.pathname==="/favicon.ico"){me.writeHead(204,{"cache-control":"no-store"}),me.end();return}if(!C0(ce,Fe,ge)){qt(me,403,{error:"Forbidden"});return}if(ce.method==="GET"&&Fe.pathname==="/"){R0(me,cu(ge));return}if(ce.method==="GET"&&Fe.pathname==="/api/policy"){let He=Et(he),Ge=x(he);qt(me,200,{...He,configState:$e(Ge),...Ge.policyScopes?{projectPolicy:{path:g(he.cwd),weakenings:Ge.policyScopes.weakenings}}:{},destructiveCommandRules:J,secretPatterns:Ze,version:Xt(),preview:He.errors.length>0?null:ht(He.policy)});return}if(ce.method==="POST"&&Fe.pathname==="/api/policy/preview"){let He=await Tr(ce);if(!He.ok){qt(me,He.status,{errors:[He.error]});return}let Ge=Pt(He.value);qt(me,Ge.errors.length>0?400:200,Ge);return}if(ce.method==="POST"&&Fe.pathname==="/api/policy/explain"){let He=await Tr(ce);if(!He.ok){qt(me,He.status,{errors:[He.error]});return}let Ge=He.value;if(Ge===null||typeof Ge.command!=="string"){qt(me,400,{errors:["command must be a string"]});return}let Dt=_(Ge.policy);if(Dt.length>0){qt(me,400,{errors:Dt});return}qt(me,200,k0(Ge.command,Ge.policy,he));return}if(ce.method==="POST"&&Fe.pathname==="/api/policy"){let He=await Tr(ce);if(!He.ok){qt(me,He.status,{errors:[He.error]});return}let Ge=Q(He.value,he);qt(me,Ge.errors.length>0?400:200,Ge);return}if(ce.method==="POST"&&Fe.pathname==="/api/reset"){qt(me,200,Q(ve,he));return}if(ce.method==="POST"&&Fe.pathname==="/api/repair"){qt(me,200,_t(he));return}if(ce.method==="POST"&&Fe.pathname==="/api/policy/project/choose-directory"){let He=await(he.chooseDirectory??ls)();if("path"in He)Se.dir=He.path,Se.revision+=1;qt(me,200,{cancelled:"cancelled"in He,..."error"in He?{error:He.error}:{}});return}if(ce.method==="GET"&&Fe.pathname==="/api/policy/project"){let He=gu(Se,he),Ge=du(He),Dt=Vn(he);qt(me,200,{dir:He,path:g(He),revision:Se.revision,baseline:Dt.baseline,userPolicyDiagnostics:Dt.diagnostics,projection:Ge.projection,projectionDiagnostics:Ge.diagnostics,canPickDirectory:as(process.platform,process.env)});return}if(ce.method==="POST"&&Fe.pathname==="/api/policy/project/diff"){let He=await uu(ce,me,Se,he);if(!He)return;let Ge=du(He.dir),Dt=Vn(he).baseline,At=X(Dt,le(He.proposal).policy);qt(me,200,{rows:dr(X(Dt,Ge.projection).policy,At.policy,!1),weakenings:At.weakenings,existingFileDiagnostics:Ge.diagnostics,errors:[]});return}if(ce.method==="POST"&&Fe.pathname==="/api/policy/project/apply"){let He=await uu(ce,me,Se,he);if(!He)return;let Ge=w0(He.dir,He.proposal);qt(me,Ge.errors.length>0?500:200,Ge);return}if(ce.method==="GET"&&Fe.pathname==="/api/activity"){let He=de(he),Ge=x0(Fe.searchParams.get("days"),He);if(Ge===null){qt(me,400,{error:`days must be an integer between 1 and ${He}`});return}qt(me,200,ru(Ge,he.activityLogsDir));return}if(ce.method==="POST"&&Fe.pathname==="/api/rules/choose-directory"){qt(me,200,await ls());return}if(ce.method==="GET"&&Fe.pathname==="/api/rules"){let He=V(he),Ge=new Map(He.rules.map((Dt)=>[Dt.name,Dt]));qt(me,200,{projectPath:he.cwd??process.cwd(),canPickDirectory:as(process.platform,process.env),rulebooks:He.rulebooks.map((Dt)=>({source:Dt.source,spec:Dt.spec,name:Dt.name,version:Dt.version,rules:Dt.rules.flatMap((At)=>{let Tt=Ge.get(At);if(!Tt)return[];return[{name:Tt.name,command:Tt.command,subcommand:Tt.subcommand,block_args:Tt.block_args,reason:Tt.reason}]})})),errors:He.errors,warnings:He.warnings});return}if(ce.method==="GET"&&Fe.pathname==="/api/star/context"){qt(me,200,await(he.fetchStarContext??(()=>$0({logsDir:he.activityLogsDir})))());return}if(ce.method==="POST"&&Fe.pathname==="/api/star"){let He=await(he.starRepo??E0)();qt(me,200,He.ok?{ok:!0}:{ok:!1,fallbackUrl:m0});return}if(ce.method==="GET"&&Fe.pathname==="/api/integrations"){qt(me,200,await(he.fetchIntegrations??_0)());return}if(ce.method==="GET"&&Fe.pathname==="/api/health"){qt(me,200,await(he.fetchHealth??T0)());return}if(ce.method==="POST"&&(Fe.pathname==="/api/install"||Fe.pathname==="/api/uninstall")){let He=await Tr(ce);if(!He.ok){qt(me,He.status,{errors:[He.error]});return}let Ge=He.value?.target;if(typeof Ge!=="string"||!yn.some((At)=>At.target===Ge)){qt(me,400,{error:"unknown target"});return}let Dt=Fe.pathname==="/api/install"?"install":"uninstall";qt(me,200,await(he.runIntegration??I0)(Dt,Ge));return}qt(me,404,{error:"Not found"})}function gu(ce,me){return ce.dir??me.cwd??process.cwd()}function du(ce){let me=g(ce),ge=u0(me)?xn(me):{value:void 0,errors:[]},he=le(ge.value);return{projection:he.policy,diagnostics:[...ge.errors,...he.diagnostics]}}async function uu(ce,me,ge,he){let Se=gu(ge,he),Fe=ge.revision,He=await Tr(ce);if(!He.ok)return qt(me,He.status,{errors:[He.error]}),null;let Ge=He.value;if(typeof Ge?.revision!=="number")return qt(me,400,{errors:["revision must be a number"]}),null;if(Ge.revision!==Fe)return qt(me,409,{errors:[h0]}),null;let Dt=L0(Ge.proposal);if(Dt.length>0)return qt(me,400,{errors:Dt}),null;return{dir:Se,proposal:Ge.proposal}}function L0(ce){let me=_(ce);if(me.length>0)return me;return ce?.audit===void 0?[]:[y0]}function w0(ce,me){let ge=g(ce),he=ur(me,f(me));try{return v(o(k(ce,"project policy"),ge),`${JSON.stringify(he,null,2)}
5979
+ `),{path:ge,errors:[]}}catch(Se){return{path:ge,errors:[Se instanceof Error?Se.message:String(Se)]}}}function k0(ce,me,ge){let he=f(me),Se=x(ge),Fe=Ee({rules:Se.policy.rules,transparentWrappers:Se.policy.transparentWrappers,safety:Qe(he.safety),worktreeMode:he.workflow.worktree_mode,destructiveCommandProtectionEnabled:he.destructive_command_protection.enabled,destructiveCommandRuleOverrides:he.destructive_command_protection.overrides,destructiveCommandAllowPaths:he.destructive_command_protection.allow_paths,secretProtection:{enabled:he.secret_protection.enabled,disabledRules:Xe(he.secret_protection.overrides),denyPaths:he.secret_protection.deny_paths,allowPaths:he.secret_protection.allow_paths}});return qn(ce,{policySnapshot:Fe,cwd:ge.cwd,userConfigDir:ge.userConfigDir})}function x0(ce,me){if(ce===null)return Math.min(g0,me);let ge=Number(ce);if(!Number.isInteger(ge)||ge<1||ge>me)return null;return ge}function C0(ce,me,ge){if(me.searchParams.get("token")!==ge)return!1;if(ce.method!=="POST")return!0;return ce.headers["x-cc-safety-net-token"]===ge}var S0=1048576;async function Tr(ce){let me=[],ge=0;for await(let he of ce){let Se=he;if(ge+=Se.byteLength,ge>S0)return{ok:!1,status:413,error:"Request body is too large"};me.push(Se)}try{return{ok:!0,value:JSON.parse(Buffer.concat(me).toString("utf-8")||"{}")}}catch(he){return{ok:!1,status:400,error:`Invalid JSON: ${he instanceof Error?he.message:String(he)}`}}}function R0(ce,me){ce.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),ce.end(me)}function qt(ce,me,ge){ce.writeHead(me,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),ce.end(JSON.stringify(ge))}function P0(ce){return new Promise((me,ge)=>{ce.close((he)=>he?ge(he):me())})}function D0(ce){return new Promise((me)=>{let ge=()=>{process.off("SIGINT",he),process.off("SIGTERM",he)},he=()=>{ge(),ce.close().then(me)};process.once("SIGINT",he),process.once("SIGTERM",he)})}function A0(ce){let me=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",ge=process.platform==="win32"?["/c","start","",ce]:[ce];return new Promise((he,Se)=>{let Fe=fu(me,ge,{detached:!0,stdio:"ignore"}),He=(Dt)=>{Fe.off("spawn",Ge),Se(Dt)},Ge=()=>{Fe.off("error",He),Fe.unref(),he()};Fe.once("error",He),Fe.once("spawn",Ge)})}async function E0(ce="gh",me=ds){return{ok:await cs(ce,["api","-X","PUT",`/user/starred/${To}`],me)===0}}async function _0(ce={}){let me=await mr(ce.fetcher),ge=hu(me,ce.homeDir);return{targets:an.map((he)=>{let Se=ge.find((Fe)=>Fe.platform===he.id);return{target:he.id,label:Kt(he.id),version:me.versions[he.id]??null,status:Se?.configured?"active":Se?.detected?"disabled":Se?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:me.version,nodeVersion:me.nodeVersion,platform:me.platform}}}function hu(ce,me){return er(process.cwd(),{homeDir:me,ampPluginListOutput:ce.ampPluginListOutput,codexPluginListOutput:ce.codexPluginListOutput,copilotCliVersion:ce.versions["copilot-cli"]})}async function T0(ce={}){let[me,ge]=await Promise.all([mr(ce.fetcher),(ce.checkUpdates??Cn)()]);return{hooks:hu(me,ce.homeDir).filter((he)=>he.detected).map((he)=>({platform:he.platform,label:Kt(he.platform),configured:he.configured})),update:{currentVersion:ge.currentVersion,latestVersion:ge.latestVersion??null,updateAvailable:ge.updateAvailable}}}var pu=Promise.resolve();function I0(ce,me,ge={}){let he=async()=>{let Fe=[],{log:He,error:Ge}=console;console.log=(...Dt)=>Fe.push(Dt.map(String).join(" ")),console.error=console.log;try{return{ok:await _r(ce,[],{selectTargets:async()=>[me],output:new f0({write(At,Tt,Ft){Fe.push(String(At).replace(/\n$/,"")),Ft()}}),...ge})===0,output:Fe.join(`
5980
+ `)}}finally{console.log=He,console.error=Ge}},Se=pu.then(he);return pu=Se.then(()=>{return},()=>{return}),Se}async function $0(ce={}){let[me,ge,he]=await Promise.all([O0(ce.command),F0(ce.fetchRepo),Promise.resolve(qr(de(),ce.logsDir).totalBlocked)]);return{starred:me,starCount:ge,blockedTotal:he}}async function O0(ce="gh",me=ds){if(await cs(ce,["auth","status"],me)!==0)return null;let ge=await cs(ce,["api",`/user/starred/${To}`],me);if(ge===0)return!0;if(ge===null)return null;return!1}function cs(ce,me,ge){return new Promise((he)=>{let Se=fu(ce,me,{stdio:"ignore",windowsHide:!0}),Fe=!1,He,Ge=(Dt)=>{if(Fe)return;if(Fe=!0,He)clearTimeout(He);he(Dt)};Se.once("error",()=>Ge(null)),Se.once("close",Ge),He=setTimeout(()=>{Se.kill(),Ge(null)},ge)})}async function F0(ce=fetch){try{let me=await ce(`https://api.github.com/repos/${To}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(ds)});if(!me.ok)return null;let ge=await me.json();return typeof ge.stargazers_count==="number"?ge.stargazers_count:null}catch{return null}}function j0(ce){if(ce[0]!=="help")return!1;let me=ce[1];if(!me)Gi(),process.exit(0);if(Pr(me))process.exit(0);console.error(`Unknown command: ${me}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var N0={hook:async(ce)=>{let me=ca(ce);if(me){await me.run();return}console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),Pr("hook",console.error),process.exit(1)},install:async(ce)=>{process.exit(await _r("install",ce))},update:async(ce)=>{process.exit(await ns(ce))},uninstall:async(ce)=>{process.exit(await _r("uninstall",ce))},rule:async(ce)=>{process.exit(await eu(ce))},policy:async(ce)=>{process.exit(await jd(ce))},status:async(ce)=>{if(vn(Wt({label:"status"},ce).errors))process.exit(1);nu()},statusline:async(ce)=>{let me=Wt({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},ce);if(me.errors.length===0&&me.flags.claudeCode){await is();return}if(vn(me.errors),!me.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");Pr("statusline",console.error),process.exit(1)},doctor:async(ce)=>{let me=ji(ce);if(!me)process.exit(1);let ge=await Rc({json:me.json,skipUpdateCheck:me.skipUpdateCheck});process.exit(ge)},logs:async(ce)=>{process.exit(await Hs(ce))},gui:async(ce)=>{process.exit(await mu(ce))},explain:async(ce)=>{process.exit(await Ic(ce))}};async function H0(){let ce=process.argv.slice(2),me=Wt({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},ce);if(j0(ce))return;let ge=ce[0],he=ge?Br(ge):void 0;if(me.help&&he&&he.name!=="rule")Pr(he.name),process.exit(0);if(!ge||me.help&&!he)Gi(),process.exit(0);if(me.flags.version)Fc(),process.exit(0);if(he){await N0[he.name](ce.slice(1));return}let Se=da(ge);if(Se){await Se.run();return}if(ge==="--statusline"){await is();return}console.error(ge.startsWith("-")?`Unknown option: ${ge}`:`Unknown command: ${ge}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}H0().catch((ce)=>{console.error("CC Safety Net error:",ce),process.exit(1)});