cc-safety-net 2.4.3 → 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
- import{a,s,ke,Ue,k,Ze,Ge,c,o,He,L,R,ve,Qe,f,We,d,r,v,i,re,n,g,le,N,tt,nt,l,ue,de,rt,A,q,oe,S,ot,F,b,Se,M,u,K,Be,ze,I,w,T,pe,fe,Re,it,m,e,Te,we,Ve,qe,ie,Ce,se,_e,J,j,Pe,me,U,Ke,G,Y,Z,ae,Je,Ye,C,H,Ae,Oe,De,E,Ne,Ee,Fe,h,t,X,ge,y,x,_,st,Me,$e,p,W}from"./chunks/index-26getn55.js";import{ee,B,je,O,D}from"./chunks/index-sp43p448.js";var Ud=["-h","--help"];function xt(P,V){let z=Object.entries(P.booleans??{}),Q=Object.entries(P.values??{}),te=Object.entries(P.lists??{}),ne=Object.fromEntries(z.map(([Xe])=>[Xe,!1])),ce={},ye=Object.fromEntries(te.map(([Xe])=>[Xe,[]])),he=[],be=[],Le=!1,Ie=-1;for(let[Xe,et]of V.entries()){if(Xe<=Ie)continue;if(et==="--"){he.push(...V.slice(Xe+1));break}if(Ud.includes(et)){Le=!0;continue}let xe=z.find(([,lt])=>lt.includes(et));if(xe){ne[xe[0]]=!0;continue}let at=Q.find(([,lt])=>lt.includes(et));if(at){let lt=V[Xe+1];if(lt===void 0||lt.startsWith("-")){be.push(`${et} requires a value`);continue}ce[at[0]]=lt,Ie=Xe+1;continue}let ct=te.find(([,lt])=>lt.includes(et));if(ct){let lt=V.slice(Xe+1),pt=lt.findIndex((gt)=>gt.startsWith("-")),mt=lt.slice(0,pt===-1?lt.length:pt);if(mt.length===0){be.push(`${et} requires at least one value`);continue}ye[ct[0]]=[...ye[ct[0]]??[],...mt],Ie=Xe+mt.length;continue}if(et.startsWith("-")){be.push(`Unknown option for ${P.label}: ${et}`);continue}if(P.positionals==="tail"){he.push(...V.slice(Xe));break}he.push(et)}if(P.positionals!=="list"&&P.positionals!=="tail")be.push(...he.map((Xe)=>`Unexpected argument for ${P.label}: ${Xe}`));return{flags:ne,values:ce,lists:ye,positionals:he,help:Le,errors:be}}function Ht(P){for(let V of P)console.error(V);return P.length>0}import{readdirSync as Wd,statSync as Ni,unlinkSync as Kd}from"node:fs";import{basename as Mi,dirname as Yd,isAbsolute as Zd,join as Xd,relative as Qd,resolve as eu,sep as tu}from"node:path";var Oi=(P)=>{let V=Date.now()-new Date(P).getTime();if(!Number.isFinite(V))return"";let z=Math.floor(V/60000),Q=Math.floor(z/60),te=Math.floor(Q/24);if(te>0)return`${te}d ago`;if(Q>0)return`${Q}h ago`;if(z>0)return`${z}m ago`;return"just now"},Qr=(P)=>{let V=(P??"").trim().split(/\s+/).filter((te)=>te&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(te)),z=V[0]?.split("/").pop();if(!z)return null;let Q=V[1];return Q&&/^[a-z][a-z0-9-]*$/.test(Q)?`${z} ${Q}`:z};function Fi(P){let V=(te)=>`${te.sessionId}
1
+ import{a,s,ke,Ue,k,Ze,Ge,c,o,He,R,L,ve,Qe,f,We,d,r,v,i,re,n,g,le,N,tt,nt,l,ue,de,rt,A,q,oe,S,ot,F,b,Se,M,u,K,Be,ze,I,w,T,pe,fe,Le,it,m,e,Te,we,Ve,qe,ie,Ce,se,_e,J,j,Pe,me,U,Ke,G,Y,Z,ae,Je,Ye,C,H,Ae,Oe,De,E,Ne,Ee,Fe,h,t,X,ge,y,x,_,st,Me,$e,p,W}from"./chunks/index-7v0rebpp.js";import{ee,B,je,O,D}from"./chunks/index-j3dfea6s.js";var Ud=["-h","--help"];function xt(P,V){let z=Object.entries(P.booleans??{}),Q=Object.entries(P.values??{}),te=Object.entries(P.lists??{}),ne=Object.fromEntries(z.map(([Xe])=>[Xe,!1])),ce={},ye=Object.fromEntries(te.map(([Xe])=>[Xe,[]])),he=[],be=[],xe=!1,Ie=-1;for(let[Xe,et]of V.entries()){if(Xe<=Ie)continue;if(et==="--"){he.push(...V.slice(Xe+1));break}if(Ud.includes(et)){xe=!0;continue}let Re=z.find(([,lt])=>lt.includes(et));if(Re){ne[Re[0]]=!0;continue}let at=Q.find(([,lt])=>lt.includes(et));if(at){let lt=V[Xe+1];if(lt===void 0||lt.startsWith("-")){be.push(`${et} requires a value`);continue}ce[at[0]]=lt,Ie=Xe+1;continue}let ct=te.find(([,lt])=>lt.includes(et));if(ct){let lt=V.slice(Xe+1),pt=lt.findIndex((gt)=>gt.startsWith("-")),mt=lt.slice(0,pt===-1?lt.length:pt);if(mt.length===0){be.push(`${et} requires at least one value`);continue}ye[ct[0]]=[...ye[ct[0]]??[],...mt],Ie=Xe+mt.length;continue}if(et.startsWith("-")){be.push(`Unknown option for ${P.label}: ${et}`);continue}if(P.positionals==="tail"){he.push(...V.slice(Xe));break}he.push(et)}if(P.positionals!=="list"&&P.positionals!=="tail")be.push(...he.map((Xe)=>`Unexpected argument for ${P.label}: ${Xe}`));return{flags:ne,values:ce,lists:ye,positionals:he,help:xe,errors:be}}function Ht(P){for(let V of P)console.error(V);return P.length>0}import{readdirSync as Wd,statSync as Ni,unlinkSync as Kd}from"node:fs";import{basename as Mi,dirname as Yd,isAbsolute as Zd,join as Xd,relative as Qd,resolve as eu,sep as tu}from"node:path";var Oi=(P)=>{let V=Date.now()-new Date(P).getTime();if(!Number.isFinite(V))return"";let z=Math.floor(V/60000),Q=Math.floor(z/60),te=Math.floor(Q/24);if(te>0)return`${te}d ago`;if(Q>0)return`${Q}h ago`;if(z>0)return`${z}m ago`;return"just now"},Qr=(P)=>{let V=(P??"").trim().split(/\s+/).filter((te)=>te&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(te)),z=V[0]?.split("/").pop();if(!z)return null;let Q=V[1];return Q&&/^[a-z][a-z0-9-]*$/.test(Q)?`${z} ${Q}`:z};function Fi(P){let V=(te)=>`${te.sessionId}
2
2
  ${Qr(te.segment||te.command)}`,z=P.filter((te)=>te.decision!=="allow"),Q=z.filter((te)=>te.sessionId).reduce((te,ne)=>te.set(V(ne),(te.get(V(ne))??0)+1),new Map);return new Set(z.filter((te)=>te.failureStage||(Q.get(V(te))??0)>=2))}import{existsSync as Gd,readdirSync as Bd,readFileSync as qd}from"node:fs";import{join as Vd}from"node:path";function Yt(P,V){try{return Bd(P,{withFileTypes:!0,encoding:"utf8"}).flatMap((z)=>{let Q=Vd(P,z.name);if(z.isDirectory())return Yt(Q,V);if(z.name.endsWith(".jsonl"))return[Q];return[]})}catch{if(V&&Gd(P))V.count++;return[]}}var zd=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function Jd(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let V=P;if(typeof V.ts!=="string"||typeof V.command!=="string")return!1;return zd.every((z)=>V[z]===void 0||typeof V[z]==="string")}function pn(P,V){try{return qd(P,"utf-8").split(`
3
- `).filter(Boolean).flatMap((z)=>{try{let Q=JSON.parse(z);if(!Jd(Q)){if(V)V.count++;return[]}return[Q]}catch{if(V)V.count++;return[]}})}catch{if(V)V.count++;return[]}}function Ct(P){return Array.from(P,(V)=>{let z=V.charCodeAt(0);if(z<=31||z>=127&&z<=159)return`\\x${z.toString(16).padStart(2,"0")}`;return V}).join("")}function nu(P,V){let z=ee(P),Q=xt({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"]}},V);if(Ht(Q.errors))return null;if(Q.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(Q.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let te=Q.values.limit===void 0?20:ji(Q.values.limit);if(te===null)return console.error("--limit must be a positive number"),null;let ne=Q.values.since===void 0?Math.min(30,z):ji(Q.values.since);if(ne===null||ne>z)return console.error(`--since must be a positive number of days no greater than ${z}`),null;let ce={limit:te,limitExplicit:Q.values.limit!==void 0,since:ne,sinceExplicit:Q.values.since!==void 0,all:Q.flags.all,json:Q.flags.json,suspect:Q.flags.suspect,pruneLegacy:Q.flags.pruneLegacy,dryRun:Q.flags.dryRun,id:Q.values.id,agent:Q.values.agent,rule:Q.values.rule,session:Q.values.session,project:Q.values.project===void 0?void 0:eu(Q.values.project)};if(ce.id&&(ce.agent!==void 0||ce.rule!==void 0||ce.session!==void 0||ce.project!==void 0||ce.suspect||ce.sinceExplicit||ce.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(ce.pruneLegacy&&(ce.id!==void 0||ce.agent!==void 0||ce.rule!==void 0||ce.session!==void 0||ce.project!==void 0||ce.suspect||ce.all||ce.sinceExplicit||ce.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(ce.dryRun&&!ce.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return ce}async function Hi(P,V,z={}){let Q=nu(P,V);if(!Q)return 1;let te=z.logsDir??O(P);if(Q.pruneLegacy)return ru(te,Q.json,Q.dryRun);if(!te)return console.log(Q.json?"[]":Q.id?`No retained audit log entry found for id ${Ct(Q.id)}.`:"No audit log entries found."),0;B(P,te);let ne={count:0},ce=Yt(te,ne).flatMap((Ie)=>pn(Ie,ne).map((Xe)=>({entry:Xe,file:Ie})));if(ne.count>0)console.error(`warning: ${ne.count} audit log ${ne.count===1?"source":"sources"} could not be read; these results are incomplete`);if(Q.id)return au(ce,Q,z.timeZone);let ye=Date.now()-Q.since*24*60*60*1000,he=ce.filter((Ie)=>lu(Ie,Q,te,ye)),be=Q.suspect?Fi(he.map((Ie)=>Ie.entry)):null,Le=(be?he.filter((Ie)=>be.has(Ie.entry)):he).sort((Ie,Xe)=>Date.parse(Xe.entry.ts)-Date.parse(Ie.entry.ts)).slice(0,Q.limit);if(Q.json)return console.log(JSON.stringify(Le.map((Ie)=>Ie.entry),null,2)),0;if(Le.length===0)return console.log("No audit log entries found."),0;for(let Ie of Le)console.log(uu(Ie.entry,z.timeZone));return 0}function ru(P,V,z){let Q=P?iu(P).map((ye)=>Xd(P,ye)):[];if(z)return ou(Q,V);let te=[],ne=0,ce=0;for(let ye of Q){let he=Ni(ye,{throwIfNoEntry:!1})?.size??0,be=su(ye);if(be){te.push(`${Mi(ye)}: ${be}`);continue}ne++,ce+=he}if(V)return console.log(JSON.stringify({removedFiles:ne,removedBytes:ce,failedFiles:te.length})),te.length===0?0:1;console.log(ne===0&&te.length===0?"No legacy audit log files found.":`Removed ${ne} legacy audit log ${ne===1?"file":"files"} (${Ui(ce)}).`);for(let ye of te)console.error(`Could not remove ${Ct(ye)}`);if(console.log("Nested v2 audit logs were not changed."),ne>0)console.log("This deletion cannot be undone.");return te.length===0?0:1}function ou(P,V){let z=P.reduce((Q,te)=>Q+(Ni(te,{throwIfNoEntry:!1})?.size??0),0);if(V)return console.log(JSON.stringify({dryRun:!0,files:P.length,bytes:z})),0;if(console.log(P.length===0?"No legacy audit log files found.":`Would remove ${P.length} legacy audit log ${P.length===1?"file":"files"} (${Ui(z)}).`),console.log("Nested v2 audit logs are not included."),P.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function iu(P){try{return Wd(P,{withFileTypes:!0}).filter((V)=>V.isFile()&&V.name.endsWith(".jsonl")).map((V)=>V.name)}catch{return[]}}function su(P){try{return Kd(P),null}catch(V){return V instanceof Error?V.message:String(V)}}function Ui(P){let V=["B","KiB","MiB","GiB"],z=Math.min(Math.floor(Math.log2(Math.max(P,1))/10),V.length-1);return`${Math.round(P/1024**z*10)/10} ${V[z]}`}function au(P,V,z){let Q=P.filter((ne)=>ne.entry.id===V.id);if(Q.length>1)return console.error(`Multiple audit log entries found for id ${Ct(V.id??"")}.`),1;if(V.json)return console.log(JSON.stringify(Q.map((ne)=>ne.entry),null,2)),0;let te=Q[0];if(!te)return console.log(`No retained audit log entry found for id ${Ct(V.id??"")}.`),0;return console.log(pu(te.entry,z)),0}function lu(P,V,z,Q){if(!V.all&&P.entry.decision==="allow")return!1;if(Date.parse(P.entry.ts)<Q)return!1;if(V.agent!==void 0&&P.entry.agent!==V.agent)return!1;if(V.rule!==void 0&&P.entry.ruleId!==V.rule)return!1;if(V.session!==void 0&&!cu(P,z,V.session))return!1;if(V.project!==void 0&&!du(P.entry.cwd,V.project))return!1;return!0}function cu(P,V,z){if(P.entry.sessionId===z)return!0;return Yd(P.file)===V&&Mi(P.file,".jsonl")===z}function du(P,V){if(!P)return!1;let z=Qd(V,P);return z!==".."&&!z.startsWith(`..${tu}`)&&!Zd(z)}function uu(P,V){let z=Ct(P.id??"-"),Q=Ct(P.decision??"deny"),te=P.cwd?` [${Ct(P.cwd)}]`:"",ne=P.segment||P.command,ce=ne===P.command?"":"↳ ",ye=ne.length>50?`${ne.slice(0,50)}…`:ne;return`${z.padEnd(16)} ${Ct(Gi(P.ts,V))} ${Q.padEnd(5)} ${Ct(P.agent??"-").padEnd(15)} ${Ct(P.ruleId??"-").padEnd(20)} ${ce}${Ct(ye)}${te}`}function pu(P,V){let z=(te)=>Ct(te===void 0||te===null||te===""?"-":te),Q=P.shape?`${P.agent??"-"} (shape: ${P.shape})`:P.agent??"-";return[`id: ${z(P.id)}`,`ts: ${z(Gi(P.ts,V))}`,`decision: ${z(P.decision)}`,`agent: ${z(Q)}`,`level: ${z(P.level)}`,`tool: ${z(P.toolName)}`,`rule: ${z(P.ruleId)}`,`intent: ${z(P.intent)}`,`stage: ${z(P.failureStage)}`,`error: ${z(P.errorCode)}`,`session: ${z(P.sessionId)}`,`cwd: ${z(P.cwd)}`,`version: ${z(P.v)}`,`truncated: ${z(P.truncated===!0?"yes":void 0)}`,`reason: ${z(P.reason)}`,`command: ${z(P.command)}`,`segment: ${z(P.segment)}`].join(`
4
- `)}function Gi(P,V){let z=new Date(P);if(Number.isNaN(z.getTime()))return P;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:V}).format(z)}function ji(P){let V=Number(P);return Number.isFinite(V)&&V>0?V:null}var Bi={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 qi={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 Vi={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"]};var Yn=[{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"]}}],Zn=Yn.slice().sort((P,V)=>P.doctorOrder-V.doctorOrder).map((P)=>P.id),Sn=Yn.filter((P)=>("runtime"in P)).slice().sort((P,V)=>P.runtime.order-V.runtime.order).map((P)=>({id:P.id,displayName:"displayName"in P.runtime?P.runtime.displayName:P.displayName,flags:P.runtime.flags,legacyFlags:"legacyFlags"in P.runtime?P.runtime.legacyFlags:[],description:P.runtime.description,legacyTopLevelFlags:P.runtime.legacyTopLevelFlags})),$t=Yn.slice().sort((P,V)=>P.install.order-V.install.order).map((P)=>({id:P.id,...P.install})).map(({order:P,...V})=>V),fu=Object.fromEntries(Yn.map((P)=>[P.id,P.displayName]));function bt(P){return fu[P]}var mu=Sn.map((P)=>({flags:P.flags.join(", "),description:P.description})),gu=Sn.flatMap((P)=>P.flags.map((V)=>`cc-safety-net hook ${V}`)),zi={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...mu,{flags:"-h, --help",description:"Show this help"}],examples:gu};var Ji={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...$t.map((P)=>({flags:P.flag,description:`Install ${bt(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...$t.map((P)=>`cc-safety-net install ${P.flag}`)]},Wi={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...$t.map((P)=>({flags:P.flag,description:`Uninstall ${bt(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...$t.map((P)=>`cc-safety-net uninstall ${P.flag}`)]},Ki={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 Yi={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"],fn={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 Zi={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 Xi={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 Qn=[Zi,Bi,Yi,qi,fn,Xn,Ji,Ki,Wi,zi,Vi,Xi];function yu(P){return P.aliases??[]}function er(P){let V=P.toLowerCase();return Qn.find((z)=>z.name.toLowerCase()===V||yu(z).some((Q)=>Q.toLowerCase()===V))}import{basename as hu}from"node:path";function tr(P,V=7,z=O(P)){let Q=Date.now()-V*24*60*60*1000,te=[],ne=new Set,ce=0,ye,he,be,Le;if(z)B(P,z);let Ie={count:0},Xe=z?Yt(z,Ie):[];for(let xe of Xe)for(let at of pn(xe,Ie)){if(at.decision==="allow")continue;let ct=new Date(at.ts).getTime();if(ct>=Q){if(ce++,ne.add(at.sessionId??hu(xe,".jsonl")),he===void 0||ct<=he)ye=at.ts,he=ct;if(Le===void 0||ct>Le)be=at.ts,Le=ct;vu(te,at,ct)}}let et=te.map((xe)=>({timestamp:xe.ts,command:xe.command,reason:xe.reason,relativeTime:Oi(new Date(xe.ts))}));return{totalBlocked:ce,sessionCount:ne.size,recentEntries:et,oldestEntry:ye,newestEntry:be,unreadable:Ie.count}}function vu(P,V,z){let Q=P.findIndex((te)=>z>new Date(te.ts).getTime());if(Q===-1){if(P.length<3)P.push(V);return}if(P.splice(Q,0,V),P.length>3)P.pop()}import{dirname as Au}from"node:path";import{dirname as bu,join as Lu,resolve as wu}from"node:path";var ku="config.json";function Rt(P,V,z,Q){g(xu(P),`${JSON.stringify(V,null,2)}
3
+ `).filter(Boolean).flatMap((z)=>{try{let Q=JSON.parse(z);if(!Jd(Q)){if(V)V.count++;return[]}return[Q]}catch{if(V)V.count++;return[]}})}catch{if(V)V.count++;return[]}}function Ct(P){return Array.from(P,(V)=>{let z=V.charCodeAt(0);if(z<=31||z>=127&&z<=159)return`\\x${z.toString(16).padStart(2,"0")}`;return V}).join("")}function nu(P,V){let z=ee(P),Q=xt({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"]}},V);if(Ht(Q.errors))return null;if(Q.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(Q.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let te=Q.values.limit===void 0?20:ji(Q.values.limit);if(te===null)return console.error("--limit must be a positive number"),null;let ne=Q.values.since===void 0?Math.min(30,z):ji(Q.values.since);if(ne===null||ne>z)return console.error(`--since must be a positive number of days no greater than ${z}`),null;let ce={limit:te,limitExplicit:Q.values.limit!==void 0,since:ne,sinceExplicit:Q.values.since!==void 0,all:Q.flags.all,json:Q.flags.json,suspect:Q.flags.suspect,pruneLegacy:Q.flags.pruneLegacy,dryRun:Q.flags.dryRun,id:Q.values.id,agent:Q.values.agent,rule:Q.values.rule,session:Q.values.session,project:Q.values.project===void 0?void 0:eu(Q.values.project)};if(ce.id&&(ce.agent!==void 0||ce.rule!==void 0||ce.session!==void 0||ce.project!==void 0||ce.suspect||ce.sinceExplicit||ce.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(ce.pruneLegacy&&(ce.id!==void 0||ce.agent!==void 0||ce.rule!==void 0||ce.session!==void 0||ce.project!==void 0||ce.suspect||ce.all||ce.sinceExplicit||ce.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(ce.dryRun&&!ce.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return ce}async function Hi(P,V,z={}){let Q=nu(P,V);if(!Q)return 1;let te=z.logsDir??O(P);if(Q.pruneLegacy)return ru(te,Q.json,Q.dryRun);if(!te)return console.log(Q.json?"[]":Q.id?`No retained audit log entry found for id ${Ct(Q.id)}.`:"No audit log entries found."),0;B(P,te);let ne={count:0},ce=Yt(te,ne).flatMap((Ie)=>pn(Ie,ne).map((Xe)=>({entry:Xe,file:Ie})));if(ne.count>0)console.error(`warning: ${ne.count} audit log ${ne.count===1?"source":"sources"} could not be read; these results are incomplete`);if(Q.id)return au(ce,Q,z.timeZone);let ye=Date.now()-Q.since*24*60*60*1000,he=ce.filter((Ie)=>lu(Ie,Q,te,ye)),be=Q.suspect?Fi(he.map((Ie)=>Ie.entry)):null,xe=(be?he.filter((Ie)=>be.has(Ie.entry)):he).sort((Ie,Xe)=>Date.parse(Xe.entry.ts)-Date.parse(Ie.entry.ts)).slice(0,Q.limit);if(Q.json)return console.log(JSON.stringify(xe.map((Ie)=>Ie.entry),null,2)),0;if(xe.length===0)return console.log("No audit log entries found."),0;for(let Ie of xe)console.log(uu(Ie.entry,z.timeZone));return 0}function ru(P,V,z){let Q=P?iu(P).map((ye)=>Xd(P,ye)):[];if(z)return ou(Q,V);let te=[],ne=0,ce=0;for(let ye of Q){let he=Ni(ye,{throwIfNoEntry:!1})?.size??0,be=su(ye);if(be){te.push(`${Mi(ye)}: ${be}`);continue}ne++,ce+=he}if(V)return console.log(JSON.stringify({removedFiles:ne,removedBytes:ce,failedFiles:te.length})),te.length===0?0:1;console.log(ne===0&&te.length===0?"No legacy audit log files found.":`Removed ${ne} legacy audit log ${ne===1?"file":"files"} (${Ui(ce)}).`);for(let ye of te)console.error(`Could not remove ${Ct(ye)}`);if(console.log("Nested v2 audit logs were not changed."),ne>0)console.log("This deletion cannot be undone.");return te.length===0?0:1}function ou(P,V){let z=P.reduce((Q,te)=>Q+(Ni(te,{throwIfNoEntry:!1})?.size??0),0);if(V)return console.log(JSON.stringify({dryRun:!0,files:P.length,bytes:z})),0;if(console.log(P.length===0?"No legacy audit log files found.":`Would remove ${P.length} legacy audit log ${P.length===1?"file":"files"} (${Ui(z)}).`),console.log("Nested v2 audit logs are not included."),P.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function iu(P){try{return Wd(P,{withFileTypes:!0}).filter((V)=>V.isFile()&&V.name.endsWith(".jsonl")).map((V)=>V.name)}catch{return[]}}function su(P){try{return Kd(P),null}catch(V){return V instanceof Error?V.message:String(V)}}function Ui(P){let V=["B","KiB","MiB","GiB"],z=Math.min(Math.floor(Math.log2(Math.max(P,1))/10),V.length-1);return`${Math.round(P/1024**z*10)/10} ${V[z]}`}function au(P,V,z){let Q=P.filter((ne)=>ne.entry.id===V.id);if(Q.length>1)return console.error(`Multiple audit log entries found for id ${Ct(V.id??"")}.`),1;if(V.json)return console.log(JSON.stringify(Q.map((ne)=>ne.entry),null,2)),0;let te=Q[0];if(!te)return console.log(`No retained audit log entry found for id ${Ct(V.id??"")}.`),0;return console.log(pu(te.entry,z)),0}function lu(P,V,z,Q){if(!V.all&&P.entry.decision==="allow")return!1;if(Date.parse(P.entry.ts)<Q)return!1;if(V.agent!==void 0&&P.entry.agent!==V.agent)return!1;if(V.rule!==void 0&&P.entry.ruleId!==V.rule)return!1;if(V.session!==void 0&&!cu(P,z,V.session))return!1;if(V.project!==void 0&&!du(P.entry.cwd,V.project))return!1;return!0}function cu(P,V,z){if(P.entry.sessionId===z)return!0;return Yd(P.file)===V&&Mi(P.file,".jsonl")===z}function du(P,V){if(!P)return!1;let z=Qd(V,P);return z!==".."&&!z.startsWith(`..${tu}`)&&!Zd(z)}function uu(P,V){let z=Ct(P.id??"-"),Q=Ct(P.decision??"deny"),te=P.cwd?` [${Ct(P.cwd)}]`:"",ne=P.segment||P.command,ce=ne===P.command?"":"↳ ",ye=ne.length>50?`${ne.slice(0,50)}…`:ne;return`${z.padEnd(16)} ${Ct(Gi(P.ts,V))} ${Q.padEnd(5)} ${Ct(P.agent??"-").padEnd(15)} ${Ct(P.ruleId??"-").padEnd(20)} ${ce}${Ct(ye)}${te}`}function pu(P,V){let z=(te)=>Ct(te===void 0||te===null||te===""?"-":te),Q=P.shape?`${P.agent??"-"} (shape: ${P.shape})`:P.agent??"-";return[`id: ${z(P.id)}`,`ts: ${z(Gi(P.ts,V))}`,`decision: ${z(P.decision)}`,`agent: ${z(Q)}`,`level: ${z(P.level)}`,`tool: ${z(P.toolName)}`,`rule: ${z(P.ruleId)}`,`intent: ${z(P.intent)}`,`stage: ${z(P.failureStage)}`,`error: ${z(P.errorCode)}`,`session: ${z(P.sessionId)}`,`cwd: ${z(P.cwd)}`,`version: ${z(P.v)}`,`truncated: ${z(P.truncated===!0?"yes":void 0)}`,`reason: ${z(P.reason)}`,`command: ${z(P.command)}`,`segment: ${z(P.segment)}`].join(`
4
+ `)}function Gi(P,V){let z=new Date(P);if(Number.isNaN(z.getTime()))return P;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:V}).format(z)}function ji(P){let V=Number(P);return Number.isFinite(V)&&V>0?V:null}var Bi={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 qi={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 Vi={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"]};var Yn=[{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"]}}],Zn=Yn.slice().sort((P,V)=>P.doctorOrder-V.doctorOrder).map((P)=>P.id),Sn=Yn.filter((P)=>("runtime"in P)).slice().sort((P,V)=>P.runtime.order-V.runtime.order).map((P)=>({id:P.id,displayName:"displayName"in P.runtime?P.runtime.displayName:P.displayName,flags:P.runtime.flags,legacyFlags:"legacyFlags"in P.runtime?P.runtime.legacyFlags:[],description:P.runtime.description,legacyTopLevelFlags:P.runtime.legacyTopLevelFlags})),$t=Yn.slice().sort((P,V)=>P.install.order-V.install.order).map((P)=>({id:P.id,...P.install})).map(({order:P,...V})=>V),fu=Object.fromEntries(Yn.map((P)=>[P.id,P.displayName]));function bt(P){return fu[P]}var mu=Sn.map((P)=>({flags:P.flags.join(", "),description:P.description})),gu=Sn.flatMap((P)=>P.flags.map((V)=>`cc-safety-net hook ${V}`)),zi={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...mu,{flags:"-h, --help",description:"Show this help"}],examples:gu};var Ji={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...$t.map((P)=>({flags:P.flag,description:`Install ${bt(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...$t.map((P)=>`cc-safety-net install ${P.flag}`)]},Wi={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...$t.map((P)=>({flags:P.flag,description:`Uninstall ${bt(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...$t.map((P)=>`cc-safety-net uninstall ${P.flag}`)]},Ki={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 Yi={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"],fn={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 Zi={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 Xi={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 Qn=[Zi,Bi,Yi,qi,fn,Xn,Ji,Ki,Wi,zi,Vi,Xi];function yu(P){return P.aliases??[]}function er(P){let V=P.toLowerCase();return Qn.find((z)=>z.name.toLowerCase()===V||yu(z).some((Q)=>Q.toLowerCase()===V))}import{basename as hu}from"node:path";function tr(P,V=7,z=O(P)){let Q=Date.now()-V*24*60*60*1000,te=[],ne=new Set,ce=0,ye,he,be,xe;if(z)B(P,z);let Ie={count:0},Xe=z?Yt(z,Ie):[];for(let Re of Xe)for(let at of pn(Re,Ie)){if(at.decision==="allow")continue;let ct=new Date(at.ts).getTime();if(ct>=Q){if(ce++,ne.add(at.sessionId??hu(Re,".jsonl")),he===void 0||ct<=he)ye=at.ts,he=ct;if(xe===void 0||ct>xe)be=at.ts,xe=ct;vu(te,at,ct)}}let et=te.map((Re)=>({timestamp:Re.ts,command:Re.command,reason:Re.reason,relativeTime:Oi(new Date(Re.ts))}));return{totalBlocked:ce,sessionCount:ne.size,recentEntries:et,oldestEntry:ye,newestEntry:be,unreadable:Ie.count}}function vu(P,V,z){let Q=P.findIndex((te)=>z>new Date(te.ts).getTime());if(Q===-1){if(P.length<3)P.push(V);return}if(P.splice(Q,0,V),P.length>3)P.pop()}import{dirname as Au}from"node:path";import{dirname as bu,join as Lu,resolve as wu}from"node:path";var ku="config.json";function Rt(P,V,z,Q){g(xu(P),`${JSON.stringify(V,null,2)}
5
5
  `,z,Q)}function xu(P){return typeof P==="string"?re(P):P}function ro(P){return{errors:ie(Su(P),": "," "),ruleNames:new Set(_e(P).map((V)=>V.toLowerCase()))}}var Cu="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",Qi="must match pattern (letters, numbers, hyphens, underscores)";function Su(P){if(!es(P))return[e([],"Config must be an object")];return[...P.version===1?[]:[e(["version"],"must be 1")],...Ru(P.rules)]}function Ru(P){if(P===void 0)return[];if(!Array.isArray(P))return[e(["rules"],"must be an array")];return[...P.flatMap((V,z)=>es(V)?Pu(V,["rules",z]):[e(["rules",z],"must be an object")]),...Te(P)]}function Pu(P,V){return[...no(P.name,[...V,"name"],"required string",l,Cu),...no(P.command,[...V,"command"],"required string",w,Qi),...P.subcommand===void 0?[]:no(P.subcommand,[...V,"subcommand"],"must be a string if provided",w,Qi),...Eu(P.block_args,[...V,"block_args"]),...Du(P.reason,[...V,"reason"]),...P.intent===void 0||Ce(P.intent)?[]:[e([...V,"intent"],we)]]}function no(P,V,z,Q,te){if(typeof P!=="string")return[e(V,z)];return Q.test(P)?[]:[e(V,te)]}function Eu(P,V){if(!Array.isArray(P))return[e(V,"required array")];if(P.length===0)return[e(V,"must have at least one element")];return P.flatMap((z,Q)=>{if(typeof z!=="string")return[e([...V,Q],"must be a string")];return z===""?[e([...V,Q],"must not be empty")]:[]})}function Du(P,V){if(typeof P!=="string")return[e(V,"required string")];if(P==="")return[e(V,"must not be empty")];return P.length>T?[e(V,`must be at most ${T} characters`)]:[]}function es(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function oo(P){let V=ts(P);if(!V.ok)return V.result;return ro(V.parsed)}function ts(P){let V=[],z=new Set;try{let Q=typeof P==="string"?re(P):P,te=n(Q);if(te===null)return V.push(`File not found: ${Q.path}`),{ok:!1,result:{errors:V,ruleNames:z}};if(!te.trim())return V.push("Config file is empty"),{ok:!1,result:{errors:V,ruleNames:z}};return{ok:!0,parsed:JSON.parse(te)}}catch(Q){if(Q instanceof r)return V.push(Q.message),{ok:!1,result:{errors:V,ruleNames:z}};let te=Q instanceof Error?Q.message:String(Q);return V.push(Q instanceof SyntaxError?"Invalid JSON":te),{ok:!1,result:{errors:V,ruleNames:z}}}}function ns(P){return wu(P,".safety-net.json")}function Jt(P){let V=ts(P);if(!V.ok)return V.result;let z=Ve(V.parsed);return{errors:z.errors,ruleNames:z.sources}}function nr(P,V={}){return Lu(bu(Se(P,V)),ku)}function rs(P,V,z){let Q;try{if(n(V)===null)return{path:P,exists:!1,valid:!1,ruleCount:0};Q=Jt(V),Q.errors.push(...j(P,z))}catch(te){if(!(te instanceof r))throw te;Q={errors:[te.message],ruleNames:new Set}}return{path:P,exists:!0,valid:Q.errors.length===0,ruleCount:Q.ruleNames.size,...Q.errors.length>0?{errors:Q.errors}:{}}}function _u(P,V){return{source:V,name:P.name,command:P.command,subcommand:P.subcommand,blockArgs:[...P.block_args],reason:P.reason}}function os(P,V){let z=M(P),Q=F(V),te=Au(z),ne=J(P,{cwd:V,userConfigPath:z,projectConfigPath:Q,userConfigDir:te}),ce=K(P,{cwd:V,userConfigPath:z,projectConfigPath:Q,userConfigDir:te}),ye=new Map(ne.rulebooks.flatMap((he)=>he.rules.map((be)=>[be,he.source])));return{userConfig:rs(z,ce.userConfigTarget,ce.userScope),projectConfig:rs(Q,ce.projectConfigTarget,ce.projectScope),effectiveRules:ne.rules.map((he)=>_u(he,ye.get(he.name)??"project"))}}var Tu=[{flag:o.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:o.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:o.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:o.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:o.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:o.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:o.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:o.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function is(P){return[...Tu.map((V)=>({name:V.flag.name,value:ve(V.flag,P.env),isSet:Qe(V.flag,P.env),legacyName:V.flag.legacyName,legacyValue:V.flag.legacyName?P.env.get(V.flag.legacyName):void 0,legacyIsSet:V.flag.legacyName?P.env.get(V.flag.legacyName)!==void 0:void 0,description:V.description,defaultBehavior:V.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:P.env.get("CC_SAFETY_NET_HOME"),isSet:P.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var ss={error:0,warning:1,info:2},$u=["policy","config","audit"];function Iu(P){return P.map((V)=>{if(V==="ownership")return"is not owned by the current user";if(V==="permissions")return"has unsafe permissions";if(V==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Ou=[{derive:(P)=>P.hooks.length>0&&P.hooks.every((V)=>!V.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:(P)=>P.hooks.filter((V)=>V.inspectionStatus==="failed").map((V)=>{let z=bt(V.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${z} inspection failed`,detail:`Doctor could not verify the ${z} integration configuration.`,fixHint:`Correct the reported ${z} configuration error, then run \`cc-safety-net doctor\` again.`,integration:V.platform}})},{derive:(P)=>P.userConfig.exists&&!P.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:P.userConfig.path}]:[]},{derive:(P)=>P.projectConfig.exists&&!P.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:P.projectConfig.path}]:[]},{derive:(P)=>P.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${P.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:(P)=>P.v2Leftovers&&P.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: ${P.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(P)=>{let V=P.environment.find((z)=>z.name==="CC_SAFETY_NET_AUDIT_SCOPE");return He(V?.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."}]:[]}},...$u.map((P)=>({derive:(V)=>V.posture.directories.filter((z)=>z.kind===P&&z.status==="unsafe").map((z)=>({checkId:`posture.${P}-directory-unsafe`,severity:"error",title:`${P[0]?.toUpperCase()}${P.slice(1)} directory is unsafe`,detail:`The ${P} directory ${Iu(z.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...z.path?{path:z.path}:{}}))})),{derive:(P)=>{let V=[...P.effectiveSafety.weakenedRuleOverrides].sort();return V.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: ${V.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${V.join(", ")}.`}]:[]}}];function as(P){return Ou.flatMap((V,z)=>V.derive(P).map((Q,te)=>({finding:Q,catalogOrder:z,occurrence:te}))).sort((V,z)=>ss[V.finding.severity]-ss[z.finding.severity]||V.catalogOrder-z.catalogOrder||V.occurrence-z.occurrence).map((V)=>V.finding)}function Ut(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var Fu=(P)=>Ut()?`\x1B[32m${P}\x1B[0m`:P,ju=(P)=>Ut()?`\x1B[33m${P}\x1B[0m`:P,Nu=(P)=>Ut()?`\x1B[34m${P}\x1B[0m`:P,Mu=(P)=>Ut()?`\x1B[36m${P}\x1B[0m`:P,Hu=(P)=>Ut()?`\x1B[31m${P}\x1B[0m`:P,Uu=(P)=>Ut()?`\x1B[2m${P}\x1B[0m`:P,Gu=(P)=>Ut()?`\x1B[1m${P}\x1B[0m`:P,dt={green:Fu,yellow:ju,blue:Nu,cyan:Mu,red:Hu,dim:Uu,bold:Gu},Bu="\x1B[0m",qu=[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 Vu(P){let V=P;return()=>(V=(V*1664525+1013904223)%4294967296,V/4294967296)}function zu(P){let V=[...qu],z=Vu(P);for(let Q=V.length-1;Q>0;Q--){let te=Math.floor(z()*(Q+1)),ne=V[Q];V[Q]=V[te],V[te]=ne}return V}function Ju(P,V=0){if(!Ut())return"";let z=zu(V);return`\x1B[38;5;${z[P%z.length]}m`}function ls(P,V,z=0){if(!Ut())return`"${P}"`;return`${Ju(V,z)}"${P}"${Bu}`}function rr(P){return P==="default"?"built-in default":`${P} policy`}var Wu=new RegExp("\x1B\\[[0-9;]*m","g"),io=(P)=>P.replace(Wu,"").length;function Zt(P){let V=(P.headers??P.rows[0]??[]).map((ce,ye)=>{let he=Math.max(...P.rows.map((be)=>io(be[ye]??"")));return Math.max(io(ce),he)}),z=(ce,ye)=>ce+" ".repeat(Math.max(0,ye-io(ce))),Q=(ce,ye)=>ye[0]+V.map((he)=>ce.repeat(he+2)).join(ye[1])+ye[2],te=(ce)=>`│ ${ce.map((ye,he)=>z(ye,V[he]??0)).join(" │ ")} │`,ne=P.headers?[` ${te(P.headers)}`,` ${Q("─",["├","┼","┤"])}`]:[];return[` ${Q("─",["┌","┬","┐"])}`,...ne,...P.rows.map((ce)=>` ${te(ce)}`),` ${Q("─",["└","┴","┘"])}`].join(`
6
6
  `)}function cs(P){let V=[];V.push("Hook Integration"),V.push(Ku(P));let z=[],Q=[];for(let te of P){let ne=bt(te.platform);if(te.errors&&te.errors.length>0)for(let ce of te.errors)if(te.configured)z.push({platform:ne,message:ce});else Q.push({platform:ne,message:ce})}for(let te of z)V.push(` Warning (${te.platform}): ${te.message}`);for(let te of Q)V.push(dt.red(` Error (${te.platform}): ${te.message}`));return V.join(`
7
7
  `)}function Ku(P){let V=["Platform","Discovery","Configuration","Inspection"],z=P.map((Q)=>{let te=bt(Q.platform);if(Q.inspectionStatus==="not-inspected"){let he=dt.dim("Not inspected");return[te,he,he,he]}let ne=Q.detected?dt.green("Detected"):Q.inspectionStatus==="failed"?dt.red("Unknown"):dt.dim("Not detected"),ce=Q.configured?dt.green("Configured"):Q.detected?dt.yellow("Not configured"):Q.inspectionStatus==="failed"?dt.red("Unknown"):dt.dim("Not applicable"),ye=Q.inspectionStatus==="verified"?dt.green("Verified"):Q.inspectionStatus==="failed"?dt.red("Failed"):dt.dim("Not applicable");return[te,ne,ce,ye]});return Zt({headers:V,rows:z})}function ds(P){let z=["Guard Engine Verification",` Synthetic self-test: ${P.failed>0?dt.red(`${P.passed}/${P.total} FAIL`):dt.green(`${P.passed}/${P.total} passed`)}`],Q=P.results.filter((te)=>!te.passed);if(Q.length>0){z.push(""),z.push(dt.red(" Failures:"));for(let te of Q)z.push(dt.red(` • ${te.description}`)),z.push(dt.red(` expected ${te.expected}, got ${te.actual}`))}return z.join(`
@@ -18,19 +18,19 @@ ${Qr(te.segment||te.command)}`,z=P.filter((te)=>te.decision!=="allow"),Q=z.filte
18
18
  `)}function or(P){return Zt({rows:P})}function hs(P){let V=[];return V.push("System Info"),V.push(ep(P)),V.join(`
19
19
  `)}function ep(P){let V=["Component","Version"],z=(ne)=>{if(ne===null)return dt.dim("not found");return ne},te=[{label:"cc-safety-net",value:P.version},...Zn.map((ne)=>({label:bt(ne),value:P.versions[ne]??null})),{label:"Node.js",value:P.nodeVersion},{label:"npm",value:P.npmVersion},{label:"Bun",value:P.bunVersion},{label:"Platform",value:P.platform}].map((ne)=>[ne.label,z(ne.value)]);return Zt({headers:V,rows:te})}function vs(P){if(P.findings.length===0)return dt.green(`
20
20
  No findings from inspected doctor facts.`);let V={error:P.findings.filter((ne)=>ne.severity==="error").length,warning:P.findings.filter((ne)=>ne.severity==="warning").length,info:P.findings.filter((ne)=>ne.severity==="info").length},z=["error","warning","info"].filter((ne)=>V[ne]>0).map((ne)=>`${V[ne]} ${ne}`),Q=P.findings.length===1?"finding":"findings",te=`
21
- ${P.findings.length} ${Q}: ${z.join(", ")}.`;if(V.error>0)return dt.red(te);if(V.warning>0)return dt.yellow(te);return dt.blue(te)}import{lstatSync as tp}from"node:fs";import{dirname as so}from"node:path";function ao(P,V){try{let z=tp(V);if(z.isSymbolicLink())return{kind:P,path:V,status:"unsafe",issues:["symlink"]};if(!z.isDirectory())return{kind:P,path:V,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:P,path:V,status:"unknown",issues:[]};let Q=[...z.uid!==process.getuid()?["ownership"]:[],...(z.mode&18)!==0?["permissions"]:[]];return{kind:P,path:V,status:Q.length>0?"unsafe":"safe",issues:Q}}catch(z){if(typeof z==="object"&&z!==null&&"code"in z&&z.code==="ENOENT")return{kind:P,path:V,status:"not-applicable",issues:[]};return{kind:P,path:V,status:"unknown",issues:[]}}}function bs(P,V){let z=O(P);return{directories:[ao("policy",so(so(V))),ao("config",so(V)),...z?[ao("audit",z)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as np}from"node:child_process";import{existsSync as Ls}from"node:fs";import{delimiter as rp,extname as op,join as ip}from"node:path";import{stripVTControlCharacters as ws}from"node:util";var xs="2.4.3",sp=5000,ap="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function wt(){return xs}function lo(P,V){let z=P[V];if(z)return z;let Q=Object.keys(P).find((te)=>te.toLowerCase()===V.toLowerCase()&&!!P[te]);return Q?P[Q]:z}function lp(P){return(lo(P,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((V)=>V.length>0)}function cp(P,V){let z=op(P)?[P]:[...lp(V).map((Q)=>`${P}${Q}`),P];if(P.includes("/")||P.includes("\\"))return z.find((Q)=>Ls(Q))??P;return(lo(V,"PATH")??"").split(rp).flatMap((Q)=>z.map((te)=>ip(Q,te))).find((Q)=>Ls(Q))??P}function ks(P){if(!/[\s"&|<>^]/.test(P))return P;return`"${P.replace(/"/g,'""')}"`}function Xt(P,V){let[z,...Q]=P,te=V[ap]==="win32"?"win32":process.platform;if(!z||te!=="win32")return{cmd:z??"",args:Q};let ne=cp(z,V);if(!/\.(?:bat|cmd)$/i.test(ne))return{cmd:ne,args:Q};return{cmd:lo(V,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",ks(ne),...Q.map(ks)].join(" ")]}}var mn=async(P,V=sp)=>{let z=await dp(P,{timeoutMs:V});if(z.code!==0)return null;return ws(z.stdout).trim()||ws(z.stderr).trim()||null};function dp(P,V){let[z,...Q]=P;if(!z)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((te)=>{try{let ne=Xt([z,...Q],process.env),ce=np(ne.cmd,ne.args,{stdio:["ignore","pipe","pipe"]}),ye=!1,he="",be="";ce.stdout.on("data",(Xe)=>{he+=Xe.toString()}),ce.stderr.on("data",(Xe)=>{be+=Xe.toString()});let Le=(Xe)=>{if(ye)return;ye=!0,clearTimeout(Ie),te(Xe)},Ie=setTimeout(()=>{ce.kill(),Le({code:null,stdout:he,stderr:be})},V.timeoutMs);ce.on("close",(Xe)=>{Le({code:Xe,stdout:he,stderr:be})}),ce.on("error",()=>{Le({code:null,stdout:he,stderr:be})})}catch{te({code:null,stdout:"",stderr:""})}})}function ir(P){if(!P)return null;let V=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(P);if(V)return V[1]??null;let z=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(P);if(z)return z[1]??null;return P.split(`
22
- `)[0]?.trim()||null}async function sr(P=mn){let[V,z,Q,te,ne,ce]=await Promise.all([Promise.all($t.map(async(ye)=>[ye.id,ir(await P([...ye.probeCommand]))])),P(["codex","plugin","list"],30000),P(["amp","plugins","list"],30000),P(["node","--version"]),P(["npm","--version"]),P(["bun","--version"])]);return{version:xs,versions:Object.fromEntries(V),codexPluginListOutput:z,ampPluginListOutput:Q,nodeVersion:ir(te),npmVersion:ir(ne),bunVersion:ir(ce),platform:`${process.platform} ${process.arch}`}}function co(P,V){if(V==="dev")return!1;let z=P.split(".").map(Number),Q=V.split(".").map(Number),[te=0,ne=0,ce=0]=z,[ye=0,he=0,be=0]=Q;if(te!==ye)return te>ye;if(ne!==he)return ne>he;return ce>be}async function Wt(){let P=wt(),V=new AbortController,z=setTimeout(()=>V.abort(),3000);try{let Q=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:V.signal});if(!Q.ok)return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${Q.status}`};let te=await Q.json(),ne=co(te.version,P);return{currentVersion:P,latestVersion:te.version,updateAvailable:ne}}catch(Q){return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:Q instanceof Error?Q.message:"Network error"}}finally{clearTimeout(z)}}import*as _s from"node:readline";var Ps=(P)=>`\x1B[${P}B`,up=(P)=>`\x1B[${P}A`;var Cs=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function pp(P){return new Promise((V)=>setTimeout(V,P))}function fp(P,V,z){if(!z)return V(P);if(z.aborted)return Promise.resolve();return new Promise((Q,te)=>{let ne=()=>z.removeEventListener("abort",ce),ce=()=>{ne(),Q()};z.addEventListener("abort",ce,{once:!0}),V(P).then(()=>{ne(),Q()},(ye)=>{ne(),te(ye)})})}function ar(P){return Math.max(0,Math.min(1,P))}function gn(P){return Math.max(0,Math.min(255,Math.round(P)))}function uo(P){return P<=0.0031308?12.92*P:1.055*P**0.4166666666666667-0.055}function mp(P,V,z){let Q=z*Math.PI/180,te=V*Math.cos(Q),ne=V*Math.sin(Q),ce=(P+0.3963377774*te+0.2158037573*ne)**3,ye=(P-0.1055613458*te-0.0638541728*ne)**3,he=(P-0.0894841775*te-1.291485548*ne)**3;return{blue:gn(uo(ar(-0.0041960863*ce-0.7034186147*ye+1.707614701*he))*255),green:gn(uo(ar(-1.2684380046*ce+2.6097574011*ye-0.3413193965*he))*255),red:gn(uo(ar(4.0767416621*ce-3.3077115913*ye+0.2309699292*he))*255)}}function po(P,V){let z=(V*P*180/Math.PI%360+360)%360;return mp(0.72,0.15,z)}function Es(P,V=0.1){let z=po(V,P);return`\x1B[38;2;${z.red};${z.green};${z.blue}m`}function gp(P,V){return{blue:gn(P.blue+(255-P.blue)*V),green:gn(P.green+(255-P.green)*V),red:gn(P.red+(255-P.red)*V)}}function Ds(P,V,z){let Q=Math.imul(P+2654435769,2246822507)^Math.imul(V+3266489909,668265263)^Math.imul(z+374761393,2654435761),te=Q^Q>>>15,ne=Math.imul(te,739982445),ce=ne^ne>>>12,ye=Math.imul(ce,695872825);return((ye^ye>>>15)>>>0)/4294967296}function yp(P,V,z){let Q=Math.floor(Ds(P,V,z)*Cs.length);return Cs[Q]??"░"}function Ss(P){let V=ar(P);return V*V*V*(V*(V*6-15)+10)}function hp(P){if(P.length===0)return"";let V=[],z=!1,Q="";for(let te of P){let ne=`${te.red};${te.green};${te.blue}`;if(te.bold!==z)V.push(te.bold?"\x1B[1m":"\x1B[22m"),z=te.bold;if(ne!==Q)V.push(`\x1B[38;2;${ne}m`),Q=ne;V.push(te.character)}return`${V.join("")}\x1B[22m\x1B[39m`}function vp(P,V,z,Q,te){return P.map((ne,ce)=>({...po(z,Q+V+ce/te),bold:!1,character:ne}))}function bp(P,V,z,Q,te,ne,ce,ye){let he=Math.max(1,Q*0.75),be=Math.min(1,z/he),Le=te*Ss(be),Ie=Math.max(0,(z-he)/Math.max(1,Q-he)),Xe=(1-Ss(z/Q))*ye*2,et=0.35*Math.max(0,1-Ie*2),xe=be>=1,at=Math.min(P.length,Math.ceil(Le+2+1));return P.slice(0,at).map((ct,lt)=>{let pt=po(ne,ce+V+lt/ye+Xe),mt=lt+Ds(V,lt,7919)*2-1;if(mt>Le+2)return{...pt,bold:!1,character:" "};let gt=Le-mt,ut=0.8*Math.exp(-(gt*gt)/12.5),vt=Math.min(0.9,ut+et),Dt=!xe&&mt>Le-4;return{...gp(pt,vt),bold:vt>0.3,character:Dt?yp(V,lt,z):ct}})}function Rs(P){return`\x1B[?2026h${P.map((V,z)=>`\x1B8${z>0?Ps(z):""}${hp(V)}`).join("")}\x1B[?2026l`}async function fo(P,V={}){if(!P)return;let z=V.output??process.stdout,Q=V.sleep??pp,te=V.seed??0,ne=P.split(`
23
- `).map((Le)=>Array.from(Le)),ce=Math.max(...ne.map((Le)=>Le.length)),ye=12000*ne.filter((Le)=>Le.length>0).length/40,he=ce>0?Math.max(1,Math.ceil(ye/16.666666666666668)):0,be=he>0?ye/he:0;z.write(`\x1B[?25l${ne.length>1?`${`
24
- `.repeat(ne.length-1)}${up(ne.length-1)}`:""}\x1B7`);try{for(let Le=1;Le<=he;Le+=1){if(V.signal?.aborted)break;z.write(Rs(ne.map((Ie,Xe)=>bp(Ie,Xe,Le,he,ce,0.1,te,3)))),await fp(be,Q,V.signal)}}finally{if(z.write(Rs(ne.map((Le,Ie)=>vp(Le,Ie,0.1,te,3)))),z.write("\x1B8"),ne.length>1)z.write(Ps(ne.length-1));z.write(`
21
+ ${P.findings.length} ${Q}: ${z.join(", ")}.`;if(V.error>0)return dt.red(te);if(V.warning>0)return dt.yellow(te);return dt.blue(te)}import{lstatSync as tp}from"node:fs";import{dirname as so}from"node:path";function ao(P,V){try{let z=tp(V);if(z.isSymbolicLink())return{kind:P,path:V,status:"unsafe",issues:["symlink"]};if(!z.isDirectory())return{kind:P,path:V,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:P,path:V,status:"unknown",issues:[]};let Q=[...z.uid!==process.getuid()?["ownership"]:[],...(z.mode&18)!==0?["permissions"]:[]];return{kind:P,path:V,status:Q.length>0?"unsafe":"safe",issues:Q}}catch(z){if(typeof z==="object"&&z!==null&&"code"in z&&z.code==="ENOENT")return{kind:P,path:V,status:"not-applicable",issues:[]};return{kind:P,path:V,status:"unknown",issues:[]}}}function bs(P,V){let z=O(P);return{directories:[ao("policy",so(so(V))),ao("config",so(V)),...z?[ao("audit",z)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as np}from"node:child_process";import{existsSync as Ls}from"node:fs";import{delimiter as rp,extname as op,join as ip}from"node:path";import{stripVTControlCharacters as ws}from"node:util";var xs="2.4.5",sp=5000,ap="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function wt(){return xs}function lo(P,V){let z=P[V];if(z)return z;let Q=Object.keys(P).find((te)=>te.toLowerCase()===V.toLowerCase()&&!!P[te]);return Q?P[Q]:z}function lp(P){return(lo(P,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((V)=>V.length>0)}function cp(P,V){let z=op(P)?[P]:[...lp(V).map((Q)=>`${P}${Q}`),P];if(P.includes("/")||P.includes("\\"))return z.find((Q)=>Ls(Q))??P;return(lo(V,"PATH")??"").split(rp).flatMap((Q)=>z.map((te)=>ip(Q,te))).find((Q)=>Ls(Q))??P}function ks(P){if(!/[\s"&|<>^]/.test(P))return P;return`"${P.replace(/"/g,'""')}"`}function Xt(P,V){let[z,...Q]=P,te=V[ap]==="win32"?"win32":process.platform;if(!z||te!=="win32")return{cmd:z??"",args:Q};let ne=cp(z,V);if(!/\.(?:bat|cmd)$/i.test(ne))return{cmd:ne,args:Q};return{cmd:lo(V,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",ks(ne),...Q.map(ks)].join(" ")]}}var mn=async(P,V=sp)=>{let z=await dp(P,{timeoutMs:V});if(z.code!==0)return null;return ws(z.stdout).trim()||ws(z.stderr).trim()||null};function dp(P,V){let[z,...Q]=P;if(!z)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((te)=>{try{let ne=Xt([z,...Q],process.env),ce=np(ne.cmd,ne.args,{stdio:["ignore","pipe","pipe"]}),ye=!1,he="",be="";ce.stdout.on("data",(Xe)=>{he+=Xe.toString()}),ce.stderr.on("data",(Xe)=>{be+=Xe.toString()});let xe=(Xe)=>{if(ye)return;ye=!0,clearTimeout(Ie),te(Xe)},Ie=setTimeout(()=>{ce.kill(),xe({code:null,stdout:he,stderr:be})},V.timeoutMs);ce.on("close",(Xe)=>{xe({code:Xe,stdout:he,stderr:be})}),ce.on("error",()=>{xe({code:null,stdout:he,stderr:be})})}catch{te({code:null,stdout:"",stderr:""})}})}function ir(P){if(!P)return null;let V=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(P);if(V)return V[1]??null;let z=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(P);if(z)return z[1]??null;return P.split(`
22
+ `)[0]?.trim()||null}async function sr(P=mn){let[V,z,Q,te,ne,ce]=await Promise.all([Promise.all($t.map(async(ye)=>[ye.id,ir(await P([...ye.probeCommand]))])),P(["codex","plugin","list"],30000),P(["amp","plugins","list"],30000),P(["node","--version"]),P(["npm","--version"]),P(["bun","--version"])]);return{version:xs,versions:Object.fromEntries(V),codexPluginListOutput:z,ampPluginListOutput:Q,nodeVersion:ir(te),npmVersion:ir(ne),bunVersion:ir(ce),platform:`${process.platform} ${process.arch}`}}function co(P,V){if(V==="dev")return!1;let z=P.split(".").map(Number),Q=V.split(".").map(Number),[te=0,ne=0,ce=0]=z,[ye=0,he=0,be=0]=Q;if(te!==ye)return te>ye;if(ne!==he)return ne>he;return ce>be}async function Wt(){let P=wt(),V=new AbortController,z=setTimeout(()=>V.abort(),3000);try{let Q=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:V.signal});if(!Q.ok)return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${Q.status}`};let te=await Q.json(),ne=co(te.version,P);return{currentVersion:P,latestVersion:te.version,updateAvailable:ne}}catch(Q){return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:Q instanceof Error?Q.message:"Network error"}}finally{clearTimeout(z)}}import*as _s from"node:readline";var Ps=(P)=>`\x1B[${P}B`,up=(P)=>`\x1B[${P}A`;var Cs=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function pp(P){return new Promise((V)=>setTimeout(V,P))}function fp(P,V,z){if(!z)return V(P);if(z.aborted)return Promise.resolve();return new Promise((Q,te)=>{let ne=()=>z.removeEventListener("abort",ce),ce=()=>{ne(),Q()};z.addEventListener("abort",ce,{once:!0}),V(P).then(()=>{ne(),Q()},(ye)=>{ne(),te(ye)})})}function ar(P){return Math.max(0,Math.min(1,P))}function gn(P){return Math.max(0,Math.min(255,Math.round(P)))}function uo(P){return P<=0.0031308?12.92*P:1.055*P**0.4166666666666667-0.055}function mp(P,V,z){let Q=z*Math.PI/180,te=V*Math.cos(Q),ne=V*Math.sin(Q),ce=(P+0.3963377774*te+0.2158037573*ne)**3,ye=(P-0.1055613458*te-0.0638541728*ne)**3,he=(P-0.0894841775*te-1.291485548*ne)**3;return{blue:gn(uo(ar(-0.0041960863*ce-0.7034186147*ye+1.707614701*he))*255),green:gn(uo(ar(-1.2684380046*ce+2.6097574011*ye-0.3413193965*he))*255),red:gn(uo(ar(4.0767416621*ce-3.3077115913*ye+0.2309699292*he))*255)}}function po(P,V){let z=(V*P*180/Math.PI%360+360)%360;return mp(0.72,0.15,z)}function Es(P,V=0.1){let z=po(V,P);return`\x1B[38;2;${z.red};${z.green};${z.blue}m`}function gp(P,V){return{blue:gn(P.blue+(255-P.blue)*V),green:gn(P.green+(255-P.green)*V),red:gn(P.red+(255-P.red)*V)}}function Ds(P,V,z){let Q=Math.imul(P+2654435769,2246822507)^Math.imul(V+3266489909,668265263)^Math.imul(z+374761393,2654435761),te=Q^Q>>>15,ne=Math.imul(te,739982445),ce=ne^ne>>>12,ye=Math.imul(ce,695872825);return((ye^ye>>>15)>>>0)/4294967296}function yp(P,V,z){let Q=Math.floor(Ds(P,V,z)*Cs.length);return Cs[Q]??"░"}function Ss(P){let V=ar(P);return V*V*V*(V*(V*6-15)+10)}function hp(P){if(P.length===0)return"";let V=[],z=!1,Q="";for(let te of P){let ne=`${te.red};${te.green};${te.blue}`;if(te.bold!==z)V.push(te.bold?"\x1B[1m":"\x1B[22m"),z=te.bold;if(ne!==Q)V.push(`\x1B[38;2;${ne}m`),Q=ne;V.push(te.character)}return`${V.join("")}\x1B[22m\x1B[39m`}function vp(P,V,z,Q,te){return P.map((ne,ce)=>({...po(z,Q+V+ce/te),bold:!1,character:ne}))}function bp(P,V,z,Q,te,ne,ce,ye){let he=Math.max(1,Q*0.75),be=Math.min(1,z/he),xe=te*Ss(be),Ie=Math.max(0,(z-he)/Math.max(1,Q-he)),Xe=(1-Ss(z/Q))*ye*2,et=0.35*Math.max(0,1-Ie*2),Re=be>=1,at=Math.min(P.length,Math.ceil(xe+2+1));return P.slice(0,at).map((ct,lt)=>{let pt=po(ne,ce+V+lt/ye+Xe),mt=lt+Ds(V,lt,7919)*2-1;if(mt>xe+2)return{...pt,bold:!1,character:" "};let gt=xe-mt,ut=0.8*Math.exp(-(gt*gt)/12.5),vt=Math.min(0.9,ut+et),Dt=!Re&&mt>xe-4;return{...gp(pt,vt),bold:vt>0.3,character:Dt?yp(V,lt,z):ct}})}function Rs(P){return`\x1B[?2026h${P.map((V,z)=>`\x1B8${z>0?Ps(z):""}${hp(V)}`).join("")}\x1B[?2026l`}async function fo(P,V={}){if(!P)return;let z=V.output??process.stdout,Q=V.sleep??pp,te=V.seed??0,ne=P.split(`
23
+ `).map((xe)=>Array.from(xe)),ce=Math.max(...ne.map((xe)=>xe.length)),ye=12000*ne.filter((xe)=>xe.length>0).length/40,he=ce>0?Math.max(1,Math.ceil(ye/16.666666666666668)):0,be=he>0?ye/he:0;z.write(`\x1B[?25l${ne.length>1?`${`
24
+ `.repeat(ne.length-1)}${up(ne.length-1)}`:""}\x1B7`);try{for(let xe=1;xe<=he;xe+=1){if(V.signal?.aborted)break;z.write(Rs(ne.map((Ie,Xe)=>bp(Ie,Xe,xe,he,ce,0.1,te,3)))),await fp(be,Q,V.signal)}}finally{if(z.write(Rs(ne.map((xe,Ie)=>vp(xe,Ie,0.1,te,3)))),z.write("\x1B8"),ne.length>1)z.write(Ps(ne.length-1));z.write(`
25
25
  \x1B[0m\x1B[?25h`)}}var As=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
- `);function Lp(P){return Boolean(P.isTTY)}async function Rn(P={}){let V=P.output??process.stdout;if(!Lp(V))return;let z=P.input??process.stdin,Q={output:V,seed:P.seed??Math.random()*8192,sleep:P.sleep};if(!z.isTTY||typeof z.setRawMode!=="function"){await fo(As,Q);return}let te=new AbortController,ne=z.readableFlowing===!0,ce=z.isRaw===!0,ye=!1,he=(be,Le)=>{if(Le.ctrl&&Le.name==="c")ye=!0;if(ye||Le.name==="return"||Le.name==="enter")te.abort()};_s.emitKeypressEvents(z),z.on("keypress",he),z.setRawMode(!0),z.resume();try{await fo(As,{...Q,signal:te.signal})}finally{if(z.off("keypress",he),z.setRawMode(ce),!ne)z.pause()}if(!ye)return;if(P.onInterrupt){P.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as Sp}from"node:crypto";import{existsSync as Is}from"node:fs";import{dirname as lr,join as Os}from"node:path";import{dirname as Ts,join as wp,resolve as kp}from"node:path";var xp="rule.lock";function Cp(P){return wp(Ts(P),xp)}function $s(P={}){return kp(P.cwd??process.cwd(),".safety-net.json")}function Pt(P,V){let z=V.global?V.userConfigPath??M(P,V):V.projectConfigPath??F(V.cwd??process.cwd()),Q=V.global?Be(P,V):ze(z,V.cwd??process.cwd()),te=Cp(z);return{configDir:Ts(z),configPath:z,lockPath:te,filesystemScope:Q,configTarget:i(Q,z),lockTarget:i(Q,te)}}var Rp="`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.",Pp="cache",Ep="rulebooks";function Fs(P,V={}){let z=Pt(P,V),Q=i(z.filesystemScope,Ns(z.configDir)),te=n(z.lockTarget);if(console.log(Rp),te===null&&!Is(Q.path))return console.log(`No v2 lock or cache leftovers found in ${lr(z.configDir)}; nothing to migrate.`),0;let ne=$p(te),ce=m(z.configTarget);if(!ce.config&&(n(z.configTarget)!==null||ne.size>0))return console.error(`Cannot migrate: the rules config in ${lr(z.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let ye=ce.config?.rules??[];for(let he of ye.flatMap((be)=>Dp(be,ne,z,Q,V.global===!0)))console.log(he);return N(z.lockTarget),tt(Q),console.log(`Removed the v2 lock and cache under ${lr(z.configDir)}.`),0}function js(P,V){return[...new Set([{cwd:V},{cwd:V,global:!0}].flatMap((z)=>{let Q=Pt(P,z);return[Q.lockPath,Ns(Q.configDir)]}))].filter((z)=>Is(z))}function Dp(P,V,z,Q,te){if(!S(P))return[];let ne=A(P).name,ce=i(z.filesystemScope,I(z.configDir,ne)),ye=n(ce);if(ye!==null&&Ap(ye,ne))return[];let he=V.get(P),be=he?_p(he,ne,Q.path,z.filesystemScope):null;if(be===null)return[`Could not migrate ${P} from the v2 cache. Run \`cc-safety-net rule update ${P}${te?" --global":""}\` to vendor it.`];if(g(ce,be),ye!==null)return[`Restored ${P} from the v2 cache over an invalid file.`];return[`Vendored ${P} from the v2 cache.`]}function Ap(P,V){let z=me(P);return!("problem"in z)&&z.rulebook.name===V}function _p(P,V,z,Q){let te=Os(z,Ep,`${Tp(P)}--${P.digest.replace("sha256:","").slice(0,12)}`,ue),ne=n(i(Q,te));if(ne===null||Fp(ne)!==P.digest)return null;let ce=me(ne);if("problem"in ce||ce.rulebook.name!==V)return null;return ne}function Ns(P){return Os(lr(P),Pp)}function Tp(P){return([P.owner,P.repo,P.display_ref,P.name].every((Q)=>typeof Q==="string"&&Q!=="")?`${P.owner}/${P.repo}#${P.display_ref}/${P.name}`:P.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function $p(P){let V=P===null?null:Op(P),z=Ms(V)&&Array.isArray(V.rulebooks)?V.rulebooks:[];return new Map(z.filter(Ip).map((Q)=>[Q.spec,Q]))}function Ip(P){return Ms(P)&&typeof P.spec==="string"&&typeof P.digest==="string"}function Ms(P){return!!P&&typeof P==="object"}function Op(P){try{return JSON.parse(P)}catch{return null}}function Fp(P){return`sha256:${Sp("sha256").update(P).digest("hex")}`}var Hs="\r\x1B[2K",jp="\x1B[?25l",Np="\x1B[39m",Mp="\x1B[?25h",Hp=100,Up=0.55,Gp=80,Us=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function Bp(P){return new Promise((V)=>setTimeout(V,P))}async function cr(P,V={}){let z=V.output??process.stdout;if(!z.isTTY)return P;let Q=V.sleep??Bp,te=!1,ne=P.then((ye)=>(te=!0,ye),(ye)=>{throw te=!0,ye});if(await Promise.race([ne.then(()=>!0),Q(Hp).then(()=>!1)]))return ne;z.write(jp);try{for(let ye=0;!te;ye+=1)z.write(`${Hs}${Es(ye*Up)}${Us[ye%Us.length]}${Np} ${V.loadingMessage??"Loading…"}`),await Promise.race([ne,Q(Gp)]);return await ne}finally{z.write(`${Hs}${Mp}`)}}async function Pn(P,V,z,Q={}){let te=V();if(P)await z();if(P&&te.ready)await cr(te.ready,Q);return te.finish()}import{stripVTControlCharacters as qp}from"node:util";var dr="amp plugins list",Vp=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function Gs(P){if(!P.ampPluginListOutput)return{platform:"amp",status:"n/a"};let V=qp(P.ampPluginListOutput).split(`
26
+ `);function Lp(P){return Boolean(P.isTTY)}async function Rn(P={}){let V=P.output??process.stdout;if(!Lp(V))return;let z=P.input??process.stdin,Q={output:V,seed:P.seed??Math.random()*8192,sleep:P.sleep};if(!z.isTTY||typeof z.setRawMode!=="function"){await fo(As,Q);return}let te=new AbortController,ne=z.readableFlowing===!0,ce=z.isRaw===!0,ye=!1,he=(be,xe)=>{if(xe.ctrl&&xe.name==="c")ye=!0;if(ye||xe.name==="return"||xe.name==="enter")te.abort()};_s.emitKeypressEvents(z),z.on("keypress",he),z.setRawMode(!0),z.resume();try{await fo(As,{...Q,signal:te.signal})}finally{if(z.off("keypress",he),z.setRawMode(ce),!ne)z.pause()}if(!ye)return;if(P.onInterrupt){P.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as Sp}from"node:crypto";import{existsSync as Is}from"node:fs";import{dirname as lr,join as Os}from"node:path";import{dirname as Ts,join as wp,resolve as kp}from"node:path";var xp="rule.lock";function Cp(P){return wp(Ts(P),xp)}function $s(P={}){return kp(P.cwd??process.cwd(),".safety-net.json")}function Pt(P,V){let z=V.global?V.userConfigPath??M(P,V):V.projectConfigPath??F(V.cwd??process.cwd()),Q=V.global?Be(P,V):ze(z,V.cwd??process.cwd()),te=Cp(z);return{configDir:Ts(z),configPath:z,lockPath:te,filesystemScope:Q,configTarget:i(Q,z),lockTarget:i(Q,te)}}var Rp="`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.",Pp="cache",Ep="rulebooks";function Fs(P,V={}){let z=Pt(P,V),Q=i(z.filesystemScope,Ns(z.configDir)),te=n(z.lockTarget);if(console.log(Rp),te===null&&!Is(Q.path))return console.log(`No v2 lock or cache leftovers found in ${lr(z.configDir)}; nothing to migrate.`),0;let ne=$p(te),ce=m(z.configTarget);if(!ce.config&&(n(z.configTarget)!==null||ne.size>0))return console.error(`Cannot migrate: the rules config in ${lr(z.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let ye=ce.config?.rules??[];for(let he of ye.flatMap((be)=>Dp(be,ne,z,Q,V.global===!0)))console.log(he);return N(z.lockTarget),tt(Q),console.log(`Removed the v2 lock and cache under ${lr(z.configDir)}.`),0}function js(P,V){return[...new Set([{cwd:V},{cwd:V,global:!0}].flatMap((z)=>{let Q=Pt(P,z);return[Q.lockPath,Ns(Q.configDir)]}))].filter((z)=>Is(z))}function Dp(P,V,z,Q,te){if(!S(P))return[];let ne=A(P).name,ce=i(z.filesystemScope,I(z.configDir,ne)),ye=n(ce);if(ye!==null&&Ap(ye,ne))return[];let he=V.get(P),be=he?_p(he,ne,Q.path,z.filesystemScope):null;if(be===null)return[`Could not migrate ${P} from the v2 cache. Run \`cc-safety-net rule update ${P}${te?" --global":""}\` to vendor it.`];if(g(ce,be),ye!==null)return[`Restored ${P} from the v2 cache over an invalid file.`];return[`Vendored ${P} from the v2 cache.`]}function Ap(P,V){let z=me(P);return!("problem"in z)&&z.rulebook.name===V}function _p(P,V,z,Q){let te=Os(z,Ep,`${Tp(P)}--${P.digest.replace("sha256:","").slice(0,12)}`,ue),ne=n(i(Q,te));if(ne===null||Fp(ne)!==P.digest)return null;let ce=me(ne);if("problem"in ce||ce.rulebook.name!==V)return null;return ne}function Ns(P){return Os(lr(P),Pp)}function Tp(P){return([P.owner,P.repo,P.display_ref,P.name].every((Q)=>typeof Q==="string"&&Q!=="")?`${P.owner}/${P.repo}#${P.display_ref}/${P.name}`:P.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function $p(P){let V=P===null?null:Op(P),z=Ms(V)&&Array.isArray(V.rulebooks)?V.rulebooks:[];return new Map(z.filter(Ip).map((Q)=>[Q.spec,Q]))}function Ip(P){return Ms(P)&&typeof P.spec==="string"&&typeof P.digest==="string"}function Ms(P){return!!P&&typeof P==="object"}function Op(P){try{return JSON.parse(P)}catch{return null}}function Fp(P){return`sha256:${Sp("sha256").update(P).digest("hex")}`}var Hs="\r\x1B[2K",jp="\x1B[?25l",Np="\x1B[39m",Mp="\x1B[?25h",Hp=100,Up=0.55,Gp=80,Us=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function Bp(P){return new Promise((V)=>setTimeout(V,P))}async function cr(P,V={}){let z=V.output??process.stdout;if(!z.isTTY)return P;let Q=V.sleep??Bp,te=!1,ne=P.then((ye)=>(te=!0,ye),(ye)=>{throw te=!0,ye});if(await Promise.race([ne.then(()=>!0),Q(Hp).then(()=>!1)]))return ne;z.write(jp);try{for(let ye=0;!te;ye+=1)z.write(`${Hs}${Es(ye*Up)}${Us[ye%Us.length]}${Np} ${V.loadingMessage??"Loading…"}`),await Promise.race([ne,Q(Gp)]);return await ne}finally{z.write(`${Hs}${Mp}`)}}async function Pn(P,V,z,Q={}){let te=V();if(P)await z();if(P&&te.ready)await cr(te.ready,Q);return te.finish()}import{stripVTControlCharacters as qp}from"node:util";var dr="amp plugins list",Vp=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function Gs(P){if(!P.ampPluginListOutput)return{platform:"amp",status:"n/a"};let V=qp(P.ampPluginListOutput).split(`
27
27
  `).map((z)=>Vp.exec(z)?.[1]).find((z)=>z!==void 0);if(!V)return{platform:"amp",status:"n/a"};if(V!=="active")return{platform:"amp",status:"disabled",method:dr,configPath:dr,errors:[`Amp personal plugin cc-safety-net is ${V}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:dr,configPath:dr}}import{existsSync as Wp,readFileSync as Kp}from"node:fs";import{isAbsolute as Y1,join as Jp,relative as Z1}from"node:path";function En(P){return Jp(P,".gemini","config","hooks.json")}var Yp=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Zp(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];return Object.values(P).flatMap((V)=>{if(!V||typeof V!=="object"||Array.isArray(V))return[];let z=V,Q=z.PreToolUse;if(!Array.isArray(Q))return[];return Q.flatMap((te)=>{if(!te||typeof te!=="object"||Array.isArray(te))return[];let ne=te.hooks;if(!Array.isArray(ne))return[];return ne.flatMap((ce)=>{if(!ce||typeof ce!=="object"||Array.isArray(ce))return[];let ye=ce.command;if(typeof ye!=="string"||!Yp.test(ye))return[];return[{command:ye,enabled:z.enabled!==!1}]})})})}function Bs(P){let V=En(P.environment.home);if(!Wp(V))return{platform:"antigravity-cli",status:"n/a",configPath:V};let z;try{z=Zp(JSON.parse(Kp(V,"utf-8")))}catch(Q){return{platform:"antigravity-cli",status:"n/a",configPath:V,errors:[`Failed to parse Antigravity hooks config ${V}: ${Q instanceof Error?Q.message:String(Q)}`]}}if(z.some((Q)=>Q.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:V};if(z.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:V};return{platform:"antigravity-cli",status:"n/a",configPath:V}}import{join as qs}from"node:path";import{existsSync as Xp,lstatSync as Qp,readFileSync as e2}from"node:fs";function Ft(P,V=(z)=>z){if(!Xp(P))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(V(e2(P,"utf-8")))}}catch{return{kind:"unreadable"}}}function Lt(P){try{return Qp(P)}catch{return}}function ur(P,V){let z=Lt(V);if(!z)return{platform:P,status:"n/a",configPath:V};if(!z.isSymbolicLink()&&z.isDirectory())return;return{platform:P,status:"n/a",configPath:V,errors:[`${V} is a symlink or not a directory; move or remove it before installing`]}}function ft(P,V){return typeof P==="object"&&P!==null?P[V]:void 0}var mo="cc-safety-net@cc-marketplace";function Vs(P){return qs(P.home,".claude","plugins","installed_plugins.json")}function zs(P,V){let z=ft(ft(P,"plugins"),V);return Array.isArray(z)&&z.length>0}function pr(P,V){let z=Ft(Vs(P));return z.kind==="ok"&&zs(z.value,V)}function go(P){let V=Vs(P),z=Ft(V);if(z.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(z.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!zs(z.value,mo))return{platform:"claude-code",status:"n/a"};let Q=qs(P.home,".claude","settings.json"),te=Ft(Q);if(te.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(te.kind==="ok"&&ft(ft(te.value,"enabledPlugins"),mo)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:Q,errors:[`${mo} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:V}}function Js(P){return go(P.environment)}function Ws(P){if(!P.codexPluginListOutput)return{platform:"codex",status:"n/a"};let V=P.codexPluginListOutput.split(`
28
28
  `).find((z)=>z.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!V)return{platform:"codex",status:"n/a"};if(!V.includes("installed,"))return{platform:"codex",status:"n/a"};if(!V.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 hr,readdirSync as t2,readFileSync as n2}from"node:fs";import{join as St}from"node:path";function At(P){let V="",z=0,Q=!1,te=!1,ne=-1;while(z<P.length){let ce=P[z],ye=P[z+1];if(te){V+=ce,te=!1,z++;continue}if(ce==='"'&&!Q){Q=!0,ne=-1,V+=ce,z++;continue}if(ce==='"'&&Q){Q=!1,V+=ce,z++;continue}if(ce==="\\"&&Q){te=!0,V+=ce,z++;continue}if(Q){V+=ce,z++;continue}if(ce==="/"&&ye==="/"){while(z<P.length&&P[z]!==`
29
29
  `)z++;continue}if(ce==="/"&&ye==="*"){z+=2;while(z<P.length-1){if(P[z]==="*"&&P[z+1]==="/"){z+=2;break}z++}continue}if(ce===","){ne=V.length,V+=ce,z++;continue}if(ce==="}"||ce==="]"){if(ne!==-1){let he=V.slice(ne+1);if(/^\s*$/.test(he))V=V.slice(0,ne)+he}ne=-1,V+=ce,z++;continue}if(!/\s/.test(ce))ne=-1;V+=ce,z++}return V}function Ys(P,V,z){let Q=V+1,te=!1;while(Q<P.length){if(te){te=!1,Q++;continue}if(P[Q]==="\\"){te=!0,Q++;continue}if(P[Q]==='"')return Q+1;Q++}throw Error(z)}function ho(P,V,z){let Q=P[V],te=Q==="["?"]":"}",ne=0,ce=V;while(ce<P.length){let ye=z.skipComment?.(P,ce)??ce;if(ye!==ce){ce=ye;continue}if(P[ce]==='"'){ce=Ys(P,ce,z.stringError);continue}if(P[ce]===Q)ne++;if(P[ce]===te){if(ne--,ne===0)return ce}ce++}throw Error(z.bracketError)}function Zs(P,V){let z=P.lastIndexOf(`
30
30
  `,V)+1;return/^[ \t]*/.exec(P.slice(z))?.[0]??""}function fr(P,V){let z=V.end+(/^\s*/.exec(P.slice(V.end))?.[0].length??0);if(P[z]===","){let ce=P[z+1]===`
31
31
  `?z+2:z+1;return`${P.slice(0,V.start)}${P.slice(ce)}`}let Q=P.slice(0,V.start).search(/\s*$/)-1;if(P[Q]!==",")return`${P.slice(0,V.start)}${P.slice(V.end)}`;let te=P.lastIndexOf(`
32
32
  `,Q-1),ne=te!==-1&&/^\s*$/.test(P.slice(te+1,Q))?te:Q;return`${P.slice(0,ne)}${P.slice(V.end)}`}function yo(P,V){if(P.startsWith("//",V)){let z=P.indexOf(`
33
- `,V+2);return z===-1?P.length:z+1}if(P.startsWith("/*",V)){let z=P.indexOf("*/",V+2);return z===-1?P.length:z+2}return V}function Ks(P,V){let z=V;while(z<P.length){if(/\s/.test(P[z]??"")){z++;continue}let Q=yo(P,z);if(Q===z)return z;z=Q}return z}function Xs(P,V,z){let Q=0,te=0;while(te<P.length){let ne=yo(P,te);if(ne!==te){te=ne;continue}if(P[te]==='"'){let ce=Ys(P,te,z.stringError);if(Q===1&&JSON.parse(P.slice(te,ce))===V){let ye=Ks(P,ce),he=Ks(P,ye+1);if(P[ye]===":"&&P[he]==="[")return{start:he,end:ho(P,he,{skipComment:yo,...z})}}te=ce;continue}if(P[te]==="{"||P[te]==="[")Q++;if(P[te]==="}"||P[te]==="]")Q--;te++}return}var jt="cc-safety-net@cc-marketplace",mr=["cc-marketplace","cc-safety-net"],Qs=["_direct","copilot-safety-net"],ea=["cc-marketplace","safety-net"],ta="safety-net@cc-marketplace";function gr(P,V){let z=V.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${z}([^a-z0-9-]|$)`,"m").test(P??"")}function na(P){return gr(P,"cc-safety-net@cc-marketplace")}function ra(P){return gr(P,"cc-marketplace")}function oa(P){return gr(P,"copilot-safety-net")}function ia(P){return gr(P,"safety-net@cc-marketplace")}function vo(P){if(!P?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(P)}function aa(P,V){if(!P)return null;let z=P.match(/(\d+)\.(\d+)\.(\d+)/);if(!z)return null;let Q=[Number(z[1]),Number(z[2]),Number(z[3])];for(let te=0;te<V.length;te++){let ne=Q[te]??0,ce=V[te]??0;if(ne!==ce)return ne>ce}return!0}function r2(P){return aa(P,[0,0,422])}function o2(P){return aa(P,[1,0,8])}function Dn(P){return P.env.get("COPILOT_HOME")||St(P.home,".copilot")}function bo(P){return(P.hooks?.preToolUse??[]).some((z)=>{if(z.type!=="command")return!1;return vo(z.command)||vo(z.bash)||vo(z.powershell)})}function yr(P){return P===void 0||typeof P==="string"}function i2(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let V=P;if(V.disableAllHooks!==void 0&&typeof V.disableAllHooks!=="boolean")return!1;if(V.hooks===void 0)return!0;if(!V.hooks||typeof V.hooks!=="object"||Array.isArray(V.hooks))return!1;let z=V.hooks.preToolUse;if(z===void 0)return!0;return Array.isArray(z)&&z.every((Q)=>Q!==null&&typeof Q==="object"&&!Array.isArray(Q)&&yr(Q.type)&&yr(Q.command)&&yr(Q.bash)&&yr(Q.powershell))}function Lo(P,V){try{let z=JSON.parse(At(n2(P,"utf-8")));if(!i2(z)){V?.push(`Invalid hook config ${P}: hooks.preToolUse must be an array of hook objects`);return}return z}catch(z){V?.push(`Failed to parse ${P}: ${z instanceof Error?z.message:String(z)}`);return}}function la(P,V){try{return t2(P).filter((z)=>z.endsWith(".json")).sort((z,Q)=>z.localeCompare(Q))}catch(z){return V?.push(`Failed to read ${P}: ${z instanceof Error?z.message:String(z)}`),[]}}function s2(P,V){if(!hr(P))return[];let z=[];for(let Q of la(P,V)){let te=St(P,Q),ne=Lo(te,V);if(ne&&bo(ne))z.push(te)}return z}function yn(P,V){if(!hr(P))return;let z=Lo(P,V);if(!z)return;return{path:P,config:z}}function sa(P,V,z,Q){if(V){P.push(`GitHub Copilot CLI ${V} does not support ${z}; requires ${Q}+`);return}P.push(`GitHub Copilot CLI version unavailable; skipping ${z} because it requires ${Q}+`)}function a2(P){for(let V of P){if(V?.config.disableAllHooks===!0)return V.path;if(V?.config.disableAllHooks===!1)return}return}function l2(P,V,z,Q){let te=Dn(P),ne=St(V,".github","hooks"),ce=St(te,"hooks"),ye=St(V,".github","copilot"),he=St(V,".claude"),be=o2(z),Le=be===!0?Q:void 0,Ie=[yn(St(ye,"settings.local.json"),Le),yn(St(ye,"settings.json"),Le),yn(St(he,"settings.local.json"),Le),yn(St(he,"settings.json"),Le)],Xe=[yn(St(te,"settings.json"),Le),yn(St(te,"config.json"),Le)];if(be!==!1){let gt=a2([...Ie,...Xe]);if(gt){if(be===null)Q.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${gt} as active`);return{activeConfigPaths:[],disabledBy:gt}}}let et=s2(ne,Q),xe=r2(z),at=xe===!0?Q:void 0,ct=hr(ce)?la(ce,at):[],lt=[];for(let gt of ct){let ut=St(ce,gt),vt=Lo(ut,at);if(vt&&bo(vt))lt.push(ut)}if(xe!==!0&&lt.length>0)sa(Q,z,`user hook files in ${ce}`,"0.0.422"),lt.length=0;let pt=[];for(let gt of[...Ie,...Xe]){if(!gt)continue;if(!bo(gt.config))continue;if(be===!0){pt.push(gt);continue}sa(Q,z,"inline hook definitions in Copilot config files","1.0.8");break}let mt=(gt)=>gt.filter((ut)=>!!ut&&pt.includes(ut)).map((ut)=>ut.path);return{activeConfigPaths:[...mt(Ie),...et,...mt(Xe),...lt]}}function ca(P){let V=[],z=l2(P.environment,P.cwd,P.copilotCliVersion,V);if(z.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:z.disabledBy,configPaths:[z.disabledBy],errors:V.length>0?V:void 0};let Q=Dn(P.environment),te=St(Q,"installed-plugins",...mr),ne=hr(te),ce=St(Q,"settings.json"),ye=Ft(ce,At);if(ne&&ye.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(ne&&ye.kind==="ok"&&ft(ft(ye.value,"enabledPlugins"),jt)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:ce,errors:[`${jt} is installed but not enabled in Copilot CLI`]};if(ne||z.activeConfigPaths.length>0){let he=ne,be=z.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:he?"plugin config":"hook config",configPath:be??(he?te:void 0),configPaths:z.activeConfigPaths.length>0?z.activeConfigPaths:void 0,errors:V.length>0?V:void 0}}return{platform:"copilot-cli",status:"n/a",errors:V.length>0?V:void 0}}import{existsSync as v2,readFileSync as b2}from"node:fs";import{existsSync as da,mkdirSync as u2,readFileSync as p2}from"node:fs";import{dirname as f2,join as m2}from"node:path";import{renameSync as c2,writeFileSync as d2}from"node:fs";function kt(P,V){let z=`${P}.${process.pid}.tmp`;d2(z,V),c2(z,P)}var Nt=Object.fromEntries(Sn.map((P)=>[P.id,`npx -y cc-safety-net hook ${P.flags[1]}`]));var An=Nt.cursor,ua=30;function br(P){return m2(P.home,".cursor","hooks.json")}function Qt(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function wo(){return{command:An,timeout:ua,failClosed:!0}}function vr(P){return Qt(P)&&P.command===An}function g2(P){return Object.keys(P).length===3&&P.command===An&&P.timeout===ua&&P.failClosed===!0}function y2(P){try{return JSON.parse(p2(P,"utf-8"))}catch(V){if(V instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${P}: ${V.message}`);throw V}}function pa(P){let V=y2(P);if(!Qt(V))throw Error(`Cursor hooks config ${P} must be a JSON object`);if(V.version!==1)throw Error(`Cursor hooks config ${P} must set "version": 1`);if(V.hooks!==void 0&&!Qt(V.hooks))throw Error(`Cursor hooks config ${P} "hooks" must be an object`);let z=Qt(V.hooks)?V.hooks.preToolUse:void 0;if(z!==void 0&&!Array.isArray(z))throw Error(`Cursor hooks config ${P} "hooks.preToolUse" must be an array`);return V}function fa(P){let V=Qt(P.hooks)?P.hooks.preToolUse:void 0;return Array.isArray(V)?V:[]}function h2(P){if(!P.some(vr))return[...P,wo()];return P.reduce((V,z)=>{if(!vr(z))return V.result.push(z),V;if(!V.inserted)V.result.push(wo()),V.inserted=!0;return V},{result:[],inserted:!1}).result}function ma(P,V,z){let Q=Qt(V.hooks)?V.hooks:{},te={...V,hooks:{...Q,preToolUse:z}};kt(P,`${JSON.stringify(te,null,2)}
33
+ `,V+2);return z===-1?P.length:z+1}if(P.startsWith("/*",V)){let z=P.indexOf("*/",V+2);return z===-1?P.length:z+2}return V}function Ks(P,V){let z=V;while(z<P.length){if(/\s/.test(P[z]??"")){z++;continue}let Q=yo(P,z);if(Q===z)return z;z=Q}return z}function Xs(P,V,z){let Q=0,te=0;while(te<P.length){let ne=yo(P,te);if(ne!==te){te=ne;continue}if(P[te]==='"'){let ce=Ys(P,te,z.stringError);if(Q===1&&JSON.parse(P.slice(te,ce))===V){let ye=Ks(P,ce),he=Ks(P,ye+1);if(P[ye]===":"&&P[he]==="[")return{start:he,end:ho(P,he,{skipComment:yo,...z})}}te=ce;continue}if(P[te]==="{"||P[te]==="[")Q++;if(P[te]==="}"||P[te]==="]")Q--;te++}return}var jt="cc-safety-net@cc-marketplace",mr=["cc-marketplace","cc-safety-net"],Qs=["_direct","copilot-safety-net"],ea=["cc-marketplace","safety-net"],ta="safety-net@cc-marketplace";function gr(P,V){let z=V.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${z}([^a-z0-9-]|$)`,"m").test(P??"")}function na(P){return gr(P,"cc-safety-net@cc-marketplace")}function ra(P){return gr(P,"cc-marketplace")}function oa(P){return gr(P,"copilot-safety-net")}function ia(P){return gr(P,"safety-net@cc-marketplace")}function vo(P){if(!P?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(P)}function aa(P,V){if(!P)return null;let z=P.match(/(\d+)\.(\d+)\.(\d+)/);if(!z)return null;let Q=[Number(z[1]),Number(z[2]),Number(z[3])];for(let te=0;te<V.length;te++){let ne=Q[te]??0,ce=V[te]??0;if(ne!==ce)return ne>ce}return!0}function r2(P){return aa(P,[0,0,422])}function o2(P){return aa(P,[1,0,8])}function Dn(P){return P.env.get("COPILOT_HOME")||St(P.home,".copilot")}function bo(P){return(P.hooks?.preToolUse??[]).some((z)=>{if(z.type!=="command")return!1;return vo(z.command)||vo(z.bash)||vo(z.powershell)})}function yr(P){return P===void 0||typeof P==="string"}function i2(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let V=P;if(V.disableAllHooks!==void 0&&typeof V.disableAllHooks!=="boolean")return!1;if(V.hooks===void 0)return!0;if(!V.hooks||typeof V.hooks!=="object"||Array.isArray(V.hooks))return!1;let z=V.hooks.preToolUse;if(z===void 0)return!0;return Array.isArray(z)&&z.every((Q)=>Q!==null&&typeof Q==="object"&&!Array.isArray(Q)&&yr(Q.type)&&yr(Q.command)&&yr(Q.bash)&&yr(Q.powershell))}function Lo(P,V){try{let z=JSON.parse(At(n2(P,"utf-8")));if(!i2(z)){V?.push(`Invalid hook config ${P}: hooks.preToolUse must be an array of hook objects`);return}return z}catch(z){V?.push(`Failed to parse ${P}: ${z instanceof Error?z.message:String(z)}`);return}}function la(P,V){try{return t2(P).filter((z)=>z.endsWith(".json")).sort((z,Q)=>z.localeCompare(Q))}catch(z){return V?.push(`Failed to read ${P}: ${z instanceof Error?z.message:String(z)}`),[]}}function s2(P,V){if(!hr(P))return[];let z=[];for(let Q of la(P,V)){let te=St(P,Q),ne=Lo(te,V);if(ne&&bo(ne))z.push(te)}return z}function yn(P,V){if(!hr(P))return;let z=Lo(P,V);if(!z)return;return{path:P,config:z}}function sa(P,V,z,Q){if(V){P.push(`GitHub Copilot CLI ${V} does not support ${z}; requires ${Q}+`);return}P.push(`GitHub Copilot CLI version unavailable; skipping ${z} because it requires ${Q}+`)}function a2(P){for(let V of P){if(V?.config.disableAllHooks===!0)return V.path;if(V?.config.disableAllHooks===!1)return}return}function l2(P,V,z,Q){let te=Dn(P),ne=St(V,".github","hooks"),ce=St(te,"hooks"),ye=St(V,".github","copilot"),he=St(V,".claude"),be=o2(z),xe=be===!0?Q:void 0,Ie=[yn(St(ye,"settings.local.json"),xe),yn(St(ye,"settings.json"),xe),yn(St(he,"settings.local.json"),xe),yn(St(he,"settings.json"),xe)],Xe=[yn(St(te,"settings.json"),xe),yn(St(te,"config.json"),xe)];if(be!==!1){let gt=a2([...Ie,...Xe]);if(gt){if(be===null)Q.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${gt} as active`);return{activeConfigPaths:[],disabledBy:gt}}}let et=s2(ne,Q),Re=r2(z),at=Re===!0?Q:void 0,ct=hr(ce)?la(ce,at):[],lt=[];for(let gt of ct){let ut=St(ce,gt),vt=Lo(ut,at);if(vt&&bo(vt))lt.push(ut)}if(Re!==!0&&lt.length>0)sa(Q,z,`user hook files in ${ce}`,"0.0.422"),lt.length=0;let pt=[];for(let gt of[...Ie,...Xe]){if(!gt)continue;if(!bo(gt.config))continue;if(be===!0){pt.push(gt);continue}sa(Q,z,"inline hook definitions in Copilot config files","1.0.8");break}let mt=(gt)=>gt.filter((ut)=>!!ut&&pt.includes(ut)).map((ut)=>ut.path);return{activeConfigPaths:[...mt(Ie),...et,...mt(Xe),...lt]}}function ca(P){let V=[],z=l2(P.environment,P.cwd,P.copilotCliVersion,V);if(z.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:z.disabledBy,configPaths:[z.disabledBy],errors:V.length>0?V:void 0};let Q=Dn(P.environment),te=St(Q,"installed-plugins",...mr),ne=hr(te),ce=St(Q,"settings.json"),ye=Ft(ce,At);if(ne&&ye.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(ne&&ye.kind==="ok"&&ft(ft(ye.value,"enabledPlugins"),jt)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:ce,errors:[`${jt} is installed but not enabled in Copilot CLI`]};if(ne||z.activeConfigPaths.length>0){let he=ne,be=z.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:he?"plugin config":"hook config",configPath:be??(he?te:void 0),configPaths:z.activeConfigPaths.length>0?z.activeConfigPaths:void 0,errors:V.length>0?V:void 0}}return{platform:"copilot-cli",status:"n/a",errors:V.length>0?V:void 0}}import{existsSync as v2,readFileSync as b2}from"node:fs";import{existsSync as da,mkdirSync as u2,readFileSync as p2}from"node:fs";import{dirname as f2,join as m2}from"node:path";import{renameSync as c2,writeFileSync as d2}from"node:fs";function kt(P,V){let z=`${P}.${process.pid}.tmp`;d2(z,V),c2(z,P)}var Nt=Object.fromEntries(Sn.map((P)=>[P.id,`npx -y cc-safety-net hook ${P.flags[1]}`]));var An=Nt.cursor,ua=30;function br(P){return m2(P.home,".cursor","hooks.json")}function Qt(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function wo(){return{command:An,timeout:ua,failClosed:!0}}function vr(P){return Qt(P)&&P.command===An}function g2(P){return Object.keys(P).length===3&&P.command===An&&P.timeout===ua&&P.failClosed===!0}function y2(P){try{return JSON.parse(p2(P,"utf-8"))}catch(V){if(V instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${P}: ${V.message}`);throw V}}function pa(P){let V=y2(P);if(!Qt(V))throw Error(`Cursor hooks config ${P} must be a JSON object`);if(V.version!==1)throw Error(`Cursor hooks config ${P} must set "version": 1`);if(V.hooks!==void 0&&!Qt(V.hooks))throw Error(`Cursor hooks config ${P} "hooks" must be an object`);let z=Qt(V.hooks)?V.hooks.preToolUse:void 0;if(z!==void 0&&!Array.isArray(z))throw Error(`Cursor hooks config ${P} "hooks.preToolUse" must be an array`);return V}function fa(P){let V=Qt(P.hooks)?P.hooks.preToolUse:void 0;return Array.isArray(V)?V:[]}function h2(P){if(!P.some(vr))return[...P,wo()];return P.reduce((V,z)=>{if(!vr(z))return V.result.push(z),V;if(!V.inserted)V.result.push(wo()),V.inserted=!0;return V},{result:[],inserted:!1}).result}function ma(P,V,z){let Q=Qt(V.hooks)?V.hooks:{},te={...V,hooks:{...Q,preToolUse:z}};kt(P,`${JSON.stringify(te,null,2)}
34
34
  `)}function ga(P){let V=br(P);if(!da(V))return u2(f2(V),{recursive:!0}),kt(V,`${JSON.stringify({version:1,hooks:{preToolUse:[wo()]}},null,2)}
35
35
  `),{path:V,alreadyInstalled:!1};let z=pa(V),Q=fa(z),te=Q.filter(vr);if(Qt(z.hooks)&&Array.isArray(z.hooks.preToolUse)&&te.length===1&&te[0]!==void 0&&g2(te[0]))return{path:V,alreadyInstalled:!0};return ma(V,z,h2(Q)),{path:V,alreadyInstalled:!1}}function ya(P){let V=br(P);if(!da(V))return{path:V,alreadyInstalled:!1};let z=pa(V),Q=fa(z),te=Q.filter((ne)=>!vr(ne));if(te.length===Q.length)return{path:V,alreadyInstalled:!1};return ma(V,z,te),{path:V,alreadyInstalled:!0}}function L2(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];let V=P.hooks;if(!V||typeof V!=="object"||Array.isArray(V))return[];let z=V.preToolUse;if(!Array.isArray(z))return[];return z.filter((Q)=>!!Q&&typeof Q==="object"&&!Array.isArray(Q)&&Q.command===An)}function w2(P){let V=[];if(P.length>1)V.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let z=P[0];if(z&&z.failClosed!==!0)V.push('Managed hook is missing "failClosed": true; reinstall to repair');if(z&&z.timeout!==30)V.push('Managed hook "timeout" is not 30; reinstall to repair');return V}function ha(P){let V=br(P.environment);if(!v2(V))return{platform:"cursor",status:"n/a",configPath:V};let z;try{z=JSON.parse(b2(V,"utf-8"))}catch(ne){return{platform:"cursor",status:"n/a",configPath:V,errors:[`Failed to parse Cursor hooks config ${V}: ${ne instanceof Error?ne.message:String(ne)}`]}}let Q=L2(z);if(Q.length===0)return{platform:"cursor",status:"n/a",configPath:V};let te=w2(Q);return{platform:"cursor",status:"configured",method:"hook config",configPath:V,errors:te.length>0?te:void 0}}import{existsSync as k2}from"node:fs";import{join as ko}from"node:path";var xo="gemini-safety-net";function Co(P){let V=ko(P.home,".gemini","extensions"),z=ko(V,xo);if(!k2(z))return{platform:"gemini-cli",status:"n/a"};let Q=ko(V,"extension-enablement.json"),te=Ft(Q);if(te.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let ne=te.kind==="ok"?ft(ft(te.value,xo),"overrides"):void 0;if(Array.isArray(ne)&&ne.some((ye)=>typeof ye==="string"&&ye.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:Q,errors:[`${xo} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:z}}function va(P){return Co(P.environment)}import{existsSync as R2,readFileSync as P2}from"node:fs";import{existsSync as La,mkdirSync as x2,readFileSync as wa,rmSync as C2}from"node:fs";import{dirname as S2,join as ba}from"node:path";var _n=Nt["grok-build"],kr=30;function xr(P){return ba(P.env.get("GROK_HOME")??ba(P.home,".grok"),"hooks","cc-safety-net.json")}function en(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Lr(){return{hooks:[{type:"command",command:_n,timeout:kr}]}}function ka(P){return en(P)&&P.command===_n}function xa(P){return P.flatMap((V)=>{if(!en(V)||!Array.isArray(V.hooks))return[V];let z=V.hooks.filter((Q)=>!ka(Q));if(z.length===V.hooks.length)return[V];return z.length===0?[]:[{...V,hooks:z}]})}function Ca(P){try{let V=JSON.parse(P);return en(V)?V:null}catch{return null}}function Sa(P){let V=en(P.hooks)?P.hooks.PreToolUse:void 0;return Array.isArray(V)?V:[]}function wr(P,V,z){let Q=en(V.hooks)?V.hooks:{};kt(P,`${JSON.stringify({...V,hooks:{...Q,PreToolUse:z}},null,2)}
36
36
  `)}function Ra(P){let V=xr(P);if(!La(V))return x2(S2(V),{recursive:!0}),wr(V,{},[Lr()]),{path:V,alreadyInstalled:!1};let z=Ca(wa(V,"utf-8"));if(!z)return wr(V,{},[Lr()]),{path:V,alreadyInstalled:!1};let Q=Sa(z),te=Q.filter((ne)=>en(ne)&&Array.isArray(ne.hooks)&&ne.hooks.some(ka));if(te.length===1&&JSON.stringify(te[0])===JSON.stringify(Lr()))return{path:V,alreadyInstalled:!0};return wr(V,z,[...xa(Q),Lr()]),{path:V,alreadyInstalled:!1}}function Pa(P){let V=xr(P);if(!La(V))return{path:V,alreadyInstalled:!1};let z=Ca(wa(V,"utf-8"));if(!z)return{path:V,alreadyInstalled:!1};let Q=Sa(z),te=xa(Q);if(JSON.stringify(te)===JSON.stringify(Q))return{path:V,alreadyInstalled:!1};let ne=en(z.hooks)?z.hooks:{};if(te.length===0&&Object.keys(z).length===1&&Object.keys(ne).length===1)return C2(V),{path:V,alreadyInstalled:!0};return wr(V,z,te),{path:V,alreadyInstalled:!0}}function Tn(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function E2(P){if(!Tn(P)||!Tn(P.hooks))return[];let V=P.hooks.PreToolUse;if(!Array.isArray(V))return[];return V.filter((z)=>Tn(z)&&Array.isArray(z.hooks)&&z.hooks.some((Q)=>Tn(Q)&&Q.command===_n))}function D2(P){let z=(Array.isArray(P.hooks)?P.hooks.filter(Tn):[]).find((Q)=>Q.command===_n);return[...P.matcher===void 0||P.matcher===""||P.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...z?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...z?.timeout===kr?[]:[`Managed hook "timeout" is not ${kr}; reinstall to repair`]]}function Ea(P){let V=xr(P.environment);if(!R2(V))return{platform:"grok-build",status:"n/a",configPath:V};let z;try{z=JSON.parse(P2(V,"utf-8"))}catch(ne){return{platform:"grok-build",status:"n/a",configPath:V,errors:[`Failed to parse Grok Build hooks config ${V}: ${ne instanceof Error?ne.message:String(ne)}`]}}let Q=E2(z)[0];if(!Q)return{platform:"grok-build",status:"n/a",configPath:V};let te=D2(Q);return{platform:"grok-build",status:"configured",method:"hook config",configPath:V,errors:te.length>0?te:void 0}}import{readFileSync as Fa}from"node:fs";import{join as ja}from"node:path";var Tt="cc-safety-net",So="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",A2=30;function Da(P){return`${So}
@@ -206,18 +206,18 @@ def register(ctx):
206
206
  `}function $n(P){return[{name:"__init__.py",content:T2(P)},{name:"plugin.yaml",content:_2(P)}]}import{mkdirSync as $2,readdirSync as I2,readFileSync as O2,rmSync as Ro}from"node:fs";import{join as tn}from"node:path";var F2="__pycache__";function Po(P){let V=P.env.get("HERMES_HOME")?.trim();return V?V:tn(P.home,".hermes")}function Eo(P){return tn(Po(P),"plugins",Tt)}function Do(P){return P.startsWith(So)}function Ao(P,V){let z=Eo(P),Q=Lt(z);if(Q&&(Q.isSymbolicLink()||!Q.isDirectory()))throw Error(`Refusing to ${V} ${z}: not a regular directory. Move or remove it and rerun ${V==="install"?"install":"uninstall"} --hermes-agent.`);return z}function Aa(P,V){let z=Lt(P);if(!z)return;if(z.isSymbolicLink()||!z.isFile())throw Error(`Refusing to ${V} ${P}: not a regular file. Move or remove it.`);let Q=O2(P,"utf-8");if(!Do(Q))throw Error(`Refusing to ${V} unmanaged file at ${P}. Move or remove it.`);return Q}function _a(P){let V=Ao(P,"install"),z=$n(wt());if(z.map((te)=>Aa(tn(V,te.name),"overwrite")).every((te,ne)=>te===z[ne]?.content))return{path:V,alreadyInstalled:!0};return $2(V,{recursive:!0}),z.forEach((te)=>{kt(tn(V,te.name),te.content)}),{path:V,alreadyInstalled:!1}}function _o(P){let V=Ao(P,"remove");if(!Lt(V))return[];return $n(wt()).filter((z)=>Aa(tn(V,z.name),"remove")!==void 0)}function Ta(P){let V=Ao(P,"remove");if(!Lt(V))return{path:V,alreadyInstalled:!1};let z=_o(P);if(z.forEach((Q)=>{Ro(tn(V,Q.name))}),Ro(tn(V,F2),{recursive:!0,force:!0}),I2(V).length===0)Ro(V,{recursive:!0});return{path:V,alreadyInstalled:z.length>0}}var Cr="hermes-agent",$a=/^([^\s#][^:]*):/,j2=/^\s+([A-Za-z_][\w-]*):/,Ia=/^\s+-\s*(.*)$/;function N2(P){return P.trim().replace(/^(["'])(.*)\1$/,"$2")}function M2(P){let V=P.split(/\r?\n/),z=V.findIndex((ne)=>$a.exec(ne)?.[1]?.trim()==="plugins");if(z===-1)return[];let Q=V.slice(z+1),te=Q.findIndex((ne)=>$a.test(ne));return te===-1?Q:Q.slice(0,te)}function Oa(P,V){let z=M2(P),Q=z.findIndex((ce)=>j2.exec(ce)?.[1]===V);if(Q===-1)return[];let te=z.slice(Q+1),ne=te.findIndex((ce)=>!Ia.test(ce));return(ne===-1?te:te.slice(0,ne)).map((ce)=>N2(Ia.exec(ce)?.[1]??""))}function H2(P){try{return Fa(ja(Po(P),"config.yaml"),"utf-8")}catch{return}}function To(P){let V=H2(P)??"";return Oa(V,"enabled").includes(Tt)&&!Oa(V,"disabled").includes(Tt)}function Na(P){return/^# version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function U2(P,V){let z=Lt(P);if(!z)return{error:`${V.name} is missing from ${P}; run install --hermes-agent`};if(z.isSymbolicLink()||!z.isFile())return{error:`${P} is a symlink or not a regular file; move or remove it`};try{let Q=Fa(P,"utf-8");if(!Do(Q))return{error:`Unmanaged ${V.name} occupies ${P}; move or remove it`};if(Na(Q)===wt()&&Q!==V.content)return{error:`Modified ${V.name} occupies ${P}; run install --hermes-agent to restore it`};return{content:Q}}catch(Q){return{error:`Failed to read ${P}: ${Q instanceof Error?Q.message:String(Q)}`}}}function Ma(P){let V=Eo(P.environment),z=ur(Cr,V);if(z)return z;let Q=$n(wt()).map((ye)=>U2(ja(V,ye.name),ye)),te=Q.flatMap((ye)=>("error"in ye)?[ye.error]:[]);if(te.length>0)return{platform:Cr,status:"n/a",configPath:V,errors:te};let ne=Q.some((ye)=>("content"in ye)&&Na(ye.content)!==wt()),ce=ne?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!To(P.environment))return{platform:Cr,status:"disabled",method:"plugin directory",configPath:V,errors:[`${Tt} is not enabled in Hermes; run \`hermes plugins enable ${Tt}\``,...ce]};return{platform:Cr,status:"configured",method:"plugin directory",configPath:V,errors:ne?ce:void 0}}import{existsSync as G2,readFileSync as B2}from"node:fs";import{join as Ha}from"node:path";var q2=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function V2(P){return Ha(P.env.get("KIMI_CODE_HOME")||Ha(P.home,".kimi-code"),"config.toml")}function In(P){let V=V2(P.environment);if(!G2(V))return{platform:"kimi-code",status:"n/a",configPath:V};try{if(!q2.test(B2(V,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:V}}catch(z){return{platform:"kimi-code",status:"n/a",configPath:V,errors:[`Failed to read ${V}: ${z instanceof Error?z.message:String(z)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:V}}import{readFileSync as Ka}from"node:fs";import{join as Fn}from"node:path";var ht="cc-safety-net",It="index.js",hn="openclaw.plugin.json",vn="package.json";var Sr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as W2,lstatSync as K2,readdirSync as Y2,readFileSync as Z2}from"node:fs";import{dirname as Ga,join as Gt}from"node:path";import{fileURLToPath as X2}from"node:url";import{spawn as z2}from"node:child_process";function J2(P){return P.join(" ")}function $o(P,V,z){return[`Failed to run ${J2(P)}${V===null?"":` (exit ${V})`}.`,z.trim()].filter(Boolean).join(`
207
207
  `)}function Io(P){let V={stdout:"",stderr:""};return P.stdout.setEncoding("utf-8"),P.stderr.setEncoding("utf-8"),P.stdout.on("data",(z)=>{V.stdout+=z}),P.stderr.on("data",(z)=>{V.stderr+=z}),V}function _t(P,V){return new Promise((z,Q)=>{let te=Xt([...P],process.env),ne=z2(te.cmd,te.args,{stdio:["ignore","pipe","pipe"]}),ce=Io(ne),ye=()=>[ce.stdout,ce.stderr].filter(Boolean).join(`
208
208
  `),he=V?.timeoutMs??120000,be=setTimeout(()=>{ne.kill(),Q(Error($o(P,null,`Timed out after ${he}ms.
209
- ${ye()}`.trim())))},he);ne.on("error",(Le)=>{clearTimeout(be),Q(Error($o(P,null,`${Le.message}
210
- ${ye()}`.trim())))}),ne.on("close",(Le)=>{if(clearTimeout(be),Le!==0){Q(Error($o(P,Le,ye())));return}z(V?.stdoutOnly?ce.stdout:ye())})})}async function Oo(P){for(let V of P)await _t(V)}async function Ua(P){for(let V of P)try{await _t(V)}catch(z){console.warn(z instanceof Error?z.message:String(z))}}var Fo=Gt("openclaw",ht),Q2=[It,hn,vn];function jo(P,V){if(P==="~")return V;if(P.startsWith("~/")||P.startsWith("~\\"))return Gt(V,P.slice(2));return P}function Ba(P){let V=P.env.get("OPENCLAW_STATE_DIR")?.trim();if(V)return jo(V,P.home);let z=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return z?Ga(jo(z,P.home)):Gt(P.home,".openclaw")}function qa(P){let V=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return V?jo(V,P.home):Gt(Ba(P),"openclaw.json")}function No(P){return Gt(Ba(P),"extensions",ht)}function ef(P){let V=Y2(P);if(V.length===0)return!0;if(V.some((te)=>!Q2.includes(te)))return!1;let z=Gt(P,It),Q=Lt(z);return Q!==void 0&&!Q.isSymbolicLink()&&Q.isFile()&&Z2(z,"utf-8").startsWith(Sr)}function Mo(P){let V=No(P),z=Lt(V);if(!z)return;if(!z.isSymbolicLink()&&z.isDirectory()&&ef(V))return;throw Error(`Refusing to modify ${V}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function Va(){let P=Ga(X2(import.meta.url));return[Gt(P,Fo),Gt(P,"..",Fo),Gt(P,"..","..","..","dist",Fo)]}function Ho(P=Va()){return P.find((V)=>W2(V)&&K2(V).isDirectory())}function tf(P=Va()){let V=Ho(P);if(!V)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return V}function za(P=tf()){return[["openclaw","plugins","install",P,"--force"],["openclaw","plugins","enable",ht]]}function nf(P){let V=(()=>{try{return JSON.parse(P)}catch{return}})(),z=ft(ft(V,"plugin"),"status");return typeof z==="string"?z:void 0}async function Ja(){let P=nf(await _t(["openclaw","plugins","inspect",ht,"--runtime","--json"],{stdoutOnly:!0}));if(P==="loaded")return;throw Error(`${P===void 0?`The ${ht} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${ht} plugin with status "${P}".`} Run \`openclaw plugins inspect ${ht} --runtime\` for details.`)}var Rr="openclaw",On=`run \`openclaw plugins enable ${ht}\``;function bn(P,V){let z=Fn(P,V),Q=Lt(z);if(!Q)return{error:`${V} is missing from ${z}; run install --openclaw`};if(Q.isSymbolicLink()||!Q.isFile())return{error:`${z} is a symlink or not a regular file; move or remove it`};try{return{content:Ka(z,"utf-8")}}catch(te){return{error:`Failed to read ${z}: ${te instanceof Error?te.message:String(te)}`}}}function Ya(P){try{return JSON.parse(At(P))}catch{return}}function rf(P){let V=bn(P,hn);if("error"in V)return V.error;if(ft(Ya(V.content),"id")===ht)return;return`${Fn(P,hn)} is not a valid ${ht} manifest; run install --openclaw`}function of(P){let V=bn(P,vn);if("error"in V)return V.error;let z=ft(ft(Ya(V.content),"openclaw"),"extensions");if(Array.isArray(z)&&z.includes(`./${It}`))return;return`${Fn(P,vn)} does not point OpenClaw at ${It}; run install --openclaw`}function Wa(P){return Array.isArray(P)?P.filter((V)=>typeof V==="string"):[]}function sf(P){let V=qa(P);if(!Lt(V))return`${ht} is not enabled; ${On}`;let z=(()=>{try{return JSON.parse(At(Ka(V,"utf-8")))}catch{return}})();if(z===void 0)return`Failed to read ${V}; fix it, then ${On}`;let Q=ft(z,"plugins");if(ft(Q,"enabled")===!1)return`plugins.enabled is false in ${V}; no OpenClaw plugin loads`;let te=ft(ft(ft(Q,"entries"),ht),"enabled");if(Wa(ft(Q,"deny")).includes(ht)||te===!1)return`${ht} is disabled in ${V}; ${On}`;let ne=Wa(ft(Q,"allow"));if(ne.length>0&&!ne.includes(ht))return`plugins.allow in ${V} does not list ${ht}; add it, then ${On}`;if(ne.includes(ht)||te===!0)return;return`${ht} is not enabled; ${On}`}function Za(P){return/^\/\/ version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function af(P,V,z){if(z===void 0)return[];let Q=bn(z,It);if("error"in Q||Za(Q.content)!==V)return[];return[It,hn,vn].flatMap((te)=>{let ne=bn(P,te),ce=bn(z,te);if("error"in ne||"error"in ce||ne.content===ce.content)return[];return[`Modified ${te} occupies ${Fn(P,te)}; run install --openclaw to restore it`]})}function Xa(P){let V=No(P.environment),z=ur(Rr,V);if(z)return z;let Q=bn(V,It),ne=["error"in Q?Q.error:Q.content.startsWith(Sr)?void 0:`Unmanaged ${It} occupies ${Fn(V,It)}; move or remove it`,rf(V),of(V)].filter((Le)=>Le!==void 0),ce="content"in Q?Za(Q.content):void 0,ye=ne.length>0?ne:af(V,ce,Ho());if(ye.length>0)return{platform:Rr,status:"n/a",configPath:V,errors:ye};let he=ce===wt()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],be=sf(P.environment);if(be)return{platform:Rr,status:"disabled",method:"plugin directory",configPath:V,errors:[be,...he]};return{platform:Rr,status:"configured",method:"plugin directory",configPath:V,errors:he.length>0?he:void 0}}import{existsSync as mf,readFileSync as gf}from"node:fs";import{join as yf}from"node:path";import{existsSync as Pr,readFileSync as Uo,rmSync as lf}from"node:fs";import{join as Bt}from"node:path";import{pathToFileURL as cf}from"node:url";var Er="cc-safety-net",nn=`${Er}@latest`,el=["opencode.json","opencode.jsonc"],Qa="CCSafetyNetPlugin",df={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function Dr(P){return P.env.get("OPENCODE_CONFIG_DIR")??Bt(P.env.get("XDG_CONFIG_HOME")||Bt(P.home,".config"),"opencode")}function uf(P){return Bt(Dr(P),el[0])}function tl(P){return el.map((V)=>Bt(Dr(P),V))}function nl(P){return Bt(P.env.get("XDG_CACHE_HOME")||Bt(P.home,".cache"),"opencode","packages",nn)}function rl(P){lf(nl(P),{recursive:!0,force:!0})}async function ol(P){let V=(await _t(["opencode","--version"],{stdoutOnly:!0})).trim(),z=/^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(V),Q=Number(z?.[1]),te=Number(z?.[2]),ne=Number(z?.[3]);if(!z||Q!==1&&Q!==2||Q===1&&(te<18||te===18&&ne<29)||Q===2&&te===0&&ne<6)throw Error(`OpenCode 1.18.29+ or 2.0.6+ is required; found ${V||"an unknown version"}.`);if(Q===2){for(let ce of tl(P)){if(!Pr(ce))continue;let ye=Go(Uo(ce,"utf-8"),ce);if(["plugin","plugins"].some((be)=>{let Le=ft(ye,be);return Array.isArray(Le)&&Le.some((Ie)=>Bo(Ie)&&(typeof Ie==="string"?Ie:ft(Ie,"package"))!==nn)}))throw Error(`Change the cc-safety-net package spec in ${ce} to ${nn}, preserving its options, then retry. Adding another spec would create a duplicate plugin ID.`)}return{commands:[["opencode","plugin","add",nn],["opencode","plugin","update",nn]],afterInstall:async()=>{let ce=await _t(["opencode","plugin","list"],{stdoutOnly:!0});if(/^cc-safety-net\s+\S+\s+cc-safety-net@latest\s*$/m.test(ce))return;throw Error("OpenCode did not load cc-safety-net from cc-safety-net@latest. Run `opencode plugin list` for details.")}}}return rl(P),{commands:[["opencode","plugin","-g","-f",nn]],afterInstall:()=>pf(P)}}async function pf(P){let V=Bt(nl(P),"node_modules",Er),z=Bt(V,"package.json");if(!Pr(z))throw Error(`The OpenCode plugin cache at ${V} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${nn}\` for details.`);let Q=ft(JSON.parse(Uo(z,"utf-8")),"main");if(typeof Q!=="string")throw Error(`The cached OpenCode plugin at ${V} declares no "main" entry.`);let te=Bt(V,Q);if(typeof(await import(cf(te).href))[Qa]==="function")return;throw Error(`The cached OpenCode plugin at ${te} does not export a callable ${Qa}, so OpenCode would load nothing and fail open.`)}function Go(P,V){try{return JSON.parse(At(P))}catch(z){if(z instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${V}: ${z.message}`);throw z}}function Bo(P){let V=typeof P==="string"?P:ft(P,"package");return typeof V==="string"&&(V===Er||V.startsWith(`${Er}@`))}function qo(P){return["plugin","plugins"].some((V)=>{let z=ft(P,V);return Array.isArray(z)&&z.some(Bo)})}function ff(P,V){let Q=["plugin","plugins"].flatMap((te)=>{let ne=Xs(P,te,df);if(!ne)return[];let ce=[],ye=0,he=ne.start+1,be=P.slice(ne.start+1,ne.end).matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|[^"\s{}[\],/]+|[{}[\],]/g);for(let Le of be){if(Le[0].startsWith("//")||Le[0].startsWith("/*"))continue;let Ie=ne.start+1+Le.index;if(ye===0)he=Ie;if(Le[0]==="{"||Le[0]==="[")ye++;if(Le[0]==="}"||Le[0]==="]")ye--;if(ye!==0||Le[0]===",")continue;let Xe=Ie+Le[0].length;if(Bo(JSON.parse(At(P.slice(he,Xe)))))ce.push({start:he,end:Xe})}return ce}).sort((te,ne)=>te.start-ne.start).reverse().reduce((te,ne)=>{let ce=/^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*,/.exec(te.slice(ne.end));if(ce?.[0].includes("/")){let ye=ne.end+ce[0].length-1;return te.slice(0,ne.start)+te.slice(ne.end,ye)+te.slice(ye+1)}return fr(te,ne)},P);return Go(Q,V),Q}function il(P){rl(P);let V=tl(P),z=V.find((ne)=>Pr(ne)),Q=[],te=[];for(let ne of V){if(!Pr(ne))continue;try{let ce=Uo(ne,"utf-8");if(!qo(Go(ce,ne)))continue;kt(ne,ff(ce,ne)),te.push(ne)}catch(ce){Q.push(ce instanceof Error?ce.message:String(ce))}}if(Q.length>0)throw Error(Q.join(`
211
- `));return{path:te[0]??z??uf(P),alreadyInstalled:te.length>0}}function sl(P){let V=[],z=Dr(P.environment),Q=["opencode.json","opencode.jsonc"];for(let te of Q){let ne=yf(z,te);if(mf(ne))try{let ce=gf(ne,"utf-8"),ye=At(ce),he=JSON.parse(ye);if(qo(he))return{platform:"opencode",status:"configured",method:"plugin array",configPath:ne,errors:V.length>0?V:void 0}}catch(ce){V.push(`Failed to parse ${te}: ${ce instanceof Error?ce.message:String(ce)}`)}}return{platform:"opencode",status:"n/a",errors:V.length>0?V:void 0}}import{join as hf}from"node:path";function Vo(P){return hf(P.home,".pi","agent","settings.json")}function zo(P){if(typeof P!=="string")return!1;return P==="npm:cc-safety-net"||P.startsWith("npm:cc-safety-net@")}function al(P){let V=Vo(P.environment),z=Ft(V);if(z.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(z.kind==="missing")return{platform:"pi",status:"n/a"};let Q=ft(z.value,"packages");if(!Array.isArray(Q))return{platform:"pi",status:"n/a"};let te=Q.find((ye)=>zo(typeof ye==="string"?ye:ft(ye,"source")));if(te===void 0)return{platform:"pi",status:"n/a"};let ne=ft(te,"extensions");if(Array.isArray(ne)&&ne.some((ye)=>typeof ye==="string"&&ye.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:V,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:V}}var vf={amp:Gs,"antigravity-cli":Bs,"claude-code":Js,codex:Ws,"copilot-cli":ca,cursor:ha,"gemini-cli":va,"grok-build":Ea,"hermes-agent":Ma,"kimi-code":In,openclaw:Xa,opencode:sl,pi:al};function Ln(P,V,z){let Q={...z,cwd:V,environment:P};return Zn.map((te)=>bf(vf[te](Q)))}function bf(P){if(P.status==="not-inspected")return{platform:P.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:P.platform,detected:P.status!=="n/a",configured:P.status==="configured",inspectionStatus:P.status!=="n/a"?"verified":P.errors&&P.errors.length>0?"failed":"not-applicable",method:P.method,configPath:P.configPath,configPaths:P.configPaths,errors:P.errors}}import{join as Lf}from"node:path";var wf=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}]),kf=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([])})})}),xf={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 ll(P){let V=Lf(P.tmpdir,"cc-safety-net-self-test"),z=wf.map((Q)=>{let te=D(P,d("self-test",{command:Q.command},{kind:"command",shell:"auto"},{configCwd:V,executionCwd:V},Q.command),{guard:{dependencies:{loadPolicySnapshot:()=>kf,getModes:()=>xf,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),ne=Q.expectBlocked?"blocked":"allowed",ce=te.decision.kind==="deny"?"blocked":"allowed";return{command:Q.command,description:Q.description,expected:ne,actual:ce,passed:ne===ce,reason:te.decision.kind==="deny"?te.decision.reason:void 0,ruleId:te.decision.kind==="deny"?te.decision.ruleId:void 0}});return{passed:z.filter((Q)=>Q.passed).length,failed:z.filter((Q)=>!Q.passed).length,total:z.length,results:z}}function Jo(P){let V=xt({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},P);if(Ht(V.errors))return null;return{json:V.flags.json,skipUpdateCheck:V.flags.skipUpdateCheck}}async function cl(P,V={}){let z=await Pn(!V.json,()=>{let Q=Cf(P,V);return{ready:Q,finish:()=>Q}},()=>Rn(),{loadingMessage:"Checking system status…"});if(V.json)console.log(JSON.stringify(z,null,2));else Sf(z);return z.engineSelfTest.failed>0||z.findings.some((Q)=>Q.severity==="error")?1:0}async function Cf(P,V){let z=V.cwd??process.cwd(),Q=await sr(),te=Ln(P,z,{ampPluginListOutput:Q.ampPluginListOutput,codexPluginListOutput:Q.codexPluginListOutput,copilotCliVersion:Q.versions["copilot-cli"]}),ne=os(P,z),ce=is(P),ye=E(P,{cwd:z}),he=ye.policy,be=L(he,P.env),Le=G(he,be.capabilities),Ie=tr(P,7),Xe=js(P,z),et=V.skipUpdateCheck?{currentVersion:wt(),latestVersion:null,updateAvailable:!1}:await Wt(),xe={hooks:te,engineSelfTest:ll(P),userConfig:ne.userConfig,projectConfig:ne.projectConfig,configState:Ne(ye),effectiveRules:ne.effectiveRules,environment:ce,effectiveSafety:{selectedPreset:he.safety.level??"standard",level:be.effectiveLevel,capabilities:be.capabilities,ruleOverrides:he.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(Le).filter(([,at])=>at.source==="rule_override"&&at.override==="off"&&at.inheritedEnabled&&at.changesInherited).map(([at])=>at),ruleCounts:{stored:Object.keys(he.destructiveCommandRuleOverrides).length,effective:Object.values(Le).filter((at)=>at.changesInherited).length},...ye.policyScopes?{policyScopes:ye.policyScopes}:{}},...Xe.length>0?{v2Leftovers:Xe}:{},posture:bs(P,ne.userConfig.path),activity:Ie,update:et,system:Q};return{...xe,findings:as(xe)}}function Sf(P){console.log(),console.log(cs(P.hooks)),console.log(),console.log(ds(P.engineSelfTest)),console.log(),console.log(us(P)),console.log(),console.log(ps(P.environment)),console.log(),console.log(fs(P)),console.log(),console.log(ms(P.findings)),console.log(),console.log(gs(P.activity)),console.log(),console.log(hs(P.system)),console.log(),console.log(ys(P.update)),console.log(vs(P))}import{existsSync as Rf}from"node:fs";var Pf=/^[A-Za-z0-9_@%+=:,./-]+$/,dl="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Wo(P){let V=xt({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},P);if(Ht(V.errors))return console.error(dl),console.error("Pass -- before a command that starts with dashes."),null;if(V.values.cwd!==void 0&&!Rf(V.values.cwd))return console.error(`Error: --cwd path does not exist: ${V.values.cwd}`),null;let z=V.positionals.length===1?V.positionals[0]:V.positionals.map((Q)=>Pf.test(Q)?Q:`'${Q.replaceAll("'","'\\''")}'`).join(" ");if(!z)return console.error("Error: No command provided"),console.error(dl),null;return{json:V.flags.json,cwd:V.values.cwd,command:z}}function ul(P){if(P)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 pl(P,V){let Q=V-18;return[`${P.dtl}${P.dh.repeat(V)}${P.dtr}`,`${P.dv} Command Analysis${" ".repeat(Q)}${P.dv}`,`${P.dbl}${P.dh.repeat(V)}${P.dbr}`]}function Ko(P){return JSON.stringify(P)}function fl(P,V=0){return`[${P.map((Q,te)=>ls(Q,te,V)).join(",")}]`}function jn(P,V,z=70){let Q=P.split(" "),te=[],ne="";for(let ce of Q)if(ne&&ne.length+ce.length+1>z)te.push(ne),ne=ce;else ne=ne?`${ne} ${ce}`:ce;if(ne)te.push(ne);return te.map((ce,ye)=>ye===0?ce:`${V}${ce}`)}function ml(P,V,z){let Q=[];switch(P.type){case"parse":return null;case"env-strip":return Q.push(""),Q.push(`STEP ${V} ${z.h} Strip environment variables`),Q.push(` Removed: ${P.envVars.map((te)=>`${te}=<redacted>`).join(", ")}`),Q.push(` Tokens: ${Ko(P.output)}`),{lines:Q,incrementStep:!0};case"leading-tokens-stripped":return Q.push(""),Q.push(`STEP ${V} ${z.h} Strip wrappers`),Q.push(` Removed: ${P.removed.join(", ")}`),Q.push(` Tokens: ${Ko(P.output)}`),{lines:Q,incrementStep:!0};case"shell-wrapper":return Q.push(""),Q.push(`STEP ${V} ${z.h} Detect shell wrapper`),Q.push(` Wrapper: ${P.wrapper} -c`),Q.push(` Inner: ${P.innerCommand}`),{lines:Q,incrementStep:!0};case"interpreter":{if(Q.push(""),Q.push(`STEP ${V} ${z.h} Detect interpreter`),Q.push(` Interpreter: ${P.interpreter}`),Q.push(` Code: ${P.codeArg}`),P.paranoidBlocked)Q.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:Q,incrementStep:!0}}case"busybox":return Q.push(""),Q.push(`STEP ${V} ${z.h} Busybox wrapper`),Q.push(` Subcommand: ${P.subcommand}`),{lines:Q,incrementStep:!0};case"transparent-wrapper":return Q.push(""),Q.push(`STEP ${V} ${z.h} Transparent wrapper`),Q.push(` Wrapper: ${P.wrapper}`),Q.push(` Tokens: ${Ko(P.output)}`),{lines:Q,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(Q.push(""),Q.push(`STEP ${V} ${z.h} Match rules`),Q.push(` Rule: ${P.rule}()`),P.matched)Q.push(" Result: MATCHED");else Q.push(" Result: No match");return{lines:Q,incrementStep:!0}}case"worktree-relaxation":return Q.push(""),Q.push(`STEP ${V} ${z.h} Worktree relaxation`),Q.push(` Mode: ${o.worktree.name}`),Q.push(` Git cwd: ${P.gitCwd}`),Q.push(" Result: Allowed local discard in linked worktree"),{lines:Q,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(P.embeddedCommandFound)return Q.push(""),Q.push(`STEP ${V} ${z.h} Fallback scan`),Q.push(` Found: ${P.embeddedCommandFound}`),{lines:Q,incrementStep:!0};return null}case"custom-rules-check":{if(P.rulesChecked){if(Q.push(""),Q.push(`STEP ${V} ${z.h} Custom rules`),P.matched)Q.push(" Result: MATCHED");else Q.push(" Result: No match");return{lines:Q,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(P.matched)return Q.push(""),Q.push(`STEP ${V} ${z.h} Dangerous text check`),Q.push(` Token: ${P.token}`),Q.push(" Result: MATCHED"),{lines:Q,incrementStep:!0};return null}case"strict-unparseable":return Q.push(""),Q.push(`STEP ${V} ${z.h} Strict mode check`),Q.push(` Command: ${P.rawCommand}`),Q.push(" Result: ✗ UNPARSEABLE"),{lines:Q,incrementStep:!0};case"segment-skipped":return null;case"error":return Q.push(""),Q.push(`ERROR: ${P.message}`),{lines:Q,incrementStep:!1};default:return P}}function Yo(P,V){let z=ul(V?.asciiOnly??!1),Q=58,te=[],ne=1;te.push(...pl(z,58)),te.push("");let ce=P.trace.steps.find((xe)=>xe.type==="error");if(ce&&ce.type==="error"){te.push("ERROR"),te.push(` ${ce.message}`),te.push(""),te.push("RESULT"),te.push(` Status: ${P.result==="blocked"?dt.red("BLOCKED"):dt.green("ALLOWED")}`),te.push(""),te.push("CONFIG");let xe=P.configSource??"none";return te.push(` Path: ${xe}`),te.join(`
212
- `)}let ye=P.trace.steps.find((xe)=>xe.type==="parse");if(ye&&ye.type==="parse"){te.push("INPUT"),te.push(` ${ye.input}`),te.push(""),te.push(`STEP ${ne} ${z.h} Split shell commands`),ne++;for(let xe=0;xe<ye.segments.length;xe++){let at=ye.segments[xe];if(at){let ct=Math.random();te.push(` Segment ${xe+1}: ${fl(at,ct)}`)}}}let he=P.trace.segments,be=he.length>1;for(let xe of he){if(be){te.push("");let pt="";if(ye&&ye.type==="parse"){let Xr=ye.segments[xe.index];if(Xr)pt=Xr.join(" ")}let mt=54,gt=pt,ut=` Segment ${xe.index+1}: `,vt=" ";if(pt){if(ut.length+pt.length+vt.length>mt){let Hd=mt-ut.length-vt.length;gt=`${pt.substring(0,Hd-1)}…`}}let Dt=pt?`${ut}${gt}${vt}`:` Segment ${xe.index+1} `,Nd=pt?`${ut}${dt.cyan(gt)}${vt}`:Dt,$i=58-Dt.length,Ii=Math.floor($i/2),Md=$i-Ii;te.push(`${z.sh.repeat(Ii)}${Nd}${z.sh.repeat(Md)}`)}if(xe.steps.find((pt)=>pt.type==="segment-skipped")){te.push(""),te.push(" (skipped — prior segment blocked)");continue}let ct=!1,lt=!1;for(let pt of xe.steps){let mt=ml(pt,ne,z);if(mt){if(lt=!0,pt.type==="recurse"){te.push("");let gt=" RECURSING ",ut=58-gt.length-4;te.push(` ${z.tl}${z.h}${gt}${z.h.repeat(ut)}`),te.push(` ${z.v}`),ct=!0;continue}for(let gt of mt.lines)if(ct)te.push(` ${z.v} ${gt}`);else te.push(gt);if(mt.incrementStep)ne++}}if(ct)te.push(` ${z.v}`),te.push(` ${z.bl}${z.h.repeat(56)}`),ct=!1;if(!lt)te.push(""),te.push(` ${dt.green("✓")} Allowed (no matching rules)`)}if(te.push(""),te.push("RESULT"),P.result==="blocked"){if(te.push(` Status: ${dt.red("BLOCKED")}`),P.customRule){if(te.push(` Rule: ${P.customRule.id}`),P.customRule.rulebook)te.push(` Rulebook: ${P.customRule.rulebook.name} ${P.customRule.rulebook.version}`);if(P.customRule.source)te.push(` Source: ${P.customRule.source}`);if(P.customRule.override)te.push(` Override: reason ${P.customRule.override.reason}`)}if(P.reason){let xe=jn(P.reason," ");te.push(` Reason: ${xe[0]}`);for(let at=1;at<xe.length;at++)te.push(xe[at]??"")}}else te.push(` Status: ${dt.green("ALLOWED")}`);te.push(""),te.push("CONFIG");let Le=P.configSource??"none",Ie=P.configValid?"":" (invalid)";te.push(` Path: ${Le}${Ie}`);let Xe=P.safetyPresetScope;te.push(` Safety preset: ${P.selectedPreset??"standard"}${Xe?` (${rr(Xe)})`:""}`),te.push(` Effective capabilities: ${P.effectiveLevel}`);let et=Object.entries(P.destructiveCommandRuleOverrides??{});if(te.push(` Rule customizations: ${et.length}`),P.ruleActivation)te.push(` Rule activation: ${P.ruleActivation.id} — ${P.ruleActivation.enabled?"on":"off"} via ${P.ruleActivation.source}`);return te.join(`
213
- `)}function Zo(P){return JSON.stringify(P,null,2)}import{resolve as Tf}from"node:path";var Ef=["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 gl(P){let V=0,z={allocateSegment(){return V++},getNextSegmentIndex(){return V},recordGlobal(Q){P.record({kind:"step",scope:"global",step:Q})},recordSegment(Q,te=z.currentSegmentIndex){if(te===void 0)return;P.record({kind:"step",scope:"segment",segmentIndex:te,step:Q})}};return z}function yl(P={}){let V=[],z=P.maxEvents??512,Q={maxTextLength:P.maxTextLength??2048,maxListLength:P.maxListLength??128,maxObjectProperties:P.maxObjectProperties??P.maxListLength??128,maxDepth:P.maxDepth??16},te,ne=new Set;return{record(ce){if(te)return;if(!ce||V.length>=z)return;try{V.push(ei(Df(ce,Q,ne)))}catch{}},finish(){if(te)return te;return te=ei({events:Object.freeze(V)}),te}}}function Df(P,V,z){if(P.kind!=="step")throw TypeError("invalid trace event");let{scope:Q,step:te}=P;Ar(te,z,V);let ne=Xo(te,V,z);if(Q==="global")return{kind:"step",scope:"global",step:ne};if(Q!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:P.segmentIndex,step:ne}}function Ar(P,V,z,Q=0,te=new WeakSet){if(typeof P==="string"){let ye=P.slice(0,z.maxTextLength);if(!Ge(ye))return;for(let he of Ze(ye))for(let be of he.match(/[^\s"'()$]+/g)??[])V.add(hl(be));return}if(!P||typeof P!=="object"||Q>=z.maxDepth||te.has(P))return;if(te.add(P),Array.isArray(P)){let ye=Math.min(P.length,z.maxListLength);for(let he=0;he<ye;he++)Ar(P[he],V,z,Q+1,te);return}let ne=0,ce=new Set;for(let ye in P){if(!Object.hasOwn(P,ye))continue;if(ne>=z.maxObjectProperties)break;ne++,Ar(ye,V,z);let he=Qo(ye,z,V);if(ce.has(he))continue;ce.add(he),Ar(P[ye],V,z,Q+1,te)}}function Xo(P,V,z,Q=0,te=new WeakSet){if(typeof P==="string")return Qo(P,V,z);if(!P||typeof P!=="object")return P;if(Q>=V.maxDepth)return;if(te.has(P))return;if(te.add(P),Array.isArray(P)){let ye=[],he=Math.min(P.length,V.maxListLength);for(let be=0;be<he;be++)ye.push(Xo(P[be],V,z,Q+1,te));return ye}let ne={},ce=0;for(let ye in P){if(!Object.hasOwn(P,ye))continue;if(ce>=V.maxObjectProperties)break;ce++;let he=Qo(ye,V,z);if(Object.hasOwn(ne,he))continue;Object.defineProperty(ne,he,{value:Xo(P[ye],V,z,Q+1,te),enumerable:!0,configurable:!0,writable:!0})}return ne}function Qo(P,V,z){let Q=P.slice(0,V.maxTextLength),te=Ge(Q)?Ue(Q):Q,ne=z.size>0?_f(te,z):te;return(Af(ne)?ke(ne):ne).slice(0,V.maxTextLength)}function Af(P){return P.includes("PRIVATE KEY")||P.includes("://")||P.includes("eyJ")||P.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(P)||P.length>=14&&Ef.some((V)=>P.includes(V))||P.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(P)}function _f(P,V){return P.replace(/[^\s"'()$]+/g,(z)=>V.has(hl(z))?"<redacted>":z)}function hl(P){let V=2166136261,z=2166136261;for(let Q=0;Q<P.length;Q++)V=Math.imul(V^P.charCodeAt(Q),16777619),z=Math.imul(z^P.charCodeAt(P.length-Q-1),16777619);return`${V>>>0}:${z>>>0}:${P.length}`}function ei(P){if(P&&typeof P==="object"&&!Object.isFrozen(P)){for(let V of Object.values(P))ei(V);Object.freeze(P)}return P}function Nn(P,V={},z){let Q=Tf(V.cwd??process.cwd()),te=V.policySnapshot??E(z,{cwd:Q,userConfigDir:V.userConfigDir}),ne=L(te.policy,z.env),ce=Fe({policySnapshot:te,effectiveCapabilities:ne.capabilities,strict:ne.strict,paranoidRm:ne.paranoidRm,paranoidInterpreters:ne.paranoidInterpreters,worktreeMode:ne.worktreeMode}),ye={effectiveLevel:ce.effectiveLevel,selectedPreset:te.policy.safety.level??"standard",...te.policyScopes?{safetyPresetScope:te.policyScopes.levelScope}:{},effectiveCapabilities:ce.effectiveCapabilities,destructiveCommandRuleOverrides:te.policy.destructiveCommandRuleOverrides},{configSource:he,configValid:be}=If(z,{cwd:Q,userConfigDir:V.userConfigDir});if(!P||!P.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:he,configValid:be,...ye};let Le=h(P,"auto");if(Le.status==="limited")throw new y;let Ie=Le.dialect==="powershell"?h(P,"posix"):Le,Xe=st(Ie),et=yl(),xe=gl(et);xe.recordGlobal({type:"parse",input:P,segments:Xe.map((Dt)=>[...Dt])});let at=d("Bash",{command:P},{kind:"command",shell:"auto"},{configCwd:Q,executionCwd:Q},P),ct=W(at,{environment:z,trace:xe,dependencies:{loadPolicySnapshot:()=>te}}),lt=ct.decision.kind==="deny"?ct.decision:null;if(lt&&(ct.stage==="policy-protection"||ct.stage==="secret-protection")){let Dt=$f(lt);return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Dt.rule,matched:!0,reason:lt.reason}]}]},result:"blocked",reason:k(lt.reason),segment:k(vl(lt,P)),...Dt.ruleId?{ruleId:k(Dt.ruleId)}:{},configSource:he,configValid:be,...ye}}let pt=xe.getNextSegmentIndex();if(lt&&pt>0&&pt<Xe.length)xe.recordSegment({type:"segment-skipped",index:pt,reason:"prior-segment-blocked"},pt);let mt=et.finish(),gt=lt?.ruleId??Of(at,te,ne,z),ut=U.find((Dt)=>Dt.id===gt&&Dt.activationCapability),vt=ut?ce.policy.effectiveDestructiveCommandRules[ut.id]:void 0;return{trace:jf(mt),result:lt?"blocked":"allowed",reason:lt?k(lt.reason):void 0,segment:lt?k(vl(lt,P)):void 0,ruleId:lt?.ruleId?k(lt.ruleId):void 0,customRule:Ff(Nf(lt?.ruleId,te)),configSource:he,configValid:be,...ye,...ut&&vt?{ruleActivation:{id:ut.id,...vt}}:{}}}function vl(P,V){return P.evidence?.segment??V}function $f(P){if(P.reason===$e)return{ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};if(P.reason===Me)return{ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};if(P.reason===x)return{ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};return{ruleId:P.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"}}function If(P,V){let z=F(V.cwd),Q=M(P,V),te=K(P,{cwd:V.cwd,userConfigDir:V.userConfigDir});try{if(n(te.projectConfigTarget)!==null){if(Jt(te.projectConfigTarget).errors.length===0)return{configSource:z,configValid:!0};return{configSource:z,configValid:!1}}}catch(ne){if(ne instanceof r)return{configSource:z,configValid:!1};throw ne}try{if(n(te.userConfigTarget)!==null){let ne=Jt(te.userConfigTarget);return{configSource:Q,configValid:ne.errors.length===0}}return{configSource:null,configValid:!0}}catch(ne){if(ne instanceof r)return{configSource:Q,configValid:!1};throw ne}}function Of(P,V,z,Q){let te=V.policy,ne=Ee({...te,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...te.destructiveCommandRuleOverrides,...Object.fromEntries(U.flatMap((ye)=>ye.activationCapability?[[ye.id,"on"]]:[]))}},V.state==="degraded"?{diagnostics:V.diagnostics,reason:V.reason}:void 0),ce=W(P,{environment:Q,dependencies:{loadPolicySnapshot:()=>ne,getModes:()=>({...z,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return ce.decision.kind==="deny"?ce.decision.ruleId:void 0}function Ff(P){if(!P)return;return{id:k(P.id),...P.rulebook?{rulebook:{name:k(P.rulebook.name),version:k(P.rulebook.version)}}:{},...P.source?{source:k(P.source)}:{},...P.override?{override:{type:"reason",reason:k(P.override.reason)}}:{}}}function jf(P){let V=P.events.flatMap((Q)=>Q.kind==="step"&&Q.scope==="global"?[Q.step]:[]),z=new Map;for(let Q of P.events){if(Q.kind!=="step"||Q.scope!=="segment")continue;let te=z.get(Q.segmentIndex)??{index:Q.segmentIndex,steps:[]};te.steps.push(Q.step),z.set(Q.segmentIndex,te)}return{steps:V,segments:[...z.values()]}}function Nf(P,V){let z=P?.replace(/^custom\./,"");if(!z||!V.policy.rules.some((Q)=>Q.name===z))return;return V.ruleMetadata[z]??Object.freeze({id:z})}function bl(P){return new Promise((V)=>{process.stdout.write(`${P}
214
- `,()=>V())})}async function Ll(P,V){let z=Wo(V);if(!z)return 1;try{let Q=Nn(z.command,{cwd:z.cwd},P),te=!!process.env.NO_COLOR||!process.stdout.isTTY;return await bl(z.json?Zo(Q):Yo(Q,{asciiOnly:te})),0}catch(Q){let te=Mf(Q instanceof p?Q.cause:Q);if(te===void 0)throw Q;if(z.json)return await bl(JSON.stringify({error:te})),1;return console.error(te),1}}function Mf(P){if(P instanceof y)return P.message;if(P instanceof f)return P.message;if(P instanceof s&&a[P.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var wl="2.4.3",Ot=" ",rn="cc-safety-net";function kl(P){return P.argument?`${P.flags} ${P.argument}`:P.flags}function Hf(P){return Math.max(...P.map((V)=>kl(V).length))}function Uf(P){return Math.max(...P.map((V)=>V.usage.length))}function Gf(P){return Math.max(...P.map((V)=>`${rn} ${V.usage}`.length))}function Bf(P,V){let z=`${rn} ${P.usage}`;return`${Ot}${z.padEnd(V+2)}${P.description}`}function qt(P,V){return`${Ot}${P.padEnd(Math.max(40,P.length+2))}${V}`}function wn(P,V=console.log){let z=[];if(z.push(`${rn} ${P.name}`),z.push(""),z.push(`${Ot}${P.description}`),z.push(""),z.push("USAGE:"),z.push(`${Ot}${rn} ${P.usage}`),z.push(""),P.subcommands&&P.subcommands.length>0){z.push("SUBCOMMANDS:");let Q=Uf(P.subcommands);for(let te of P.subcommands)z.push(`${Ot}${te.usage.padEnd(Q+2)}${te.description}`);z.push("")}if(P.options.length>0){z.push("OPTIONS:");let Q=Hf(P.options);for(let te of P.options){let ne=kl(te),ce=te.default?`${te.description} (default: ${te.default})`:te.description;z.push(`${Ot}${ne.padEnd(Q+2)}${ce}`)}z.push("")}if(P.examples&&P.examples.length>0){z.push("EXAMPLES:");for(let Q of P.examples)z.push(`${Ot}${Q}`)}V(z.join(`
209
+ ${ye()}`.trim())))},he);ne.on("error",(xe)=>{clearTimeout(be),Q(Error($o(P,null,`${xe.message}
210
+ ${ye()}`.trim())))}),ne.on("close",(xe)=>{if(clearTimeout(be),xe!==0){Q(Error($o(P,xe,ye())));return}z(V?.stdoutOnly?ce.stdout:ye())})})}async function Oo(P){for(let V of P)await _t(V)}async function Ua(P){for(let V of P)try{await _t(V)}catch(z){console.warn(z instanceof Error?z.message:String(z))}}var Fo=Gt("openclaw",ht),Q2=[It,hn,vn];function jo(P,V){if(P==="~")return V;if(P.startsWith("~/")||P.startsWith("~\\"))return Gt(V,P.slice(2));return P}function Ba(P){let V=P.env.get("OPENCLAW_STATE_DIR")?.trim();if(V)return jo(V,P.home);let z=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return z?Ga(jo(z,P.home)):Gt(P.home,".openclaw")}function qa(P){let V=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return V?jo(V,P.home):Gt(Ba(P),"openclaw.json")}function No(P){return Gt(Ba(P),"extensions",ht)}function ef(P){let V=Y2(P);if(V.length===0)return!0;if(V.some((te)=>!Q2.includes(te)))return!1;let z=Gt(P,It),Q=Lt(z);return Q!==void 0&&!Q.isSymbolicLink()&&Q.isFile()&&Z2(z,"utf-8").startsWith(Sr)}function Mo(P){let V=No(P),z=Lt(V);if(!z)return;if(!z.isSymbolicLink()&&z.isDirectory()&&ef(V))return;throw Error(`Refusing to modify ${V}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function Va(){let P=Ga(X2(import.meta.url));return[Gt(P,Fo),Gt(P,"..",Fo),Gt(P,"..","..","..","dist",Fo)]}function Ho(P=Va()){return P.find((V)=>W2(V)&&K2(V).isDirectory())}function tf(P=Va()){let V=Ho(P);if(!V)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return V}function za(P=tf()){return[["openclaw","plugins","install",P,"--force"],["openclaw","plugins","enable",ht]]}function nf(P){let V=(()=>{try{return JSON.parse(P)}catch{return}})(),z=ft(ft(V,"plugin"),"status");return typeof z==="string"?z:void 0}async function Ja(){let P=nf(await _t(["openclaw","plugins","inspect",ht,"--runtime","--json"],{stdoutOnly:!0}));if(P==="loaded")return;throw Error(`${P===void 0?`The ${ht} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${ht} plugin with status "${P}".`} Run \`openclaw plugins inspect ${ht} --runtime\` for details.`)}var Rr="openclaw",On=`run \`openclaw plugins enable ${ht}\``;function bn(P,V){let z=Fn(P,V),Q=Lt(z);if(!Q)return{error:`${V} is missing from ${z}; run install --openclaw`};if(Q.isSymbolicLink()||!Q.isFile())return{error:`${z} is a symlink or not a regular file; move or remove it`};try{return{content:Ka(z,"utf-8")}}catch(te){return{error:`Failed to read ${z}: ${te instanceof Error?te.message:String(te)}`}}}function Ya(P){try{return JSON.parse(At(P))}catch{return}}function rf(P){let V=bn(P,hn);if("error"in V)return V.error;if(ft(Ya(V.content),"id")===ht)return;return`${Fn(P,hn)} is not a valid ${ht} manifest; run install --openclaw`}function of(P){let V=bn(P,vn);if("error"in V)return V.error;let z=ft(ft(Ya(V.content),"openclaw"),"extensions");if(Array.isArray(z)&&z.includes(`./${It}`))return;return`${Fn(P,vn)} does not point OpenClaw at ${It}; run install --openclaw`}function Wa(P){return Array.isArray(P)?P.filter((V)=>typeof V==="string"):[]}function sf(P){let V=qa(P);if(!Lt(V))return`${ht} is not enabled; ${On}`;let z=(()=>{try{return JSON.parse(At(Ka(V,"utf-8")))}catch{return}})();if(z===void 0)return`Failed to read ${V}; fix it, then ${On}`;let Q=ft(z,"plugins");if(ft(Q,"enabled")===!1)return`plugins.enabled is false in ${V}; no OpenClaw plugin loads`;let te=ft(ft(ft(Q,"entries"),ht),"enabled");if(Wa(ft(Q,"deny")).includes(ht)||te===!1)return`${ht} is disabled in ${V}; ${On}`;let ne=Wa(ft(Q,"allow"));if(ne.length>0&&!ne.includes(ht))return`plugins.allow in ${V} does not list ${ht}; add it, then ${On}`;if(ne.includes(ht)||te===!0)return;return`${ht} is not enabled; ${On}`}function Za(P){return/^\/\/ version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function af(P,V,z){if(z===void 0)return[];let Q=bn(z,It);if("error"in Q||Za(Q.content)!==V)return[];return[It,hn,vn].flatMap((te)=>{let ne=bn(P,te),ce=bn(z,te);if("error"in ne||"error"in ce||ne.content===ce.content)return[];return[`Modified ${te} occupies ${Fn(P,te)}; run install --openclaw to restore it`]})}function Xa(P){let V=No(P.environment),z=ur(Rr,V);if(z)return z;let Q=bn(V,It),ne=["error"in Q?Q.error:Q.content.startsWith(Sr)?void 0:`Unmanaged ${It} occupies ${Fn(V,It)}; move or remove it`,rf(V),of(V)].filter((xe)=>xe!==void 0),ce="content"in Q?Za(Q.content):void 0,ye=ne.length>0?ne:af(V,ce,Ho());if(ye.length>0)return{platform:Rr,status:"n/a",configPath:V,errors:ye};let he=ce===wt()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],be=sf(P.environment);if(be)return{platform:Rr,status:"disabled",method:"plugin directory",configPath:V,errors:[be,...he]};return{platform:Rr,status:"configured",method:"plugin directory",configPath:V,errors:he.length>0?he:void 0}}import{existsSync as mf,readFileSync as gf}from"node:fs";import{join as yf}from"node:path";import{existsSync as Pr,readFileSync as Uo,rmSync as lf}from"node:fs";import{join as Bt}from"node:path";import{pathToFileURL as cf}from"node:url";var Er="cc-safety-net",nn=`${Er}@latest`,el=["opencode.json","opencode.jsonc"],Qa="CCSafetyNetPlugin",df={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function Dr(P){return P.env.get("OPENCODE_CONFIG_DIR")??Bt(P.env.get("XDG_CONFIG_HOME")||Bt(P.home,".config"),"opencode")}function uf(P){return Bt(Dr(P),el[0])}function tl(P){return el.map((V)=>Bt(Dr(P),V))}function nl(P){return Bt(P.env.get("XDG_CACHE_HOME")||Bt(P.home,".cache"),"opencode","packages",nn)}function rl(P){lf(nl(P),{recursive:!0,force:!0})}async function ol(P){let V=(await _t(["opencode","--version"],{stdoutOnly:!0})).trim(),z=/^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(V),Q=Number(z?.[1]),te=Number(z?.[2]),ne=Number(z?.[3]);if(!z||Q!==1&&Q!==2||Q===1&&(te<18||te===18&&ne<29)||Q===2&&te===0&&ne<6)throw Error(`OpenCode 1.18.29+ or 2.0.6+ is required; found ${V||"an unknown version"}.`);if(Q===2){for(let ce of tl(P)){if(!Pr(ce))continue;let ye=Go(Uo(ce,"utf-8"),ce);if(["plugin","plugins"].some((be)=>{let xe=ft(ye,be);return Array.isArray(xe)&&xe.some((Ie)=>Bo(Ie)&&(typeof Ie==="string"?Ie:ft(Ie,"package"))!==nn)}))throw Error(`Change the cc-safety-net package spec in ${ce} to ${nn}, preserving its options, then retry. Adding another spec would create a duplicate plugin ID.`)}return{commands:[["opencode","plugin","add",nn],["opencode","plugin","update",nn]],afterInstall:async()=>{let ce=await _t(["opencode","plugin","list"],{stdoutOnly:!0});if(/^cc-safety-net\s+\S+\s+cc-safety-net@latest\s*$/m.test(ce))return;throw Error("OpenCode did not load cc-safety-net from cc-safety-net@latest. Run `opencode plugin list` for details.")}}}return rl(P),{commands:[["opencode","plugin","-g","-f",nn]],afterInstall:()=>pf(P)}}async function pf(P){let V=Bt(nl(P),"node_modules",Er),z=Bt(V,"package.json");if(!Pr(z))throw Error(`The OpenCode plugin cache at ${V} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${nn}\` for details.`);let Q=ft(JSON.parse(Uo(z,"utf-8")),"main");if(typeof Q!=="string")throw Error(`The cached OpenCode plugin at ${V} declares no "main" entry.`);let te=Bt(V,Q);if(typeof(await import(cf(te).href))[Qa]==="function")return;throw Error(`The cached OpenCode plugin at ${te} does not export a callable ${Qa}, so OpenCode would load nothing and fail open.`)}function Go(P,V){try{return JSON.parse(At(P))}catch(z){if(z instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${V}: ${z.message}`);throw z}}function Bo(P){let V=typeof P==="string"?P:ft(P,"package");return typeof V==="string"&&(V===Er||V.startsWith(`${Er}@`))}function qo(P){return["plugin","plugins"].some((V)=>{let z=ft(P,V);return Array.isArray(z)&&z.some(Bo)})}function ff(P,V){let Q=["plugin","plugins"].flatMap((te)=>{let ne=Xs(P,te,df);if(!ne)return[];let ce=[],ye=0,he=ne.start+1,be=P.slice(ne.start+1,ne.end).matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|[^"\s{}[\],/]+|[{}[\],]/g);for(let xe of be){if(xe[0].startsWith("//")||xe[0].startsWith("/*"))continue;let Ie=ne.start+1+xe.index;if(ye===0)he=Ie;if(xe[0]==="{"||xe[0]==="[")ye++;if(xe[0]==="}"||xe[0]==="]")ye--;if(ye!==0||xe[0]===",")continue;let Xe=Ie+xe[0].length;if(Bo(JSON.parse(At(P.slice(he,Xe)))))ce.push({start:he,end:Xe})}return ce}).sort((te,ne)=>te.start-ne.start).reverse().reduce((te,ne)=>{let ce=/^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*,/.exec(te.slice(ne.end));if(ce?.[0].includes("/")){let ye=ne.end+ce[0].length-1;return te.slice(0,ne.start)+te.slice(ne.end,ye)+te.slice(ye+1)}return fr(te,ne)},P);return Go(Q,V),Q}function il(P){rl(P);let V=tl(P),z=V.find((ne)=>Pr(ne)),Q=[],te=[];for(let ne of V){if(!Pr(ne))continue;try{let ce=Uo(ne,"utf-8");if(!qo(Go(ce,ne)))continue;kt(ne,ff(ce,ne)),te.push(ne)}catch(ce){Q.push(ce instanceof Error?ce.message:String(ce))}}if(Q.length>0)throw Error(Q.join(`
211
+ `));return{path:te[0]??z??uf(P),alreadyInstalled:te.length>0}}function sl(P){let V=[],z=Dr(P.environment),Q=["opencode.json","opencode.jsonc"];for(let te of Q){let ne=yf(z,te);if(mf(ne))try{let ce=gf(ne,"utf-8"),ye=At(ce),he=JSON.parse(ye);if(qo(he))return{platform:"opencode",status:"configured",method:"plugin array",configPath:ne,errors:V.length>0?V:void 0}}catch(ce){V.push(`Failed to parse ${te}: ${ce instanceof Error?ce.message:String(ce)}`)}}return{platform:"opencode",status:"n/a",errors:V.length>0?V:void 0}}import{join as hf}from"node:path";function Vo(P){return hf(P.home,".pi","agent","settings.json")}function zo(P){if(typeof P!=="string")return!1;return P==="npm:cc-safety-net"||P.startsWith("npm:cc-safety-net@")}function al(P){let V=Vo(P.environment),z=Ft(V);if(z.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(z.kind==="missing")return{platform:"pi",status:"n/a"};let Q=ft(z.value,"packages");if(!Array.isArray(Q))return{platform:"pi",status:"n/a"};let te=Q.find((ye)=>zo(typeof ye==="string"?ye:ft(ye,"source")));if(te===void 0)return{platform:"pi",status:"n/a"};let ne=ft(te,"extensions");if(Array.isArray(ne)&&ne.some((ye)=>typeof ye==="string"&&ye.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:V,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:V}}var vf={amp:Gs,"antigravity-cli":Bs,"claude-code":Js,codex:Ws,"copilot-cli":ca,cursor:ha,"gemini-cli":va,"grok-build":Ea,"hermes-agent":Ma,"kimi-code":In,openclaw:Xa,opencode:sl,pi:al};function Ln(P,V,z){let Q={...z,cwd:V,environment:P};return Zn.map((te)=>bf(vf[te](Q)))}function bf(P){if(P.status==="not-inspected")return{platform:P.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:P.platform,detected:P.status!=="n/a",configured:P.status==="configured",inspectionStatus:P.status!=="n/a"?"verified":P.errors&&P.errors.length>0?"failed":"not-applicable",method:P.method,configPath:P.configPath,configPaths:P.configPaths,errors:P.errors}}import{join as Lf}from"node:path";var wf=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}]),kf=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([])})})}),xf={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 ll(P){let V=Lf(P.tmpdir,"cc-safety-net-self-test"),z=wf.map((Q)=>{let te=D(P,d("self-test",{command:Q.command},{kind:"command",shell:"auto"},{configCwd:V,executionCwd:V},Q.command),{guard:{dependencies:{loadPolicySnapshot:()=>kf,getModes:()=>xf,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),ne=Q.expectBlocked?"blocked":"allowed",ce=te.decision.kind==="deny"?"blocked":"allowed";return{command:Q.command,description:Q.description,expected:ne,actual:ce,passed:ne===ce,reason:te.decision.kind==="deny"?te.decision.reason:void 0,ruleId:te.decision.kind==="deny"?te.decision.ruleId:void 0}});return{passed:z.filter((Q)=>Q.passed).length,failed:z.filter((Q)=>!Q.passed).length,total:z.length,results:z}}function Jo(P){let V=xt({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},P);if(Ht(V.errors))return null;return{json:V.flags.json,skipUpdateCheck:V.flags.skipUpdateCheck}}async function cl(P,V={}){let z=await Pn(!V.json,()=>{let Q=Cf(P,V);return{ready:Q,finish:()=>Q}},()=>Rn(),{loadingMessage:"Checking system status…"});if(V.json)console.log(JSON.stringify(z,null,2));else Sf(z);return z.engineSelfTest.failed>0||z.findings.some((Q)=>Q.severity==="error")?1:0}async function Cf(P,V){let z=V.cwd??process.cwd(),Q=await sr(),te=Ln(P,z,{ampPluginListOutput:Q.ampPluginListOutput,codexPluginListOutput:Q.codexPluginListOutput,copilotCliVersion:Q.versions["copilot-cli"]}),ne=os(P,z),ce=is(P),ye=E(P,{cwd:z}),he=ye.policy,be=R(he,P.env),xe=G(he,be.capabilities),Ie=tr(P,7),Xe=js(P,z),et=V.skipUpdateCheck?{currentVersion:wt(),latestVersion:null,updateAvailable:!1}:await Wt(),Re={hooks:te,engineSelfTest:ll(P),userConfig:ne.userConfig,projectConfig:ne.projectConfig,configState:Ne(ye),effectiveRules:ne.effectiveRules,environment:ce,effectiveSafety:{selectedPreset:he.safety.level??"standard",level:be.effectiveLevel,capabilities:be.capabilities,ruleOverrides:he.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(xe).filter(([,at])=>at.source==="rule_override"&&at.override==="off"&&at.inheritedEnabled&&at.changesInherited).map(([at])=>at),ruleCounts:{stored:Object.keys(he.destructiveCommandRuleOverrides).length,effective:Object.values(xe).filter((at)=>at.changesInherited).length},...ye.policyScopes?{policyScopes:ye.policyScopes}:{}},...Xe.length>0?{v2Leftovers:Xe}:{},posture:bs(P,ne.userConfig.path),activity:Ie,update:et,system:Q};return{...Re,findings:as(Re)}}function Sf(P){console.log(),console.log(cs(P.hooks)),console.log(),console.log(ds(P.engineSelfTest)),console.log(),console.log(us(P)),console.log(),console.log(ps(P.environment)),console.log(),console.log(fs(P)),console.log(),console.log(ms(P.findings)),console.log(),console.log(gs(P.activity)),console.log(),console.log(hs(P.system)),console.log(),console.log(ys(P.update)),console.log(vs(P))}import{existsSync as Rf}from"node:fs";var Pf=/^[A-Za-z0-9_@%+=:,./-]+$/,dl="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Wo(P){let V=xt({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},P);if(Ht(V.errors))return console.error(dl),console.error("Pass -- before a command that starts with dashes."),null;if(V.values.cwd!==void 0&&!Rf(V.values.cwd))return console.error(`Error: --cwd path does not exist: ${V.values.cwd}`),null;let z=V.positionals.length===1?V.positionals[0]:V.positionals.map((Q)=>Pf.test(Q)?Q:`'${Q.replaceAll("'","'\\''")}'`).join(" ");if(!z)return console.error("Error: No command provided"),console.error(dl),null;return{json:V.flags.json,cwd:V.values.cwd,command:z}}function ul(P){if(P)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 pl(P,V){let Q=V-18;return[`${P.dtl}${P.dh.repeat(V)}${P.dtr}`,`${P.dv} Command Analysis${" ".repeat(Q)}${P.dv}`,`${P.dbl}${P.dh.repeat(V)}${P.dbr}`]}function Ko(P){return JSON.stringify(P)}function fl(P,V=0){return`[${P.map((Q,te)=>ls(Q,te,V)).join(",")}]`}function jn(P,V,z=70){let Q=P.split(" "),te=[],ne="";for(let ce of Q)if(ne&&ne.length+ce.length+1>z)te.push(ne),ne=ce;else ne=ne?`${ne} ${ce}`:ce;if(ne)te.push(ne);return te.map((ce,ye)=>ye===0?ce:`${V}${ce}`)}function ml(P,V,z){let Q=[];switch(P.type){case"parse":return null;case"env-strip":return Q.push(""),Q.push(`STEP ${V} ${z.h} Strip environment variables`),Q.push(` Removed: ${P.envVars.map((te)=>`${te}=<redacted>`).join(", ")}`),Q.push(` Tokens: ${Ko(P.output)}`),{lines:Q,incrementStep:!0};case"leading-tokens-stripped":return Q.push(""),Q.push(`STEP ${V} ${z.h} Strip wrappers`),Q.push(` Removed: ${P.removed.join(", ")}`),Q.push(` Tokens: ${Ko(P.output)}`),{lines:Q,incrementStep:!0};case"shell-wrapper":return Q.push(""),Q.push(`STEP ${V} ${z.h} Detect shell wrapper`),Q.push(` Wrapper: ${P.wrapper} -c`),Q.push(` Inner: ${P.innerCommand}`),{lines:Q,incrementStep:!0};case"interpreter":{if(Q.push(""),Q.push(`STEP ${V} ${z.h} Detect interpreter`),Q.push(` Interpreter: ${P.interpreter}`),Q.push(` Code: ${P.codeArg}`),P.paranoidBlocked)Q.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:Q,incrementStep:!0}}case"busybox":return Q.push(""),Q.push(`STEP ${V} ${z.h} Busybox wrapper`),Q.push(` Subcommand: ${P.subcommand}`),{lines:Q,incrementStep:!0};case"transparent-wrapper":return Q.push(""),Q.push(`STEP ${V} ${z.h} Transparent wrapper`),Q.push(` Wrapper: ${P.wrapper}`),Q.push(` Tokens: ${Ko(P.output)}`),{lines:Q,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(Q.push(""),Q.push(`STEP ${V} ${z.h} Match rules`),Q.push(` Rule: ${P.rule}()`),P.matched)Q.push(" Result: MATCHED");else Q.push(" Result: No match");return{lines:Q,incrementStep:!0}}case"worktree-relaxation":return Q.push(""),Q.push(`STEP ${V} ${z.h} Worktree relaxation`),Q.push(` Mode: ${o.worktree.name}`),Q.push(` Git cwd: ${P.gitCwd}`),Q.push(" Result: Allowed local discard in linked worktree"),{lines:Q,incrementStep:!0};case"temp-root-relaxation":return Q.push(""),Q.push(`STEP ${V} ${z.h} Temp-root relaxation`),Q.push(` Git cwd: ${P.gitCwd}`),Q.push(" Result: Allowed git discard in a temp-root repository"),{lines:Q,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(P.embeddedCommandFound)return Q.push(""),Q.push(`STEP ${V} ${z.h} Fallback scan`),Q.push(` Found: ${P.embeddedCommandFound}`),{lines:Q,incrementStep:!0};return null}case"custom-rules-check":{if(P.rulesChecked){if(Q.push(""),Q.push(`STEP ${V} ${z.h} Custom rules`),P.matched)Q.push(" Result: MATCHED");else Q.push(" Result: No match");return{lines:Q,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(P.matched)return Q.push(""),Q.push(`STEP ${V} ${z.h} Dangerous text check`),Q.push(` Token: ${P.token}`),Q.push(" Result: MATCHED"),{lines:Q,incrementStep:!0};return null}case"strict-unparseable":return Q.push(""),Q.push(`STEP ${V} ${z.h} Strict mode check`),Q.push(` Command: ${P.rawCommand}`),Q.push(" Result: ✗ UNPARSEABLE"),{lines:Q,incrementStep:!0};case"segment-skipped":return null;case"error":return Q.push(""),Q.push(`ERROR: ${P.message}`),{lines:Q,incrementStep:!1};default:return P}}function Yo(P,V){let z=ul(V?.asciiOnly??!1),Q=58,te=[],ne=1;te.push(...pl(z,58)),te.push("");let ce=P.trace.steps.find((Re)=>Re.type==="error");if(ce&&ce.type==="error"){te.push("ERROR"),te.push(` ${ce.message}`),te.push(""),te.push("RESULT"),te.push(` Status: ${P.result==="blocked"?dt.red("BLOCKED"):dt.green("ALLOWED")}`),te.push(""),te.push("CONFIG");let Re=P.configSource??"none";return te.push(` Path: ${Re}`),te.join(`
212
+ `)}let ye=P.trace.steps.find((Re)=>Re.type==="parse");if(ye&&ye.type==="parse"){te.push("INPUT"),te.push(` ${ye.input}`),te.push(""),te.push(`STEP ${ne} ${z.h} Split shell commands`),ne++;for(let Re=0;Re<ye.segments.length;Re++){let at=ye.segments[Re];if(at){let ct=Math.random();te.push(` Segment ${Re+1}: ${fl(at,ct)}`)}}}let he=P.trace.segments,be=he.length>1;for(let Re of he){if(be){te.push("");let pt="";if(ye&&ye.type==="parse"){let Xr=ye.segments[Re.index];if(Xr)pt=Xr.join(" ")}let mt=54,gt=pt,ut=` Segment ${Re.index+1}: `,vt=" ";if(pt){if(ut.length+pt.length+vt.length>mt){let Hd=mt-ut.length-vt.length;gt=`${pt.substring(0,Hd-1)}…`}}let Dt=pt?`${ut}${gt}${vt}`:` Segment ${Re.index+1} `,Nd=pt?`${ut}${dt.cyan(gt)}${vt}`:Dt,$i=58-Dt.length,Ii=Math.floor($i/2),Md=$i-Ii;te.push(`${z.sh.repeat(Ii)}${Nd}${z.sh.repeat(Md)}`)}if(Re.steps.find((pt)=>pt.type==="segment-skipped")){te.push(""),te.push(" (skipped — prior segment blocked)");continue}let ct=!1,lt=!1;for(let pt of Re.steps){let mt=ml(pt,ne,z);if(mt){if(lt=!0,pt.type==="recurse"){te.push("");let gt=" RECURSING ",ut=58-gt.length-4;te.push(` ${z.tl}${z.h}${gt}${z.h.repeat(ut)}`),te.push(` ${z.v}`),ct=!0;continue}for(let gt of mt.lines)if(ct)te.push(` ${z.v} ${gt}`);else te.push(gt);if(mt.incrementStep)ne++}}if(ct)te.push(` ${z.v}`),te.push(` ${z.bl}${z.h.repeat(56)}`),ct=!1;if(!lt)te.push(""),te.push(` ${dt.green("✓")} Allowed (no matching rules)`)}if(te.push(""),te.push("RESULT"),P.result==="blocked"){if(te.push(` Status: ${dt.red("BLOCKED")}`),P.customRule){if(te.push(` Rule: ${P.customRule.id}`),P.customRule.rulebook)te.push(` Rulebook: ${P.customRule.rulebook.name} ${P.customRule.rulebook.version}`);if(P.customRule.source)te.push(` Source: ${P.customRule.source}`);if(P.customRule.override)te.push(` Override: reason ${P.customRule.override.reason}`)}if(P.reason){let Re=jn(P.reason," ");te.push(` Reason: ${Re[0]}`);for(let at=1;at<Re.length;at++)te.push(Re[at]??"")}}else te.push(` Status: ${dt.green("ALLOWED")}`);te.push(""),te.push("CONFIG");let xe=P.configSource??"none",Ie=P.configValid?"":" (invalid)";te.push(` Path: ${xe}${Ie}`);let Xe=P.safetyPresetScope;te.push(` Safety preset: ${P.selectedPreset??"standard"}${Xe?` (${rr(Xe)})`:""}`),te.push(` Effective capabilities: ${P.effectiveLevel}`);let et=Object.entries(P.destructiveCommandRuleOverrides??{});if(te.push(` Rule customizations: ${et.length}`),P.ruleActivation)te.push(` Rule activation: ${P.ruleActivation.id} — ${P.ruleActivation.enabled?"on":"off"} via ${P.ruleActivation.source}`);return te.join(`
213
+ `)}function Zo(P){return JSON.stringify(P,null,2)}import{resolve as Tf}from"node:path";var Ef=["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 gl(P){let V=0,z={allocateSegment(){return V++},getNextSegmentIndex(){return V},recordGlobal(Q){P.record({kind:"step",scope:"global",step:Q})},recordSegment(Q,te=z.currentSegmentIndex){if(te===void 0)return;P.record({kind:"step",scope:"segment",segmentIndex:te,step:Q})}};return z}function yl(P={}){let V=[],z=P.maxEvents??512,Q={maxTextLength:P.maxTextLength??2048,maxListLength:P.maxListLength??128,maxObjectProperties:P.maxObjectProperties??P.maxListLength??128,maxDepth:P.maxDepth??16},te,ne=new Set;return{record(ce){if(te)return;if(!ce||V.length>=z)return;try{V.push(ei(Df(ce,Q,ne)))}catch{}},finish(){if(te)return te;return te=ei({events:Object.freeze(V)}),te}}}function Df(P,V,z){if(P.kind!=="step")throw TypeError("invalid trace event");let{scope:Q,step:te}=P;Ar(te,z,V);let ne=Xo(te,V,z);if(Q==="global")return{kind:"step",scope:"global",step:ne};if(Q!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:P.segmentIndex,step:ne}}function Ar(P,V,z,Q=0,te=new WeakSet){if(typeof P==="string"){let ye=P.slice(0,z.maxTextLength);if(!Ge(ye))return;for(let he of Ze(ye))for(let be of he.match(/[^\s"'()$]+/g)??[])V.add(hl(be));return}if(!P||typeof P!=="object"||Q>=z.maxDepth||te.has(P))return;if(te.add(P),Array.isArray(P)){let ye=Math.min(P.length,z.maxListLength);for(let he=0;he<ye;he++)Ar(P[he],V,z,Q+1,te);return}let ne=0,ce=new Set;for(let ye in P){if(!Object.hasOwn(P,ye))continue;if(ne>=z.maxObjectProperties)break;ne++,Ar(ye,V,z);let he=Qo(ye,z,V);if(ce.has(he))continue;ce.add(he),Ar(P[ye],V,z,Q+1,te)}}function Xo(P,V,z,Q=0,te=new WeakSet){if(typeof P==="string")return Qo(P,V,z);if(!P||typeof P!=="object")return P;if(Q>=V.maxDepth)return;if(te.has(P))return;if(te.add(P),Array.isArray(P)){let ye=[],he=Math.min(P.length,V.maxListLength);for(let be=0;be<he;be++)ye.push(Xo(P[be],V,z,Q+1,te));return ye}let ne={},ce=0;for(let ye in P){if(!Object.hasOwn(P,ye))continue;if(ce>=V.maxObjectProperties)break;ce++;let he=Qo(ye,V,z);if(Object.hasOwn(ne,he))continue;Object.defineProperty(ne,he,{value:Xo(P[ye],V,z,Q+1,te),enumerable:!0,configurable:!0,writable:!0})}return ne}function Qo(P,V,z){let Q=P.slice(0,V.maxTextLength),te=Ge(Q)?Ue(Q):Q,ne=z.size>0?_f(te,z):te;return(Af(ne)?ke(ne):ne).slice(0,V.maxTextLength)}function Af(P){return P.includes("PRIVATE KEY")||P.includes("://")||P.includes("eyJ")||P.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(P)||P.length>=14&&Ef.some((V)=>P.includes(V))||P.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(P)}function _f(P,V){return P.replace(/[^\s"'()$]+/g,(z)=>V.has(hl(z))?"<redacted>":z)}function hl(P){let V=2166136261,z=2166136261;for(let Q=0;Q<P.length;Q++)V=Math.imul(V^P.charCodeAt(Q),16777619),z=Math.imul(z^P.charCodeAt(P.length-Q-1),16777619);return`${V>>>0}:${z>>>0}:${P.length}`}function ei(P){if(P&&typeof P==="object"&&!Object.isFrozen(P)){for(let V of Object.values(P))ei(V);Object.freeze(P)}return P}function Nn(P,V={},z){let Q=Tf(V.cwd??process.cwd()),te=V.policySnapshot??E(z,{cwd:Q,userConfigDir:V.userConfigDir}),ne=R(te.policy,z.env),ce=Fe({policySnapshot:te,effectiveCapabilities:ne.capabilities,strict:ne.strict,paranoidRm:ne.paranoidRm,paranoidInterpreters:ne.paranoidInterpreters,worktreeMode:ne.worktreeMode}),ye={effectiveLevel:ce.effectiveLevel,selectedPreset:te.policy.safety.level??"standard",...te.policyScopes?{safetyPresetScope:te.policyScopes.levelScope}:{},effectiveCapabilities:ce.effectiveCapabilities,destructiveCommandRuleOverrides:te.policy.destructiveCommandRuleOverrides},{configSource:he,configValid:be}=If(z,{cwd:Q,userConfigDir:V.userConfigDir});if(!P||!P.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:he,configValid:be,...ye};let xe=h(P,"auto");if(xe.status==="limited")throw new y;let Ie=xe.dialect==="powershell"?h(P,"posix"):xe,Xe=st(Ie),et=yl(),Re=gl(et);Re.recordGlobal({type:"parse",input:P,segments:Xe.map((Dt)=>[...Dt])});let at=d("Bash",{command:P},{kind:"command",shell:"auto"},{configCwd:Q,executionCwd:Q},P),ct=W(at,{environment:z,trace:Re,dependencies:{loadPolicySnapshot:()=>te}}),lt=ct.decision.kind==="deny"?ct.decision:null;if(lt&&(ct.stage==="policy-protection"||ct.stage==="secret-protection")){let Dt=$f(lt);return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Dt.rule,matched:!0,reason:lt.reason}]}]},result:"blocked",reason:k(lt.reason),segment:k(vl(lt,P)),...Dt.ruleId?{ruleId:k(Dt.ruleId)}:{},configSource:he,configValid:be,...ye}}let pt=Re.getNextSegmentIndex();if(lt&&pt>0&&pt<Xe.length)Re.recordSegment({type:"segment-skipped",index:pt,reason:"prior-segment-blocked"},pt);let mt=et.finish(),gt=lt?.ruleId??Of(at,te,ne,z),ut=U.find((Dt)=>Dt.id===gt&&Dt.activationCapability),vt=ut?ce.policy.effectiveDestructiveCommandRules[ut.id]:void 0;return{trace:jf(mt),result:lt?"blocked":"allowed",reason:lt?k(lt.reason):void 0,segment:lt?k(vl(lt,P)):void 0,ruleId:lt?.ruleId?k(lt.ruleId):void 0,customRule:Ff(Nf(lt?.ruleId,te)),configSource:he,configValid:be,...ye,...ut&&vt?{ruleActivation:{id:ut.id,...vt}}:{}}}function vl(P,V){return P.evidence?.segment??V}function $f(P){if(P.reason===$e)return{ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};if(P.reason===Me)return{ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};if(P.reason===x)return{ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};return{ruleId:P.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"}}function If(P,V){let z=F(V.cwd),Q=M(P,V),te=K(P,{cwd:V.cwd,userConfigDir:V.userConfigDir});try{if(n(te.projectConfigTarget)!==null){if(Jt(te.projectConfigTarget).errors.length===0)return{configSource:z,configValid:!0};return{configSource:z,configValid:!1}}}catch(ne){if(ne instanceof r)return{configSource:z,configValid:!1};throw ne}try{if(n(te.userConfigTarget)!==null){let ne=Jt(te.userConfigTarget);return{configSource:Q,configValid:ne.errors.length===0}}return{configSource:null,configValid:!0}}catch(ne){if(ne instanceof r)return{configSource:Q,configValid:!1};throw ne}}function Of(P,V,z,Q){let te=V.policy,ne=Ee({...te,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...te.destructiveCommandRuleOverrides,...Object.fromEntries(U.flatMap((ye)=>ye.activationCapability?[[ye.id,"on"]]:[]))}},V.state==="degraded"?{diagnostics:V.diagnostics,reason:V.reason}:void 0),ce=W(P,{environment:Q,dependencies:{loadPolicySnapshot:()=>ne,getModes:()=>({...z,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return ce.decision.kind==="deny"?ce.decision.ruleId:void 0}function Ff(P){if(!P)return;return{id:k(P.id),...P.rulebook?{rulebook:{name:k(P.rulebook.name),version:k(P.rulebook.version)}}:{},...P.source?{source:k(P.source)}:{},...P.override?{override:{type:"reason",reason:k(P.override.reason)}}:{}}}function jf(P){let V=P.events.flatMap((Q)=>Q.kind==="step"&&Q.scope==="global"?[Q.step]:[]),z=new Map;for(let Q of P.events){if(Q.kind!=="step"||Q.scope!=="segment")continue;let te=z.get(Q.segmentIndex)??{index:Q.segmentIndex,steps:[]};te.steps.push(Q.step),z.set(Q.segmentIndex,te)}return{steps:V,segments:[...z.values()]}}function Nf(P,V){let z=P?.replace(/^custom\./,"");if(!z||!V.policy.rules.some((Q)=>Q.name===z))return;return V.ruleMetadata[z]??Object.freeze({id:z})}function bl(P){return new Promise((V)=>{process.stdout.write(`${P}
214
+ `,()=>V())})}async function Ll(P,V){let z=Wo(V);if(!z)return 1;try{let Q=Nn(z.command,{cwd:z.cwd},P),te=!!process.env.NO_COLOR||!process.stdout.isTTY;return await bl(z.json?Zo(Q):Yo(Q,{asciiOnly:te})),0}catch(Q){let te=Mf(Q instanceof p?Q.cause:Q);if(te===void 0)throw Q;if(z.json)return await bl(JSON.stringify({error:te})),1;return console.error(te),1}}function Mf(P){if(P instanceof y)return P.message;if(P instanceof f)return P.message;if(P instanceof s&&a[P.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var wl="2.4.5",Ot=" ",rn="cc-safety-net";function kl(P){return P.argument?`${P.flags} ${P.argument}`:P.flags}function Hf(P){return Math.max(...P.map((V)=>kl(V).length))}function Uf(P){return Math.max(...P.map((V)=>V.usage.length))}function Gf(P){return Math.max(...P.map((V)=>`${rn} ${V.usage}`.length))}function Bf(P,V){let z=`${rn} ${P.usage}`;return`${Ot}${z.padEnd(V+2)}${P.description}`}function qt(P,V){return`${Ot}${P.padEnd(Math.max(40,P.length+2))}${V}`}function wn(P,V=console.log){let z=[];if(z.push(`${rn} ${P.name}`),z.push(""),z.push(`${Ot}${P.description}`),z.push(""),z.push("USAGE:"),z.push(`${Ot}${rn} ${P.usage}`),z.push(""),P.subcommands&&P.subcommands.length>0){z.push("SUBCOMMANDS:");let Q=Uf(P.subcommands);for(let te of P.subcommands)z.push(`${Ot}${te.usage.padEnd(Q+2)}${te.description}`);z.push("")}if(P.options.length>0){z.push("OPTIONS:");let Q=Hf(P.options);for(let te of P.options){let ne=kl(te),ce=te.default?`${te.description} (default: ${te.default})`:te.description;z.push(`${Ot}${ne.padEnd(Q+2)}${ce}`)}z.push("")}if(P.examples&&P.examples.length>0){z.push("EXAMPLES:");for(let Q of P.examples)z.push(`${Ot}${Q}`)}V(z.join(`
215
215
  `))}function ti(){let P=Gf(Qn),V=[];V.push(`${rn} v${wl}`),V.push(""),V.push("Blocks destructive commands and secret access."),V.push(""),V.push("COMMANDS:");for(let z of Qn)V.push(Bf(z,P));V.push(""),V.push("GLOBAL OPTIONS:"),V.push(`${Ot}-h, --help Show help (use with command for command-specific help)`),V.push(`${Ot}-V, --version Show version`),V.push(""),V.push("HELP:"),V.push(`${Ot}${rn} help <command> Show help for a specific command`),V.push(`${Ot}${rn} <command> --help Show help for a specific command`),V.push(""),V.push("ENVIRONMENT VARIABLES:"),V.push(qt(`${o.level.name}=standard|strict|paranoid`,"Set session safety level")),V.push(qt(`${o.worktree.name}=1`,"Allow local git discards in linked worktrees")),V.push(qt(`${o.debug.name}=1`,"Print diagnostic messages to stderr")),V.push(qt(`${o.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),V.push(qt("CC_SAFETY_NET_HOME","Override rule config home directory")),V.push(""),V.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),V.push(qt(`${o.strict.name}=1`,"Force safety.overrides.fail_closed on")),V.push(qt(`${o.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),V.push(qt(`${o.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),V.push(qt(`${o.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),V.push(""),V.push("Documentation: https://ccsafetynet.com/docs"),console.log(V.join(`
216
- `))}function xl(){console.log(wl)}function Mn(P,V=console.log){let z=er(P);if(!z)return!1;if(z.name.toLowerCase()!==P.toLowerCase())return!1;return wn(z,V),!0}import{existsSync as mi,readFileSync as bc}from"node:fs";import{join as pi}from"node:path";import*as Kt from"node:readline";function qf(P){return P==="install"?"Install":"Uninstall"}function Vf(P){return P==="install"?"Installing":"Uninstalling"}function zf(P){return P==="install"?"into":"from"}function Rl(P){return P?.available===!0}function Jf(P,V){let z=new Set(V);return P.filter((Q)=>z.has(Q.target)).map((Q)=>Q.target)}function Cl(P,V,z){if(P.length===0||P.every((Q)=>!Q.available))return V;return Array.from({length:P.length},(Q,te)=>te+1).map((Q)=>(V+Q*z+P.length)%P.length).find((Q)=>Rl(P[Q]))}function Wf(P,V,z){if(z.ctrl&&z.name==="c")return"interrupt";if(z.name==="escape"||V==="q")return"abort";if(P==="install"&&(V==="u"||V==="U"))return"update";if(z.name==="up"||V==="k")return"up";if(z.name==="down"||V==="j")return"down";if(z.name==="space"||V===" ")return"toggle";if(z.name==="return"||z.name==="enter")return"confirm";return null}function Kf(P){return{cursor:P.findIndex((V)=>V.available),selected:[]}}function Yf(P,V,z){if(z==="confirm"||z==="update"||z==="abort"||z==="interrupt")return{state:P,done:z};if(z==="up")return{state:{...P,cursor:Cl(V,P.cursor,-1)}};if(z==="down")return{state:{...P,cursor:Cl(V,P.cursor,1)}};let Q=V[P.cursor];if(!Rl(Q))return{state:P};let te=P.selected.includes(Q.target)?P.selected.filter((ne)=>ne!==Q.target):Jf(V,[...P.selected,Q.target]);return{state:{...P,selected:te}}}var Pl="◉",El="◯",Dl=">",Al=" ";function Zf(P,V,z,Q={}){let te=Q.color!==!1,ne=te?dt.dim:(he)=>he,ce=te?dt.green:(he)=>he,ye=te?dt.bold:(he)=>he;return["",`${qf(P)} CC Safety Net ${zf(P)}:`,"",...V.map((he,be)=>{let Le=z.selected.includes(he.target),Ie=be===z.cursor,Xe=Le?Pl:El,et=Ie?Dl:Al,xe=he.available?"":` (${he.unavailableReason??"not installed"})`,at=`${Xe} ${he.label}${xe}`,ct=!he.available?ne(at):Le?ce(at):Ie?ye(at):at;return`${et} ${ct}`}),"",P==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":V.some((he)=>he.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${P}. q/Esc: close`].join(`
216
+ `))}function xl(){console.log(wl)}function Mn(P,V=console.log){let z=er(P);if(!z)return!1;if(z.name.toLowerCase()!==P.toLowerCase())return!1;return wn(z,V),!0}import{existsSync as mi,readFileSync as bc}from"node:fs";import{join as pi}from"node:path";import*as Kt from"node:readline";function qf(P){return P==="install"?"Install":"Uninstall"}function Vf(P){return P==="install"?"Installing":"Uninstalling"}function zf(P){return P==="install"?"into":"from"}function Rl(P){return P?.available===!0}function Jf(P,V){let z=new Set(V);return P.filter((Q)=>z.has(Q.target)).map((Q)=>Q.target)}function Cl(P,V,z){if(P.length===0||P.every((Q)=>!Q.available))return V;return Array.from({length:P.length},(Q,te)=>te+1).map((Q)=>(V+Q*z+P.length)%P.length).find((Q)=>Rl(P[Q]))}function Wf(P,V,z){if(z.ctrl&&z.name==="c")return"interrupt";if(z.name==="escape"||V==="q")return"abort";if(P==="install"&&(V==="u"||V==="U"))return"update";if(z.name==="up"||V==="k")return"up";if(z.name==="down"||V==="j")return"down";if(z.name==="space"||V===" ")return"toggle";if(z.name==="return"||z.name==="enter")return"confirm";return null}function Kf(P){return{cursor:P.findIndex((V)=>V.available),selected:[]}}function Yf(P,V,z){if(z==="confirm"||z==="update"||z==="abort"||z==="interrupt")return{state:P,done:z};if(z==="up")return{state:{...P,cursor:Cl(V,P.cursor,-1)}};if(z==="down")return{state:{...P,cursor:Cl(V,P.cursor,1)}};let Q=V[P.cursor];if(!Rl(Q))return{state:P};let te=P.selected.includes(Q.target)?P.selected.filter((ne)=>ne!==Q.target):Jf(V,[...P.selected,Q.target]);return{state:{...P,selected:te}}}var Pl="◉",El="◯",Dl=">",Al=" ";function Zf(P,V,z,Q={}){let te=Q.color!==!1,ne=te?dt.dim:(he)=>he,ce=te?dt.green:(he)=>he,ye=te?dt.bold:(he)=>he;return["",`${qf(P)} CC Safety Net ${zf(P)}:`,"",...V.map((he,be)=>{let xe=z.selected.includes(he.target),Ie=be===z.cursor,Xe=xe?Pl:El,et=Ie?Dl:Al,Re=he.available?"":` (${he.unavailableReason??"not installed"})`,at=`${Xe} ${he.label}${Re}`,ct=!he.available?ne(at):xe?ce(at):Ie?ye(at):at;return`${et} ${ct}`}),"",P==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":V.some((he)=>he.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${P}. q/Esc: close`].join(`
217
217
  `)}var Sl=["global-hook","plugin"];function Xf(P,V,z={}){let Q=z.color!==!1?dt.bold:(ne)=>ne;return["","Install the Kimi Code integration as:","",...[`Global hook — ${V?"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((ne,ce)=>{let ye=ce===P,he=`${ye?Pl:El} ${ne}`;return`${ye?Dl:Al} ${ye?Q(he):he}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
218
218
  `)}function _l(P){let{input:V,output:z}=P;Kt.emitKeypressEvents(V);let Q=V.isRaw===!0;V.setRawMode(!0),V.resume();let te=0,ne=()=>{if(te===0)return;Kt.moveCursor(z,0,-te),Kt.cursorTo(z,0),Kt.clearScreenDown(z)},ce=()=>{ne();let ye=P.render();z.write(`${ye}
219
219
  `),te=ye.split(`
220
- `).length};return new Promise((ye)=>{let he=(Le)=>{V.off("keypress",be),V.setRawMode(Q),V.pause(),ne(),ye(Le)};function be(Le,Ie){P.onKey(Le,Ie,{finish:he,draw:ce})}V.on("keypress",be),ce()})}function Tl(P={}){let V=0;return _l({input:P.input??process.stdin,output:P.output??process.stdout,render:()=>Xf(V,P.globalHookInstalled===!0),onKey:(z,Q,te)=>{if(Q.ctrl&&Q.name==="c"){te.finish(null),(P.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(Q.name==="escape"||z==="q")return te.finish(null);if(Q.name==="return"||Q.name==="enter")return te.finish(Sl[V]);if(Q.name==="up"||Q.name==="down"||z==="k"||z==="j")V=(V+1)%Sl.length,te.draw()}})}function ni(P=process.stdin,V=process.stdout){return Boolean(P.isTTY&&V.isTTY&&typeof P.setRawMode==="function")}function $l(P,V,z={}){let Q=z.output??process.stdout,te=Kf(V);return _l({input:z.input??process.stdin,output:Q,render:()=>Zf(P,V,te),onKey:(ne,ce,ye)=>{let he=Wf(P,ne,ce);if(!he)return;let be=Yf(te,V,he);if(te=be.state,be.done==="interrupt"){ye.finish(null),(z.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(be.done==="abort")return ye.finish(null);if(be.done==="update")return ye.finish("update");if(be.done==="confirm"){if(te.selected.length===0){Q.write("\x07"),ye.draw();return}ye.finish([...te.selected]),Q.write(`${Vf(P)} selected integrations...
220
+ `).length};return new Promise((ye)=>{let he=(xe)=>{V.off("keypress",be),V.setRawMode(Q),V.pause(),ne(),ye(xe)};function be(xe,Ie){P.onKey(xe,Ie,{finish:he,draw:ce})}V.on("keypress",be),ce()})}function Tl(P={}){let V=0;return _l({input:P.input??process.stdin,output:P.output??process.stdout,render:()=>Xf(V,P.globalHookInstalled===!0),onKey:(z,Q,te)=>{if(Q.ctrl&&Q.name==="c"){te.finish(null),(P.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(Q.name==="escape"||z==="q")return te.finish(null);if(Q.name==="return"||Q.name==="enter")return te.finish(Sl[V]);if(Q.name==="up"||Q.name==="down"||z==="k"||z==="j")V=(V+1)%Sl.length,te.draw()}})}function ni(P=process.stdin,V=process.stdout){return Boolean(P.isTTY&&V.isTTY&&typeof P.setRawMode==="function")}function $l(P,V,z={}){let Q=z.output??process.stdout,te=Kf(V);return _l({input:z.input??process.stdin,output:Q,render:()=>Zf(P,V,te),onKey:(ne,ce,ye)=>{let he=Wf(P,ne,ce);if(!he)return;let be=Yf(te,V,he);if(te=be.state,be.done==="interrupt"){ye.finish(null),(z.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(be.done==="abort")return ye.finish(null);if(be.done==="update")return ye.finish("update");if(be.done==="confirm"){if(te.selected.length===0){Q.write("\x07"),ye.draw();return}ye.finish([...te.selected]),Q.write(`${Vf(P)} selected integrations...
221
221
  `);return}ye.draw()}})}import{existsSync as Il,lstatSync as em,mkdirSync as tm,mkdtempSync as nm,readdirSync as rm,readFileSync as xn,rmSync as Tr}from"node:fs";import{basename as om,dirname as im,join as Et}from"node:path";import{fileURLToPath as sm}from"node:url";var ri="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",on="cc-safety-net",sn="cc-safety-net/index.ts";import{spawn as Qf}from"node:child_process";var oi=(P,V)=>{let z=Xt([...P],process.env);return new Promise((Q)=>{let te=Qf(z.cmd,z.args,{cwd:V,stdio:["ignore","pipe","pipe"]}),ne=Io(te),ce=!1,ye=setTimeout(()=>{ce=!0,te.kill()},120000);te.on("error",(he)=>{clearTimeout(ye),Q({status:null,errorCode:he.code,stdout:ne.stdout,stderr:[he.message,ne.stderr].filter(Boolean).join(`
222
222
  `)})}),te.on("close",(he)=>{clearTimeout(ye),Q({status:ce?null:he,errorCode:ce?"ETIMEDOUT":void 0,stdout:ne.stdout,stderr:ne.stderr})})})};var kn="cc-safety-net.ts",ii=Et("amp",sn);function am(P){return Et(P.home,".config","amp","plugins","cc-safety-net.ts")}function lm(){let P=im(sm(import.meta.url));return[Et(P,ii),Et(P,"..",ii),Et(P,"..","..","..","dist",ii)]}function cm(P=lm()){let V=P.find((z)=>Il(z)&&em(z).isFile());if(!V)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return V}function Ol(P){try{return JSON.parse(P)}catch{return}}function $r(P){return P.subarray(0,Buffer.byteLength(ri)).toString("utf-8")===ri}async function Hn(P,V,z){let Q=await P(V,z);if(Q.status===0)return Q;throw Error([`Failed to run ${V.join(" ")}${Q.status===null?"":` (exit ${Q.status})`}.`,[Q.stdout,Q.stderr].filter(Boolean).join(`
223
223
  `).trim()].filter(Boolean).join(`
@@ -251,7 +251,7 @@ Removing the plugin files anyway; ${Tt} may still be listed in the Hermes config
251
251
  `)}function vc(P,V){return V.map((z)=>P==="install"&&z.target==="kimi-code"&&z.unavailableReason==="already installed"?{...z,available:!0,unavailableReason:void 0,label:`${z.label} (global hook installed)`}:z)}function Wm(P,V){if(P.selectKimiInstallMethod)return P.selectKimiInstallMethod();if(!ni(P.input,P.output))return Promise.resolve("global-hook");return Tl({input:P.input,output:P.output,globalHookInstalled:In({environment:V,cwd:process.cwd()}).status==="configured"})}async function Rc(P,V,z,Q=!1,te){let ne=qm[V];if(P==="install")ne?.beforeInstall?.(z,Q);if(P==="uninstall")ne?.beforeUninstall?.(z);if(Vm(V))return Gm(P,V,z,Q);if(zm(V))return Bm(P,V,z,Q);if(P==="uninstall")return V==="opencode"?Um(z):Hm(V);return[await Mm(V,z,Q,te),await ne?.afterInstall?.(z)].filter(Boolean).join(`
252
252
  `)}function Km(P){let V=xt({label:"update"},P).errors[0];if(V)throw Error(V)}async function Ym(P,V=mn){let z=await xc(P,V),Q=pi(Dn(P),"installed-plugins");return{targets:li([...z.hooks.filter((ne)=>ne.platform!=="copilot-cli"&&ne.detected).map((ne)=>ne.platform),...[mr,ea,Qs].flatMap((ne)=>mi(pi(Q,...ne))?["copilot-cli"]:[]),...pr(P,fi)?["claude-code"]:[],...gi(z.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:z.codexPluginListOutput}}async function Zm(P){let V=c(),z=P.output??process.stdout,Q=(P.scriptPath??process.argv[1]??"").split(/[\\/]/),te=Q.find((et)=>/^bunx-\d+-/.test(et)),ne=te!==void 0||Q.includes("_npx")?null:(P.checkLatestVersion??Wt)(),ce=async()=>{let et=ne&&await ne;if(et?.updateAvailable)z.write(`
253
253
  Update available: cc-safety-net ${et.currentVersion} → ${et.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
254
- `)},ye=Ym(V,P.fetchVersion??mn).then(async(et)=>{let xe=new Set(et.targets);return{targets:et.targets,codexPluginListOutput:et.codexPluginListOutput,available:new Map(await Promise.all(Mt.filter((at)=>xe.has(at.target)&&mc.has(at.target)).map(async(at)=>[at.target,await ci(at.probeCommand)])))}}),he=await Pn(P.showBanner??!0,()=>({ready:ye,finish:()=>ye}),()=>Rn({input:P.input??process.stdin,output:z}),{loadingMessage:"Checking installed integrations…",output:z}),be=await Promise.resolve().then(()=>(Yl(V.tmpdir,process.platform,te),null)).catch((et)=>Gn(et));if(he.targets.length===0){if(z.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),be!==null)console.error(be);return await ce(),be===null?0:1}let Le=he.targets.some((et)=>gc.has(et))?await Promise.resolve().then(()=>(Fr(V),null)).catch((et)=>Gn(et)):null,Ie=await cr(Promise.all(he.targets.map((et)=>{if(mc.has(et)&&!he.available.get(et))return Promise.resolve({message:`${bt(et)} not found; skipped`,failed:!1});if(Le!==null&&gc.has(et))return Promise.resolve({message:Le,failed:!0});return Rc("install",et,V,!0,he.codexPluginListOutput).then((xe)=>({message:xe,failed:!1}),(xe)=>({message:Gn(xe),failed:!0}))})),{loadingMessage:`Updating ${he.targets.length} integration${he.targets.length===1?"":"s"}…`,output:z}),Xe=be===null?Ie:[...Ie,{message:be,failed:!0}];return Xe.forEach((et)=>{et.failed?console.error(et.message):z.write(`${et.message}
254
+ `)},ye=Ym(V,P.fetchVersion??mn).then(async(et)=>{let Re=new Set(et.targets);return{targets:et.targets,codexPluginListOutput:et.codexPluginListOutput,available:new Map(await Promise.all(Mt.filter((at)=>Re.has(at.target)&&mc.has(at.target)).map(async(at)=>[at.target,await ci(at.probeCommand)])))}}),he=await Pn(P.showBanner??!0,()=>({ready:ye,finish:()=>ye}),()=>Rn({input:P.input??process.stdin,output:z}),{loadingMessage:"Checking installed integrations…",output:z}),be=await Promise.resolve().then(()=>(Yl(V.tmpdir,process.platform,te),null)).catch((et)=>Gn(et));if(he.targets.length===0){if(z.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),be!==null)console.error(be);return await ce(),be===null?0:1}let xe=he.targets.some((et)=>gc.has(et))?await Promise.resolve().then(()=>(Fr(V),null)).catch((et)=>Gn(et)):null,Ie=await cr(Promise.all(he.targets.map((et)=>{if(mc.has(et)&&!he.available.get(et))return Promise.resolve({message:`${bt(et)} not found; skipped`,failed:!1});if(xe!==null&&gc.has(et))return Promise.resolve({message:xe,failed:!0});return Rc("install",et,V,!0,he.codexPluginListOutput).then((Re)=>({message:Re,failed:!1}),(Re)=>({message:Gn(Re),failed:!0}))})),{loadingMessage:`Updating ${he.targets.length} integration${he.targets.length===1?"":"s"}…`,output:z}),Xe=be===null?Ie:[...Ie,{message:be,failed:!0}];return Xe.forEach((et)=>{et.failed?console.error(et.message):z.write(`${et.message}
255
255
  `)}),await ce(),Xe.some((et)=>et.failed)?1:0}function yi(P,V={}){return Promise.resolve().then(()=>Km(P)).then(()=>Zm(V)).catch((z)=>(console.error(Gn(z)),1))}async function Bn(P,V,z={}){try{let Q=c(),te=await Pn(!0,()=>Nm(Q,P,V,z),()=>Rn({input:z.input??process.stdin,output:z.output??process.stdout}),{loadingMessage:P==="install"?"Checking available integrations…":"Checking installed integrations…",output:z.output??process.stdout});if(!te)return(z.output??process.stdout).write(`Cancelled: nothing was ${P}ed.
256
256
  `),0;if(te==="update")return(z.runUpdate??(()=>yi([],{fetchVersion:z.fetchVersion,input:z.input,output:z.output,showBanner:!1})))();let ne=z.output??process.stdout;return await Zl(te,async(ce)=>{if(ce==="kimi-code"&&P==="install"){let he=await Wm(z,Q);if(he===null){ne.write(`Cancelled: Kimi Code integration was not installed.
257
257
  `);return}if(he==="plugin"){ne.write(`${Jm(Q)}
@@ -260,19 +260,19 @@ Update available: cc-safety-net ${et.currentVersion} → ${et.latestVersion}. Up
260
260
  Check file permissions for the target config file and parent directory.`;if(z==="ENOENT")return`${V}
261
261
  Check that the target config path and parent directory exist.`;if(z==="ENOTDIR")return`${V}
262
262
  Check that every parent path component is a directory.`;return V}import{mkdirSync as rg}from"node:fs";import{dirname as og}from"node:path";import{createInterface as ig}from"node:readline";import{existsSync as Ec,readFileSync as Xm}from"node:fs";function cn(P,V){let z=Ye(P,V);return{policy:z.policy,errors:ie(qe(z.issues,Je,(Q)=>Q.kind==="custom")," "," ")}}function qn(P,V){return cn(P,V).errors}function Pc(P,V){return{"safety.level":P.safety.level,...hi("safety.overrides",P.safety.overrides),"workflow.worktree_mode":String(P.workflow.worktree_mode),"destructive_command_protection.enabled":String(P.destructive_command_protection.enabled),...hi("destructive_command_protection.overrides",P.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":vi(P.destructive_command_protection.allow_paths),"secret_protection.enabled":String(P.secret_protection.enabled),...hi("secret_protection.overrides",P.secret_protection.overrides),"secret_protection.deny_paths":vi(P.secret_protection.deny_paths),"secret_protection.allow_paths":vi(P.secret_protection.allow_paths),...V?{"audit.retention_days":String(P.audit.retention_days)}:{}}}function jr(P,V,z){let Q=Pc(P,z),te=Pc(V,z);return[...new Set([...Object.keys(Q),...Object.keys(te)])].flatMap((ne)=>Q[ne]===te[ne]?[]:[{field:ne,before:Q[ne],after:te[ne]}])}function Vn(P,V){let z=u(P,V);if(!Ec(z))return{baseline:C(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,P.home),diagnostics:[]};let Q=dn(z),te=cn(Q.value,P.home);return{baseline:te.policy,diagnostics:Q.errors.length>0?Q.errors:te.errors}}function dn(P){if(!Ec(P))return{errors:[`${P}: file not found`]};try{return{value:JSON.parse(Xm(P,"utf-8")),errors:[]}}catch(V){let z=V instanceof Error?V.message:String(V);return{errors:[`${P}: ${V instanceof SyntaxError?`Invalid JSON: ${z}`:z}`]}}}function Nr(P,V){let z=Qm(P)?P:{};return{version:V.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((Q)=>z[Q]!==void 0).map((Q)=>[Q,z[Q]]))}}function hi(P,V){return Object.fromEntries(Object.entries(V).flatMap(([z,Q])=>Q===void 0?[]:[[`${P}.${z}`,String(Q)]]))}function vi(P){return P.length===0?"(none)":P.join(", ")}function Qm(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{chmodSync as eg,existsSync as Dc,mkdirSync as tg,readFileSync as Ac}from"node:fs";import{dirname as ng}from"node:path";function _c(P,V={}){let z=u(P,V);if(!Dc(z))return{path:z,exists:!1,raw:"",policy:H(),errors:[]};let Q=Ac(z,"utf-8");if(!Q.trim())return{path:z,exists:!0,raw:Q,policy:H(),errors:["Config file is empty"]};try{let te=cn(JSON.parse(Q),P.home);return{path:z,exists:!0,raw:Q,policy:te.policy,errors:te.errors}}catch(te){return{path:z,exists:!0,raw:Q,policy:H(),errors:[`Invalid JSON: ${te instanceof Error?te.message:String(te)}`]}}}function Vt(P,V,z={}){let Q=u(P,z),te=cn(V,P.home);if(te.errors.length>0)return{path:Q,policy:H(),errors:te.errors};let ne=te.policy;return tg(ng(Q),{recursive:!0,mode:448}),g(re(Q),`${JSON.stringify(ne,null,2)}
263
- `,384),eg(Q,384),{path:Q,policy:ne,errors:[]}}function Tc(P,V){let z=cn(V,P.home);if(z.errors.length>0)return{errors:z.errors};return{preview:Ae(z.policy,P.env),errors:[]}}function $c(P,V={}){let z=u(P,V);if(!Dc(z))return Vt(P,Z,V);let Q=Ac(z,"utf-8");if(!Q.trim())return Vt(P,Z,V);try{return Vt(P,C(JSON.parse(Q),P.home),V)}catch{return Vt(P,Z,V)}}var Ic=new Set(["check","apply"]),Oc="(unset)";async function jc(P,V,z={}){let Q=xt({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},V),te=Q.positionals[0],ne=[...Q.errors,...te&&!Ic.has(te)?[`Unknown policy subcommand: ${te}`]:[],...te&&Ic.has(te)&&!Q.positionals[1]?[`policy ${te} requires a file`]:[],...Q.positionals.slice(2).map((xe)=>`Unexpected policy argument: ${xe}`)];if(ne.length>0){for(let xe of ne)console.error(xe);return 1}let ce=Q.positionals[1];if(!te||!ce)return wn(Xn,console.error),1;let ye=Q.flags.global?u(P):b(z.cwd??process.cwd()),he=dn(ce),be=[...he.errors,...qn(he.value,P.home).map((xe)=>`${ce}: ${xe}`),...!Q.flags.global&&lg(he.value)&&he.value.audit!==void 0?[`${ce}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(be.length>0){for(let xe of be)console.error(xe);return 1}let Le=C(he.value,P.home);if(console.log(`Scope: ${Q.flags.global?"user":"project"} (${ye})`),console.log(`Proposal: ${ce}`),Q.flags.global)Fc(C(dn(ye).value,P.home),Le,!0);if(!Q.flags.global){let xe=Vn(P).baseline;console.log("Effective policy (user + project merged):"),Fc(Y(xe,ae(dn(ye).value,P.home).policy).policy,Y(xe,ae(he.value,P.home).policy).policy,!1)}if(te==="check")return 0;let Ie=z.input??process.stdin,Xe=z.output??process.stdout;if(!Ie.isTTY||!Xe.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${ce}${Q.flags.global?" --global":""}`),1;if(!await sg(`Apply this policy to ${ye}? [y/N] `,Ie,Xe))return console.log("Cancelled; nothing was written."),0;return ag(P,ye,he.value,Le,Q.flags.global),console.log(`Policy applied: ${ye}`),0}function sg(P,V,z){let Q=ig({input:V,output:z,terminal:!1});return new Promise((te)=>{Q.once("close",()=>te(!1)),Q.question(P,(ne)=>{te(/^y(es)?$/i.test(ne.trim())),Q.close()})})}function ag(P,V,z,Q,te){if(te){Vt(P,Q);return}rg(og(V),{recursive:!0}),Rt(V,Nr(z,Q))}function Fc(P,V,z){let Q=jr(P,V,z);if(Q.length===0){console.log("No changes.");return}console.log(`Changes (${Q.length}):`);for(let te of Q)console.log(` ${te.field}: ${te.before??Oc} -> ${te.after??Oc}`)}function lg(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{join as wy}from"node:path";var Nc="# 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 Mr(P,V){if(!P.ok){Bc(P);return}Uc(P,V)}function Hc(P,V,z){if(P.ok)console.log(z);if(!P.add){Mr(P,`Added rulebook source: ${V}`);return}if(!P.ok){Bc(P);return}if(P.add.added.length>0)console.log(`Added ${P.add.added.length} ${P.add.added.length===1?"rulebook":"rulebooks"} from ${P.add.source} at ${P.add.ref}:`),P.add.added.forEach((Q)=>{console.log(` - ${Q}`)});if(P.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${P.add.source} at ${P.add.ref}: ${P.add.alreadyConfigured.join(", ")}`);if(P.add.commits.length>0)console.log(`Vendored at ${P.add.commits.map((Q)=>Q.slice(0,7)).join(", ")}.`);Uc(P,"Rule config updated.")}function Uc(P,V){for(let z of P.changes??[])console.log(z);console.log(V),console.log(""),cg(P.entries)}function cg(P){if(P.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${P.length}):`);for(let V of P)console.log(` - ${V.name} ${V.version} (${dg(V.ruleCount)})`),console.log(` Source: ${V.spec}`)}function dg(P){return`${P} ${P===1?"rule":"rules"}`}function Gc(P){un("Active sources",P.rulebooks,(V)=>[`[${V.source}] ${V.name} ${V.version}`,` Source: ${V.spec}`]),un("Active rules",P.rules,(V)=>[`[${pg(P,V.name)}] ${V.name}`,...ug(V),` Reason: ${V.reason}`]),un("Disabled rules",Mc(P,"off"),(V)=>[V.key]),un("Reason overrides",Mc(P,"reason"),(V)=>[V.key,` Reason: ${V.value.reason}`]),un("Transparent wrappers",P.transparent_wrappers,(V)=>[V]),un("Issues",P.errors,(V)=>[V]),un("Warnings",P.warnings,(V)=>[V])}function un(P,V,z){if(V.length===0){console.log(`${P}: (none)`);return}console.log(`${P} (${V.length}):`);for(let Q of V){let[te,...ne]=z(Q);console.log(` - ${te}`);for(let ce of ne)console.log(` ${ce}`)}}function ug(P){if(!P.match)return[` Command: ${P.subcommand?`${P.command} ${P.subcommand}`:P.command}`,` Block args: ${P.block_args.join(", ")}`];return[` Command: ${[P.command,...P.match.command_path].join(" ")}`,...P.match.any_args?[` Any args: ${P.match.any_args.join(", ")}`]:[],...P.match.exclude_args?[` Exclude args: ${P.match.exclude_args.join(", ")}`]:[]]}function pg(P,V){return P.rulebooks.find((z)=>z.rules.includes(V))?.source??"project"}function Mc(P,V){return Object.entries({...P.userConfig?.overrides??{},...P.projectConfig?.overrides??{}}).filter((z)=>{if(V==="off")return z[1]==="off";return!!z[1]&&typeof z[1]==="object"}).map(([z,Q])=>({key:z,value:Q}))}function Bc(P){for(let V of P.errors)console.error(V)}import{dirname as pd,join as Jr}from"node:path";import{join as xi,resolve as Cg}from"node:path";function bi(P){let V=m(P);if(V.errors.length>0)return{ok:!1,result:{ok:!1,errors:V.errors,entries:[]}};return{ok:!0,config:V.config??it}}function qc(P){Rt(P,{version:1,rules:[],overrides:{},transparent_wrappers:[]})}function Vc(P){Rt(P,{rulebook_version:1,name:"example-rules",version:"1.0.0",description:"Project-specific CC Safety Net rules.",author:"project",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as Br}from"node:path";var fg="custom.";function Hr(P){if(P.rulebook_version!==2)return[];let V=P.rules.map((z)=>({name:z.name,command:z.command,block_args:[],match:z.match,reason:z.reason,intent:z.intent}));return(P.tests??[]).flatMap((z,Q)=>{let te=Li(h(z.command));if(te.length===0)return[`tests[${Q}]: could not parse fixture command: ${z.command}`];let ne=te.reduce((ce,ye)=>ce??_(ye,V)?.id.slice(fg.length),void 0);if(z.expect==="blocked"){if(ne===z.rule)return[];let ce=ne?`"${ne}" matched first`:"no rule matched";return[`tests[${Q}]: expected "${z.rule}" to block "${z.command}" but ${ce}`]}return ne?[`tests[${Q}]: expected "${z.command}" to be allowed but "${ne}" matched`]:[]})}function Li(P){return P.nodes.flatMap((V)=>{if(V.kind==="group"||V.kind==="function")return Li(V.body);if(V.kind!=="command")return[];let z=ge(X(V.dialect,V.words)).words.map(t);return[...z.length>0?[z]:[],...V.nested.flatMap((Q)=>Li(Q))]})}var Ur=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function Gr(P={}){return{requests:0,responseBytes:0,maxRequests:P.maxRequests??Ur.maxRequests,maxResponseBytes:P.maxResponseBytes??Ur.maxResponseBytes}}function zt(P){return{controller:new AbortController,budget:Gr(),resolveUrl:P}}function zc(P){return P instanceof Error&&P.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function Jc(P){if(P.requests>=P.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.requests++}function Wc(P,V){if(V>P.maxResponseBytes-P.responseBytes)throw P.responseBytes+=V,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.responseBytes+=V}var Zc=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function Kc(P,V,z=v(Br(Br(V)),"rules policy"),Q=zt()){if(S(P))return hg(P,Q);return yg(P,V,z)}async function Xc(P,V,z,Q,te,ne){if(!S(P))return Kc(P,V,z,Q);let ce=te?null:mg(P,V,z);if(ce)return ce;if(!te&&!ne)throw Error(`${P} is not vendored; run rule update ${P} to vendor it`);return Kc(P,V,z,Q)}function mg(P,V,z=v(Br(Br(V)),"rules policy")){let Q=A(P),te=I(V,Q.name),ne=n(i(z,te));if(ne===null)return null;let ce=se(wi(ne,`Invalid rulebook ${te}.`));if(ce.name!==Q.name)throw Error(`rulebook name "${ce.name}" in ${te} must match "${Q.name}"`);return{spec:P,rulebook:ce,content:ne}}async function Qc(P,V={}){if(!q(P))throw Error(`Invalid GitHub repository source: ${P}`);let[z,Q]=P.split("/");if(!z||!Q)throw Error(`Invalid GitHub repository source: ${P}`);if(V.ref!==void 0&&!oe(V.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${V.ref}`);let te=V.operation??zt(),ne=V.ref??await gg(z,Q,P,te),ce=await td(z,Q,ne,P,te),ye=await qr(`https://api.github.com/repos/${z}/${Q}/git/trees/${ce}?recursive=1`,"tree",te),he=ye.response;if(!he.ok)throw Error(`Failed to inspect ${P}: GitHub tree returned ${he.status}`);let be=JSON.parse(ye.content);if(!Array.isArray(be?.tree))throw Error(`Failed to inspect ${P}: unexpected GitHub tree response`);let Le=be.tree,Ie=[...new Set(Le.flatMap((Xe)=>{if(!Xe||typeof Xe!=="object")return[];let et=Xe;if(et.type!=="blob"||typeof et.path!=="string")return[];let xe=et.path.match(rt);return xe?.[1]?[xe[1]]:[]}))].sort();if(Ie.length===0)throw Error(`No rulebooks found in ${P} under ${de}/`);return{source:P,owner:z,repo:Q,ref:ne,commit:ce,names:Ie}}async function gg(P,V,z,Q){let te=await qr(`https://api.github.com/repos/${P}/${V}`,"metadata",Q),ne=te.response;if(!ne.ok)throw Error(`Failed to inspect ${z}: GitHub returned ${ne.status}`);let ye=JSON.parse(te.content)?.default_branch;if(typeof ye!=="string"||ye==="")throw Error(`Failed to inspect ${z}: missing default branch`);if(!oe(ye))throw Error(`GitHub returned an invalid default branch: ${ye}`);return ye}function yg(P,V,z){ot(P);let Q=I(V,P),te=n(i(z,Q));if(te===null)throw Error(`Rulebook source not found: ${P}`);let ne=ed(wi(te,"Invalid local rulebook source."));if(ne.name!==P)throw Error(`rulebook name "${ne.name}" must match local source "${P}"`);return{spec:P,rulebook:ne,content:te}}async function hg(P,V){let z=A(P),Q=await td(z.owner,z.repo,z.ref,P,V),te=await qr(`https://raw.githubusercontent.com/${z.owner}/${z.repo}/${Q}/${z.path}`,"raw",V),ne=te.response;if(!ne.ok)throw Error(`Failed to fetch ${P}: GitHub raw returned ${ne.status}`);let ce=te.content,ye=ed(wi(ce,"Invalid GitHub rulebook response."));if(ye.name!==z.name)throw Error(`rulebook name "${ye.name}" must match GitHub source "${z.name}"`);return{spec:P,rulebook:ye,content:ce}}function ed(P){let V=se(P),z=Hr(V);if(z.length>0)throw Error(z.join("; "));return V}function wi(P,V){try{return JSON.parse(P)}catch{throw Error(V)}}async function td(P,V,z,Q,te){let ne=await qr(`https://api.github.com/repos/${P}/${V}/commits/${encodeURIComponent(z)}`,"commit",te),ce=ne.response;if(!ce.ok)throw Error(`Failed to resolve ${Q}: GitHub returned ${ce.status}`);let ye=JSON.parse(ne.content);if(typeof ye?.sha!=="string"||ye.sha==="")throw Error(`Failed to resolve commit for ${Q}`);return ye.sha}async function vg(P,V,z={}){if(z.signal?.aborted)throw z.signal.reason;let Q=z.budget??Gr(),te=new AbortController,ne=()=>te.abort(z.signal?.reason);z.signal?.addEventListener("abort",ne,{once:!0});let ce=!1,ye=setTimeout(()=>{if(te.signal.aborted)return;ce=!0,te.abort()},z.timeoutMs??Zc.timeoutMs);try{if(z.signal?.aborted)throw z.signal.reason;Jc(Q);let he=await fetch(P,{signal:te.signal,redirect:"error"});if(!he.ok)return nd(he),{response:he,content:""};return{response:he,content:await bg(he,V,Q,()=>te.abort())}}catch(he){if(ce)throw Error("GitHub request timed out",{cause:he});if(z.signal?.aborted)throw z.signal.reason;throw he}finally{clearTimeout(ye),z.signal?.removeEventListener("abort",ne)}}function qr(P,V,z){return vg(z.resolveUrl?.(P)??P,V,{budget:z.budget,signal:z.controller.signal})}async function bg(P,V,z=Gr(),Q){let te=Zc[`${V}Bytes`],ne=Number(P.headers.get("content-length"));if(Number.isFinite(ne)&&ne>te)throw nd(P),Error(`GitHub ${V} response exceeds ${te} bytes`);if(!P.body)return"";let ce=P.body.getReader(),ye=[],he=0;while(!0){let be=await ce.read();if(be.done)break;try{Wc(z,be.value.byteLength)}catch(Le){throw Q?.(),Yc(ce),Le}if(he+=be.value.byteLength,he>te)throw Q?.(),Yc(ce),Error(`GitHub ${V} response exceeds ${te} bytes`);ye.push(Buffer.from(be.value))}return Buffer.concat(ye,he).toString("utf-8")}function nd(P){if(!P.body)return;rd(()=>P.body?.cancel())}function Yc(P){rd(()=>P.cancel())}function rd(P){try{Promise.resolve(P()).catch(()=>{})}catch{}}var Lg=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function od(P,V){let z=ad(P.rules,V);if(z.length>0)return{ok:!0,specs:z};return sd(P.rules,V)}function id(P,V){let z=ad(P,V);if(z.length>0)return{ok:!0,specs:z};let Q=kg(P,V);if(Q.length>0)return{ok:!0,specs:Q};let te=xg(P,V);if(!te.ok)return te;if(te.specs.length>0)return{ok:!0,specs:te.specs};return sd(P,V)}function sd(P,V){let z=P.filter((Q)=>ki(Q)?.name===V);if(z.length===1)return{ok:!0,specs:z};return wg(V,z)}function wg(P,V){return{ok:!1,result:{ok:!1,errors:V.length===0?[`No configured rulebook matches ${P}`]:[`Ambiguous rulebook match ${P}: ${V.join(", ")}`],entries:[]}}}function ad(P,V){return P.filter((z)=>z===V)}function kg(P,V){let z=V.match(Lg),Q=z?.[1],te=z?.[2],ne=z?.[3];if(!Q||!te||!ne||!oe(ne))return[];return ld(P,(ce)=>ce.owner===Q&&ce.repo===te&&ce.ref===ne)}function xg(P,V){if(!q(V))return{ok:!0,specs:[]};let[z,Q]=V.split("/"),te=ld(P,(ce)=>ce.owner===z&&ce.repo===Q);if(new Set(te.map((ce)=>ki(ce)?.ref).filter((ce)=>!!ce)).size<2)return{ok:!0,specs:te};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${V}. Use an explicit ref:`,` cc-safety-net rule remove ${V}#<ref>`],entries:[]}}}function ki(P){try{return A(P)}catch{return null}}function ld(P,V){return P.filter((z)=>{let Q=ki(z);return Q?V(Q):!1})}async function zr(P,V={}){let z=Ci(V);return Sg(P,z,await Vr(P,z,zt()))}function Sg(P,V,z){if(!z.ok)return z;let Q=Pt(P,V),te=[...new Set(j(Q.configPath,Q.filesystemScope))];if(te.length===0)return z;return{ok:!1,errors:te,entries:z.entries}}async function Vr(P,V,z,Q={},te=new Set,ne=new Set){try{let ce=Pt(P,V),ye=bi(ce.configTarget);if(!ye.ok)return ye.result;let he=ye.config,be=V.only?od(he,V.only):{ok:!0,specs:he.rules};if(!be.ok)return be.result;let Le=new Set([...V.refresh?be.specs:[],...te]),Ie=(ut)=>Xc(ut,ce.configDir,ce.filesystemScope,z,Le.has(ut),!V.refresh||Le.has(ut)),Xe=await Fg(he.rules,V.refresh?(ut)=>Ie(ut).then((vt)=>({ok:!0,item:vt})).catch((vt)=>{if(zc(vt))throw vt;return{ok:!1,spec:ut,message:vt instanceof Error?vt.message:String(vt)}}):async(ut)=>({ok:!0,item:await Ie(ut)}),z),et=Xe.filter((ut)=>!ut.ok),xe=Xe.filter((ut)=>ut.ok).map((ut)=>ut.item),at=xe.flatMap((ut)=>Rg(ut,he.rules)),ct=xe.flatMap((ut)=>Pg(ut,ne,ce)),lt=new Set([...at,...ct].map((ut)=>ut.spec)),pt=[...et,...at,...ct],mt=[],gt=Dg(mt,()=>xe.flatMap((ut)=>lt.has(ut.spec)||pt.length>0&&ne.has(ut.spec)?[]:Eg(ut,ce,Q,mt)));return{ok:pt.length===0,errors:pt.map((ut)=>`Failed to update ${ut.spec}: ${ut.message}`),entries:xe.map(_g),changes:gt}}catch(ce){return Jn(ce)}}function Rg(P,V){if(!S(P.spec))return[];let z=Pe(P.spec),Q=V.filter((te)=>te!==P.spec&&Pe(te).toLowerCase()===z.toLowerCase());if(Q.length===0)return[];return[{ok:!1,spec:P.spec,message:`rulebook name "${z}" is also claimed by ${Q.join(", ")}; rename one of them`}]}function Pg(P,V,z){if(!V.has(P.spec)||!S(P.spec))return[];let Q=I(z.configDir,P.rulebook.name),te=n(i(z.filesystemScope,Q));if(te===null||te===P.content)return[];return[{ok:!1,spec:P.spec,message:`${Q} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Eg(P,V,z,Q){if(!S(P.spec))return[];let te=I(V.configDir,P.rulebook.name),ne=i(V.filesystemScope,te),ce=n(ne);if(ce===P.content)return[];return Q?.push({target:ne,previous:ce}),g(ne,P.content,void 0,z._testAfterPolicyRename),Ag(P,ce)}function Dg(P,V){try{return V()}catch(z){for(let Q of[...P].reverse()){if(Q.previous===null){N(Q.target);continue}g(Q.target,Q.previous)}throw z}}function Ag(P,V){if(V===null)return[`Vendored ${P.spec} (${P.rulebook.version})`];let z=me(V),Q="problem"in z?null:z.rulebook,te=new Map(Q?.rules.map((ce)=>[ce.name,JSON.stringify(ce)])??[]),ne=new Set(P.rulebook.rules.map((ce)=>ce.name));return[`Updated ${P.spec} (${Q?.version??"unreadable"} -> ${P.rulebook.version})`,...[...ne].filter((ce)=>!te.has(ce)).map((ce)=>` + ${ce}`),...[...te.keys()].filter((ce)=>!ne.has(ce)).map((ce)=>` - ${ce}`),...P.rulebook.rules.filter((ce)=>{let ye=te.get(ce.name);return ye!==void 0&&ye!==JSON.stringify(ce)}).map((ce)=>` ~ ${ce.name}`)]}function _g(P){return{spec:P.spec,name:P.rulebook.name,version:P.rulebook.version,ruleCount:P.rulebook.rules.length}}async function cd(P,V,z={}){return Tg(P,V,Ng(z),zt())}async function Tg(P,V,z,Q,te={}){let ne=null,ce=!1;try{let ye=Pt(P,z),he=n(ye.configTarget);ne={target:ye.configTarget,content:he};let be=bi(ye.configTarget);if(!be.ok)return be.result;let Le=be.config,Ie=q(V);$g(V,z,Ie);let Xe=Ie?await Qc(V,{ref:z.ref,operation:Q}):null,et=Xe?Ig(Xe,z.rulebooks):[],xe=Xe?et.map((mt)=>Og(Le.rules,Xe,mt)??`${V}#${Xe.ref}/${mt}`):[V],at=xe.filter((mt)=>!Le.rules.includes(mt)),ct=[...Le.rules,...at];if(ct.length>pe)return jg();if(ct.length!==Le.rules.length)ce=!0,Rt(ye.configTarget,{version:1,rules:ct,overrides:Le.overrides??{},transparent_wrappers:Le.transparent_wrappers??[]},void 0,te._testAfterPolicyRename);let lt=await Vr(P,z,Q,te,new Set(at),new Set(at));if(!lt.ok)zn(ye.configTarget,he);if(!lt.ok||!Xe)return lt;let pt=et.filter((mt,gt)=>at.includes(xe[gt]??""));return{...lt,add:{source:V,ref:Xe.ref,selected:et,added:pt,alreadyConfigured:et.filter((mt)=>!pt.includes(mt)),commits:at.length>0?[Xe.commit]:[]}}}catch(ye){if(ce&&ne)try{zn(ne.target,ne.content)}catch(he){return Jn(he)}return Jn(ye)}}function $g(P,V,z){if(!z&&V.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!z&&V.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${P}`);if(V.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let Q=V.rulebooks?.filter((te)=>!l.test(te))??[];if(Q.length>0)throw Error(`Invalid rulebook names: ${Q.join(", ")}`)}function Ig(P,V){let z=V?[...new Set(V)]:P.names,Q=z.filter((te)=>!P.names.includes(te));if(Q.length>0)throw Error(`Rulebooks not found in ${P.source} at ${P.ref}: ${Q.join(", ")}
264
- Available rulebooks: ${P.names.join(", ")}`);return z}function Og(P,V,z){let Q=`${V.source}#${V.ref}/${z}`;if(P.includes(Q))return Q;let te=`${V.source}#${V.commit}/${z}`;return P.find((ne)=>ne===te)}async function Fg(P,V,z=zt()){if(P.length>pe)throw Error(fe);let Q=Array(P.length),te=0,ne,ce=Array.from({length:Math.min(P.length,Ur.concurrency)},async()=>{while(!ne){let ye=te;if(ye>=P.length)return;te++;try{Q[ye]=await V(P[ye],ye,z.controller.signal)}catch(he){if(!ne)ne={value:he},te=P.length,z.controller.abort(he);return}}});if(await Promise.all(ce),ne)throw ne.value;return Q}function jg(){return{ok:!1,errors:[fe],entries:[]}}function Ci(P){return{cwd:P.cwd,userConfigDir:P.userConfigDir,userConfigPath:P.userConfigPath,projectConfigPath:P.projectConfigPath,global:P.global,only:P.only,refresh:P.refresh}}function Ng(P){return{...Ci(P),ref:P.ref,rulebooks:P.rulebooks}}function Mg(P){return{...Ci(P),deleteSource:P.deleteSource}}async function dd(P,V,z={}){try{return await Hg(P,V,Mg(z),{})}catch(Q){return Jn(Q)}}async function Hg(P,V,z,Q){let te=Pt(P,z),ne=m(te.configTarget);if(ne.errors.length>0)return{ok:!1,errors:ne.errors,entries:[]};if(!ne.config)return{ok:!1,errors:[`No config found at ${te.configPath}`],entries:[]};let ce=id(ne.config.rules,V);if(!ce.ok)return ce.result;let ye=z.deleteSource?Ug(te.configDir,ce.specs,te.filesystemScope):{ok:!0,dirs:[]};if(!ye.ok)return ye.result;let he=n(te.configTarget);if(he===null)return Jn(Error("Rules config is unavailable."));try{Rt(te.configTarget,{version:1,rules:ne.config.rules.filter((Ie)=>!ce.specs.includes(Ie)),overrides:ne.config.overrides??{},transparent_wrappers:ne.config.transparent_wrappers??[]},void 0,Q._testAfterPolicyRename)}catch(Ie){throw zn(te.configTarget,he),Ie}let be=await Vr(P,z,zt(),Q);if(!be.ok)return zn(te.configTarget,he),be;let Le=Gg(ye.dirs,Q,te.filesystemScope);if(!Le.ok){zn(te.configTarget,he);let Ie=await Vr(P,z,zt(),Q);if(!Ie.ok)return{ok:!1,errors:[...Le.result.errors,...Ie.errors],entries:Ie.entries};return Le.result}return be}function Ug(P,V,z){let Q=V.flatMap((ye)=>l.test(ye)?[]:["--delete-source can only delete local rulebook sources"]),te=V.map((ye)=>xi(P,ye)),ne=Q.length>0?[]:te.flatMap((ye)=>ud(ye,z)),ce=[...Q,...ne];return ce.length>0?{ok:!1,result:{ok:!1,errors:ce,entries:[]}}:{ok:!0,dirs:te}}function ud(P,V){let z=Cg(P),Q=i(V,z),te=le(Q);if(!te)return[`Local rulebook source directory not found: ${P}`];let ne=te.find((ce)=>ce.name==="rulebook.json");if(!ne)return[`Local rulebook source directory is missing rulebook.json: ${P}`];if(ne.kind!=="file")throw new r(V.label);if(n(i(V,xi(z,"rulebook.json"))),te.length>1)return[`Local rulebook source directory contains extra files: ${P}. delete manually if you really want to remove the directory.`];return[]}function Gg(P,V,z){let Q=P.flatMap((te)=>{try{if(!le(i(z,te)))return[];let ne=ud(te,z);if(ne.length>0)return ne;return Bg(te,V,z),[]}catch(ne){return[`Failed to delete local rulebook source ${te}: ${ne instanceof Error?ne.message:String(ne)}`]}});return Q.length>0?{ok:!1,result:{ok:!1,errors:Q,entries:[]}}:{ok:!0}}function Bg(P,V,z){if(V._testDeleteLocalSourceDir){V._testDeleteLocalSourceDir(P);return}N(i(z,xi(P,ue))),nt(i(z,P))}function zn(P,V){if(V===null){N(P);return}g(P,V)}function Jn(P){return{ok:!1,errors:[P instanceof Error?P.message:String(P)],entries:[]}}var qg=".safety-net.json",Vg="~/.cc-safety-net/config.json";async function gd(P,V){return[await fd(P,{legacyPath:$s({cwd:V.cwd}),configPath:F(V.cwd),defaultRulebookName:"project-rules",migratedFrom:qg,cleanup:V.cleanup,syncOptions:{cwd:V.cwd}}),await fd(P,{legacyPath:nr(P),configPath:M(P),defaultRulebookName:"user-rules",migratedFrom:Vg,cleanup:V.cleanup,syncOptions:{cwd:V.cwd,global:!0}})].every((Q)=>Q)?0:1}async function fd(P,V){let z=Pt(P,V.syncOptions),Q=i(z.filesystemScope,V.legacyPath),te=n(Q);if(te===null)return console.log(`No legacy config found at ${V.legacyPath}`),!0;let ne=Jg(te);if(!ne.ok){for(let et of ne.errors)console.error(et);return!1}let ce=m(z.configTarget);if(ce.errors.length>0){for(let et of ce.errors)console.error(et);return!1}let ye=ce.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},he=Wg(pd(V.configPath),ye.rules,V.defaultRulebookName,V.migratedFrom,z.filesystemScope),be=Jr(pd(V.configPath),he,"rulebook.json"),Le=i(z.filesystemScope,be),Ie=[md(z.configTarget),md(Le)],Xe=await zg(P,V,z.configTarget,Le,he,ne.config.rules,ye.rules.includes(he)?ye.rules:[...ye.rules,he],ye.overrides??{},ye.transparent_wrappers??[]);if(!Xe.ok){Zg(Ie);for(let et of Xe.errors)console.error(et);return!1}if(!V.cleanup)return console.log(`Migrated legacy config at ${V.legacyPath}. Legacy file is no longer used.`),!0;if(!Yg(z.configTarget,Le,he,V.migratedFrom,ne.config.rules))return console.error(`Migration cleanup verification failed for ${V.legacyPath}`),!1;return N(Q),console.log(`Deleted legacy config at ${V.legacyPath}`),!0}async function zg(P,V,z,Q,te,ne,ce,ye,he){try{return Rt(z,{version:1,rules:ce,overrides:ye,transparent_wrappers:he}),Rt(Q,Kg(te,V.migratedFrom,ne)),await zr(P,V.syncOptions)}catch(be){return{ok:!1,errors:[be instanceof Error?be.message:String(be)]}}}function Jg(P){try{let V=JSON.parse(P),z=ro(V);if(z.errors.length>0)return{ok:!1,errors:z.errors};return{ok:!0,config:{version:1,rules:V.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function Wg(P,V,z,Q,te){let ne=V.find((ce)=>Xg(i(te,Jr(P,ce,"rulebook.json")))===Q);if(ne)return ne;if(n(i(te,Jr(P,z,"rulebook.json")))===null)return z;for(let ce=2;;ce++){let ye=`${z}-${ce}`;if(n(i(te,Jr(P,ye,"rulebook.json")))===null)return ye}}function Kg(P,V,z){return{rulebook_version:1,name:P,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:V,allowed_commands:[...new Set(z.map((Q)=>Q.command))],rules:z,tests:z.map((Q)=>({command:[Q.command,Q.subcommand,Q.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:Q.name}))}}function Yg(P,V,z,Q,te){if(!m(P).config?.rules.includes(z))return!1;try{let ce=n(V);if(ce===null)return!1;let ye=JSON.parse(ce);return ye.migrated_from===Q&&JSON.stringify(ye.rules)===JSON.stringify(te)}catch{return!1}}function md(P){return{target:P,content:n(P)}}function Zg(P){for(let V of P){if(V.content===null){N(V.target);continue}g(V.target,V.content)}}function Xg(P){let V=n(P);if(V===null)return null;try{let z=JSON.parse(V);return typeof z.migrated_from==="string"?z.migrated_from:null}catch{return null}}import{mkdir as Qg,readFile as ey,writeFile as ty}from"node:fs/promises";import{dirname as ny,join as ry}from"node:path";var oy=86400000,iy=604800000;async function hd(P,V=Date.now()){if(P.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let z=je(P);if(!z)return null;let Q=ry(z,".cc-safety-net","update-check.json"),te=await sy(Q,V);if(!te.lastCheck||V-te.lastCheck>oy){let ye=await Wt();if(te.lastCheck=V,ye.latestVersion)te.latestVersion=ye.latestVersion;if(!await yd(Q,te))return null;if(ye.error)return null}let ne=te.latestVersion,ce=wt();if(!ne||!co(ne,ce))return null;if(te.notifiedVersion===ne&&te.notifiedAt!==void 0&&V-te.notifiedAt<iy)return null;if(te.notifiedVersion=ne,te.notifiedAt=V,!await yd(Q,te))return null;return`UPDATE_AVAILABLE: cc-safety-net v${ne} is available (running v${ce}). 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 sy(P,V){let z=await ey(P,"utf8").then((ne)=>JSON.parse(ne)).catch(()=>{return});if(!z||typeof z!=="object"||Array.isArray(z))return{};let Q=z,te=(ne)=>typeof ne==="number"&&Number.isFinite(ne)&&ne<=V?ne:void 0;return{lastCheck:te(Q.lastCheck),latestVersion:typeof Q.latestVersion==="string"?Q.latestVersion:void 0,notifiedVersion:typeof Q.notifiedVersion==="string"?Q.notifiedVersion:void 0,notifiedAt:te(Q.notifiedAt)}}async function yd(P,V){return Qg(ny(P),{recursive:!0,mode:448}).then(()=>ty(P,JSON.stringify(V),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as ay,resolve as Si}from"node:path";var vd="CC Safety Net Config",ly="═".repeat(vd.length),cy="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",dy=new Set(["rule.json","rule.lock","cache"]);function bd(P,V={}){try{return uy(P,V)}catch(z){if(z instanceof r)return console.error(z.message),1;throw z}}function uy(P,V){let z=V.cwd??process.cwd(),Q=K(P,{cwd:z}),te=nr(P),ne=ns(z),ce=Si(z,de),ye=i(Q.userScope,te),he=i(Q.projectScope,ne),be=!1,Le=!1,Ie=[],Xe=[],et=py(i(Q.projectScope,ce));if(my(),n(Q.userConfigTarget)!==null){let xe=Jt(Q.userConfigTarget);if(xe.errors.push(...j(Q.userConfigPath,Q.userScope)),Ie.push({scope:"User",path:Q.userConfigPath,result:xe,schema:"rules",target:Q.userConfigTarget}),xe.errors.length>0)be=!0}if(n(ye)!==null)if(Le=!0,n(Q.userConfigTarget)!==null)Xe.push(Wr("user","cleanup"));else{let xe=oo(ye);if(Ie.push({scope:"User",path:te,result:xe,schema:"legacy",inactive:!0,target:ye}),Xe.push(Wr("user",xe.errors.length>0?"fix-or-delete":"migrate")),xe.errors.length>0)be=!0}if(n(Q.projectConfigTarget)!==null){let xe=Jt(Q.projectConfigTarget);if(xe.errors.push(...j(Q.projectConfigPath,Q.projectScope)),Ie.push({scope:"Project",path:Si(Q.projectConfigPath),result:xe,schema:"rules",target:Q.projectConfigTarget}),xe.errors.length>0)be=!0;if(n(he)!==null)Le=!0,Xe.push(Wr("project","cleanup"))}else if(n(he)!==null){Le=!0,be=!0;let xe=oo(he);Ie.push({scope:"Project",path:Si(ne),result:xe,schema:"legacy",inactive:!0,target:he}),Xe.push(Wr("project",xe.errors.length>0?"fix-or-delete":"migrate"))}if(et?.result.errors.length)be=!0;if(Ie.length===0&&!et)return console.log(`
265
- No config files found. Using built-in rules only.`),0;for(let xe of Ie)if(xe.inactive)yy(xe.scope,xe.path,xe.result);else if(xe.result.errors.length>0)hy(xe.scope,xe.path,xe.result.errors);else{if(xe.schema==="rules"&&Ly(xe.target))console.log(`
266
- Added $schema to ${xe.scope.toLowerCase()} config.`);gy(xe.scope,xe.path,xe.result,xe.schema)}for(let xe of Xe)console.error(`
267
- ${dt.red(xe)}`);if(et)if(et.result.errors.length>0)by(et.path,et.result.errors);else vy(et.path,et.result);if(be)return console.error(`
268
- Config validation failed.`),1;return console.log(Le?`
263
+ `,384),eg(Q,384),{path:Q,policy:ne,errors:[]}}function Tc(P,V){let z=cn(V,P.home);if(z.errors.length>0)return{errors:z.errors};return{preview:Ae(z.policy,P.env),errors:[]}}function $c(P,V={}){let z=u(P,V);if(!Dc(z))return Vt(P,Z,V);let Q=Ac(z,"utf-8");if(!Q.trim())return Vt(P,Z,V);try{return Vt(P,C(JSON.parse(Q),P.home),V)}catch{return Vt(P,Z,V)}}var Ic=new Set(["check","apply"]),Oc="(unset)";async function jc(P,V,z={}){let Q=xt({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},V),te=Q.positionals[0],ne=[...Q.errors,...te&&!Ic.has(te)?[`Unknown policy subcommand: ${te}`]:[],...te&&Ic.has(te)&&!Q.positionals[1]?[`policy ${te} requires a file`]:[],...Q.positionals.slice(2).map((Re)=>`Unexpected policy argument: ${Re}`)];if(ne.length>0){for(let Re of ne)console.error(Re);return 1}let ce=Q.positionals[1];if(!te||!ce)return wn(Xn,console.error),1;let ye=Q.flags.global?u(P):b(z.cwd??process.cwd()),he=dn(ce),be=[...he.errors,...qn(he.value,P.home).map((Re)=>`${ce}: ${Re}`),...!Q.flags.global&&lg(he.value)&&he.value.audit!==void 0?[`${ce}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(be.length>0){for(let Re of be)console.error(Re);return 1}let xe=C(he.value,P.home);if(console.log(`Scope: ${Q.flags.global?"user":"project"} (${ye})`),console.log(`Proposal: ${ce}`),Q.flags.global)Fc(C(dn(ye).value,P.home),xe,!0);if(!Q.flags.global){let Re=Vn(P).baseline;console.log("Effective policy (user + project merged):"),Fc(Y(Re,ae(dn(ye).value,P.home).policy).policy,Y(Re,ae(he.value,P.home).policy).policy,!1)}if(te==="check")return 0;let Ie=z.input??process.stdin,Xe=z.output??process.stdout;if(!Ie.isTTY||!Xe.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${ce}${Q.flags.global?" --global":""}`),1;if(!await sg(`Apply this policy to ${ye}? [y/N] `,Ie,Xe))return console.log("Cancelled; nothing was written."),0;return ag(P,ye,he.value,xe,Q.flags.global),console.log(`Policy applied: ${ye}`),0}function sg(P,V,z){let Q=ig({input:V,output:z,terminal:!1});return new Promise((te)=>{Q.once("close",()=>te(!1)),Q.question(P,(ne)=>{te(/^y(es)?$/i.test(ne.trim())),Q.close()})})}function ag(P,V,z,Q,te){if(te){Vt(P,Q);return}rg(og(V),{recursive:!0}),Rt(V,Nr(z,Q))}function Fc(P,V,z){let Q=jr(P,V,z);if(Q.length===0){console.log("No changes.");return}console.log(`Changes (${Q.length}):`);for(let te of Q)console.log(` ${te.field}: ${te.before??Oc} -> ${te.after??Oc}`)}function lg(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{join as wy}from"node:path";var Nc="# 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 Mr(P,V){if(!P.ok){Bc(P);return}Uc(P,V)}function Hc(P,V,z){if(P.ok)console.log(z);if(!P.add){Mr(P,`Added rulebook source: ${V}`);return}if(!P.ok){Bc(P);return}if(P.add.added.length>0)console.log(`Added ${P.add.added.length} ${P.add.added.length===1?"rulebook":"rulebooks"} from ${P.add.source} at ${P.add.ref}:`),P.add.added.forEach((Q)=>{console.log(` - ${Q}`)});if(P.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${P.add.source} at ${P.add.ref}: ${P.add.alreadyConfigured.join(", ")}`);if(P.add.commits.length>0)console.log(`Vendored at ${P.add.commits.map((Q)=>Q.slice(0,7)).join(", ")}.`);Uc(P,"Rule config updated.")}function Uc(P,V){for(let z of P.changes??[])console.log(z);console.log(V),console.log(""),cg(P.entries)}function cg(P){if(P.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${P.length}):`);for(let V of P)console.log(` - ${V.name} ${V.version} (${dg(V.ruleCount)})`),console.log(` Source: ${V.spec}`)}function dg(P){return`${P} ${P===1?"rule":"rules"}`}function Gc(P){un("Active sources",P.rulebooks,(V)=>[`[${V.source}] ${V.name} ${V.version}`,` Source: ${V.spec}`]),un("Active rules",P.rules,(V)=>[`[${pg(P,V.name)}] ${V.name}`,...ug(V),` Reason: ${V.reason}`]),un("Disabled rules",Mc(P,"off"),(V)=>[V.key]),un("Reason overrides",Mc(P,"reason"),(V)=>[V.key,` Reason: ${V.value.reason}`]),un("Transparent wrappers",P.transparent_wrappers,(V)=>[V]),un("Issues",P.errors,(V)=>[V]),un("Warnings",P.warnings,(V)=>[V])}function un(P,V,z){if(V.length===0){console.log(`${P}: (none)`);return}console.log(`${P} (${V.length}):`);for(let Q of V){let[te,...ne]=z(Q);console.log(` - ${te}`);for(let ce of ne)console.log(` ${ce}`)}}function ug(P){if(!P.match)return[` Command: ${P.subcommand?`${P.command} ${P.subcommand}`:P.command}`,` Block args: ${P.block_args.join(", ")}`];return[` Command: ${[P.command,...P.match.command_path].join(" ")}`,...P.match.any_args?[` Any args: ${P.match.any_args.join(", ")}`]:[],...P.match.exclude_args?[` Exclude args: ${P.match.exclude_args.join(", ")}`]:[]]}function pg(P,V){return P.rulebooks.find((z)=>z.rules.includes(V))?.source??"project"}function Mc(P,V){return Object.entries({...P.userConfig?.overrides??{},...P.projectConfig?.overrides??{}}).filter((z)=>{if(V==="off")return z[1]==="off";return!!z[1]&&typeof z[1]==="object"}).map(([z,Q])=>({key:z,value:Q}))}function Bc(P){for(let V of P.errors)console.error(V)}import{dirname as pd,join as Jr}from"node:path";import{join as xi,resolve as Cg}from"node:path";function bi(P){let V=m(P);if(V.errors.length>0)return{ok:!1,result:{ok:!1,errors:V.errors,entries:[]}};return{ok:!0,config:V.config??it}}function qc(P){Rt(P,{version:1,rules:[],overrides:{},transparent_wrappers:[]})}function Vc(P){Rt(P,{rulebook_version:1,name:"example-rules",version:"1.0.0",description:"Project-specific CC Safety Net rules.",author:"project",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as Br}from"node:path";var fg="custom.";function Hr(P){if(P.rulebook_version!==2)return[];let V=P.rules.map((z)=>({name:z.name,command:z.command,block_args:[],match:z.match,reason:z.reason,intent:z.intent}));return(P.tests??[]).flatMap((z,Q)=>{let te=Li(h(z.command));if(te.length===0)return[`tests[${Q}]: could not parse fixture command: ${z.command}`];let ne=te.reduce((ce,ye)=>ce??_(ye,V)?.id.slice(fg.length),void 0);if(z.expect==="blocked"){if(ne===z.rule)return[];let ce=ne?`"${ne}" matched first`:"no rule matched";return[`tests[${Q}]: expected "${z.rule}" to block "${z.command}" but ${ce}`]}return ne?[`tests[${Q}]: expected "${z.command}" to be allowed but "${ne}" matched`]:[]})}function Li(P){return P.nodes.flatMap((V)=>{if(V.kind==="group"||V.kind==="function")return Li(V.body);if(V.kind!=="command")return[];let z=ge(X(V.dialect,V.words)).words.map(t);return[...z.length>0?[z]:[],...V.nested.flatMap((Q)=>Li(Q))]})}var Ur=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function Gr(P={}){return{requests:0,responseBytes:0,maxRequests:P.maxRequests??Ur.maxRequests,maxResponseBytes:P.maxResponseBytes??Ur.maxResponseBytes}}function zt(P){return{controller:new AbortController,budget:Gr(),resolveUrl:P}}function zc(P){return P instanceof Error&&P.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function Jc(P){if(P.requests>=P.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.requests++}function Wc(P,V){if(V>P.maxResponseBytes-P.responseBytes)throw P.responseBytes+=V,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.responseBytes+=V}var Zc=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function Kc(P,V,z=v(Br(Br(V)),"rules policy"),Q=zt()){if(S(P))return hg(P,Q);return yg(P,V,z)}async function Xc(P,V,z,Q,te,ne){if(!S(P))return Kc(P,V,z,Q);let ce=te?null:mg(P,V,z);if(ce)return ce;if(!te&&!ne)throw Error(`${P} is not vendored; run rule update ${P} to vendor it`);return Kc(P,V,z,Q)}function mg(P,V,z=v(Br(Br(V)),"rules policy")){let Q=A(P),te=I(V,Q.name),ne=n(i(z,te));if(ne===null)return null;let ce=se(wi(ne,`Invalid rulebook ${te}.`));if(ce.name!==Q.name)throw Error(`rulebook name "${ce.name}" in ${te} must match "${Q.name}"`);return{spec:P,rulebook:ce,content:ne}}async function Qc(P,V={}){if(!q(P))throw Error(`Invalid GitHub repository source: ${P}`);let[z,Q]=P.split("/");if(!z||!Q)throw Error(`Invalid GitHub repository source: ${P}`);if(V.ref!==void 0&&!oe(V.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${V.ref}`);let te=V.operation??zt(),ne=V.ref??await gg(z,Q,P,te),ce=await td(z,Q,ne,P,te),ye=await qr(`https://api.github.com/repos/${z}/${Q}/git/trees/${ce}?recursive=1`,"tree",te),he=ye.response;if(!he.ok)throw Error(`Failed to inspect ${P}: GitHub tree returned ${he.status}`);let be=JSON.parse(ye.content);if(!Array.isArray(be?.tree))throw Error(`Failed to inspect ${P}: unexpected GitHub tree response`);let xe=be.tree,Ie=[...new Set(xe.flatMap((Xe)=>{if(!Xe||typeof Xe!=="object")return[];let et=Xe;if(et.type!=="blob"||typeof et.path!=="string")return[];let Re=et.path.match(rt);return Re?.[1]?[Re[1]]:[]}))].sort();if(Ie.length===0)throw Error(`No rulebooks found in ${P} under ${de}/`);return{source:P,owner:z,repo:Q,ref:ne,commit:ce,names:Ie}}async function gg(P,V,z,Q){let te=await qr(`https://api.github.com/repos/${P}/${V}`,"metadata",Q),ne=te.response;if(!ne.ok)throw Error(`Failed to inspect ${z}: GitHub returned ${ne.status}`);let ye=JSON.parse(te.content)?.default_branch;if(typeof ye!=="string"||ye==="")throw Error(`Failed to inspect ${z}: missing default branch`);if(!oe(ye))throw Error(`GitHub returned an invalid default branch: ${ye}`);return ye}function yg(P,V,z){ot(P);let Q=I(V,P),te=n(i(z,Q));if(te===null)throw Error(`Rulebook source not found: ${P}`);let ne=ed(wi(te,"Invalid local rulebook source."));if(ne.name!==P)throw Error(`rulebook name "${ne.name}" must match local source "${P}"`);return{spec:P,rulebook:ne,content:te}}async function hg(P,V){let z=A(P),Q=await td(z.owner,z.repo,z.ref,P,V),te=await qr(`https://raw.githubusercontent.com/${z.owner}/${z.repo}/${Q}/${z.path}`,"raw",V),ne=te.response;if(!ne.ok)throw Error(`Failed to fetch ${P}: GitHub raw returned ${ne.status}`);let ce=te.content,ye=ed(wi(ce,"Invalid GitHub rulebook response."));if(ye.name!==z.name)throw Error(`rulebook name "${ye.name}" must match GitHub source "${z.name}"`);return{spec:P,rulebook:ye,content:ce}}function ed(P){let V=se(P),z=Hr(V);if(z.length>0)throw Error(z.join("; "));return V}function wi(P,V){try{return JSON.parse(P)}catch{throw Error(V)}}async function td(P,V,z,Q,te){let ne=await qr(`https://api.github.com/repos/${P}/${V}/commits/${encodeURIComponent(z)}`,"commit",te),ce=ne.response;if(!ce.ok)throw Error(`Failed to resolve ${Q}: GitHub returned ${ce.status}`);let ye=JSON.parse(ne.content);if(typeof ye?.sha!=="string"||ye.sha==="")throw Error(`Failed to resolve commit for ${Q}`);return ye.sha}async function vg(P,V,z={}){if(z.signal?.aborted)throw z.signal.reason;let Q=z.budget??Gr(),te=new AbortController,ne=()=>te.abort(z.signal?.reason);z.signal?.addEventListener("abort",ne,{once:!0});let ce=!1,ye=setTimeout(()=>{if(te.signal.aborted)return;ce=!0,te.abort()},z.timeoutMs??Zc.timeoutMs);try{if(z.signal?.aborted)throw z.signal.reason;Jc(Q);let he=await fetch(P,{signal:te.signal,redirect:"error"});if(!he.ok)return nd(he),{response:he,content:""};return{response:he,content:await bg(he,V,Q,()=>te.abort())}}catch(he){if(ce)throw Error("GitHub request timed out",{cause:he});if(z.signal?.aborted)throw z.signal.reason;throw he}finally{clearTimeout(ye),z.signal?.removeEventListener("abort",ne)}}function qr(P,V,z){return vg(z.resolveUrl?.(P)??P,V,{budget:z.budget,signal:z.controller.signal})}async function bg(P,V,z=Gr(),Q){let te=Zc[`${V}Bytes`],ne=Number(P.headers.get("content-length"));if(Number.isFinite(ne)&&ne>te)throw nd(P),Error(`GitHub ${V} response exceeds ${te} bytes`);if(!P.body)return"";let ce=P.body.getReader(),ye=[],he=0;while(!0){let be=await ce.read();if(be.done)break;try{Wc(z,be.value.byteLength)}catch(xe){throw Q?.(),Yc(ce),xe}if(he+=be.value.byteLength,he>te)throw Q?.(),Yc(ce),Error(`GitHub ${V} response exceeds ${te} bytes`);ye.push(Buffer.from(be.value))}return Buffer.concat(ye,he).toString("utf-8")}function nd(P){if(!P.body)return;rd(()=>P.body?.cancel())}function Yc(P){rd(()=>P.cancel())}function rd(P){try{Promise.resolve(P()).catch(()=>{})}catch{}}var Lg=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function od(P,V){let z=ad(P.rules,V);if(z.length>0)return{ok:!0,specs:z};return sd(P.rules,V)}function id(P,V){let z=ad(P,V);if(z.length>0)return{ok:!0,specs:z};let Q=kg(P,V);if(Q.length>0)return{ok:!0,specs:Q};let te=xg(P,V);if(!te.ok)return te;if(te.specs.length>0)return{ok:!0,specs:te.specs};return sd(P,V)}function sd(P,V){let z=P.filter((Q)=>ki(Q)?.name===V);if(z.length===1)return{ok:!0,specs:z};return wg(V,z)}function wg(P,V){return{ok:!1,result:{ok:!1,errors:V.length===0?[`No configured rulebook matches ${P}`]:[`Ambiguous rulebook match ${P}: ${V.join(", ")}`],entries:[]}}}function ad(P,V){return P.filter((z)=>z===V)}function kg(P,V){let z=V.match(Lg),Q=z?.[1],te=z?.[2],ne=z?.[3];if(!Q||!te||!ne||!oe(ne))return[];return ld(P,(ce)=>ce.owner===Q&&ce.repo===te&&ce.ref===ne)}function xg(P,V){if(!q(V))return{ok:!0,specs:[]};let[z,Q]=V.split("/"),te=ld(P,(ce)=>ce.owner===z&&ce.repo===Q);if(new Set(te.map((ce)=>ki(ce)?.ref).filter((ce)=>!!ce)).size<2)return{ok:!0,specs:te};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${V}. Use an explicit ref:`,` cc-safety-net rule remove ${V}#<ref>`],entries:[]}}}function ki(P){try{return A(P)}catch{return null}}function ld(P,V){return P.filter((z)=>{let Q=ki(z);return Q?V(Q):!1})}async function zr(P,V={}){let z=Ci(V);return Sg(P,z,await Vr(P,z,zt()))}function Sg(P,V,z){if(!z.ok)return z;let Q=Pt(P,V),te=[...new Set(j(Q.configPath,Q.filesystemScope))];if(te.length===0)return z;return{ok:!1,errors:te,entries:z.entries}}async function Vr(P,V,z,Q={},te=new Set,ne=new Set){try{let ce=Pt(P,V),ye=bi(ce.configTarget);if(!ye.ok)return ye.result;let he=ye.config,be=V.only?od(he,V.only):{ok:!0,specs:he.rules};if(!be.ok)return be.result;let xe=new Set([...V.refresh?be.specs:[],...te]),Ie=(ut)=>Xc(ut,ce.configDir,ce.filesystemScope,z,xe.has(ut),!V.refresh||xe.has(ut)),Xe=await Fg(he.rules,V.refresh?(ut)=>Ie(ut).then((vt)=>({ok:!0,item:vt})).catch((vt)=>{if(zc(vt))throw vt;return{ok:!1,spec:ut,message:vt instanceof Error?vt.message:String(vt)}}):async(ut)=>({ok:!0,item:await Ie(ut)}),z),et=Xe.filter((ut)=>!ut.ok),Re=Xe.filter((ut)=>ut.ok).map((ut)=>ut.item),at=Re.flatMap((ut)=>Rg(ut,he.rules)),ct=Re.flatMap((ut)=>Pg(ut,ne,ce)),lt=new Set([...at,...ct].map((ut)=>ut.spec)),pt=[...et,...at,...ct],mt=[],gt=Dg(mt,()=>Re.flatMap((ut)=>lt.has(ut.spec)||pt.length>0&&ne.has(ut.spec)?[]:Eg(ut,ce,Q,mt)));return{ok:pt.length===0,errors:pt.map((ut)=>`Failed to update ${ut.spec}: ${ut.message}`),entries:Re.map(_g),changes:gt}}catch(ce){return Jn(ce)}}function Rg(P,V){if(!S(P.spec))return[];let z=Pe(P.spec),Q=V.filter((te)=>te!==P.spec&&Pe(te).toLowerCase()===z.toLowerCase());if(Q.length===0)return[];return[{ok:!1,spec:P.spec,message:`rulebook name "${z}" is also claimed by ${Q.join(", ")}; rename one of them`}]}function Pg(P,V,z){if(!V.has(P.spec)||!S(P.spec))return[];let Q=I(z.configDir,P.rulebook.name),te=n(i(z.filesystemScope,Q));if(te===null||te===P.content)return[];return[{ok:!1,spec:P.spec,message:`${Q} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Eg(P,V,z,Q){if(!S(P.spec))return[];let te=I(V.configDir,P.rulebook.name),ne=i(V.filesystemScope,te),ce=n(ne);if(ce===P.content)return[];return Q?.push({target:ne,previous:ce}),g(ne,P.content,void 0,z._testAfterPolicyRename),Ag(P,ce)}function Dg(P,V){try{return V()}catch(z){for(let Q of[...P].reverse()){if(Q.previous===null){N(Q.target);continue}g(Q.target,Q.previous)}throw z}}function Ag(P,V){if(V===null)return[`Vendored ${P.spec} (${P.rulebook.version})`];let z=me(V),Q="problem"in z?null:z.rulebook,te=new Map(Q?.rules.map((ce)=>[ce.name,JSON.stringify(ce)])??[]),ne=new Set(P.rulebook.rules.map((ce)=>ce.name));return[`Updated ${P.spec} (${Q?.version??"unreadable"} -> ${P.rulebook.version})`,...[...ne].filter((ce)=>!te.has(ce)).map((ce)=>` + ${ce}`),...[...te.keys()].filter((ce)=>!ne.has(ce)).map((ce)=>` - ${ce}`),...P.rulebook.rules.filter((ce)=>{let ye=te.get(ce.name);return ye!==void 0&&ye!==JSON.stringify(ce)}).map((ce)=>` ~ ${ce.name}`)]}function _g(P){return{spec:P.spec,name:P.rulebook.name,version:P.rulebook.version,ruleCount:P.rulebook.rules.length}}async function cd(P,V,z={}){return Tg(P,V,Ng(z),zt())}async function Tg(P,V,z,Q,te={}){let ne=null,ce=!1;try{let ye=Pt(P,z),he=n(ye.configTarget);ne={target:ye.configTarget,content:he};let be=bi(ye.configTarget);if(!be.ok)return be.result;let xe=be.config,Ie=q(V);$g(V,z,Ie);let Xe=Ie?await Qc(V,{ref:z.ref,operation:Q}):null,et=Xe?Ig(Xe,z.rulebooks):[],Re=Xe?et.map((mt)=>Og(xe.rules,Xe,mt)??`${V}#${Xe.ref}/${mt}`):[V],at=Re.filter((mt)=>!xe.rules.includes(mt)),ct=[...xe.rules,...at];if(ct.length>pe)return jg();if(ct.length!==xe.rules.length)ce=!0,Rt(ye.configTarget,{version:1,rules:ct,overrides:xe.overrides??{},transparent_wrappers:xe.transparent_wrappers??[]},void 0,te._testAfterPolicyRename);let lt=await Vr(P,z,Q,te,new Set(at),new Set(at));if(!lt.ok)zn(ye.configTarget,he);if(!lt.ok||!Xe)return lt;let pt=et.filter((mt,gt)=>at.includes(Re[gt]??""));return{...lt,add:{source:V,ref:Xe.ref,selected:et,added:pt,alreadyConfigured:et.filter((mt)=>!pt.includes(mt)),commits:at.length>0?[Xe.commit]:[]}}}catch(ye){if(ce&&ne)try{zn(ne.target,ne.content)}catch(he){return Jn(he)}return Jn(ye)}}function $g(P,V,z){if(!z&&V.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!z&&V.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${P}`);if(V.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let Q=V.rulebooks?.filter((te)=>!l.test(te))??[];if(Q.length>0)throw Error(`Invalid rulebook names: ${Q.join(", ")}`)}function Ig(P,V){let z=V?[...new Set(V)]:P.names,Q=z.filter((te)=>!P.names.includes(te));if(Q.length>0)throw Error(`Rulebooks not found in ${P.source} at ${P.ref}: ${Q.join(", ")}
264
+ Available rulebooks: ${P.names.join(", ")}`);return z}function Og(P,V,z){let Q=`${V.source}#${V.ref}/${z}`;if(P.includes(Q))return Q;let te=`${V.source}#${V.commit}/${z}`;return P.find((ne)=>ne===te)}async function Fg(P,V,z=zt()){if(P.length>pe)throw Error(fe);let Q=Array(P.length),te=0,ne,ce=Array.from({length:Math.min(P.length,Ur.concurrency)},async()=>{while(!ne){let ye=te;if(ye>=P.length)return;te++;try{Q[ye]=await V(P[ye],ye,z.controller.signal)}catch(he){if(!ne)ne={value:he},te=P.length,z.controller.abort(he);return}}});if(await Promise.all(ce),ne)throw ne.value;return Q}function jg(){return{ok:!1,errors:[fe],entries:[]}}function Ci(P){return{cwd:P.cwd,userConfigDir:P.userConfigDir,userConfigPath:P.userConfigPath,projectConfigPath:P.projectConfigPath,global:P.global,only:P.only,refresh:P.refresh}}function Ng(P){return{...Ci(P),ref:P.ref,rulebooks:P.rulebooks}}function Mg(P){return{...Ci(P),deleteSource:P.deleteSource}}async function dd(P,V,z={}){try{return await Hg(P,V,Mg(z),{})}catch(Q){return Jn(Q)}}async function Hg(P,V,z,Q){let te=Pt(P,z),ne=m(te.configTarget);if(ne.errors.length>0)return{ok:!1,errors:ne.errors,entries:[]};if(!ne.config)return{ok:!1,errors:[`No config found at ${te.configPath}`],entries:[]};let ce=id(ne.config.rules,V);if(!ce.ok)return ce.result;let ye=z.deleteSource?Ug(te.configDir,ce.specs,te.filesystemScope):{ok:!0,dirs:[]};if(!ye.ok)return ye.result;let he=n(te.configTarget);if(he===null)return Jn(Error("Rules config is unavailable."));try{Rt(te.configTarget,{version:1,rules:ne.config.rules.filter((Ie)=>!ce.specs.includes(Ie)),overrides:ne.config.overrides??{},transparent_wrappers:ne.config.transparent_wrappers??[]},void 0,Q._testAfterPolicyRename)}catch(Ie){throw zn(te.configTarget,he),Ie}let be=await Vr(P,z,zt(),Q);if(!be.ok)return zn(te.configTarget,he),be;let xe=Gg(ye.dirs,Q,te.filesystemScope);if(!xe.ok){zn(te.configTarget,he);let Ie=await Vr(P,z,zt(),Q);if(!Ie.ok)return{ok:!1,errors:[...xe.result.errors,...Ie.errors],entries:Ie.entries};return xe.result}return be}function Ug(P,V,z){let Q=V.flatMap((ye)=>l.test(ye)?[]:["--delete-source can only delete local rulebook sources"]),te=V.map((ye)=>xi(P,ye)),ne=Q.length>0?[]:te.flatMap((ye)=>ud(ye,z)),ce=[...Q,...ne];return ce.length>0?{ok:!1,result:{ok:!1,errors:ce,entries:[]}}:{ok:!0,dirs:te}}function ud(P,V){let z=Cg(P),Q=i(V,z),te=le(Q);if(!te)return[`Local rulebook source directory not found: ${P}`];let ne=te.find((ce)=>ce.name==="rulebook.json");if(!ne)return[`Local rulebook source directory is missing rulebook.json: ${P}`];if(ne.kind!=="file")throw new r(V.label);if(n(i(V,xi(z,"rulebook.json"))),te.length>1)return[`Local rulebook source directory contains extra files: ${P}. delete manually if you really want to remove the directory.`];return[]}function Gg(P,V,z){let Q=P.flatMap((te)=>{try{if(!le(i(z,te)))return[];let ne=ud(te,z);if(ne.length>0)return ne;return Bg(te,V,z),[]}catch(ne){return[`Failed to delete local rulebook source ${te}: ${ne instanceof Error?ne.message:String(ne)}`]}});return Q.length>0?{ok:!1,result:{ok:!1,errors:Q,entries:[]}}:{ok:!0}}function Bg(P,V,z){if(V._testDeleteLocalSourceDir){V._testDeleteLocalSourceDir(P);return}N(i(z,xi(P,ue))),nt(i(z,P))}function zn(P,V){if(V===null){N(P);return}g(P,V)}function Jn(P){return{ok:!1,errors:[P instanceof Error?P.message:String(P)],entries:[]}}var qg=".safety-net.json",Vg="~/.cc-safety-net/config.json";async function gd(P,V){return[await fd(P,{legacyPath:$s({cwd:V.cwd}),configPath:F(V.cwd),defaultRulebookName:"project-rules",migratedFrom:qg,cleanup:V.cleanup,syncOptions:{cwd:V.cwd}}),await fd(P,{legacyPath:nr(P),configPath:M(P),defaultRulebookName:"user-rules",migratedFrom:Vg,cleanup:V.cleanup,syncOptions:{cwd:V.cwd,global:!0}})].every((Q)=>Q)?0:1}async function fd(P,V){let z=Pt(P,V.syncOptions),Q=i(z.filesystemScope,V.legacyPath),te=n(Q);if(te===null)return console.log(`No legacy config found at ${V.legacyPath}`),!0;let ne=Jg(te);if(!ne.ok){for(let et of ne.errors)console.error(et);return!1}let ce=m(z.configTarget);if(ce.errors.length>0){for(let et of ce.errors)console.error(et);return!1}let ye=ce.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},he=Wg(pd(V.configPath),ye.rules,V.defaultRulebookName,V.migratedFrom,z.filesystemScope),be=Jr(pd(V.configPath),he,"rulebook.json"),xe=i(z.filesystemScope,be),Ie=[md(z.configTarget),md(xe)],Xe=await zg(P,V,z.configTarget,xe,he,ne.config.rules,ye.rules.includes(he)?ye.rules:[...ye.rules,he],ye.overrides??{},ye.transparent_wrappers??[]);if(!Xe.ok){Zg(Ie);for(let et of Xe.errors)console.error(et);return!1}if(!V.cleanup)return console.log(`Migrated legacy config at ${V.legacyPath}. Legacy file is no longer used.`),!0;if(!Yg(z.configTarget,xe,he,V.migratedFrom,ne.config.rules))return console.error(`Migration cleanup verification failed for ${V.legacyPath}`),!1;return N(Q),console.log(`Deleted legacy config at ${V.legacyPath}`),!0}async function zg(P,V,z,Q,te,ne,ce,ye,he){try{return Rt(z,{version:1,rules:ce,overrides:ye,transparent_wrappers:he}),Rt(Q,Kg(te,V.migratedFrom,ne)),await zr(P,V.syncOptions)}catch(be){return{ok:!1,errors:[be instanceof Error?be.message:String(be)]}}}function Jg(P){try{let V=JSON.parse(P),z=ro(V);if(z.errors.length>0)return{ok:!1,errors:z.errors};return{ok:!0,config:{version:1,rules:V.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function Wg(P,V,z,Q,te){let ne=V.find((ce)=>Xg(i(te,Jr(P,ce,"rulebook.json")))===Q);if(ne)return ne;if(n(i(te,Jr(P,z,"rulebook.json")))===null)return z;for(let ce=2;;ce++){let ye=`${z}-${ce}`;if(n(i(te,Jr(P,ye,"rulebook.json")))===null)return ye}}function Kg(P,V,z){return{rulebook_version:1,name:P,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:V,allowed_commands:[...new Set(z.map((Q)=>Q.command))],rules:z,tests:z.map((Q)=>({command:[Q.command,Q.subcommand,Q.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:Q.name}))}}function Yg(P,V,z,Q,te){if(!m(P).config?.rules.includes(z))return!1;try{let ce=n(V);if(ce===null)return!1;let ye=JSON.parse(ce);return ye.migrated_from===Q&&JSON.stringify(ye.rules)===JSON.stringify(te)}catch{return!1}}function md(P){return{target:P,content:n(P)}}function Zg(P){for(let V of P){if(V.content===null){N(V.target);continue}g(V.target,V.content)}}function Xg(P){let V=n(P);if(V===null)return null;try{let z=JSON.parse(V);return typeof z.migrated_from==="string"?z.migrated_from:null}catch{return null}}import{mkdir as Qg,readFile as ey,writeFile as ty}from"node:fs/promises";import{dirname as ny,join as ry}from"node:path";var oy=86400000,iy=604800000;async function hd(P,V=Date.now()){if(P.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let z=je(P);if(!z)return null;let Q=ry(z,".cc-safety-net","update-check.json"),te=await sy(Q,V);if(!te.lastCheck||V-te.lastCheck>oy){let ye=await Wt();if(te.lastCheck=V,ye.latestVersion)te.latestVersion=ye.latestVersion;if(!await yd(Q,te))return null;if(ye.error)return null}let ne=te.latestVersion,ce=wt();if(!ne||!co(ne,ce))return null;if(te.notifiedVersion===ne&&te.notifiedAt!==void 0&&V-te.notifiedAt<iy)return null;if(te.notifiedVersion=ne,te.notifiedAt=V,!await yd(Q,te))return null;return`UPDATE_AVAILABLE: cc-safety-net v${ne} is available (running v${ce}). 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 sy(P,V){let z=await ey(P,"utf8").then((ne)=>JSON.parse(ne)).catch(()=>{return});if(!z||typeof z!=="object"||Array.isArray(z))return{};let Q=z,te=(ne)=>typeof ne==="number"&&Number.isFinite(ne)&&ne<=V?ne:void 0;return{lastCheck:te(Q.lastCheck),latestVersion:typeof Q.latestVersion==="string"?Q.latestVersion:void 0,notifiedVersion:typeof Q.notifiedVersion==="string"?Q.notifiedVersion:void 0,notifiedAt:te(Q.notifiedAt)}}async function yd(P,V){return Qg(ny(P),{recursive:!0,mode:448}).then(()=>ty(P,JSON.stringify(V),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as ay,resolve as Si}from"node:path";var vd="CC Safety Net Config",ly="═".repeat(vd.length),cy="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",dy=new Set(["rule.json","rule.lock","cache"]);function bd(P,V={}){try{return uy(P,V)}catch(z){if(z instanceof r)return console.error(z.message),1;throw z}}function uy(P,V){let z=V.cwd??process.cwd(),Q=K(P,{cwd:z}),te=nr(P),ne=ns(z),ce=Si(z,de),ye=i(Q.userScope,te),he=i(Q.projectScope,ne),be=!1,xe=!1,Ie=[],Xe=[],et=py(i(Q.projectScope,ce));if(my(),n(Q.userConfigTarget)!==null){let Re=Jt(Q.userConfigTarget);if(Re.errors.push(...j(Q.userConfigPath,Q.userScope)),Ie.push({scope:"User",path:Q.userConfigPath,result:Re,schema:"rules",target:Q.userConfigTarget}),Re.errors.length>0)be=!0}if(n(ye)!==null)if(xe=!0,n(Q.userConfigTarget)!==null)Xe.push(Wr("user","cleanup"));else{let Re=oo(ye);if(Ie.push({scope:"User",path:te,result:Re,schema:"legacy",inactive:!0,target:ye}),Xe.push(Wr("user",Re.errors.length>0?"fix-or-delete":"migrate")),Re.errors.length>0)be=!0}if(n(Q.projectConfigTarget)!==null){let Re=Jt(Q.projectConfigTarget);if(Re.errors.push(...j(Q.projectConfigPath,Q.projectScope)),Ie.push({scope:"Project",path:Si(Q.projectConfigPath),result:Re,schema:"rules",target:Q.projectConfigTarget}),Re.errors.length>0)be=!0;if(n(he)!==null)xe=!0,Xe.push(Wr("project","cleanup"))}else if(n(he)!==null){xe=!0,be=!0;let Re=oo(he);Ie.push({scope:"Project",path:Si(ne),result:Re,schema:"legacy",inactive:!0,target:he}),Xe.push(Wr("project",Re.errors.length>0?"fix-or-delete":"migrate"))}if(et?.result.errors.length)be=!0;if(Ie.length===0&&!et)return console.log(`
265
+ No config files found. Using built-in rules only.`),0;for(let Re of Ie)if(Re.inactive)yy(Re.scope,Re.path,Re.result);else if(Re.result.errors.length>0)hy(Re.scope,Re.path,Re.result.errors);else{if(Re.schema==="rules"&&Ly(Re.target))console.log(`
266
+ Added $schema to ${Re.scope.toLowerCase()} config.`);gy(Re.scope,Re.path,Re.result,Re.schema)}for(let Re of Xe)console.error(`
267
+ ${dt.red(Re)}`);if(et)if(et.result.errors.length>0)by(et.path,et.result.errors);else vy(et.path,et.result);if(be)return console.error(`
268
+ Config validation failed.`),1;return console.log(xe?`
269
269
  Configs valid with warnings.`:`
270
- All configs valid.`),0}function Wr(P,V){let z=`legacy ${P} config`;if(V==="cleanup")return`Warning: Legacy ${P} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(V==="migrate")return`Warning: Legacy ${P} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${P} config is no longer supported. Fix or delete the ${z}, then run \`npx -y cc-safety-net rule migrate\`.`}function py(P){if(le(P)===null)return null;let V=fy(P);if(V.ruleNames.size===0&&V.errors.length===0)return null;return{path:P.path,result:V}}function fy(P){let V=[],z=new Set,Q=(le(P)??[]).filter((te)=>!dy.has(te.name)).sort((te,ne)=>te.name.localeCompare(ne.name));if(Q.length===0)return{errors:V,ruleNames:z};for(let te of Q){if(!l.test(te.name)){V.push(`rulebook directory names must match ${l}: ${te.name}`);continue}if(te.kind!=="directory"){V.push(`${te.name} must be a rulebook directory`);continue}let ne=i(P.scope,ay(P.path,te.name,"rulebook.json")),ce=n(ne);if(ce===null){V.push(`${te.name}/rulebook.json is required`);continue}try{let ye;try{ye=JSON.parse(ce)}catch{V.push(`${te.name}/rulebook.json: invalid JSON`);continue}let he=se(ye);if(he.name!==te.name){V.push(`rulebook name "${he.name}" must match folder "${te.name}"`);continue}let be=Hr(he);if(be.length>0){V.push(...be.map((Le)=>`${te.name}/rulebook.json: ${Le}`));continue}z.add(te.name)}catch(ye){V.push(ye instanceof Error?`${te.name}/rulebook.json: ${ye.message}`:`${te.name}/rulebook.json: ${String(ye)}`)}}return{errors:V,ruleNames:z}}function my(){console.log(vd),console.log(ly)}function gy(P,V,z,Q){if(console.log(`
270
+ All configs valid.`),0}function Wr(P,V){let z=`legacy ${P} config`;if(V==="cleanup")return`Warning: Legacy ${P} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(V==="migrate")return`Warning: Legacy ${P} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${P} config is no longer supported. Fix or delete the ${z}, then run \`npx -y cc-safety-net rule migrate\`.`}function py(P){if(le(P)===null)return null;let V=fy(P);if(V.ruleNames.size===0&&V.errors.length===0)return null;return{path:P.path,result:V}}function fy(P){let V=[],z=new Set,Q=(le(P)??[]).filter((te)=>!dy.has(te.name)).sort((te,ne)=>te.name.localeCompare(ne.name));if(Q.length===0)return{errors:V,ruleNames:z};for(let te of Q){if(!l.test(te.name)){V.push(`rulebook directory names must match ${l}: ${te.name}`);continue}if(te.kind!=="directory"){V.push(`${te.name} must be a rulebook directory`);continue}let ne=i(P.scope,ay(P.path,te.name,"rulebook.json")),ce=n(ne);if(ce===null){V.push(`${te.name}/rulebook.json is required`);continue}try{let ye;try{ye=JSON.parse(ce)}catch{V.push(`${te.name}/rulebook.json: invalid JSON`);continue}let he=se(ye);if(he.name!==te.name){V.push(`rulebook name "${he.name}" must match folder "${te.name}"`);continue}let be=Hr(he);if(be.length>0){V.push(...be.map((xe)=>`${te.name}/rulebook.json: ${xe}`));continue}z.add(te.name)}catch(ye){V.push(ye instanceof Error?`${te.name}/rulebook.json: ${ye.message}`:`${te.name}/rulebook.json: ${String(ye)}`)}}return{errors:V,ruleNames:z}}function my(){console.log(vd),console.log(ly)}function gy(P,V,z,Q){if(console.log(`
271
271
  ✓ ${P} config: ${V}`),console.log(` Schema: ${Q==="rules"?"rulebook sources":"legacy inline rules"}`),z.ruleNames.size>0){console.log(` ${Q==="rules"?"Sources":"Rules"}:`);let te=1;for(let ne of z.ruleNames)console.log(` ${te}. ${ne}`),te++}else console.log(` ${Q==="rules"?"Sources":"Rules"}: (none)`)}function yy(P,V,z){if(console.error(`
272
272
  ✗ Legacy ${P.toLowerCase()} config: ${V}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),z.errors.length>0){console.error(" Errors:");let Q=1;for(let te of z.errors)for(let ne of te.split("; "))console.error(` ${Q}. ${ne}`),Q++;return}if(z.ruleNames.size>0){console.error(" Rules:");let Q=1;for(let te of z.ruleNames)console.error(` ${Q}. ${te}`),Q++;return}console.error(" Rules: (none)")}function hy(P,V,z){Ld(`${P} config`,V,z)}function vy(P,V){console.log(`
273
273
  ✓ GitHub source rules: ${P}`),console.log(" Rulebooks:");let z=1;for(let Q of V.ruleNames)console.log(` ${z}. ${Q}`),z++}function by(P,V){Ld("GitHub source rules",P,V)}function Ld(P,V,z){console.error(`
274
- ✗ ${P}: ${V}`),console.error(" Errors:");let Q=1;for(let te of z)for(let ne of te.split("; "))console.error(` ${Q}. ${ne}`),Q++}function Ly(P){try{let V=n(P);if(V===null)return!1;let z=JSON.parse(V);if(z.$schema)return!1;return g(P,JSON.stringify({$schema:cy,...z},null,2)),!0}catch(V){if(V instanceof r)throw V;return!1}}var wd=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),ky=new Set(["add","remove","list"]),xy="cc-safety-net/rulebooks";async function kd(P,V){try{return await Cy(P,V)}catch(z){if(z instanceof r)return console.error(z.message),1;throw z}}async function Cy(P,V){let z=Ry(V),Q=z.help?Sy(z.positionals):null;if(Q)return wn(Q),0;if(z.errors.length>0){for(let ye of z.errors)console.error(ye);return 1}let te=z.positionals[0];if(!te)return wn(fn,console.error),1;let ne=z.positionals[1],ce={global:z.global};if(te==="init"){let ye=Pt(P,ce);Ay(ye.configTarget);let he=wy(ye.configDir,"example-rules","rulebook.json"),be=i(ye.filesystemScope,he);if(z.example&&n(be)===null)Vc(be);let Le=j(ye.configPath,ye.filesystemScope);for(let Ie of Le)console.error(Ie);if(Le.length>0)return 1;return console.log("Rule config initialized."),0}if(te==="add"){let ye=xd(z);if(!ye)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let he=Pt(P,ce),be=await cd(P,ye,{...ce,ref:z.ref,rulebooks:z.only.length>0?z.only:void 0});return Hc(be,ye,`Scope: ${z.global?"user":"project"} (${he.configDir})`),be.ok?0:1}if(te==="remove"){if(!ne)return console.error("rule remove requires a source"),1;let ye=await dd(P,ne,{...ce,deleteSource:z.deleteSource});return Mr(ye,`Removed rulebook source: ${ne}`),ye.ok?0:1}if(te==="update"){let ye=await zr(P,{...ce,only:ne,refresh:!0});return Mr(ye,"Rule config updated."),ye.ok?0:1}if(te==="sync")return Fs(P,{global:z.global});if(te==="list"){let ye=J(P,{cwd:process.cwd()});return Gc(ye),ye.errors.length>0?1:0}if(te==="wrapper")return _y(P,z);if(te==="migrate")return gd(P,{cleanup:z.cleanup,cwd:process.cwd()});if(te==="doc"){console.log(Nc);let ye=await hd(P);if(ye)console.error(ye);return 0}if(te==="verify")return bd(P);return 1}function Sy(P){if(P.length===0)return fn;let V=fn.subcommands.filter((Q)=>Q.usage.split(" ")[0]===P[0]);if(V.length===0)return null;if(P.length===1&&V.length>1)return{name:`rule ${P[0]}`,description:`Subcommands of rule ${P[0]}`,usage:`rule ${P[0]} <subcommand>`,subcommands:V,options:[]};let z=P.length===1?V[0]:V.find((Q)=>Q.usage.split(" ")[1]===P[1]);if(!z)return null;return{name:`rule ${P[0]}`,description:z.description,usage:`rule ${z.usage}`,options:P[0]==="add"?eo:[],examples:P[0]==="add"?to:void 0}}function Ry(P){let V=xt({label:"rule",booleans:{global:["-g","--global"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},P),z={...V.flags,ref:V.values.ref,only:V.lists.only??[],help:V.help,positionals:V.positionals,errors:V.errors};return Py(z),z}function Py(P){let[V]=P.positionals;if(V&&!wd.has(V))P.errors.push(`Unknown rule subcommand: ${V}`);if(P.deleteSource&&V!=="remove")if(V&&wd.has(V))P.errors.push(`Unknown option for rule ${V}: --delete-source`);else P.errors.push("--delete-source is only valid with 'rule remove'");if(P.cleanup&&V!=="migrate")P.errors.push(Wn(V,"--cleanup"));if(P.example&&V!=="init")P.errors.push(Wn(V,"--example"));if(P.ref&&V!=="add")P.errors.push(Wn(V,"--ref"));if(P.only.length>0&&V!=="add")P.errors.push(Wn(V,"--only"));if(V==="add")Ey(P);if(V==="migrate"){if(P.global)P.errors.push(Wn(V,"--global"));if(P.positionals.length>1)P.errors.push(`Unexpected rule migrate argument: ${P.positionals[1]}`)}else if(V==="wrapper")Dy(P);else if(P.positionals.length>2)P.errors.push(`Unexpected rule argument: ${P.positionals[2]}`);if(V==="list"&&P.global)P.errors.push("Unknown option for rule list: --global")}function xd(P){if(P.positionals[1])return P.positionals[1];if(P.ref||P.only.length>0)return xy;return}function Ey(P){let V=xd(P);if(!V)return;if((P.ref||P.only.length>0)&&!q(V)){if(P.ref)P.errors.push(`--ref can only select a ref for an owner/repo source: ${V}`);if(P.only.length>0)P.errors.push("--only can only select rulebooks from an owner/repo source");return}if(P.ref&&!oe(P.ref))P.errors.push(`--ref must use valid path segments: ${P.ref}`);let z=P.only.filter((Q)=>!l.test(Q));if(z.length>0)P.errors.push(`Invalid rulebook names: ${z.join(", ")}`)}function Wn(P,V){return P?`Unknown option for rule ${P}: ${V}`:`Unknown option for rule: ${V}`}function Dy(P){let V=P.positionals[1],z=P.positionals[2];if(!V){P.errors.push("rule wrapper requires add, remove, or list");return}if(!ky.has(V)){P.errors.push(`Unknown rule wrapper action: ${V}`);return}if(V==="list"){if(z)P.errors.push(`Unexpected rule wrapper argument: ${z}`);return}if(!z){P.errors.push(`rule wrapper ${V} requires a command`);return}if(P.positionals.length>3)P.errors.push(`Unexpected rule wrapper argument: ${P.positionals[3]}`)}function Ay(P){if(n(P)===null){qc(P);return}let V=m(P);if(!V.config)return;Rt(P,{version:1,rules:V.config.rules,overrides:V.config.overrides??{},transparent_wrappers:V.config.transparent_wrappers??[]})}async function _y(P,V){let z=V.positionals[1],Q=V.positionals[2],te=Pt(P,{global:V.global}).configTarget;if(z==="list"){let he=m(te);if(he.errors.length>0){for(let be of he.errors)console.error(be);return 1}return Ty(he.config?.transparent_wrappers??[]),0}if(!Q||!w.test(Q))return console.error("transparent wrapper must match command pattern"),1;if(Re(Q))return console.error(`reserved command "${Q}" cannot be a wrapper`),1;let ne=m(te);if(ne.errors.length>0){for(let he of ne.errors)console.error(he);return 1}let ce=ne.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},ye=z==="add"?[...new Set([...ce.transparent_wrappers??[],Q])]:(ce.transparent_wrappers??[]).filter((he)=>he!==Q);return Rt(te,{version:1,rules:ce.rules,overrides:ce.overrides??{},transparent_wrappers:ye}),console.log(z==="add"?`Added transparent wrapper: ${Q}`:`Removed transparent wrapper: ${Q}`),0}function Ty(P){if(P.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${P.length}):`);for(let V of P)console.log(` - ${V}`)}import{sep as Ny}from"node:path";import{existsSync as $y,readFileSync as Iy}from"node:fs";import{join as Oy}from"node:path";async function Fy(P){if(P.isTTY)return null;return(await We(P).catch(()=>null))?.trim()||null}function jy(P){let V=P.env.get("CLAUDE_SETTINGS_PATH");if(V)return V;return Oy(P.home,".claude","settings.json")}function Ri(P){let V=jy(P);if(!$y(V))return!1;try{let z=Iy(V,"utf-8"),Q=JSON.parse(z);if(!Q.enabledPlugins)return!1;let te="cc-safety-net@cc-marketplace";if(!(te in Q.enabledPlugins))return!1;return Q.enabledPlugins[te]===!0}catch(z){if(R(o.debug,P.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${V}: ${z instanceof Error?z.message:String(z)}`);return!1}}async function Pi(P,V=process.stdin){let z=Ri(P),Q;if(!z)Q="\uD83D\uDEE1️ CC Safety Net ❌";else{let ne=E(P,{cwd:process.cwd()}),ce=ne.policy,ye=L(ce,P.env),he=Object.values(G(ce,ye.capabilities)).some((Ie)=>Ie.changesInherited),be={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[he?"custom":ye.effectiveLevel],Le=(ne.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";Q=`\uD83D\uDEE1️ CC Safety Net ${be}${ye.worktreeMode?"\uD83C\uDF33":""}${Le}${ne.state==="degraded"?"⚠️":""}`}let te=await Fy(V);if(te&&!te.startsWith("{"))console.log(`${te} | ${Q}`);else console.log(Q)}function Cd(P){let V=E(P,{cwd:process.cwd()}),z=V.policy,Q=L(z,P.env),te=!!process.env.NO_COLOR||!process.stdout.isTTY,ne=Math.min(process.stdout.columns||80,100),ce=te?"ok":"✔",ye=te?"OFF":"✘",he=(at,ct)=>{let lt=` ${at.padEnd(13)}${ct}`;return(lt.length>ne?`${lt.slice(0,ne-1)}…`:lt).replaceAll(ye,dt.red(ye))},be=Object.values(G(z,Q.capabilities)).some((at)=>at.changesInherited),Le=(at)=>at===P.home||at.startsWith(`${P.home}${Ny}`)?`~${at.slice(P.home.length)}`:at,Ie={ready:dt.green,degraded:dt.yellow}[V.state],Xe=V.policyScopes?.weakenings??[],et=[...Ri(P)?[]:["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."],...V.diagnostics],xe=te?"-":"·";console.log([`${te?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ie(V.state)}`,"",he("Protection",`destructive ${z.destructiveCommandProtectionEnabled?ce:ye} secrets ${z.secretProtection.enabled?ce:ye}`),he("Level",be?`${Q.effectiveLevel} (customised)`:Q.effectiveLevel),he("Rules",z.rules.length===0?"none active":`${z.rules.length} active`),he("Policy",Le(u(P))),...V.policyScopes?[he("Project",Le(b(process.cwd())))]:[],...Q.worktreeMode?[he("Worktree","relaxations active")]:[],"",...Xe.length===0?[]:[" Project policy",...Xe.flatMap((at)=>jn(at," ",ne-6).map((ct,lt)=>lt===0?` ${ct}`:ct)),""],...et.length===0?[" Everything configured is active."]:[" Not active",...et.flatMap((at)=>jn(at," ",ne-6).map((ct,lt)=>lt===0?` ${xe} ${ct}`:ct)),""," Full report: cc-safety-net doctor"]].join(`
275
- `))}import{spawn as Od}from"node:child_process";import{randomBytes as Wy}from"node:crypto";import{existsSync as Ky}from"node:fs";import{createServer as Yy}from"node:http";import{Writable as Zy}from"node:stream";var Kr=500;function My(P){let V=P.filter((te)=>te.decision!=="allow"),z=P.filter((te)=>te.decision==="allow"),Q=Math.min(V.length,Math.max(Kr-z.length,Math.ceil(Kr/2)));return[...V.slice(0,Q),...z.slice(0,Kr-Q)]}function Sd(P,V,z=O(P)){if(z)B(P,z);let Q=(ct)=>new Date(ct.getFullYear(),ct.getMonth(),ct.getDate()).getTime(),te=Q(new Date),ne=new Date(te);ne.setDate(ne.getDate()-(V-1));let ce=ne.getTime(),ye=[],he={count:0};for(let ct of z?Yt(z,he):[])for(let lt of pn(ct,he)){let pt=new Date(lt.ts).getTime();if(!Number.isFinite(pt))continue;if(pt>=ce)ye.push(lt)}ye.sort((ct,lt)=>new Date(lt.ts).getTime()-new Date(ct.ts).getTime());let be=Array.from({length:V},()=>0),Le=Array.from({length:V},()=>0),Ie={},Xe={},et={},xe=0,at=0;for(let ct of ye){let lt=ct.agent||"unknown";Ie[lt]=(Ie[lt]??0)+1;let pt=Math.round((te-Q(new Date(ct.ts)))/86400000),mt=V-1-pt,gt=pt>=0&&pt<V;if(gt)Le[mt]=(Le[mt]??0)+1;if(ct.decision!=="allow"){if(xe++,ct.ruleId)Xe[ct.ruleId]=(Xe[ct.ruleId]??0)+1;let ut=Qr(ct.segment||ct.command);if(ut)et[ut]=(et[ut]??0)+1;if(ct.failureStage)at++;if(gt)be[mt]=(be[mt]??0)+1}}return{days:V,logsDir:z,homeDir:P.home,totalInWindow:ye.length,truncated:ye.length>Kr,unreadable:he.count,counts:{blocked:xe,allowed:ye.length-xe,agents:Ie,blockedByDay:be,analyzedByDay:Le,rules:Xe,commands:et,errors:at},entries:My(ye).sort((ct,lt)=>new Date(lt.ts).getTime()-new Date(ct.ts).getTime())}}import{spawn as Hy}from"node:child_process";import{existsSync as Uy,statSync as Rd}from"node:fs";import{delimiter as Gy,join as By}from"node:path";var qy=120000,Yr="Choose the project folder",Vy=`try
274
+ ✗ ${P}: ${V}`),console.error(" Errors:");let Q=1;for(let te of z)for(let ne of te.split("; "))console.error(` ${Q}. ${ne}`),Q++}function Ly(P){try{let V=n(P);if(V===null)return!1;let z=JSON.parse(V);if(z.$schema)return!1;return g(P,JSON.stringify({$schema:cy,...z},null,2)),!0}catch(V){if(V instanceof r)throw V;return!1}}var wd=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),ky=new Set(["add","remove","list"]),xy="cc-safety-net/rulebooks";async function kd(P,V){try{return await Cy(P,V)}catch(z){if(z instanceof r)return console.error(z.message),1;throw z}}async function Cy(P,V){let z=Ry(V),Q=z.help?Sy(z.positionals):null;if(Q)return wn(Q),0;if(z.errors.length>0){for(let ye of z.errors)console.error(ye);return 1}let te=z.positionals[0];if(!te)return wn(fn,console.error),1;let ne=z.positionals[1],ce={global:z.global};if(te==="init"){let ye=Pt(P,ce);Ay(ye.configTarget);let he=wy(ye.configDir,"example-rules","rulebook.json"),be=i(ye.filesystemScope,he);if(z.example&&n(be)===null)Vc(be);let xe=j(ye.configPath,ye.filesystemScope);for(let Ie of xe)console.error(Ie);if(xe.length>0)return 1;return console.log("Rule config initialized."),0}if(te==="add"){let ye=xd(z);if(!ye)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let he=Pt(P,ce),be=await cd(P,ye,{...ce,ref:z.ref,rulebooks:z.only.length>0?z.only:void 0});return Hc(be,ye,`Scope: ${z.global?"user":"project"} (${he.configDir})`),be.ok?0:1}if(te==="remove"){if(!ne)return console.error("rule remove requires a source"),1;let ye=await dd(P,ne,{...ce,deleteSource:z.deleteSource});return Mr(ye,`Removed rulebook source: ${ne}`),ye.ok?0:1}if(te==="update"){let ye=await zr(P,{...ce,only:ne,refresh:!0});return Mr(ye,"Rule config updated."),ye.ok?0:1}if(te==="sync")return Fs(P,{global:z.global});if(te==="list"){let ye=J(P,{cwd:process.cwd()});return Gc(ye),ye.errors.length>0?1:0}if(te==="wrapper")return _y(P,z);if(te==="migrate")return gd(P,{cleanup:z.cleanup,cwd:process.cwd()});if(te==="doc"){console.log(Nc);let ye=await hd(P);if(ye)console.error(ye);return 0}if(te==="verify")return bd(P);return 1}function Sy(P){if(P.length===0)return fn;let V=fn.subcommands.filter((Q)=>Q.usage.split(" ")[0]===P[0]);if(V.length===0)return null;if(P.length===1&&V.length>1)return{name:`rule ${P[0]}`,description:`Subcommands of rule ${P[0]}`,usage:`rule ${P[0]} <subcommand>`,subcommands:V,options:[]};let z=P.length===1?V[0]:V.find((Q)=>Q.usage.split(" ")[1]===P[1]);if(!z)return null;return{name:`rule ${P[0]}`,description:z.description,usage:`rule ${z.usage}`,options:P[0]==="add"?eo:[],examples:P[0]==="add"?to:void 0}}function Ry(P){let V=xt({label:"rule",booleans:{global:["-g","--global"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},P),z={...V.flags,ref:V.values.ref,only:V.lists.only??[],help:V.help,positionals:V.positionals,errors:V.errors};return Py(z),z}function Py(P){let[V]=P.positionals;if(V&&!wd.has(V))P.errors.push(`Unknown rule subcommand: ${V}`);if(P.deleteSource&&V!=="remove")if(V&&wd.has(V))P.errors.push(`Unknown option for rule ${V}: --delete-source`);else P.errors.push("--delete-source is only valid with 'rule remove'");if(P.cleanup&&V!=="migrate")P.errors.push(Wn(V,"--cleanup"));if(P.example&&V!=="init")P.errors.push(Wn(V,"--example"));if(P.ref&&V!=="add")P.errors.push(Wn(V,"--ref"));if(P.only.length>0&&V!=="add")P.errors.push(Wn(V,"--only"));if(V==="add")Ey(P);if(V==="migrate"){if(P.global)P.errors.push(Wn(V,"--global"));if(P.positionals.length>1)P.errors.push(`Unexpected rule migrate argument: ${P.positionals[1]}`)}else if(V==="wrapper")Dy(P);else if(P.positionals.length>2)P.errors.push(`Unexpected rule argument: ${P.positionals[2]}`);if(V==="list"&&P.global)P.errors.push("Unknown option for rule list: --global")}function xd(P){if(P.positionals[1])return P.positionals[1];if(P.ref||P.only.length>0)return xy;return}function Ey(P){let V=xd(P);if(!V)return;if((P.ref||P.only.length>0)&&!q(V)){if(P.ref)P.errors.push(`--ref can only select a ref for an owner/repo source: ${V}`);if(P.only.length>0)P.errors.push("--only can only select rulebooks from an owner/repo source");return}if(P.ref&&!oe(P.ref))P.errors.push(`--ref must use valid path segments: ${P.ref}`);let z=P.only.filter((Q)=>!l.test(Q));if(z.length>0)P.errors.push(`Invalid rulebook names: ${z.join(", ")}`)}function Wn(P,V){return P?`Unknown option for rule ${P}: ${V}`:`Unknown option for rule: ${V}`}function Dy(P){let V=P.positionals[1],z=P.positionals[2];if(!V){P.errors.push("rule wrapper requires add, remove, or list");return}if(!ky.has(V)){P.errors.push(`Unknown rule wrapper action: ${V}`);return}if(V==="list"){if(z)P.errors.push(`Unexpected rule wrapper argument: ${z}`);return}if(!z){P.errors.push(`rule wrapper ${V} requires a command`);return}if(P.positionals.length>3)P.errors.push(`Unexpected rule wrapper argument: ${P.positionals[3]}`)}function Ay(P){if(n(P)===null){qc(P);return}let V=m(P);if(!V.config)return;Rt(P,{version:1,rules:V.config.rules,overrides:V.config.overrides??{},transparent_wrappers:V.config.transparent_wrappers??[]})}async function _y(P,V){let z=V.positionals[1],Q=V.positionals[2],te=Pt(P,{global:V.global}).configTarget;if(z==="list"){let he=m(te);if(he.errors.length>0){for(let be of he.errors)console.error(be);return 1}return Ty(he.config?.transparent_wrappers??[]),0}if(!Q||!w.test(Q))return console.error("transparent wrapper must match command pattern"),1;if(Le(Q))return console.error(`reserved command "${Q}" cannot be a wrapper`),1;let ne=m(te);if(ne.errors.length>0){for(let he of ne.errors)console.error(he);return 1}let ce=ne.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},ye=z==="add"?[...new Set([...ce.transparent_wrappers??[],Q])]:(ce.transparent_wrappers??[]).filter((he)=>he!==Q);return Rt(te,{version:1,rules:ce.rules,overrides:ce.overrides??{},transparent_wrappers:ye}),console.log(z==="add"?`Added transparent wrapper: ${Q}`:`Removed transparent wrapper: ${Q}`),0}function Ty(P){if(P.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${P.length}):`);for(let V of P)console.log(` - ${V}`)}import{sep as Ny}from"node:path";import{existsSync as $y,readFileSync as Iy}from"node:fs";import{join as Oy}from"node:path";async function Fy(P){if(P.isTTY)return null;return(await We(P).catch(()=>null))?.trim()||null}function jy(P){let V=P.env.get("CLAUDE_SETTINGS_PATH");if(V)return V;return Oy(P.home,".claude","settings.json")}function Ri(P){let V=jy(P);if(!$y(V))return!1;try{let z=Iy(V,"utf-8"),Q=JSON.parse(z);if(!Q.enabledPlugins)return!1;let te="cc-safety-net@cc-marketplace";if(!(te in Q.enabledPlugins))return!1;return Q.enabledPlugins[te]===!0}catch(z){if(L(o.debug,P.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${V}: ${z instanceof Error?z.message:String(z)}`);return!1}}async function Pi(P,V=process.stdin){let z=Ri(P),Q;if(!z)Q="\uD83D\uDEE1️ CC Safety Net ❌";else{let ne=E(P,{cwd:process.cwd()}),ce=ne.policy,ye=R(ce,P.env),he=Object.values(G(ce,ye.capabilities)).some((Ie)=>Ie.changesInherited),be={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[he?"custom":ye.effectiveLevel],xe=(ne.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";Q=`\uD83D\uDEE1️ CC Safety Net ${be}${ye.worktreeMode?"\uD83C\uDF33":""}${xe}${ne.state==="degraded"?"⚠️":""}`}let te=await Fy(V);if(te&&!te.startsWith("{"))console.log(`${te} | ${Q}`);else console.log(Q)}function Cd(P){let V=E(P,{cwd:process.cwd()}),z=V.policy,Q=R(z,P.env),te=!!process.env.NO_COLOR||!process.stdout.isTTY,ne=Math.min(process.stdout.columns||80,100),ce=te?"ok":"✔",ye=te?"OFF":"✘",he=(at,ct)=>{let lt=` ${at.padEnd(13)}${ct}`;return(lt.length>ne?`${lt.slice(0,ne-1)}…`:lt).replaceAll(ye,dt.red(ye))},be=Object.values(G(z,Q.capabilities)).some((at)=>at.changesInherited),xe=(at)=>at===P.home||at.startsWith(`${P.home}${Ny}`)?`~${at.slice(P.home.length)}`:at,Ie={ready:dt.green,degraded:dt.yellow}[V.state],Xe=V.policyScopes?.weakenings??[],et=[...Ri(P)?[]:["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."],...V.diagnostics],Re=te?"-":"·";console.log([`${te?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ie(V.state)}`,"",he("Protection",`destructive ${z.destructiveCommandProtectionEnabled?ce:ye} secrets ${z.secretProtection.enabled?ce:ye}`),he("Level",be?`${Q.effectiveLevel} (customised)`:Q.effectiveLevel),he("Rules",z.rules.length===0?"none active":`${z.rules.length} active`),he("Policy",xe(u(P))),...V.policyScopes?[he("Project",xe(b(process.cwd())))]:[],...Q.worktreeMode?[he("Worktree","relaxations active")]:[],"",...Xe.length===0?[]:[" Project policy",...Xe.flatMap((at)=>jn(at," ",ne-6).map((ct,lt)=>lt===0?` ${ct}`:ct)),""],...et.length===0?[" Everything configured is active."]:[" Not active",...et.flatMap((at)=>jn(at," ",ne-6).map((ct,lt)=>lt===0?` ${Re} ${ct}`:ct)),""," Full report: cc-safety-net doctor"]].join(`
275
+ `))}import{spawn as Od}from"node:child_process";import{randomBytes as Wy}from"node:crypto";import{existsSync as Ky}from"node:fs";import{createServer as Yy}from"node:http";import{Writable as Zy}from"node:stream";var Kr=500;function My(P){let V=P.filter((te)=>te.decision!=="allow"),z=P.filter((te)=>te.decision==="allow"),Q=Math.min(V.length,Math.max(Kr-z.length,Math.ceil(Kr/2)));return[...V.slice(0,Q),...z.slice(0,Kr-Q)]}function Sd(P,V,z=O(P)){if(z)B(P,z);let Q=(ct)=>new Date(ct.getFullYear(),ct.getMonth(),ct.getDate()).getTime(),te=Q(new Date),ne=new Date(te);ne.setDate(ne.getDate()-(V-1));let ce=ne.getTime(),ye=[],he={count:0};for(let ct of z?Yt(z,he):[])for(let lt of pn(ct,he)){let pt=new Date(lt.ts).getTime();if(!Number.isFinite(pt))continue;if(pt>=ce)ye.push(lt)}ye.sort((ct,lt)=>new Date(lt.ts).getTime()-new Date(ct.ts).getTime());let be=Array.from({length:V},()=>0),xe=Array.from({length:V},()=>0),Ie={},Xe={},et={},Re=0,at=0;for(let ct of ye){let lt=ct.agent||"unknown";Ie[lt]=(Ie[lt]??0)+1;let pt=Math.round((te-Q(new Date(ct.ts)))/86400000),mt=V-1-pt,gt=pt>=0&&pt<V;if(gt)xe[mt]=(xe[mt]??0)+1;if(ct.decision!=="allow"){if(Re++,ct.ruleId)Xe[ct.ruleId]=(Xe[ct.ruleId]??0)+1;let ut=Qr(ct.segment||ct.command);if(ut)et[ut]=(et[ut]??0)+1;if(ct.failureStage)at++;if(gt)be[mt]=(be[mt]??0)+1}}return{days:V,logsDir:z,homeDir:P.home,totalInWindow:ye.length,truncated:ye.length>Kr,unreadable:he.count,counts:{blocked:Re,allowed:ye.length-Re,agents:Ie,blockedByDay:be,analyzedByDay:xe,rules:Xe,commands:et,errors:at},entries:My(ye).sort((ct,lt)=>new Date(lt.ts).getTime()-new Date(ct.ts).getTime())}}import{spawn as Hy}from"node:child_process";import{existsSync as Uy,statSync as Rd}from"node:fs";import{delimiter as Gy,join as By}from"node:path";var qy=120000,Yr="Choose the project folder",Vy=`try
276
276
  return POSIX path of (choose folder with prompt "${Yr}")
277
277
  on error number -128
278
278
  return ""
@@ -5905,6 +5905,6 @@ load().then((loaded) => {
5905
5905
  </script>
5906
5906
  </body>
5907
5907
  </html>
5908
- `;var Ad='<script id="ccsn-data" type="application/json">';function _d(P){return Dd.replace(Ad,()=>Ad+JSON.stringify({token:P}).replaceAll("<","\\u003c"))}var Zr="kenryu42/cc-safety-net",Xy=`https://github.com/${Zr}`,Ti=1e4,Qy=7,eh="The project draft directory changed; reload the draft before applying.",th="audit settings are user scope only; remove the audit section from a project proposal";async function Fd(P,V={}){let z=xt({label:"gui",booleans:{noOpen:["--no-open"]}},P),Q=V.log??console.log,te=V.error??console.error;if(z.errors.length>0){for(let ce of z.errors)te(ce);return te("Usage: cc-safety-net gui [--no-open]"),1}let ne=await nh(c,V);if(Q(`CC Safety Net policy GUI: ${ne.url}`),!z.flags.noOpen)try{await(V.openBrowser??fh)(ne.url)}catch(ce){te(`Failed to open browser: ${ce instanceof Error?ce.message:String(ce)}`),te(`Open this URL manually: ${ne.url}`)}if(V.keepAlive===!1)return await ne.close(),0;return await ph(ne),0}async function nh(P,V={}){let z=Wy(24).toString("base64url"),Q={dir:null,revision:0},te=Yy((ye,he)=>{rh(P,ye,he,z,V,Q)});await new Promise((ye,he)=>{te.once("error",he),te.listen(0,"127.0.0.1",()=>{te.off("error",he),ye()})});let ce=`http://127.0.0.1:${te.address().port}`;return{origin:ce,token:z,url:`${ce}/?token=${encodeURIComponent(z)}`,close:()=>uh(te)}}async function rh(P,V,z,Q,te,ne){let ce=P(),ye=new URL(V.url??"/","http://127.0.0.1");if(V.method==="GET"&&ye.pathname==="/favicon.ico"){z.writeHead(204,{"cache-control":"no-store"}),z.end();return}if(!lh(V,ye,Q)){yt(z,403,{error:"Forbidden"});return}if(V.method==="GET"&&ye.pathname==="/"){dh(z,_d(Q));return}if(V.method==="GET"&&ye.pathname==="/api/policy"){let he=_c(ce,te),be=E(ce,Ai(te));yt(z,200,{...he,configState:Ne(be),...be.policyScopes?{projectPolicy:{path:b(te.cwd??process.cwd()),weakenings:be.policyScopes.weakenings}}:{},destructiveCommandRules:U,secretPatterns:Ke,version:wt(),preview:he.errors.length>0?null:Ae(he.policy,ce.env)});return}if(V.method==="POST"&&ye.pathname==="/api/policy/preview"){let he=await Kn(V);if(!he.ok){yt(z,he.status,{errors:[he.error]});return}let be=Tc(ce,he.value);yt(z,be.errors.length>0?400:200,be);return}if(V.method==="POST"&&ye.pathname==="/api/policy/explain"){let he=await Kn(V);if(!he.ok){yt(z,he.status,{errors:[he.error]});return}let be=he.value;if(be===null||typeof be.command!=="string"){yt(z,400,{errors:["command must be a string"]});return}let Le=qn(be.policy,ce.home);if(Le.length>0){yt(z,400,{errors:Le});return}yt(z,200,sh(ce,be.command,be.policy,te));return}if(V.method==="POST"&&ye.pathname==="/api/policy"){let he=await Kn(V);if(!he.ok){yt(z,he.status,{errors:[he.error]});return}let be=Vt(ce,he.value,te);yt(z,be.errors.length>0?400:200,be);return}if(V.method==="POST"&&ye.pathname==="/api/reset"){yt(z,200,Vt(ce,Z,te));return}if(V.method==="POST"&&ye.pathname==="/api/repair"){yt(z,200,$c(ce,te));return}if(V.method==="POST"&&ye.pathname==="/api/policy/project/choose-directory"){let he=await(te.chooseDirectory??Di)();if("path"in he)ne.dir=he.path,ne.revision+=1;yt(z,200,{cancelled:"cancelled"in he,..."error"in he?{error:he.error}:{}});return}if(V.method==="GET"&&ye.pathname==="/api/policy/project"){let he=jd(ne,te),be=Td(he,ce.home),Le=Vn(ce,te);yt(z,200,{path:b(he),revision:ne.revision,baseline:Le.baseline,userPolicyDiagnostics:Le.diagnostics,projection:be.projection,projectionDiagnostics:be.diagnostics,canPickDirectory:Ei(process.platform,process.env)});return}if(V.method==="POST"&&ye.pathname==="/api/policy/project/diff"){let he=await $d(ce,V,z,ne,te);if(!he)return;let be=Td(he.dir,ce.home),Le=Vn(ce,te).baseline,Ie=Y(Le,ae(he.proposal,ce.home).policy);yt(z,200,{rows:jr(Y(Le,be.projection).policy,Ie.policy,!1),weakenings:Ie.weakenings,existingFileDiagnostics:be.diagnostics});return}if(V.method==="POST"&&ye.pathname==="/api/policy/project/apply"){let he=await $d(ce,V,z,ne,te);if(!he)return;let be=ih(he.dir,he.proposal,ce.home);yt(z,be.errors.length>0?500:200,be);return}if(V.method==="GET"&&ye.pathname==="/api/activity"){let he=ee(ce,te),be=ah(ye.searchParams.get("days"),he);if(be===null){yt(z,400,{error:`days must be an integer between 1 and ${he}`});return}yt(z,200,Sd(ce,be,te.activityLogsDir));return}if(V.method==="POST"&&ye.pathname==="/api/rules/choose-directory"){yt(z,200,await Di());return}if(V.method==="GET"&&ye.pathname==="/api/rules"){let he=J(ce,Ai(te)),be=new Map(he.rules.map((Le)=>[Le.name,Le]));yt(z,200,{projectPath:te.cwd??process.cwd(),canPickDirectory:Ei(process.platform,process.env),rulebooks:he.rulebooks.map((Le)=>({source:Le.source,spec:Le.spec,name:Le.name,version:Le.version,rules:Le.rules.flatMap((Ie)=>{let Xe=be.get(Ie);if(!Xe)return[];return[{name:Xe.name,command:Xe.command,subcommand:Xe.subcommand,block_args:Xe.block_args,reason:Xe.reason}]})})),errors:he.errors,warnings:he.warnings});return}if(V.method==="GET"&&ye.pathname==="/api/star/context"){yt(z,200,await(te.fetchStarContext??(()=>bh(ce,{logsDir:te.activityLogsDir})))());return}if(V.method==="POST"&&ye.pathname==="/api/star"){let he=await(te.starRepo??mh)();yt(z,200,he.ok?{ok:!0}:{ok:!1,fallbackUrl:Xy});return}if(V.method==="GET"&&ye.pathname==="/api/integrations"){yt(z,200,await(te.fetchIntegrations??(()=>gh(ce)))());return}if(V.method==="GET"&&ye.pathname==="/api/health"){yt(z,200,await(te.fetchHealth??hh)());return}if(V.method==="POST"&&(ye.pathname==="/api/install"||ye.pathname==="/api/uninstall")){let he=await Kn(V);if(!he.ok){yt(z,he.status,{errors:[he.error]});return}let be=he.value?.target;if(typeof be!=="string"||!Mt.some((Ie)=>Ie.target===be)){yt(z,400,{error:"unknown target"});return}let Le=ye.pathname==="/api/install"?"install":"uninstall";yt(z,200,await(te.runIntegration??vh)(Le,be));return}yt(z,404,{error:"Not found"})}function Ai(P){return{...P,cwd:P.cwd??process.cwd()}}function jd(P,V){return P.dir??V.cwd??process.cwd()}function Td(P,V){let z=b(P),Q=Ky(z)?dn(z):{value:void 0,errors:[]},te=ae(Q.value,V);return{projection:te.policy,diagnostics:[...Q.errors,...te.diagnostics]}}async function $d(P,V,z,Q,te){let ne=jd(Q,te),ce=Q.revision,ye=await Kn(V);if(!ye.ok)return yt(z,ye.status,{errors:[ye.error]}),null;let he=ye.value;if(typeof he?.revision!=="number")return yt(z,400,{errors:["revision must be a number"]}),null;if(he.revision!==ce)return yt(z,409,{errors:[eh]}),null;let be=oh(he.proposal,P.home);if(be.length>0)return yt(z,400,{errors:be}),null;return{dir:ne,proposal:he.proposal}}function oh(P,V){let z=qn(P,V);if(z.length>0)return z;return P?.audit===void 0?[]:[th]}function ih(P,V,z){let Q=b(P),te=Nr(V,C(V,z));try{return g(i(v(P,"project policy"),Q),`${JSON.stringify(te,null,2)}
5909
- `),{path:Q,errors:[]}}catch(ne){return{path:Q,errors:[ne instanceof Error?ne.message:String(ne)]}}}function sh(P,V,z,Q){let te=C(z,P.home),ne=E(P,Ai(Q)),ce=Ee({rules:ne.policy.rules,transparentWrappers:ne.policy.transparentWrappers,safety:De(te.safety),worktreeMode:te.workflow.worktree_mode,destructiveCommandProtectionEnabled:te.destructive_command_protection.enabled,destructiveCommandRuleOverrides:te.destructive_command_protection.overrides,destructiveCommandAllowPaths:te.destructive_command_protection.allow_paths,secretProtection:{enabled:te.secret_protection.enabled,disabledRules:Oe(te.secret_protection.overrides),denyPaths:te.secret_protection.deny_paths,allowPaths:te.secret_protection.allow_paths}});return Nn(V,{policySnapshot:ce,cwd:Q.cwd,userConfigDir:Q.userConfigDir},P)}function ah(P,V){if(P===null)return Math.min(Qy,V);let z=Number(P);if(!Number.isInteger(z)||z<1||z>V)return null;return z}function lh(P,V,z){if(V.searchParams.get("token")!==z)return!1;if(P.method!=="POST")return!0;return P.headers["x-cc-safety-net-token"]===z}var ch=1048576;async function Kn(P){let V=[],z=0;for await(let Q of P){let te=Q;if(z+=te.byteLength,z>ch)return{ok:!1,status:413,error:"Request body is too large"};V.push(te)}try{return{ok:!0,value:JSON.parse(Buffer.concat(V).toString("utf-8")||"{}")}}catch(Q){return{ok:!1,status:400,error:`Invalid JSON: ${Q instanceof Error?Q.message:String(Q)}`}}}function dh(P,V){P.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),P.end(V)}function yt(P,V,z){P.writeHead(V,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),P.end(JSON.stringify(z))}function uh(P){return new Promise((V,z)=>{P.close((Q)=>Q?z(Q):V())})}function ph(P){return new Promise((V)=>{let z=()=>{process.off("SIGINT",Q),process.off("SIGTERM",Q)},Q=()=>{z(),P.close().then(V)};process.once("SIGINT",Q),process.once("SIGTERM",Q)})}function fh(P){let V=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",z=process.platform==="win32"?["/c","start","",P]:[P];return new Promise((Q,te)=>{let ne=Od(V,z,{detached:!0,stdio:"ignore"}),ce=(he)=>{ne.off("spawn",ye),te(he)},ye=()=>{ne.off("error",ce),ne.unref(),Q()};ne.once("error",ce),ne.once("spawn",ye)})}async function mh(P="gh",V=Ti){return{ok:await _i(P,["api","-X","PUT",`/user/starred/${Zr}`],V)===0}}async function gh(P,V={}){let z=await sr(V.fetcher),Q=yh(P,z);return{targets:$t.map((te)=>{let ne=Q.find((ce)=>ce.platform===te.id);return{target:te.id,label:bt(te.id),version:z.versions[te.id]??null,status:ne?.configured?"active":ne?.detected?"disabled":ne?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:z.version,nodeVersion:z.nodeVersion,platform:z.platform}}}function yh(P,V){return Ln(P,process.cwd(),{ampPluginListOutput:V.ampPluginListOutput,codexPluginListOutput:V.codexPluginListOutput,copilotCliVersion:V.versions["copilot-cli"]})}async function hh(P={}){let V=await(P.checkUpdates??Wt)();return{update:{latestVersion:V.latestVersion??null,updateAvailable:V.updateAvailable}}}var Id=Promise.resolve();function vh(P,V,z={}){let Q=async()=>{let ne=[],{log:ce,error:ye}=console;console.log=(...he)=>ne.push(he.map(String).join(" ")),console.error=console.log;try{return{ok:await Bn(P,[],{selectTargets:async()=>[V],output:new Zy({write(be,Le,Ie){ne.push(String(be).replace(/\n$/,"")),Ie()}}),...z})===0,output:ne.join(`
5908
+ `;var Ad='<script id="ccsn-data" type="application/json">';function _d(P){return Dd.replace(Ad,()=>Ad+JSON.stringify({token:P}).replaceAll("<","\\u003c"))}var Zr="kenryu42/cc-safety-net",Xy=`https://github.com/${Zr}`,Ti=1e4,Qy=7,eh="The project draft directory changed; reload the draft before applying.",th="audit settings are user scope only; remove the audit section from a project proposal";async function Fd(P,V={}){let z=xt({label:"gui",booleans:{noOpen:["--no-open"]}},P),Q=V.log??console.log,te=V.error??console.error;if(z.errors.length>0){for(let ce of z.errors)te(ce);return te("Usage: cc-safety-net gui [--no-open]"),1}let ne=await nh(c,V);if(Q(`CC Safety Net policy GUI: ${ne.url}`),!z.flags.noOpen)try{await(V.openBrowser??fh)(ne.url)}catch(ce){te(`Failed to open browser: ${ce instanceof Error?ce.message:String(ce)}`),te(`Open this URL manually: ${ne.url}`)}if(V.keepAlive===!1)return await ne.close(),0;return await ph(ne),0}async function nh(P,V={}){let z=Wy(24).toString("base64url"),Q={dir:null,revision:0},te=Yy((ye,he)=>{rh(P,ye,he,z,V,Q)});await new Promise((ye,he)=>{te.once("error",he),te.listen(0,"127.0.0.1",()=>{te.off("error",he),ye()})});let ce=`http://127.0.0.1:${te.address().port}`;return{origin:ce,token:z,url:`${ce}/?token=${encodeURIComponent(z)}`,close:()=>uh(te)}}async function rh(P,V,z,Q,te,ne){let ce=P(),ye=new URL(V.url??"/","http://127.0.0.1");if(V.method==="GET"&&ye.pathname==="/favicon.ico"){z.writeHead(204,{"cache-control":"no-store"}),z.end();return}if(!lh(V,ye,Q)){yt(z,403,{error:"Forbidden"});return}if(V.method==="GET"&&ye.pathname==="/"){dh(z,_d(Q));return}if(V.method==="GET"&&ye.pathname==="/api/policy"){let he=_c(ce,te),be=E(ce,Ai(te));yt(z,200,{...he,configState:Ne(be),...be.policyScopes?{projectPolicy:{path:b(te.cwd??process.cwd()),weakenings:be.policyScopes.weakenings}}:{},destructiveCommandRules:U,secretPatterns:Ke,version:wt(),preview:he.errors.length>0?null:Ae(he.policy,ce.env)});return}if(V.method==="POST"&&ye.pathname==="/api/policy/preview"){let he=await Kn(V);if(!he.ok){yt(z,he.status,{errors:[he.error]});return}let be=Tc(ce,he.value);yt(z,be.errors.length>0?400:200,be);return}if(V.method==="POST"&&ye.pathname==="/api/policy/explain"){let he=await Kn(V);if(!he.ok){yt(z,he.status,{errors:[he.error]});return}let be=he.value;if(be===null||typeof be.command!=="string"){yt(z,400,{errors:["command must be a string"]});return}let xe=qn(be.policy,ce.home);if(xe.length>0){yt(z,400,{errors:xe});return}yt(z,200,sh(ce,be.command,be.policy,te));return}if(V.method==="POST"&&ye.pathname==="/api/policy"){let he=await Kn(V);if(!he.ok){yt(z,he.status,{errors:[he.error]});return}let be=Vt(ce,he.value,te);yt(z,be.errors.length>0?400:200,be);return}if(V.method==="POST"&&ye.pathname==="/api/reset"){yt(z,200,Vt(ce,Z,te));return}if(V.method==="POST"&&ye.pathname==="/api/repair"){yt(z,200,$c(ce,te));return}if(V.method==="POST"&&ye.pathname==="/api/policy/project/choose-directory"){let he=await(te.chooseDirectory??Di)();if("path"in he)ne.dir=he.path,ne.revision+=1;yt(z,200,{cancelled:"cancelled"in he,..."error"in he?{error:he.error}:{}});return}if(V.method==="GET"&&ye.pathname==="/api/policy/project"){let he=jd(ne,te),be=Td(he,ce.home),xe=Vn(ce,te);yt(z,200,{path:b(he),revision:ne.revision,baseline:xe.baseline,userPolicyDiagnostics:xe.diagnostics,projection:be.projection,projectionDiagnostics:be.diagnostics,canPickDirectory:Ei(process.platform,process.env)});return}if(V.method==="POST"&&ye.pathname==="/api/policy/project/diff"){let he=await $d(ce,V,z,ne,te);if(!he)return;let be=Td(he.dir,ce.home),xe=Vn(ce,te).baseline,Ie=Y(xe,ae(he.proposal,ce.home).policy);yt(z,200,{rows:jr(Y(xe,be.projection).policy,Ie.policy,!1),weakenings:Ie.weakenings,existingFileDiagnostics:be.diagnostics});return}if(V.method==="POST"&&ye.pathname==="/api/policy/project/apply"){let he=await $d(ce,V,z,ne,te);if(!he)return;let be=ih(he.dir,he.proposal,ce.home);yt(z,be.errors.length>0?500:200,be);return}if(V.method==="GET"&&ye.pathname==="/api/activity"){let he=ee(ce,te),be=ah(ye.searchParams.get("days"),he);if(be===null){yt(z,400,{error:`days must be an integer between 1 and ${he}`});return}yt(z,200,Sd(ce,be,te.activityLogsDir));return}if(V.method==="POST"&&ye.pathname==="/api/rules/choose-directory"){yt(z,200,await Di());return}if(V.method==="GET"&&ye.pathname==="/api/rules"){let he=J(ce,Ai(te)),be=new Map(he.rules.map((xe)=>[xe.name,xe]));yt(z,200,{projectPath:te.cwd??process.cwd(),canPickDirectory:Ei(process.platform,process.env),rulebooks:he.rulebooks.map((xe)=>({source:xe.source,spec:xe.spec,name:xe.name,version:xe.version,rules:xe.rules.flatMap((Ie)=>{let Xe=be.get(Ie);if(!Xe)return[];return[{name:Xe.name,command:Xe.command,subcommand:Xe.subcommand,block_args:Xe.block_args,reason:Xe.reason}]})})),errors:he.errors,warnings:he.warnings});return}if(V.method==="GET"&&ye.pathname==="/api/star/context"){yt(z,200,await(te.fetchStarContext??(()=>bh(ce,{logsDir:te.activityLogsDir})))());return}if(V.method==="POST"&&ye.pathname==="/api/star"){let he=await(te.starRepo??mh)();yt(z,200,he.ok?{ok:!0}:{ok:!1,fallbackUrl:Xy});return}if(V.method==="GET"&&ye.pathname==="/api/integrations"){yt(z,200,await(te.fetchIntegrations??(()=>gh(ce)))());return}if(V.method==="GET"&&ye.pathname==="/api/health"){yt(z,200,await(te.fetchHealth??hh)());return}if(V.method==="POST"&&(ye.pathname==="/api/install"||ye.pathname==="/api/uninstall")){let he=await Kn(V);if(!he.ok){yt(z,he.status,{errors:[he.error]});return}let be=he.value?.target;if(typeof be!=="string"||!Mt.some((Ie)=>Ie.target===be)){yt(z,400,{error:"unknown target"});return}let xe=ye.pathname==="/api/install"?"install":"uninstall";yt(z,200,await(te.runIntegration??vh)(xe,be));return}yt(z,404,{error:"Not found"})}function Ai(P){return{...P,cwd:P.cwd??process.cwd()}}function jd(P,V){return P.dir??V.cwd??process.cwd()}function Td(P,V){let z=b(P),Q=Ky(z)?dn(z):{value:void 0,errors:[]},te=ae(Q.value,V);return{projection:te.policy,diagnostics:[...Q.errors,...te.diagnostics]}}async function $d(P,V,z,Q,te){let ne=jd(Q,te),ce=Q.revision,ye=await Kn(V);if(!ye.ok)return yt(z,ye.status,{errors:[ye.error]}),null;let he=ye.value;if(typeof he?.revision!=="number")return yt(z,400,{errors:["revision must be a number"]}),null;if(he.revision!==ce)return yt(z,409,{errors:[eh]}),null;let be=oh(he.proposal,P.home);if(be.length>0)return yt(z,400,{errors:be}),null;return{dir:ne,proposal:he.proposal}}function oh(P,V){let z=qn(P,V);if(z.length>0)return z;return P?.audit===void 0?[]:[th]}function ih(P,V,z){let Q=b(P),te=Nr(V,C(V,z));try{return g(i(v(P,"project policy"),Q),`${JSON.stringify(te,null,2)}
5909
+ `),{path:Q,errors:[]}}catch(ne){return{path:Q,errors:[ne instanceof Error?ne.message:String(ne)]}}}function sh(P,V,z,Q){let te=C(z,P.home),ne=E(P,Ai(Q)),ce=Ee({rules:ne.policy.rules,transparentWrappers:ne.policy.transparentWrappers,safety:De(te.safety),worktreeMode:te.workflow.worktree_mode,destructiveCommandProtectionEnabled:te.destructive_command_protection.enabled,destructiveCommandRuleOverrides:te.destructive_command_protection.overrides,destructiveCommandAllowPaths:te.destructive_command_protection.allow_paths,secretProtection:{enabled:te.secret_protection.enabled,disabledRules:Oe(te.secret_protection.overrides),denyPaths:te.secret_protection.deny_paths,allowPaths:te.secret_protection.allow_paths}});return Nn(V,{policySnapshot:ce,cwd:Q.cwd,userConfigDir:Q.userConfigDir},P)}function ah(P,V){if(P===null)return Math.min(Qy,V);let z=Number(P);if(!Number.isInteger(z)||z<1||z>V)return null;return z}function lh(P,V,z){if(V.searchParams.get("token")!==z)return!1;if(P.method!=="POST")return!0;return P.headers["x-cc-safety-net-token"]===z}var ch=1048576;async function Kn(P){let V=[],z=0;for await(let Q of P){let te=Q;if(z+=te.byteLength,z>ch)return{ok:!1,status:413,error:"Request body is too large"};V.push(te)}try{return{ok:!0,value:JSON.parse(Buffer.concat(V).toString("utf-8")||"{}")}}catch(Q){return{ok:!1,status:400,error:`Invalid JSON: ${Q instanceof Error?Q.message:String(Q)}`}}}function dh(P,V){P.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),P.end(V)}function yt(P,V,z){P.writeHead(V,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),P.end(JSON.stringify(z))}function uh(P){return new Promise((V,z)=>{P.close((Q)=>Q?z(Q):V())})}function ph(P){return new Promise((V)=>{let z=()=>{process.off("SIGINT",Q),process.off("SIGTERM",Q)},Q=()=>{z(),P.close().then(V)};process.once("SIGINT",Q),process.once("SIGTERM",Q)})}function fh(P){let V=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",z=process.platform==="win32"?["/c","start","",P]:[P];return new Promise((Q,te)=>{let ne=Od(V,z,{detached:!0,stdio:"ignore"}),ce=(he)=>{ne.off("spawn",ye),te(he)},ye=()=>{ne.off("error",ce),ne.unref(),Q()};ne.once("error",ce),ne.once("spawn",ye)})}async function mh(P="gh",V=Ti){return{ok:await _i(P,["api","-X","PUT",`/user/starred/${Zr}`],V)===0}}async function gh(P,V={}){let z=await sr(V.fetcher),Q=yh(P,z);return{targets:$t.map((te)=>{let ne=Q.find((ce)=>ce.platform===te.id);return{target:te.id,label:bt(te.id),version:z.versions[te.id]??null,status:ne?.configured?"active":ne?.detected?"disabled":ne?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:z.version,nodeVersion:z.nodeVersion,platform:z.platform}}}function yh(P,V){return Ln(P,process.cwd(),{ampPluginListOutput:V.ampPluginListOutput,codexPluginListOutput:V.codexPluginListOutput,copilotCliVersion:V.versions["copilot-cli"]})}async function hh(P={}){let V=await(P.checkUpdates??Wt)();return{update:{latestVersion:V.latestVersion??null,updateAvailable:V.updateAvailable}}}var Id=Promise.resolve();function vh(P,V,z={}){let Q=async()=>{let ne=[],{log:ce,error:ye}=console;console.log=(...he)=>ne.push(he.map(String).join(" ")),console.error=console.log;try{return{ok:await Bn(P,[],{selectTargets:async()=>[V],output:new Zy({write(be,xe,Ie){ne.push(String(be).replace(/\n$/,"")),Ie()}}),...z})===0,output:ne.join(`
5910
5910
  `)}}finally{console.log=ce,console.error=ye}},te=Id.then(Q);return Id=te.then(()=>{return},()=>{return}),te}async function bh(P,V={}){let[z,Q,te]=await Promise.all([Lh(V.command),wh(V.fetchRepo),Promise.resolve(tr(P,ee(P),V.logsDir).totalBlocked)]);return{starred:z,starCount:Q,blockedTotal:te}}async function Lh(P="gh",V=Ti){if(await _i(P,["auth","status"],V)!==0)return null;let z=await _i(P,["api",`/user/starred/${Zr}`],V);if(z===0)return!0;if(z===null)return null;return!1}function _i(P,V,z){return new Promise((Q)=>{let te=Od(P,V,{stdio:"ignore",windowsHide:!0}),ne=!1,ce,ye=(he)=>{if(ne)return;if(ne=!0,ce)clearTimeout(ce);Q(he)};te.once("error",()=>ye(null)),te.once("close",ye),ce=setTimeout(()=>{te.kill(),ye(null)},z)})}async function wh(P=fetch){try{let V=await P(`https://api.github.com/repos/${Zr}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(Ti)});if(!V.ok)return null;let z=await V.json();return typeof z.stargazers_count==="number"?z.stargazers_count:null}catch{return null}}function kh(P){if(P[0]!=="help")return!1;let V=P[1];if(!V)ti(),process.exit(0);if(Mn(V))process.exit(0);console.error(`Unknown command: ${V}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var xh={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),Mn("hook",console.error),process.exit(1)},install:async(P)=>{process.exit(await Bn("install",P))},update:async(P)=>{process.exit(await yi(P))},uninstall:async(P)=>{process.exit(await Bn("uninstall",P))},rule:async(P)=>{process.exit(await kd(c(),P))},policy:async(P)=>{process.exit(await jc(c(),P))},status:async(P)=>{if(Ht(xt({label:"status"},P).errors))process.exit(1);Cd(c())},statusline:async(P)=>{let V=xt({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},P);if(V.errors.length===0&&V.flags.claudeCode){await Pi(c());return}if(Ht(V.errors),!V.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");Mn("statusline",console.error),process.exit(1)},doctor:async(P)=>{let V=Jo(P);if(!V)process.exit(1);let z=await cl(c(),{json:V.json,skipUpdateCheck:V.skipUpdateCheck});process.exit(z)},logs:async(P)=>{process.exit(await Hi(c(),P))},gui:async(P)=>{process.exit(await Fd(P))},explain:async(P)=>{process.exit(await Ll(c(),P))}};async function Ch(P){let V=xt({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},P);if(kh(P))return;let z=P[0],Q=z?er(z):void 0;if(V.help&&Q&&Q.name!=="rule")Mn(Q.name),process.exit(0);if(!z||V.help&&!Q)ti(),process.exit(0);if(V.flags.version)xl(),process.exit(0);if(Q){await xh[Q.name](P.slice(1));return}if(z==="--statusline"){await Pi(c());return}console.error(z.startsWith("-")?`Unknown option: ${z}`:`Unknown command: ${z}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{Ch as runCli};