cc-safety-net 2.3.3 → 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.
- package/dist/amp/cc-safety-net/index.ts +42 -42
- package/dist/api.js +1 -1
- package/dist/bin/cc-safety-net.js +113 -113
- package/dist/chunks/index-68v9n663.js +2 -0
- package/dist/chunks/index-e7vaxtyk.js +46 -0
- package/dist/chunks/index-zqqsva7r.js +18 -0
- package/dist/index.js +1 -1
- package/dist/openclaw/cc-safety-net/index.js +42 -42
- package/dist/openclaw/cc-safety-net/openclaw.plugin.json +1 -1
- package/dist/openclaw/cc-safety-net/package.json +1 -1
- package/dist/pi/index.js +2 -2
- package/dist/vendor/zod.cjs +14 -14
- package/package.json +4 -4
- package/dist/chunks/index-ebfx04sr.js +0 -18
- package/dist/chunks/index-tm5km50k.js +0 -46
- package/dist/chunks/index-y9vmf6ts.js +0 -2
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
3
|
-
${
|
|
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 Ap(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:Pp(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=Ap(e);if(!n)return 1;let r=t.logsDir??be();if(n.pruneLegacy)return Ep(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)=>Op(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(Np(d.entry,t.timeZone));return 0}function Ep(e,t,n){let r=e?Tp(e).map((a)=>Sp(e,a)):[];if(n)return _p(r,t);let o=[],i=0,s=0;for(let a of r){let l=vs(a,{throwIfNoEntry:!1})?.size??0,c=Ip(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 _p(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 Tp(e){try{return wp(e,{withFileTypes:!0}).filter((t)=>t.isFile()&&t.name.endsWith(".jsonl")).map((t)=>t.name)}catch{return[]}}function Ip(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(Hp(o.entry,n)),0}function Op(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&&!Fp(e,n,t.session))return!1;if(t.project!==void 0&&!jp(e.entry.cwd,t.project))return!1;return!0}function Fp(e,t,n){if(e.entry.sessionId===n)return!0;return xp(e.file)===t&&bs(e.file,".jsonl")===n}function jp(e,t){if(!e)return!1;let n=Rp(t,e);return n!==".."&&!n.startsWith(`..${Dp}`)&&!Cp(n)}function Np(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 Hp(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 Yp,relative as Zp}from"node:path";var Mp=8388608;function Up(e,t){console.log(JSON.stringify(e(Ps(t))))}async function Gp(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>Mp)throw Bp(e),Error("hook input byte limit exceeded");t.push(o)}return Buffer.concat(t,n).toString("utf-8")}function Bp(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,Kp(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 qp(e){let t=await Gp(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=Wp(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),Jp(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;Vp(u);let p=Kr(u.evaluation,{includeEvidence:!0,toolName:u.evaluation.stage==="command-analysis"?void 0:a});if(p)e.outputDeny(p);return}}function Vp(e){if(!Nt(S.debug))return;console.error(`CC Safety Net debug: ${zp(e.stage)}: ${Ds(e.cause)}`)}function zp(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 Kp(e){return typeof e==="string"?e:void 0}function Jp(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 Wp(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)=>Up(e.createDenyOutput,o),n=e.createAllowOutput;await qp({...e,outputDeny:t,outputAllow:n?()=>console.log(JSON.stringify(n())):void 0})}function Gt(e){return Yp(e,".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 Os(e){return j(e,Xp)}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:o2(e.toolCall?.args,t),route:Os(t)}),getContext:e2,getSessionId:(e)=>e.conversationId})}function e2(e,t,n,r){let i=r2(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=t2(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 t2(e,t,n){let r=Os(t),o=[...Ts(e,Qp),...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)=>n2(e,n)).reduce((n,r)=>r.length>n.length?r:n,"")||null}function n2(e,t){let n=Zp(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 r2(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 o2(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),Qv=Object.fromEntries(Bt.map((e)=>[e.id,e.displayName]));function D(e){return Bt.find((t)=>t.id===e)?.displayName??e}import{homedir as i2}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||i2(),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 s2=new Map([["Bash","posix"],["PowerShell","powershell"]]);function a2(e){return j(e,s2)}async function qs(){await kn({agent:"claude-code",getAgent:(e)=>Us(e.transcript_path),getToolRoute:a2})}var l2=new Map([["Bash","auto"]]);async function Vs(){await kn({agent:"codex",getToolRoute:(e)=>j(e,l2)})}var c2=new Map([["bash","auto"],["Bash","auto"],["powershell","powershell"],["PowerShell","powershell"]]);function d2(e){return j(e,c2)}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:d2(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 u2=new Map([["Shell","auto"]]);function p2(e){return j(e,u2)}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:p2(t)}),getContext:f2,getSessionId:(e)=>e.conversation_id})}function f2(e,t,n,r){let o=m2(e);if(!o[0])return T(r,t,n),null;let i=we(h2(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 m2(e){return g2(e).flatMap((t)=>{let n=Z([t]);return n?[n]:[]})}function g2(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 h2(e){return typeof e==="string"&&e.trim()!==""?e:"."}var y2=new Map([["run_shell_command","auto"]]);function v2(e){return j(e,y2)}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:v2(t)}),getContext:(e,t,n,r)=>ae(e.cwd,t,n,r),getSessionId:(e)=>e.session_id})}var b2=new Map([["run_terminal_command","auto"]]);function L2(e){return j(e,b2)}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:L2(t)}},getContext:w2,getSessionId:(e)=>e.sessionId})}function w2(e,t,n,r){let o=Z(k2(e));if(!o)return T(r,t,n),null;let i=we(x2(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 k2(e){let t=e.workspaceRoot===void 0?e.cwd:e.workspaceRoot;return typeof t==="string"&&t.trim()!==""?[t]:[]}function x2(e){return typeof e==="string"&&e.trim()!==""?e:"."}import{resolve as C2}from"node:path";var S2=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,S2)}),getContext:R2,getSessionId:(e)=>e.session_id})}function R2(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([C2(o.configCwd,i)]);if(!s)return T(r,t,n,i),null;return{...o,executionCwd:s}}var Zs=new Map([["Bash","posix"]]);function P2(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:P2(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 D2={"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:D2[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 A2=dt.map((e)=>({flags:e.flags.join(", "),description:e.description})),E2=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:[...A2,{flags:"-h, --help",description:"Show this help"}],examples:E2};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 _2(e){return e.aliases??[]}function Sn(e){let t=e.toLowerCase();return Cn.find((n)=>n.name.toLowerCase()===t||_2(n).some((r)=>r.toLowerCase()===t))}import{basename as T2}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??T2(u,".jsonl")),a===void 0||f<=a)s=p.ts,a=f;if(c===void 0||f>c)l=p.ts,c=f;I2(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 I2(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 O2(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)=>O2(l,a.get(l.name)??"project")),shadowedRules:[]}}var F2=[{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[...F2.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},j2=["policy","config","audit"];function N2(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 H2=[{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."}]:[]}},...j2.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 ${N2(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 H2.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 M2=(e)=>le()?`\x1B[32m${e}\x1B[0m`:e,U2=(e)=>le()?`\x1B[33m${e}\x1B[0m`:e,G2=(e)=>le()?`\x1B[34m${e}\x1B[0m`:e,B2=(e)=>le()?`\x1B[35m${e}\x1B[0m`:e,q2=(e)=>le()?`\x1B[36m${e}\x1B[0m`:e,V2=(e)=>le()?`\x1B[31m${e}\x1B[0m`:e,z2=(e)=>le()?`\x1B[2m${e}\x1B[0m`:e,K2=(e)=>le()?`\x1B[1m${e}\x1B[0m`:e,y={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(e){let t=e;return()=>(t=(t*1664525+1013904223)%4294967296,t/4294967296)}function Z2(e){let t=[...W2],n=Y2(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 X2(e,t=0){if(!le())return"";let n=Z2(t);return`\x1B[38;5;${n[e%n.length]}m`}function fa(e,t,n=0){if(!le())return`"${e}"`;return`${X2(t,n)}"${e}"${J2}`}function Pn(e){return e==="default"?"built-in default":`${e} policy`}var Q2=new RegExp("\x1B\\[[0-9;]*m","g"),no=(e)=>e.replace(Q2,"").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
|
|
8
|
-
`)}function ef(
|
|
9
|
-
`)}function tf(
|
|
10
|
-
`)}function nf(
|
|
11
|
-
`)}function
|
|
12
|
-
`)}function
|
|
13
|
-
`);for(let
|
|
14
|
-
`)}function rf(
|
|
15
|
-
`)}function of(
|
|
16
|
-
`);if(
|
|
17
|
-
`);if(
|
|
18
|
-
`);return
|
|
19
|
-
`)}function
|
|
20
|
-
`)}function sf(
|
|
21
|
-
No findings from inspected doctor facts.`);let
|
|
22
|
-
${
|
|
23
|
-
`)[0]?.trim()||null}async function
|
|
24
|
-
`).map((
|
|
25
|
-
`.repeat(
|
|
26
|
-
\x1B[0m\x1B[?25h`)}}var
|
|
27
|
-
`);function Rf(
|
|
28
|
-
`).map((
|
|
29
|
-
`).find((
|
|
30
|
-
`)
|
|
31
|
-
`)}function
|
|
32
|
-
`),{path:
|
|
33
|
-
`)}function
|
|
34
|
-
# version: ${
|
|
35
|
-
`}function Em(
|
|
36
|
-
version: "${
|
|
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 _m(
|
|
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
|
|
@@ -200,86 +200,86 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
|
|
|
200
200
|
|
|
201
201
|
def register(ctx):
|
|
202
202
|
ctx.register_hook("pre_tool_call", _pre_tool_call)
|
|
203
|
-
`}function
|
|
204
|
-
`)}function
|
|
205
|
-
`),
|
|
206
|
-
${
|
|
207
|
-
${
|
|
208
|
-
`,
|
|
209
|
-
`)
|
|
210
|
-
`,
|
|
211
|
-
`,
|
|
212
|
-
`));return{path:n??cg(e),alreadyInstalled:!1}}function mc(e){let t=[],n=Xn(e.homeDir),r=["opencode.json","opencode.jsonc"];for(let o of r){let i=vg(n,o);if(hg(i))try{let s=yg(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 bg}from"node:path";function Fo(e){return bg(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 wg={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??Lg()};return wn.map((r)=>kg(wg[r](n)))}function kg(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 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 hc(){let e=Cg(xg(),"cc-safety-net-self-test"),t=Sg.map((n)=>{let r=bn(st("self-test",{command:n.command},{kind:"command",shell:"auto"},{configCwd:e,executionCwd:e},n.command),{guard:{dependencies:{loadPolicySnapshot:()=>Rg,getModes:()=>Pg,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=Dg(e);return{ready:n,finish:()=>n}},()=>zt(),{loadingMessage:"Checking system status…"});if(e.json)console.log(JSON.stringify(t,null,2));else Ag(t);return t.engineSelfTest.failed>0||t.findings.some((n)=>n.severity==="error")?1:0}async function Dg(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 Ag(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 Eg}from"node:fs";var _g=/^[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&&!Eg(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)=>_g.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(`
|
|
213
|
-
`)}let
|
|
214
|
-
`)}function
|
|
215
|
-
`,()=>
|
|
216
|
-
`))}function
|
|
217
|
-
`))}function
|
|
218
|
-
`)}var
|
|
219
|
-
`)}function
|
|
220
|
-
`),
|
|
221
|
-
`).length};return new Promise((
|
|
222
|
-
`);return}
|
|
223
|
-
`)})}),
|
|
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(`
|
|
224
224
|
`).trim()].filter(Boolean).join(`
|
|
225
|
-
`))}async function
|
|
226
|
-
${
|
|
227
|
-
${[
|
|
228
|
-
`)}`.trim());let
|
|
229
|
-
`}async function
|
|
230
|
-
`)}function
|
|
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]]
|
|
231
231
|
event = "PreToolUse"
|
|
232
|
-
command = "${
|
|
233
|
-
`).reduce((
|
|
234
|
-
`)}function Rh(
|
|
235
|
-
`,
|
|
236
|
-
`,
|
|
237
|
-
${
|
|
238
|
-
`;return`${
|
|
239
|
-
|
|
240
|
-
${
|
|
241
|
-
`}function Eh(
|
|
242
|
-
`),{path:
|
|
243
|
-
`;return
|
|
244
|
-
`)},opencode:{beforeInstall
|
|
245
|
-
`),`Enabled ${
|
|
246
|
-
`),`Enabled npm:cc-safety-net extensions in ${
|
|
247
|
-
`)}async function
|
|
248
|
-
Removing the plugin files anyway; ${
|
|
249
|
-
`)}var Gh={amp:{install:(
|
|
250
|
-
`),uninstall:()=>
|
|
251
|
-
`),uninstall:()=>
|
|
252
|
-
`);function Bh(
|
|
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(`
|
|
253
253
|
`))].join(`
|
|
254
|
-
`)}function
|
|
255
|
-
Update available: cc-safety-net ${
|
|
256
|
-
`)},
|
|
257
|
-
`)}),await
|
|
258
|
-
`),0;if(
|
|
259
|
-
`);return}if(
|
|
260
|
-
`);return}}let
|
|
261
|
-
`)}),0}catch(
|
|
262
|
-
Check file permissions for the target config file and parent directory.`;if(
|
|
263
|
-
Check that the target config path and parent directory exist.`;if(
|
|
264
|
-
Check that every parent path component is a directory.`;return t}import{mkdirSync as Jh}from"node:fs";import{dirname as Wh}from"node:path";import{createInterface as Yh}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&&Qh(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 Zh(`Apply this policy to ${s}? [y/N] `,d,m))return console.log("Cancelled; nothing was written."),0;return Xh(s,a.value,c,n.flags.global),console.log(`Policy applied: ${s}`),0}function Zh(e,t,n){let r=Yh({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 Xh(e,t,n,r){if(r){cn(n);return}Jh(Wh(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 Qh(e){return!!e&&typeof e==="object"&&!Array.isArray(e)}import{join as Oy}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(""),ey(e.entries)}function ey(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} (${ty(t.ruleCount)})`),console.log(` Source: ${t.spec}`)}function ty(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)=>[`[${ry(e,t.name)}] ${t.name}`,...ny(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 ny(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 ry(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 oy=".safety-net.json",iy="~/.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:oy,cleanup:e.cleanup,syncOptions:{cwd:e.cwd}}),await Fd({legacyPath:It(),configPath:ie(),defaultRulebookName:"user-rules",migratedFrom:iy,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=ay(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=ly(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 sy(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){uy(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(!dy(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 sy(e,t,n,r,o,i,s,a){try{return J(t,{version:1,rules:i,overrides:s,transparent_wrappers:a}),J(n,cy(r,e.migratedFrom,o)),await Tt(e.syncOptions)}catch(l){return{ok:!1,errors:[l instanceof Error?l.message:String(l)]}}}function ay(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 ly(e,t,n,r,o){let i=t.find((s)=>py(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 cy(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 dy(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 uy(e){for(let t of e){if(t.content===null){he(t.target);continue}B(t.target,t.content)}}function py(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 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 Ud(e=Date.now()){if(process.env.CC_SAFETY_NET_NO_UPDATE_CHECK)return null;let t=Mr();if(!t)return null;let n=yy(t,".cc-safety-net","update-check.json"),r=await Ly(n,e);if(!r.lastCheck||e-r.lastCheck>vy){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<by)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 Ly(e,t){let n=await my(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 fy(hy(e),{recursive:!0,mode:448}).then(()=>gy(e,JSON.stringify(t),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as wy,resolve as oi}from"node:path";var Gd="CC Safety Net Config",ky="═".repeat(Gd.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 Bd(e={}){try{return Sy(e)}catch(t){if(t instanceof H)return console.error(t.message),1;throw t}}function Sy(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=Ry(x(l.projectScope,s));if(Dy(),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(`
|
|
265
|
-
No config files found. Using built-in rules only.`),0;for(let
|
|
266
|
-
Added $schema to ${
|
|
267
|
-
${
|
|
268
|
-
Config validation failed.`),1;return console.log(
|
|
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?`
|
|
269
269
|
Configs valid with warnings.`:`
|
|
270
|
-
All configs valid.`),0}function
|
|
271
|
-
✓ ${
|
|
272
|
-
✗ Legacy ${
|
|
273
|
-
✓ GitHub source rules: ${
|
|
274
|
-
✗ ${
|
|
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
|
|
276
|
-
return POSIX path of (choose folder with prompt "${
|
|
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}")
|
|
277
277
|
on error number -128
|
|
278
278
|
return ""
|
|
279
279
|
end try`,l0=`Add-Type -AssemblyName System.Windows.Forms
|
|
280
280
|
$dialog = New-Object System.Windows.Forms.FolderBrowserDialog
|
|
281
|
-
$dialog.Description = '${
|
|
282
|
-
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,
|
|
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>
|
|
283
283
|
<html lang="en">
|
|
284
284
|
<head>
|
|
285
285
|
<meta charset="utf-8">
|
|
@@ -4094,12 +4094,12 @@ var renderIntegrations = () => {
|
|
|
4094
4094
|
if (!loaded)
|
|
4095
4095
|
return;
|
|
4096
4096
|
qs("integrations-list").innerHTML = loaded.targets.map((row) => {
|
|
4097
|
-
const
|
|
4097
|
+
const busy = integrationBusy.has(row.target);
|
|
4098
4098
|
const version = row.version === null ? '<span class="muted">not detected</span>' : \`<span class="agent-badge">v\${escapeHtml(row.version)}</span>\`;
|
|
4099
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>';
|
|
4100
4100
|
const uninstall = row.status === "active";
|
|
4101
4101
|
const busyLabel = uninstall ? "Uninstalling…" : "Installing…";
|
|
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)}"\${
|
|
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>\`;
|
|
4103
4103
|
const note = row.note ? \`<div class="status \${row.note.kind}">\${escapeHtml(row.note.text)}</div>\` : "";
|
|
4104
4104
|
return \`<div class="integration-row">
|
|
4105
4105
|
<span class="integration-info"><strong>\${escapeHtml(row.label)}</strong> \${version} \${status}</span>
|
|
@@ -5975,6 +5975,6 @@ load().then((loaded) => {
|
|
|
5975
5975
|
</script>
|
|
5976
5976
|
</body>
|
|
5977
5977
|
</html>
|
|
5978
|
-
`;var
|
|
5979
|
-
`),{path:
|
|
5980
|
-
`)}}finally{console.log=
|
|
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)});
|