cc-safety-net 2.4.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,47 +1,47 @@
1
- import{n,a,Oe,Ye,R,ot,Je,l,i,Ze,P,_,Le,st,f,Xe,u,o,S,s,D,r,y,ue,G,lt,ct,c,pe,fe,dt,O,Y,ie,x,ut,A,w,me,T,d,H,Qe,et,N,L,I,J,ge,Me,pt,m,e,g,$e,ke,tt,nt,se,Ee,ae,Fe,Z,W,Re,je,he,Pe,U,rt,_e,Ae,Te,Ie,ye,ve,B,X,Q,le,h,z,Ge,We,Ue,k,Be,De,ze,v,t,ee,be,b,C,E,ft,Ve,qe,p,V}from"./chunks/index-chc1n91k.js";import{ne,q,Ke,M,F}from"./chunks/index-ver1bgty.js";var su=["-h","--help"];function At(j,K){let te=Object.entries(j.booleans??{}),re=Object.entries(j.values??{}),oe=Object.entries(j.lists??{}),ce=Object.fromEntries(te.map(([He])=>[He,!1])),de={},we=Object.fromEntries(oe.map(([He])=>[He,[]])),xe=[],Ce=[],Se=!1,Ne=-1;for(let[He,at]of K.entries()){if(He<=Ne)continue;if(at==="--"){xe.push(...K.slice(He+1));break}if(su.includes(at)){Se=!0;continue}let mt=te.find(([,ht])=>ht.includes(at));if(mt){ce[mt[0]]=!0;continue}let it=re.find(([,ht])=>ht.includes(at));if(it){let ht=K[He+1];if(ht===void 0||ht.startsWith("-")){Ce.push(`${at} requires a value`);continue}de[it[0]]=ht,Ne=He+1;continue}let gt=oe.find(([,ht])=>ht.includes(at));if(gt){let ht=K.slice(He+1),vt=ht.findIndex((kt)=>kt.startsWith("-")),yt=ht.slice(0,vt===-1?ht.length:vt);if(yt.length===0){Ce.push(`${at} requires at least one value`);continue}we[gt[0]]=[...we[gt[0]]??[],...yt],Ne=He+yt.length;continue}if(at.startsWith("-")){Ce.push(`Unknown option for ${j.label}: ${at}`);continue}if(j.positionals==="tail"){xe.push(...K.slice(He));break}xe.push(at)}if(j.positionals!=="list"&&j.positionals!=="tail")Ce.push(...xe.map((He)=>`Unexpected argument for ${j.label}: ${He}`));return{flags:ce,values:de,lists:we,positionals:xe,help:Se,errors:Ce}}function Kt(j){for(let K of j)console.error(K);return j.length>0}import{readdirSync as fu,statSync as Zi,unlinkSync as mu}from"node:fs";import{basename as Xi,dirname as gu,isAbsolute as yu,join as hu,relative as vu,resolve as bu,sep as Lu}from"node:path";import{existsSync as au,readdirSync as lu,readFileSync as cu}from"node:fs";import{join as du}from"node:path";var Wi=(j)=>{let K=Date.now()-new Date(j).getTime();if(!Number.isFinite(K))return"";let te=Math.floor(K/60000),re=Math.floor(te/60),oe=Math.floor(re/24);if(oe>0)return`${oe}d ago`;if(re>0)return`${re}h ago`;if(te>0)return`${te}m ago`;return"just now"},dr=(j)=>{let K=(j??"").trim().split(/\s+/).filter((oe)=>oe&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(oe)),te=K[0]?.split("/").pop();if(!te)return null;let re=K[1];return re&&/^[a-z][a-z0-9-]*$/.test(re)?`${te} ${re}`:te};function an(j,K){try{return lu(j,{withFileTypes:!0,encoding:"utf8"}).flatMap((te)=>{let re=du(j,te.name);if(te.isDirectory())return an(re,K);if(te.name.endsWith(".jsonl"))return[re];return[]})}catch{if(K&&au(j))K.count++;return[]}}function Ki(j){let K=(oe)=>`${oe.sessionId}
1
+ import{n,a,Oe,Ye,R,ot,Je,l,i,Ze,P,_,Le,st,f,Xe,u,o,S,s,D,r,y,ue,G,lt,ct,c,pe,fe,dt,O,Y,ie,x,ut,A,w,me,T,d,H,Qe,et,N,L,I,J,ge,Me,pt,m,e,g,$e,ke,tt,nt,se,Ee,ae,Fe,Z,W,Re,je,he,Pe,U,rt,_e,Ae,Te,Ie,ye,ve,B,X,Q,le,h,z,Ge,We,Ue,k,Be,De,ze,v,t,ee,be,b,C,E,ft,Ve,qe,p,V}from"./chunks/index-chc1n91k.js";import{ne,q,Ke,M,F}from"./chunks/index-31w7hfwv.js";var su=["-h","--help"];function At(j,K){let te=Object.entries(j.booleans??{}),re=Object.entries(j.values??{}),oe=Object.entries(j.lists??{}),ce=Object.fromEntries(te.map(([He])=>[He,!1])),de={},we=Object.fromEntries(oe.map(([He])=>[He,[]])),xe=[],Ce=[],Se=!1,Ne=-1;for(let[He,at]of K.entries()){if(He<=Ne)continue;if(at==="--"){xe.push(...K.slice(He+1));break}if(su.includes(at)){Se=!0;continue}let mt=te.find(([,ht])=>ht.includes(at));if(mt){ce[mt[0]]=!0;continue}let it=re.find(([,ht])=>ht.includes(at));if(it){let ht=K[He+1];if(ht===void 0||ht.startsWith("-")){Ce.push(`${at} requires a value`);continue}de[it[0]]=ht,Ne=He+1;continue}let gt=oe.find(([,ht])=>ht.includes(at));if(gt){let ht=K.slice(He+1),vt=ht.findIndex((kt)=>kt.startsWith("-")),yt=ht.slice(0,vt===-1?ht.length:vt);if(yt.length===0){Ce.push(`${at} requires at least one value`);continue}we[gt[0]]=[...we[gt[0]]??[],...yt],Ne=He+yt.length;continue}if(at.startsWith("-")){Ce.push(`Unknown option for ${j.label}: ${at}`);continue}if(j.positionals==="tail"){xe.push(...K.slice(He));break}xe.push(at)}if(j.positionals!=="list"&&j.positionals!=="tail")Ce.push(...xe.map((He)=>`Unexpected argument for ${j.label}: ${He}`));return{flags:ce,values:de,lists:we,positionals:xe,help:Se,errors:Ce}}function Kt(j){for(let K of j)console.error(K);return j.length>0}import{readdirSync as fu,statSync as Qi,unlinkSync as mu}from"node:fs";import{basename as es,dirname as gu,isAbsolute as yu,join as hu,relative as vu,resolve as bu,sep as Lu}from"node:path";import{existsSync as au,readdirSync as lu,readFileSync as cu}from"node:fs";import{join as du}from"node:path";var Yi=(j)=>{let K=Date.now()-new Date(j).getTime();if(!Number.isFinite(K))return"";let te=Math.floor(K/60000),re=Math.floor(te/60),oe=Math.floor(re/24);if(oe>0)return`${oe}d ago`;if(re>0)return`${re}h ago`;if(te>0)return`${te}m ago`;return"just now"},dr=(j)=>{let K=(j??"").trim().split(/\s+/).filter((oe)=>oe&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(oe)),te=K[0]?.split("/").pop();if(!te)return null;let re=K[1];return re&&/^[a-z][a-z0-9-]*$/.test(re)?`${te} ${re}`:te};function an(j,K){try{return lu(j,{withFileTypes:!0,encoding:"utf8"}).flatMap((te)=>{let re=du(j,te.name);if(te.isDirectory())return an(re,K);if(te.name.endsWith(".jsonl"))return[re];return[]})}catch{if(K&&au(j))K.count++;return[]}}function Zi(j){let K=(oe)=>`${oe.sessionId}
2
2
  ${dr(oe.segment||oe.command)}`,te=j.filter((oe)=>oe.decision!=="allow"),re=te.filter((oe)=>oe.sessionId).reduce((oe,ce)=>oe.set(K(ce),(oe.get(K(ce))??0)+1),new Map);return new Set(te.filter((oe)=>oe.failureStage||(re.get(K(oe))??0)>=2))}var uu=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function pu(j){if(!j||typeof j!=="object"||Array.isArray(j))return!1;let K=j;if(typeof K.ts!=="string"||typeof K.command!=="string")return!1;return uu.every((te)=>K[te]===void 0||typeof K[te]==="string")}function wn(j,K){try{return cu(j,"utf-8").split(`
3
- `).filter(Boolean).flatMap((te)=>{try{let re=JSON.parse(te);if(!pu(re)){if(K)K.count++;return[]}return[re]}catch{if(K)K.count++;return[]}})}catch{if(K)K.count++;return[]}}function _t(j){return Array.from(j,(K)=>{let te=K.charCodeAt(0);if(te<=31||te>=127&&te<=159)return`\\x${te.toString(16).padStart(2,"0")}`;return K}).join("")}function wu(j,K){let te=ne(j),re=At({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"]}},K);if(Kt(re.errors))return null;if(re.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(re.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let oe=re.values.limit===void 0?20:Yi(re.values.limit);if(oe===null)return console.error("--limit must be a positive number"),null;let ce=re.values.since===void 0?Math.min(30,te):Yi(re.values.since);if(ce===null||ce>te)return console.error(`--since must be a positive number of days no greater than ${te}`),null;let de={limit:oe,limitExplicit:re.values.limit!==void 0,since:ce,sinceExplicit:re.values.since!==void 0,all:re.flags.all,json:re.flags.json,suspect:re.flags.suspect,pruneLegacy:re.flags.pruneLegacy,dryRun:re.flags.dryRun,id:re.values.id,agent:re.values.agent,rule:re.values.rule,session:re.values.session,project:re.values.project===void 0?void 0:bu(re.values.project)};if(de.id&&(de.agent!==void 0||de.rule!==void 0||de.session!==void 0||de.project!==void 0||de.suspect||de.sinceExplicit||de.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(de.pruneLegacy&&(de.id!==void 0||de.agent!==void 0||de.rule!==void 0||de.session!==void 0||de.project!==void 0||de.suspect||de.all||de.sinceExplicit||de.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(de.dryRun&&!de.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return de}async function Qi(j,K,te={}){let re=wu(j,K);if(!re)return 1;let oe=te.logsDir??M(j);if(re.pruneLegacy)return ku(oe,re.json,re.dryRun);if(!oe)return console.log(re.json?"[]":re.id?`No retained audit log entry found for id ${_t(re.id)}.`:"No audit log entries found."),0;q(j,oe);let ce={count:0},de=an(oe,ce).flatMap((Ne)=>wn(Ne,ce).map((He)=>({entry:He,file:Ne})));if(ce.count>0)console.error(`warning: ${ce.count} audit log ${ce.count===1?"source":"sources"} could not be read; these results are incomplete`);if(re.id)return Ru(de,re,te.timeZone);let we=Date.now()-re.since*24*60*60*1000,xe=de.filter((Ne)=>Pu(Ne,re,oe,we)),Ce=re.suspect?Ki(xe.map((Ne)=>Ne.entry)):null,Se=(Ce?xe.filter((Ne)=>Ce.has(Ne.entry)):xe).sort((Ne,He)=>Date.parse(He.entry.ts)-Date.parse(Ne.entry.ts)).slice(0,re.limit);if(re.json)return console.log(JSON.stringify(Se.map((Ne)=>Ne.entry),null,2)),0;if(Se.length===0)return console.log("No audit log entries found."),0;for(let Ne of Se)console.log(Au(Ne.entry,te.timeZone));return 0}function ku(j,K,te){let re=j?Cu(j).map((we)=>hu(j,we)):[];if(te)return xu(re,K);let oe=[],ce=0,de=0;for(let we of re){let xe=Zi(we,{throwIfNoEntry:!1})?.size??0,Ce=Su(we);if(Ce){oe.push(`${Xi(we)}: ${Ce}`);continue}ce++,de+=xe}if(K)return console.log(JSON.stringify({removedFiles:ce,removedBytes:de,failedFiles:oe.length})),oe.length===0?0:1;console.log(ce===0&&oe.length===0?"No legacy audit log files found.":`Removed ${ce} legacy audit log ${ce===1?"file":"files"} (${es(de)}).`);for(let we of oe)console.error(`Could not remove ${_t(we)}`);if(console.log("Nested v2 audit logs were not changed."),ce>0)console.log("This deletion cannot be undone.");return oe.length===0?0:1}function xu(j,K){let te=j.reduce((re,oe)=>re+(Zi(oe,{throwIfNoEntry:!1})?.size??0),0);if(K)return console.log(JSON.stringify({dryRun:!0,files:j.length,bytes:te})),0;if(console.log(j.length===0?"No legacy audit log files found.":`Would remove ${j.length} legacy audit log ${j.length===1?"file":"files"} (${es(te)}).`),console.log("Nested v2 audit logs are not included."),j.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Cu(j){try{return fu(j,{withFileTypes:!0}).filter((K)=>K.isFile()&&K.name.endsWith(".jsonl")).map((K)=>K.name)}catch{return[]}}function Su(j){try{return mu(j),null}catch(K){return K instanceof Error?K.message:String(K)}}function es(j){let K=["B","KiB","MiB","GiB"],te=Math.min(Math.floor(Math.log2(Math.max(j,1))/10),K.length-1);return`${Math.round(j/1024**te*10)/10} ${K[te]}`}function Ru(j,K,te){let re=j.filter((ce)=>ce.entry.id===K.id);if(re.length>1)return console.error(`Multiple audit log entries found for id ${_t(K.id??"")}.`),1;if(K.json)return console.log(JSON.stringify(re.map((ce)=>ce.entry),null,2)),0;let oe=re[0];if(!oe)return console.log(`No retained audit log entry found for id ${_t(K.id??"")}.`),0;return console.log(_u(oe.entry,te)),0}function Pu(j,K,te,re){if(!K.all&&j.entry.decision==="allow")return!1;if(Date.parse(j.entry.ts)<re)return!1;if(K.agent!==void 0&&j.entry.agent!==K.agent)return!1;if(K.rule!==void 0&&j.entry.ruleId!==K.rule)return!1;if(K.session!==void 0&&!Eu(j,te,K.session))return!1;if(K.project!==void 0&&!Du(j.entry.cwd,K.project))return!1;return!0}function Eu(j,K,te){if(j.entry.sessionId===te)return!0;return gu(j.file)===K&&Xi(j.file,".jsonl")===te}function Du(j,K){if(!j)return!1;let te=vu(K,j);return te!==".."&&!te.startsWith(`..${Lu}`)&&!yu(te)}function Au(j,K){let te=_t(j.id??"-"),re=_t(j.decision??"deny"),oe=j.cwd?` [${_t(j.cwd)}]`:"",ce=j.segment||j.command,de=ce===j.command?"":"↳ ",we=ce.length>50?`${ce.slice(0,50)}…`:ce;return`${te.padEnd(16)} ${_t(ts(j.ts,K))} ${re.padEnd(5)} ${_t(j.agent??"-").padEnd(15)} ${_t(j.ruleId??"-").padEnd(20)} ${de}${_t(we)}${oe}`}function _u(j,K){let te=(oe)=>_t(oe===void 0||oe===null||oe===""?"-":oe),re=j.shape?`${j.agent??"-"} (shape: ${j.shape})`:j.agent??"-";return[`id: ${te(j.id)}`,`ts: ${te(ts(j.ts,K))}`,`decision: ${te(j.decision)}`,`agent: ${te(re)}`,`level: ${te(j.level)}`,`tool: ${te(j.toolName)}`,`rule: ${te(j.ruleId)}`,`intent: ${te(j.intent)}`,`stage: ${te(j.failureStage)}`,`error: ${te(j.errorCode)}`,`session: ${te(j.sessionId)}`,`cwd: ${te(j.cwd)}`,`version: ${te(j.v)}`,`truncated: ${te(j.truncated===!0?"yes":void 0)}`,`reason: ${te(j.reason)}`,`command: ${te(j.command)}`,`segment: ${te(j.segment)}`].join(`
4
- `)}function ts(j,K){let te=new Date(j);if(Number.isNaN(te.getTime()))return j;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:K}).format(te)}function Yi(j){let K=Number(j);return Number.isFinite(K)&&K>0?K:null}var ns={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 rs={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 os={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 Nn=[{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"]}}],ur=Nn.slice().sort((j,K)=>j.doctorOrder-K.doctorOrder).map((j)=>j.id),Mn=Nn.filter((j)=>("runtime"in j)).slice().sort((j,K)=>j.runtime.order-K.runtime.order).map((j)=>({id:j.id,displayName:"displayName"in j.runtime?j.runtime.displayName:j.displayName,flags:j.runtime.flags,legacyFlags:"legacyFlags"in j.runtime?j.runtime.legacyFlags:[],description:j.runtime.description,legacyTopLevelFlags:j.runtime.legacyTopLevelFlags})),Nt=Nn.slice().sort((j,K)=>j.install.order-K.install.order).map((j)=>({id:j.id,...j.install})).map(({order:j,...K})=>K),d0=Object.fromEntries(Nn.map((j)=>[j.id,j.displayName]));function St(j){return Nn.find((K)=>K.id===j)?.displayName??j}var Tu=Mn.map((j)=>({flags:j.flags.join(", "),description:j.description})),Iu=Mn.flatMap((j)=>j.flags.map((K)=>`cc-safety-net hook ${K}`)),is={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Tu,{flags:"-h, --help",description:"Show this help"}],examples:Iu};var ss={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...Nt.map((j)=>({flags:j.flag,description:`Install ${St(j.id)} ${j.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...Nt.map((j)=>`cc-safety-net install ${j.flag}`)]},as={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...Nt.map((j)=>({flags:j.flag,description:`Uninstall ${St(j.id)} ${j.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...Nt.map((j)=>`cc-safety-net uninstall ${j.flag}`)]},ls={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 cs={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 pr={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 go=[{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"}],yo=["cc-safety-net rule add project-rules","cc-safety-net rule add acme/safety-rules","cc-safety-net rule add acme/safety-rules --only aws gcloud","cc-safety-net rule add acme/safety-rules --ref v2 --only aws","cc-safety-net rule add --only terraform aws"],kn={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add [source] [--ref <ref>] [--only <rulebook...>]",description:"Add rulebook sources and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Re-fetch and vendor remote rulebooks"},{usage:"sync",description:"Deprecated: migrate lock and cache leftovers"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},...go.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",...yo,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var ds={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 us={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 fr=[ds,ns,cs,rs,kn,pr,ss,ls,as,is,os,us];function $u(j){return j.aliases??[]}function mr(j){let K=j.toLowerCase();return fr.find((te)=>te.name.toLowerCase()===K||$u(te).some((re)=>re.toLowerCase()===K))}import{basename as Ou}from"node:path";function gr(j,K=7,te=M(j)){let re=Date.now()-K*24*60*60*1000,oe=[],ce=new Set,de=0,we,xe,Ce,Se;if(te)q(j,te);let Ne={count:0},He=te?an(te,Ne):[];for(let mt of He)for(let it of wn(mt,Ne)){if(it.decision==="allow")continue;let gt=new Date(it.ts).getTime();if(gt>=re){if(de++,ce.add(it.sessionId??Ou(mt,".jsonl")),xe===void 0||gt<=xe)we=it.ts,xe=gt;if(Se===void 0||gt>Se)Ce=it.ts,Se=gt;ju(oe,it,gt)}}let at=oe.map((mt)=>({timestamp:mt.ts,command:mt.command,reason:mt.reason,relativeTime:Wi(new Date(mt.ts))}));return{totalBlocked:de,sessionCount:ce.size,recentEntries:at,oldestEntry:we,newestEntry:Ce,unreadable:Ne.count}}function ju(j,K,te){let re=j.findIndex((oe)=>te>new Date(oe.ts).getTime());if(re===-1){if(j.length<3)j.push(K);return}if(j.splice(re,0,K),j.length>3)j.pop()}import{dirname as Wu}from"node:path";import{dirname as Fu,join as Nu,resolve as Mu}from"node:path";var Hu="config.json";function It(j,K,te,re){y(Uu(j),`${JSON.stringify(K,null,2)}
5
- `,te,re)}function Uu(j){return typeof j==="string"?D(j):j}function vo(j){return{errors:se(Bu(j),": "," "),ruleNames:new Set(Fe(j).map((K)=>K.toLowerCase()))}}var Gu="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",ps="must match pattern (letters, numbers, hyphens, underscores)";function Bu(j){if(!fs(j))return[e([],"Config must be an object")];return[...j.version===1?[]:[e(["version"],"must be 1")],...qu(j.rules)]}function qu(j){if(j===void 0)return[];if(!Array.isArray(j))return[e(["rules"],"must be an array")];return[...j.flatMap((K,te)=>fs(K)?Vu(K,["rules",te]):[e(["rules",te],"must be an object")]),...$e(j)]}function Vu(j,K){return[...ho(j.name,[...K,"name"],"required string",c,Gu),...ho(j.command,[...K,"command"],"required string",L,ps),...j.subcommand===void 0?[]:ho(j.subcommand,[...K,"subcommand"],"must be a string if provided",L,ps),...zu(j.block_args,[...K,"block_args"]),...Ju(j.reason,[...K,"reason"]),...j.intent===void 0||Ee(j.intent)?[]:[e([...K,"intent"],ke)]]}function ho(j,K,te,re,oe){if(typeof j!=="string")return[e(K,te)];return re.test(j)?[]:[e(K,oe)]}function zu(j,K){if(!Array.isArray(j))return[e(K,"required array")];if(j.length===0)return[e(K,"must have at least one element")];return j.flatMap((te,re)=>{if(typeof te!=="string")return[e([...K,re],"must be a string")];return te===""?[e([...K,re],"must not be empty")]:[]})}function Ju(j,K){if(typeof j!=="string")return[e(K,"required string")];if(j==="")return[e(K,"must not be empty")];return j.length>I?[e(K,`must be at most ${I} characters`)]:[]}function fs(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function bo(j){let K=ms(j);if(!K.ok)return K.result;return vo(K.parsed)}function ms(j){let K=[],te=new Set;try{let re=typeof j==="string"?D(j):j,oe=r(re);if(oe===null)return K.push(`File not found: ${re.path}`),{ok:!1,result:{errors:K,ruleNames:te}};if(!oe.trim())return K.push("Config file is empty"),{ok:!1,result:{errors:K,ruleNames:te}};return{ok:!0,parsed:JSON.parse(oe)}}catch(re){if(re instanceof o)return K.push(re.message),{ok:!1,result:{errors:K,ruleNames:te}};let oe=re instanceof Error?re.message:String(re);return K.push(re instanceof SyntaxError?"Invalid JSON":oe),{ok:!1,result:{errors:K,ruleNames:te}}}}function gs(j){return Mu(j,".safety-net.json")}function en(j){let K=ms(j);if(!K.ok)return K.result;let te=tt(K.parsed);return{errors:te.errors,ruleNames:te.sources}}function yr(j,K={}){return Nu(Fu(me(j,K)),Hu)}function ys(j,K,te){let re;try{if(r(K)===null)return{path:j,exists:!1,valid:!1,ruleCount:0};re=en(K),re.errors.push(...W(j,te))}catch(oe){if(!(oe instanceof o))throw oe;re={errors:[oe.message],ruleNames:new Set}}return{path:j,exists:!0,valid:re.errors.length===0,ruleCount:re.ruleNames.size,...re.errors.length>0?{errors:re.errors}:{}}}function Ku(j,K){return{source:K,name:j.name,command:j.command,subcommand:j.subcommand,blockArgs:[...j.block_args],reason:j.reason}}function hs(j,K,te){let re=te?.userConfigPath??T(j),oe=te?.projectConfigPath??A(K),ce=Wu(re),de=Z(j,{cwd:K,userConfigPath:re,projectConfigPath:oe,userConfigDir:ce}),we=H(j,{cwd:K,userConfigPath:re,projectConfigPath:oe,userConfigDir:ce}),xe=new Map(de.rulebooks.flatMap((Ce)=>Ce.rules.map((Se)=>[Se,Ce.source])));return{userConfig:ys(re,we.userConfigTarget,we.userScope),projectConfig:ys(oe,we.projectConfigTarget,we.projectScope),effectiveRules:de.rules.map((Ce)=>Ku(Ce,xe.get(Ce.name)??"project")),shadowedRules:[]}}var Yu=[{flag:i.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:i.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:i.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:i.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:i.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:i.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:i.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:i.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function vs(j){return[...Yu.map((K)=>({name:K.flag.name,value:Le(K.flag,j.env),isSet:st(K.flag,j.env),legacyName:K.flag.legacyName,legacyValue:K.flag.legacyName?j.env.get(K.flag.legacyName):void 0,legacyIsSet:K.flag.legacyName?j.env.get(K.flag.legacyName)!==void 0:void 0,description:K.description,defaultBehavior:K.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:j.env.get("CC_SAFETY_NET_HOME"),isSet:j.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var bs={error:0,warning:1,info:2},Zu=["policy","config","audit"];function Xu(j){return j.map((K)=>{if(K==="ownership")return"is not owned by the current user";if(K==="permissions")return"has unsafe permissions";if(K==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Qu=[{derive:(j)=>j.hooks.length>0&&j.hooks.every((K)=>!K.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:(j)=>j.hooks.filter((K)=>K.inspectionStatus==="failed").map((K)=>{let te=St(K.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${te} inspection failed`,detail:`Doctor could not verify the ${te} integration configuration.`,fixHint:`Correct the reported ${te} configuration error, then run \`cc-safety-net doctor\` again.`,integration:K.platform}})},{derive:(j)=>j.userConfig.exists&&!j.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:j.userConfig.path}]:[]},{derive:(j)=>j.projectConfig.exists&&!j.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:j.projectConfig.path}]:[]},{derive:(j)=>j.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${j.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:(j)=>j.v2Leftovers&&j.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: ${j.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(j)=>{let K=j.environment.find((te)=>te.name==="CC_SAFETY_NET_AUDIT_SCOPE");return Ze(K?.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."}]:[]}},...Zu.map((j)=>({derive:(K)=>K.posture.directories.filter((te)=>te.kind===j&&te.status==="unsafe").map((te)=>({checkId:`posture.${j}-directory-unsafe`,severity:"error",title:`${j[0]?.toUpperCase()}${j.slice(1)} directory is unsafe`,detail:`The ${j} directory ${Xu(te.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...te.path?{path:te.path}:{}}))})),{derive:(j)=>{let K=[...j.effectiveSafety.weakenedRuleOverrides].sort();return K.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: ${K.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${K.join(", ")}.`}]:[]}}];function Ls(j){return Qu.flatMap((K,te)=>K.derive(j).map((re,oe)=>({finding:re,catalogOrder:te,occurrence:oe}))).sort((K,te)=>bs[K.finding.severity]-bs[te.finding.severity]||K.catalogOrder-te.catalogOrder||K.occurrence-te.occurrence).map((K)=>K.finding)}function Bt(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var ep=(j)=>Bt()?`\x1B[32m${j}\x1B[0m`:j,tp=(j)=>Bt()?`\x1B[33m${j}\x1B[0m`:j,np=(j)=>Bt()?`\x1B[34m${j}\x1B[0m`:j,rp=(j)=>Bt()?`\x1B[35m${j}\x1B[0m`:j,op=(j)=>Bt()?`\x1B[36m${j}\x1B[0m`:j,ip=(j)=>Bt()?`\x1B[31m${j}\x1B[0m`:j,sp=(j)=>Bt()?`\x1B[2m${j}\x1B[0m`:j,ap=(j)=>Bt()?`\x1B[1m${j}\x1B[0m`:j,bt={green:ep,yellow:tp,blue:np,magenta:rp,cyan:op,red:ip,dim:sp,bold:ap},lp="\x1B[0m",cp=[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 dp(j){let K=j;return()=>(K=(K*1664525+1013904223)%4294967296,K/4294967296)}function up(j){let K=[...cp],te=dp(j);for(let re=K.length-1;re>0;re--){let oe=Math.floor(te()*(re+1)),ce=K[re];K[re]=K[oe],K[oe]=ce}return K}function pp(j,K=0){if(!Bt())return"";let te=up(K);return`\x1B[38;5;${te[j%te.length]}m`}function ws(j,K,te=0){if(!Bt())return`"${j}"`;return`${pp(K,te)}"${j}"${lp}`}function hr(j){return j==="default"?"built-in default":`${j} policy`}var fp=new RegExp("\x1B\\[[0-9;]*m","g"),Lo=(j)=>j.replace(fp,"").length;function ln(j){let K=(j.headers??j.rows[0]??[]).map((de,we)=>{let xe=Math.max(...j.rows.map((Ce)=>Lo(Ce[we]??"")));return Math.max(Lo(de),xe)}),te=(de,we)=>de+" ".repeat(Math.max(0,we-Lo(de))),re=(de,we)=>we[0]+K.map((xe)=>de.repeat(xe+2)).join(we[1])+we[2],oe=(de)=>`│ ${de.map((we,xe)=>te(we,K[xe]??0)).join(" │ ")} │`,ce=j.headers?[` ${oe(j.headers)}`,` ${re("─",["├","┼","┤"])}`]:[];return[` ${re("─",["┌","┬","┐"])}`,...ce,...j.rows.map((de)=>` ${oe(de)}`),` ${re("─",["└","┴","┘"])}`].join(`
6
- `)}function ks(j){let K=[];K.push("Hook Integration"),K.push(mp(j));let te=[],re=[];for(let oe of j){let ce=St(oe.platform);if(oe.errors&&oe.errors.length>0)for(let de of oe.errors)if(oe.configured)te.push({platform:ce,message:de});else re.push({platform:ce,message:de})}for(let oe of te)K.push(` Warning (${oe.platform}): ${oe.message}`);for(let oe of re)K.push(bt.red(` Error (${oe.platform}): ${oe.message}`));return K.join(`
7
- `)}function mp(j){let K=["Platform","Discovery","Configuration","Inspection"],te=j.map((re)=>{let oe=St(re.platform);if(re.inspectionStatus==="not-inspected"){let xe=bt.dim("Not inspected");return[oe,xe,xe,xe]}let ce=re.detected?bt.green("Detected"):re.inspectionStatus==="failed"?bt.red("Unknown"):bt.dim("Not detected"),de=re.configured?bt.green("Configured"):re.detected?bt.yellow("Not configured"):re.inspectionStatus==="failed"?bt.red("Unknown"):bt.dim("Not applicable"),we=re.inspectionStatus==="verified"?bt.green("Verified"):re.inspectionStatus==="failed"?bt.red("Failed"):bt.dim("Not applicable");return[oe,ce,de,we]});return ln({headers:K,rows:te})}function xs(j){let te=["Guard Engine Verification",` Synthetic self-test: ${j.failed>0?bt.red(`${j.passed}/${j.total} FAIL`):bt.green(`${j.passed}/${j.total} passed`)}`],re=j.results.filter((oe)=>!oe.passed);if(re.length>0){te.push(""),te.push(bt.red(" Failures:"));for(let oe of re)te.push(bt.red(` • ${oe.description}`)),te.push(bt.red(` expected ${oe.expected}, got ${oe.actual}`))}return te.join(`
8
- `)}function gp(j){if(j.length===0)return" (no custom rules)";let K=["Source","Name","Command","Block Args"],te=j.map((re)=>[re.source,re.name,re.subcommand?`${re.command} ${re.subcommand}`:re.command,re.blockArgs.join(", ")]);return ln({headers:K,rows:te})}function Cs(j){let K=[];if(K.push("Configuration"),K.push(yp(j.userConfig,j.projectConfig)),K.push(""),j.effectiveRules.length>0)K.push(` Effective rules (${j.effectiveRules.length} total):`),K.push(gp(j.effectiveRules));else K.push(" Effective rules: (none - using built-in rules only)");for(let te of j.shadowedRules)K.push(""),K.push(` Note: Project rule "${te.name}" shadows user rule with same name`);return K.join(`
9
- `)}function yp(j,K){let te=["Scope","Status"],re=(ce)=>{if(!ce.exists)return bt.dim("N/A");if(!ce.valid)return bt.red(`Invalid (${ce.errors?.[0]??"unknown error"})`);return bt.green("Configured")},oe=[["User",re(j)],["Project",re(K)]];return ln({headers:te,rows:oe})}function Ss(j){let K=[];return K.push("Environment"),K.push(hp(j)),K.join(`
10
- `)}function Rs(j){let K=j.effectiveSafety.policyScopes,te=["Effective Safety",` Selected preset: ${j.effectiveSafety.selectedPreset}${K?` (${hr(K.levelScope)})`:""}`,` Effective: ${j.effectiveSafety.level}`],re=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[oe,ce]of re){let de=j.effectiveSafety.capabilities[oe],we=de.enabled?bt.green("ON"):bt.dim("OFF"),xe=de.sources.length>0?` (${de.sources.join(", ")})`:"";te.push(` ${ce}: ${we} via ${de.source}${xe}`)}if(K&&K.weakenings.length>0){te.push(" Project policy deltas:");for(let oe of K.weakenings)te.push(` ${oe}`)}te.push(` Stored rule customizations: ${j.effectiveSafety.ruleCounts.stored}`),te.push(` Effective rule customizations: ${j.effectiveSafety.ruleCounts.effective}`);for(let[oe,ce]of Object.entries(j.effectiveSafety.ruleOverrides))te.push(` ${oe}: ${ce}`);return te.join(`
11
- `)}function Ps(j){let K=["Findings"];if(j.length===0)return K.push(" No findings from inspected doctor facts."),K.join(`
3
+ `).filter(Boolean).flatMap((te)=>{try{let re=JSON.parse(te);if(!pu(re)){if(K)K.count++;return[]}return[re]}catch{if(K)K.count++;return[]}})}catch{if(K)K.count++;return[]}}function _t(j){return Array.from(j,(K)=>{let te=K.charCodeAt(0);if(te<=31||te>=127&&te<=159)return`\\x${te.toString(16).padStart(2,"0")}`;return K}).join("")}function wu(j,K){let te=ne(j),re=At({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"]}},K);if(Kt(re.errors))return null;if(re.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(re.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let oe=re.values.limit===void 0?20:Xi(re.values.limit);if(oe===null)return console.error("--limit must be a positive number"),null;let ce=re.values.since===void 0?Math.min(30,te):Xi(re.values.since);if(ce===null||ce>te)return console.error(`--since must be a positive number of days no greater than ${te}`),null;let de={limit:oe,limitExplicit:re.values.limit!==void 0,since:ce,sinceExplicit:re.values.since!==void 0,all:re.flags.all,json:re.flags.json,suspect:re.flags.suspect,pruneLegacy:re.flags.pruneLegacy,dryRun:re.flags.dryRun,id:re.values.id,agent:re.values.agent,rule:re.values.rule,session:re.values.session,project:re.values.project===void 0?void 0:bu(re.values.project)};if(de.id&&(de.agent!==void 0||de.rule!==void 0||de.session!==void 0||de.project!==void 0||de.suspect||de.sinceExplicit||de.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(de.pruneLegacy&&(de.id!==void 0||de.agent!==void 0||de.rule!==void 0||de.session!==void 0||de.project!==void 0||de.suspect||de.all||de.sinceExplicit||de.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(de.dryRun&&!de.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return de}async function ts(j,K,te={}){let re=wu(j,K);if(!re)return 1;let oe=te.logsDir??M(j);if(re.pruneLegacy)return ku(oe,re.json,re.dryRun);if(!oe)return console.log(re.json?"[]":re.id?`No retained audit log entry found for id ${_t(re.id)}.`:"No audit log entries found."),0;q(j,oe);let ce={count:0},de=an(oe,ce).flatMap((Ne)=>wn(Ne,ce).map((He)=>({entry:He,file:Ne})));if(ce.count>0)console.error(`warning: ${ce.count} audit log ${ce.count===1?"source":"sources"} could not be read; these results are incomplete`);if(re.id)return Ru(de,re,te.timeZone);let we=Date.now()-re.since*24*60*60*1000,xe=de.filter((Ne)=>Pu(Ne,re,oe,we)),Ce=re.suspect?Zi(xe.map((Ne)=>Ne.entry)):null,Se=(Ce?xe.filter((Ne)=>Ce.has(Ne.entry)):xe).sort((Ne,He)=>Date.parse(He.entry.ts)-Date.parse(Ne.entry.ts)).slice(0,re.limit);if(re.json)return console.log(JSON.stringify(Se.map((Ne)=>Ne.entry),null,2)),0;if(Se.length===0)return console.log("No audit log entries found."),0;for(let Ne of Se)console.log(Au(Ne.entry,te.timeZone));return 0}function ku(j,K,te){let re=j?Cu(j).map((we)=>hu(j,we)):[];if(te)return xu(re,K);let oe=[],ce=0,de=0;for(let we of re){let xe=Qi(we,{throwIfNoEntry:!1})?.size??0,Ce=Su(we);if(Ce){oe.push(`${es(we)}: ${Ce}`);continue}ce++,de+=xe}if(K)return console.log(JSON.stringify({removedFiles:ce,removedBytes:de,failedFiles:oe.length})),oe.length===0?0:1;console.log(ce===0&&oe.length===0?"No legacy audit log files found.":`Removed ${ce} legacy audit log ${ce===1?"file":"files"} (${ns(de)}).`);for(let we of oe)console.error(`Could not remove ${_t(we)}`);if(console.log("Nested v2 audit logs were not changed."),ce>0)console.log("This deletion cannot be undone.");return oe.length===0?0:1}function xu(j,K){let te=j.reduce((re,oe)=>re+(Qi(oe,{throwIfNoEntry:!1})?.size??0),0);if(K)return console.log(JSON.stringify({dryRun:!0,files:j.length,bytes:te})),0;if(console.log(j.length===0?"No legacy audit log files found.":`Would remove ${j.length} legacy audit log ${j.length===1?"file":"files"} (${ns(te)}).`),console.log("Nested v2 audit logs are not included."),j.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Cu(j){try{return fu(j,{withFileTypes:!0}).filter((K)=>K.isFile()&&K.name.endsWith(".jsonl")).map((K)=>K.name)}catch{return[]}}function Su(j){try{return mu(j),null}catch(K){return K instanceof Error?K.message:String(K)}}function ns(j){let K=["B","KiB","MiB","GiB"],te=Math.min(Math.floor(Math.log2(Math.max(j,1))/10),K.length-1);return`${Math.round(j/1024**te*10)/10} ${K[te]}`}function Ru(j,K,te){let re=j.filter((ce)=>ce.entry.id===K.id);if(re.length>1)return console.error(`Multiple audit log entries found for id ${_t(K.id??"")}.`),1;if(K.json)return console.log(JSON.stringify(re.map((ce)=>ce.entry),null,2)),0;let oe=re[0];if(!oe)return console.log(`No retained audit log entry found for id ${_t(K.id??"")}.`),0;return console.log(_u(oe.entry,te)),0}function Pu(j,K,te,re){if(!K.all&&j.entry.decision==="allow")return!1;if(Date.parse(j.entry.ts)<re)return!1;if(K.agent!==void 0&&j.entry.agent!==K.agent)return!1;if(K.rule!==void 0&&j.entry.ruleId!==K.rule)return!1;if(K.session!==void 0&&!Eu(j,te,K.session))return!1;if(K.project!==void 0&&!Du(j.entry.cwd,K.project))return!1;return!0}function Eu(j,K,te){if(j.entry.sessionId===te)return!0;return gu(j.file)===K&&es(j.file,".jsonl")===te}function Du(j,K){if(!j)return!1;let te=vu(K,j);return te!==".."&&!te.startsWith(`..${Lu}`)&&!yu(te)}function Au(j,K){let te=_t(j.id??"-"),re=_t(j.decision??"deny"),oe=j.cwd?` [${_t(j.cwd)}]`:"",ce=j.segment||j.command,de=ce===j.command?"":"↳ ",we=ce.length>50?`${ce.slice(0,50)}…`:ce;return`${te.padEnd(16)} ${_t(rs(j.ts,K))} ${re.padEnd(5)} ${_t(j.agent??"-").padEnd(15)} ${_t(j.ruleId??"-").padEnd(20)} ${de}${_t(we)}${oe}`}function _u(j,K){let te=(oe)=>_t(oe===void 0||oe===null||oe===""?"-":oe),re=j.shape?`${j.agent??"-"} (shape: ${j.shape})`:j.agent??"-";return[`id: ${te(j.id)}`,`ts: ${te(rs(j.ts,K))}`,`decision: ${te(j.decision)}`,`agent: ${te(re)}`,`level: ${te(j.level)}`,`tool: ${te(j.toolName)}`,`rule: ${te(j.ruleId)}`,`intent: ${te(j.intent)}`,`stage: ${te(j.failureStage)}`,`error: ${te(j.errorCode)}`,`session: ${te(j.sessionId)}`,`cwd: ${te(j.cwd)}`,`version: ${te(j.v)}`,`truncated: ${te(j.truncated===!0?"yes":void 0)}`,`reason: ${te(j.reason)}`,`command: ${te(j.command)}`,`segment: ${te(j.segment)}`].join(`
4
+ `)}function rs(j,K){let te=new Date(j);if(Number.isNaN(te.getTime()))return j;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:K}).format(te)}function Xi(j){let K=Number(j);return Number.isFinite(K)&&K>0?K:null}var os={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 is={name:"explain",description:"Show step-by-step analysis trace of how a command would be analyzed",usage:"explain [options] <command>",argument:"<command>",options:[{flags:"--json",description:"Output analysis as JSON"},{flags:"--cwd",argument:"<path>",description:"Use custom working directory"},{flags:"-h, --help",description:"Show this help"}],examples:['cc-safety-net explain "git reset --hard"','cc-safety-net explain --json "rm -rf /"','cc-safety-net explain --cwd /tmp "git status"']};var ss={name:"gui",description:"Open the local policy editor GUI",usage:"gui [options]",options:[{flags:"--no-open",description:"Print the URL without opening a browser"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net gui","cc-safety-net gui --no-open"]};var Nn=[{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"]}}],ur=Nn.slice().sort((j,K)=>j.doctorOrder-K.doctorOrder).map((j)=>j.id),Mn=Nn.filter((j)=>("runtime"in j)).slice().sort((j,K)=>j.runtime.order-K.runtime.order).map((j)=>({id:j.id,displayName:"displayName"in j.runtime?j.runtime.displayName:j.displayName,flags:j.runtime.flags,legacyFlags:"legacyFlags"in j.runtime?j.runtime.legacyFlags:[],description:j.runtime.description,legacyTopLevelFlags:j.runtime.legacyTopLevelFlags})),Nt=Nn.slice().sort((j,K)=>j.install.order-K.install.order).map((j)=>({id:j.id,...j.install})).map(({order:j,...K})=>K),d0=Object.fromEntries(Nn.map((j)=>[j.id,j.displayName]));function St(j){return Nn.find((K)=>K.id===j)?.displayName??j}var Tu=Mn.map((j)=>({flags:j.flags.join(", "),description:j.description})),Iu=Mn.flatMap((j)=>j.flags.map((K)=>`cc-safety-net hook ${K}`)),as={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Tu,{flags:"-h, --help",description:"Show this help"}],examples:Iu};var ls={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...Nt.map((j)=>({flags:j.flag,description:`Install ${St(j.id)} ${j.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...Nt.map((j)=>`cc-safety-net install ${j.flag}`)]},cs={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...Nt.map((j)=>({flags:j.flag,description:`Uninstall ${St(j.id)} ${j.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...Nt.map((j)=>`cc-safety-net uninstall ${j.flag}`)]},ds={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 us={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 pr={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 go=[{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"}],yo=["cc-safety-net rule add project-rules","cc-safety-net rule add acme/safety-rules","cc-safety-net rule add acme/safety-rules --only aws gcloud","cc-safety-net rule add acme/safety-rules --ref v2 --only aws","cc-safety-net rule add --only terraform aws"],kn={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add [source] [--ref <ref>] [--only <rulebook...>]",description:"Add rulebook sources and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Re-fetch and vendor remote rulebooks"},{usage:"sync",description:"Deprecated: migrate lock and cache leftovers"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},...go.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",...yo,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var ps={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 fs={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 fr=[ps,os,us,is,kn,pr,ls,ds,cs,as,ss,fs];function $u(j){return j.aliases??[]}function mr(j){let K=j.toLowerCase();return fr.find((te)=>te.name.toLowerCase()===K||$u(te).some((re)=>re.toLowerCase()===K))}import{basename as Ou}from"node:path";function gr(j,K=7,te=M(j)){let re=Date.now()-K*24*60*60*1000,oe=[],ce=new Set,de=0,we,xe,Ce,Se;if(te)q(j,te);let Ne={count:0},He=te?an(te,Ne):[];for(let mt of He)for(let it of wn(mt,Ne)){if(it.decision==="allow")continue;let gt=new Date(it.ts).getTime();if(gt>=re){if(de++,ce.add(it.sessionId??Ou(mt,".jsonl")),xe===void 0||gt<=xe)we=it.ts,xe=gt;if(Se===void 0||gt>Se)Ce=it.ts,Se=gt;ju(oe,it,gt)}}let at=oe.map((mt)=>({timestamp:mt.ts,command:mt.command,reason:mt.reason,relativeTime:Yi(new Date(mt.ts))}));return{totalBlocked:de,sessionCount:ce.size,recentEntries:at,oldestEntry:we,newestEntry:Ce,unreadable:Ne.count}}function ju(j,K,te){let re=j.findIndex((oe)=>te>new Date(oe.ts).getTime());if(re===-1){if(j.length<3)j.push(K);return}if(j.splice(re,0,K),j.length>3)j.pop()}import{dirname as Wu}from"node:path";import{dirname as Fu,join as Nu,resolve as Mu}from"node:path";var Hu="config.json";function It(j,K,te,re){y(Uu(j),`${JSON.stringify(K,null,2)}
5
+ `,te,re)}function Uu(j){return typeof j==="string"?D(j):j}function vo(j){return{errors:se(Bu(j),": "," "),ruleNames:new Set(Fe(j).map((K)=>K.toLowerCase()))}}var Gu="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",ms="must match pattern (letters, numbers, hyphens, underscores)";function Bu(j){if(!gs(j))return[e([],"Config must be an object")];return[...j.version===1?[]:[e(["version"],"must be 1")],...qu(j.rules)]}function qu(j){if(j===void 0)return[];if(!Array.isArray(j))return[e(["rules"],"must be an array")];return[...j.flatMap((K,te)=>gs(K)?Vu(K,["rules",te]):[e(["rules",te],"must be an object")]),...$e(j)]}function Vu(j,K){return[...ho(j.name,[...K,"name"],"required string",c,Gu),...ho(j.command,[...K,"command"],"required string",L,ms),...j.subcommand===void 0?[]:ho(j.subcommand,[...K,"subcommand"],"must be a string if provided",L,ms),...zu(j.block_args,[...K,"block_args"]),...Ju(j.reason,[...K,"reason"]),...j.intent===void 0||Ee(j.intent)?[]:[e([...K,"intent"],ke)]]}function ho(j,K,te,re,oe){if(typeof j!=="string")return[e(K,te)];return re.test(j)?[]:[e(K,oe)]}function zu(j,K){if(!Array.isArray(j))return[e(K,"required array")];if(j.length===0)return[e(K,"must have at least one element")];return j.flatMap((te,re)=>{if(typeof te!=="string")return[e([...K,re],"must be a string")];return te===""?[e([...K,re],"must not be empty")]:[]})}function Ju(j,K){if(typeof j!=="string")return[e(K,"required string")];if(j==="")return[e(K,"must not be empty")];return j.length>I?[e(K,`must be at most ${I} characters`)]:[]}function gs(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function bo(j){let K=ys(j);if(!K.ok)return K.result;return vo(K.parsed)}function ys(j){let K=[],te=new Set;try{let re=typeof j==="string"?D(j):j,oe=r(re);if(oe===null)return K.push(`File not found: ${re.path}`),{ok:!1,result:{errors:K,ruleNames:te}};if(!oe.trim())return K.push("Config file is empty"),{ok:!1,result:{errors:K,ruleNames:te}};return{ok:!0,parsed:JSON.parse(oe)}}catch(re){if(re instanceof o)return K.push(re.message),{ok:!1,result:{errors:K,ruleNames:te}};let oe=re instanceof Error?re.message:String(re);return K.push(re instanceof SyntaxError?"Invalid JSON":oe),{ok:!1,result:{errors:K,ruleNames:te}}}}function hs(j){return Mu(j,".safety-net.json")}function tn(j){let K=ys(j);if(!K.ok)return K.result;let te=tt(K.parsed);return{errors:te.errors,ruleNames:te.sources}}function yr(j,K={}){return Nu(Fu(me(j,K)),Hu)}function vs(j,K,te){let re;try{if(r(K)===null)return{path:j,exists:!1,valid:!1,ruleCount:0};re=tn(K),re.errors.push(...W(j,te))}catch(oe){if(!(oe instanceof o))throw oe;re={errors:[oe.message],ruleNames:new Set}}return{path:j,exists:!0,valid:re.errors.length===0,ruleCount:re.ruleNames.size,...re.errors.length>0?{errors:re.errors}:{}}}function Ku(j,K){return{source:K,name:j.name,command:j.command,subcommand:j.subcommand,blockArgs:[...j.block_args],reason:j.reason}}function bs(j,K,te){let re=te?.userConfigPath??T(j),oe=te?.projectConfigPath??A(K),ce=Wu(re),de=Z(j,{cwd:K,userConfigPath:re,projectConfigPath:oe,userConfigDir:ce}),we=H(j,{cwd:K,userConfigPath:re,projectConfigPath:oe,userConfigDir:ce}),xe=new Map(de.rulebooks.flatMap((Ce)=>Ce.rules.map((Se)=>[Se,Ce.source])));return{userConfig:vs(re,we.userConfigTarget,we.userScope),projectConfig:vs(oe,we.projectConfigTarget,we.projectScope),effectiveRules:de.rules.map((Ce)=>Ku(Ce,xe.get(Ce.name)??"project")),shadowedRules:[]}}var Yu=[{flag:i.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:i.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:i.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:i.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:i.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:i.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:i.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:i.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function Ls(j){return[...Yu.map((K)=>({name:K.flag.name,value:Le(K.flag,j.env),isSet:st(K.flag,j.env),legacyName:K.flag.legacyName,legacyValue:K.flag.legacyName?j.env.get(K.flag.legacyName):void 0,legacyIsSet:K.flag.legacyName?j.env.get(K.flag.legacyName)!==void 0:void 0,description:K.description,defaultBehavior:K.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:j.env.get("CC_SAFETY_NET_HOME"),isSet:j.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var ws={error:0,warning:1,info:2},Zu=["policy","config","audit"];function Xu(j){return j.map((K)=>{if(K==="ownership")return"is not owned by the current user";if(K==="permissions")return"has unsafe permissions";if(K==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Qu=[{derive:(j)=>j.hooks.length>0&&j.hooks.every((K)=>!K.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:(j)=>j.hooks.filter((K)=>K.inspectionStatus==="failed").map((K)=>{let te=St(K.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${te} inspection failed`,detail:`Doctor could not verify the ${te} integration configuration.`,fixHint:`Correct the reported ${te} configuration error, then run \`cc-safety-net doctor\` again.`,integration:K.platform}})},{derive:(j)=>j.userConfig.exists&&!j.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:j.userConfig.path}]:[]},{derive:(j)=>j.projectConfig.exists&&!j.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:j.projectConfig.path}]:[]},{derive:(j)=>j.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${j.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:(j)=>j.v2Leftovers&&j.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: ${j.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(j)=>{let K=j.environment.find((te)=>te.name==="CC_SAFETY_NET_AUDIT_SCOPE");return Ze(K?.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."}]:[]}},...Zu.map((j)=>({derive:(K)=>K.posture.directories.filter((te)=>te.kind===j&&te.status==="unsafe").map((te)=>({checkId:`posture.${j}-directory-unsafe`,severity:"error",title:`${j[0]?.toUpperCase()}${j.slice(1)} directory is unsafe`,detail:`The ${j} directory ${Xu(te.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...te.path?{path:te.path}:{}}))})),{derive:(j)=>{let K=[...j.effectiveSafety.weakenedRuleOverrides].sort();return K.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: ${K.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${K.join(", ")}.`}]:[]}}];function ks(j){return Qu.flatMap((K,te)=>K.derive(j).map((re,oe)=>({finding:re,catalogOrder:te,occurrence:oe}))).sort((K,te)=>ws[K.finding.severity]-ws[te.finding.severity]||K.catalogOrder-te.catalogOrder||K.occurrence-te.occurrence).map((K)=>K.finding)}function Bt(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var ep=(j)=>Bt()?`\x1B[32m${j}\x1B[0m`:j,tp=(j)=>Bt()?`\x1B[33m${j}\x1B[0m`:j,np=(j)=>Bt()?`\x1B[34m${j}\x1B[0m`:j,rp=(j)=>Bt()?`\x1B[35m${j}\x1B[0m`:j,op=(j)=>Bt()?`\x1B[36m${j}\x1B[0m`:j,ip=(j)=>Bt()?`\x1B[31m${j}\x1B[0m`:j,sp=(j)=>Bt()?`\x1B[2m${j}\x1B[0m`:j,ap=(j)=>Bt()?`\x1B[1m${j}\x1B[0m`:j,bt={green:ep,yellow:tp,blue:np,magenta:rp,cyan:op,red:ip,dim:sp,bold:ap},lp="\x1B[0m",cp=[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 dp(j){let K=j;return()=>(K=(K*1664525+1013904223)%4294967296,K/4294967296)}function up(j){let K=[...cp],te=dp(j);for(let re=K.length-1;re>0;re--){let oe=Math.floor(te()*(re+1)),ce=K[re];K[re]=K[oe],K[oe]=ce}return K}function pp(j,K=0){if(!Bt())return"";let te=up(K);return`\x1B[38;5;${te[j%te.length]}m`}function xs(j,K,te=0){if(!Bt())return`"${j}"`;return`${pp(K,te)}"${j}"${lp}`}function hr(j){return j==="default"?"built-in default":`${j} policy`}var fp=new RegExp("\x1B\\[[0-9;]*m","g"),Lo=(j)=>j.replace(fp,"").length;function ln(j){let K=(j.headers??j.rows[0]??[]).map((de,we)=>{let xe=Math.max(...j.rows.map((Ce)=>Lo(Ce[we]??"")));return Math.max(Lo(de),xe)}),te=(de,we)=>de+" ".repeat(Math.max(0,we-Lo(de))),re=(de,we)=>we[0]+K.map((xe)=>de.repeat(xe+2)).join(we[1])+we[2],oe=(de)=>`│ ${de.map((we,xe)=>te(we,K[xe]??0)).join(" │ ")} │`,ce=j.headers?[` ${oe(j.headers)}`,` ${re("─",["├","┼","┤"])}`]:[];return[` ${re("─",["┌","┬","┐"])}`,...ce,...j.rows.map((de)=>` ${oe(de)}`),` ${re("─",["└","┴","┘"])}`].join(`
6
+ `)}function Cs(j){let K=[];K.push("Hook Integration"),K.push(mp(j));let te=[],re=[];for(let oe of j){let ce=St(oe.platform);if(oe.errors&&oe.errors.length>0)for(let de of oe.errors)if(oe.configured)te.push({platform:ce,message:de});else re.push({platform:ce,message:de})}for(let oe of te)K.push(` Warning (${oe.platform}): ${oe.message}`);for(let oe of re)K.push(bt.red(` Error (${oe.platform}): ${oe.message}`));return K.join(`
7
+ `)}function mp(j){let K=["Platform","Discovery","Configuration","Inspection"],te=j.map((re)=>{let oe=St(re.platform);if(re.inspectionStatus==="not-inspected"){let xe=bt.dim("Not inspected");return[oe,xe,xe,xe]}let ce=re.detected?bt.green("Detected"):re.inspectionStatus==="failed"?bt.red("Unknown"):bt.dim("Not detected"),de=re.configured?bt.green("Configured"):re.detected?bt.yellow("Not configured"):re.inspectionStatus==="failed"?bt.red("Unknown"):bt.dim("Not applicable"),we=re.inspectionStatus==="verified"?bt.green("Verified"):re.inspectionStatus==="failed"?bt.red("Failed"):bt.dim("Not applicable");return[oe,ce,de,we]});return ln({headers:K,rows:te})}function Ss(j){let te=["Guard Engine Verification",` Synthetic self-test: ${j.failed>0?bt.red(`${j.passed}/${j.total} FAIL`):bt.green(`${j.passed}/${j.total} passed`)}`],re=j.results.filter((oe)=>!oe.passed);if(re.length>0){te.push(""),te.push(bt.red(" Failures:"));for(let oe of re)te.push(bt.red(` • ${oe.description}`)),te.push(bt.red(` expected ${oe.expected}, got ${oe.actual}`))}return te.join(`
8
+ `)}function gp(j){if(j.length===0)return" (no custom rules)";let K=["Source","Name","Command","Block Args"],te=j.map((re)=>[re.source,re.name,re.subcommand?`${re.command} ${re.subcommand}`:re.command,re.blockArgs.join(", ")]);return ln({headers:K,rows:te})}function Rs(j){let K=[];if(K.push("Configuration"),K.push(yp(j.userConfig,j.projectConfig)),K.push(""),j.effectiveRules.length>0)K.push(` Effective rules (${j.effectiveRules.length} total):`),K.push(gp(j.effectiveRules));else K.push(" Effective rules: (none - using built-in rules only)");for(let te of j.shadowedRules)K.push(""),K.push(` Note: Project rule "${te.name}" shadows user rule with same name`);return K.join(`
9
+ `)}function yp(j,K){let te=["Scope","Status"],re=(ce)=>{if(!ce.exists)return bt.dim("N/A");if(!ce.valid)return bt.red(`Invalid (${ce.errors?.[0]??"unknown error"})`);return bt.green("Configured")},oe=[["User",re(j)],["Project",re(K)]];return ln({headers:te,rows:oe})}function Ps(j){let K=[];return K.push("Environment"),K.push(hp(j)),K.join(`
10
+ `)}function Es(j){let K=j.effectiveSafety.policyScopes,te=["Effective Safety",` Selected preset: ${j.effectiveSafety.selectedPreset}${K?` (${hr(K.levelScope)})`:""}`,` Effective: ${j.effectiveSafety.level}`],re=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[oe,ce]of re){let de=j.effectiveSafety.capabilities[oe],we=de.enabled?bt.green("ON"):bt.dim("OFF"),xe=de.sources.length>0?` (${de.sources.join(", ")})`:"";te.push(` ${ce}: ${we} via ${de.source}${xe}`)}if(K&&K.weakenings.length>0){te.push(" Project policy deltas:");for(let oe of K.weakenings)te.push(` ${oe}`)}te.push(` Stored rule customizations: ${j.effectiveSafety.ruleCounts.stored}`),te.push(` Effective rule customizations: ${j.effectiveSafety.ruleCounts.effective}`);for(let[oe,ce]of Object.entries(j.effectiveSafety.ruleOverrides))te.push(` ${oe}: ${ce}`);return te.join(`
11
+ `)}function Ds(j){let K=["Findings"];if(j.length===0)return K.push(" No findings from inspected doctor facts."),K.join(`
12
12
  `);for(let te of j){let re=`[${te.severity.toUpperCase()}] ${te.checkId}: ${_t(te.title)}`,oe=te.severity==="error"?bt.red:te.severity==="warning"?bt.yellow:bt.blue;if(K.push(` ${oe(re)}`),K.push(` ${_t(te.detail)}`),te.path)K.push(` Path: ${_t(te.path)}`);if(te.fixHint)K.push(` Fix: ${_t(te.fixHint)}`)}return K.join(`
13
- `)}function hp(j){let K=["Variable","Status","Legacy"],te=j.map((re)=>{let oe=re.isSet?bt.green("✓"):bt.dim("✗"),ce=re.legacyName&&re.legacyIsSet?`${re.legacyName} ${bt.green("✓")}`:re.legacyName??"";return[re.name,oe,ce]});return ln({headers:K,rows:te})}function Es(j){let K=[];if(j.totalBlocked===0)K.push("Recent Activity"),K.push(" No blocked commands in the last 7 days"),K.push(" Tip: This is normal for new installations");else K.push(`Recent Activity · last 7 days (${j.totalBlocked} blocked / ${j.sessionCount} sessions)`),K.push(vp(j.recentEntries));if(j.unreadable>0)K.push(` Warning: ${j.unreadable} audit log ${j.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return K.join(`
14
- `)}function vp(j){let K=["Time","Command"],te=j.map((re)=>{let oe=_t(re.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),ce=oe.length>40?`${oe.slice(0,37)}...`:oe;return[re.relativeTime,ce]});return ln({headers:K,rows:te})}function Ds(j){let K=[];if(K.push("Update Check"),j.latestVersion===null&&!j.error)return K.push(vr([["Status",bt.dim("Skipped")],["Installed",j.currentVersion]])),K.join(`
13
+ `)}function hp(j){let K=["Variable","Status","Legacy"],te=j.map((re)=>{let oe=re.isSet?bt.green("✓"):bt.dim("✗"),ce=re.legacyName&&re.legacyIsSet?`${re.legacyName} ${bt.green("✓")}`:re.legacyName??"";return[re.name,oe,ce]});return ln({headers:K,rows:te})}function As(j){let K=[];if(j.totalBlocked===0)K.push("Recent Activity"),K.push(" No blocked commands in the last 7 days"),K.push(" Tip: This is normal for new installations");else K.push(`Recent Activity · last 7 days (${j.totalBlocked} blocked / ${j.sessionCount} sessions)`),K.push(vp(j.recentEntries));if(j.unreadable>0)K.push(` Warning: ${j.unreadable} audit log ${j.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return K.join(`
14
+ `)}function vp(j){let K=["Time","Command"],te=j.map((re)=>{let oe=_t(re.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),ce=oe.length>40?`${oe.slice(0,37)}...`:oe;return[re.relativeTime,ce]});return ln({headers:K,rows:te})}function _s(j){let K=[];if(K.push("Update Check"),j.latestVersion===null&&!j.error)return K.push(vr([["Status",bt.dim("Skipped")],["Installed",j.currentVersion]])),K.join(`
15
15
  `);if(j.error)return K.push(vr([["Status",`${bt.yellow("⚠")} Error`],["Installed",j.currentVersion],["Error",bt.dim(j.error)]])),K.join(`
16
16
  `);if(j.updateAvailable)return K.push(vr([["Status",`${bt.yellow("⚠")} Update Available`],["Current",j.currentVersion],["Latest",bt.green(j.latestVersion??"")]])),K.push(""),K.push(" Run: bunx cc-safety-net@latest doctor"),K.push(" Or: npx cc-safety-net@latest doctor"),K.join(`
17
17
  `);return K.push(vr([["Status",`${bt.green("✓")} Up to date`],["Version",j.currentVersion]])),K.join(`
18
- `)}function vr(j){return ln({rows:j})}function As(j){let K=[];return K.push("System Info"),K.push(bp(j)),K.join(`
19
- `)}function bp(j){let K=["Component","Version"],te=(ce)=>{if(ce===null)return bt.dim("not found");return ce},oe=[{label:"cc-safety-net",value:j.version},...ur.map((ce)=>({label:St(ce),value:j.versions[ce]??null})),{label:"Node.js",value:j.nodeVersion},{label:"npm",value:j.npmVersion},{label:"Bun",value:j.bunVersion},{label:"Platform",value:j.platform}].map((ce)=>[ce.label,te(ce.value)]);return ln({headers:K,rows:oe})}function _s(j){if(j.findings.length===0)return bt.green(`
18
+ `)}function vr(j){return ln({rows:j})}function Ts(j){let K=[];return K.push("System Info"),K.push(bp(j)),K.join(`
19
+ `)}function bp(j){let K=["Component","Version"],te=(ce)=>{if(ce===null)return bt.dim("not found");return ce},oe=[{label:"cc-safety-net",value:j.version},...ur.map((ce)=>({label:St(ce),value:j.versions[ce]??null})),{label:"Node.js",value:j.nodeVersion},{label:"npm",value:j.npmVersion},{label:"Bun",value:j.bunVersion},{label:"Platform",value:j.platform}].map((ce)=>[ce.label,te(ce.value)]);return ln({headers:K,rows:oe})}function Is(j){if(j.findings.length===0)return bt.green(`
20
20
  No findings from inspected doctor facts.`);let K={error:j.findings.filter((ce)=>ce.severity==="error").length,warning:j.findings.filter((ce)=>ce.severity==="warning").length,info:j.findings.filter((ce)=>ce.severity==="info").length},te=["error","warning","info"].filter((ce)=>K[ce]>0).map((ce)=>`${K[ce]} ${ce}`),re=j.findings.length===1?"finding":"findings",oe=`
21
- ${j.findings.length} ${re}: ${te.join(", ")}.`;if(K.error>0)return bt.red(oe);if(K.warning>0)return bt.yellow(oe);return bt.blue(oe)}import{lstatSync as Lp}from"node:fs";import{dirname as wo}from"node:path";function ko(j,K){try{let te=Lp(K);if(te.isSymbolicLink())return{kind:j,path:K,status:"unsafe",issues:["symlink"]};if(!te.isDirectory())return{kind:j,path:K,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:j,path:K,status:"unknown",issues:[]};let re=[...te.uid!==process.getuid()?["ownership"]:[],...(te.mode&18)!==0?["permissions"]:[]];return{kind:j,path:K,status:re.length>0?"unsafe":"safe",issues:re}}catch(te){if(typeof te==="object"&&te!==null&&"code"in te&&te.code==="ENOENT")return{kind:j,path:K,status:"not-applicable",issues:[]};return{kind:j,path:K,status:"unknown",issues:[]}}}function Ts(j,K){let te=M(j);return{directories:[ko("policy",wo(wo(K))),ko("config",wo(K)),...te?[ko("audit",te)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as wp}from"node:child_process";import{existsSync as Is}from"node:fs";import{delimiter as kp,extname as xp,join as Cp}from"node:path";import{stripVTControlCharacters as $s}from"node:util";var js="2.4.0",Sp=5000,Rp="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function Et(){return js}function xo(j,K){let te=j[K];if(te)return te;let re=Object.keys(j).find((oe)=>oe.toLowerCase()===K.toLowerCase()&&!!j[oe]);return re?j[re]:te}function Pp(j){return(xo(j,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((K)=>K.length>0)}function Ep(j,K){let te=xp(j)?[j]:[...Pp(K).map((re)=>`${j}${re}`),j];if(j.includes("/")||j.includes("\\"))return te.find((re)=>Is(re))??j;return(xo(K,"PATH")??"").split(kp).flatMap((re)=>te.map((oe)=>Cp(re,oe))).find((re)=>Is(re))??j}function Os(j){if(!/[\s"&|<>^]/.test(j))return j;return`"${j.replace(/"/g,'""')}"`}function cn(j,K){let[te,...re]=j,oe=K[Rp]==="win32"?"win32":process.platform;if(!te||oe!=="win32")return{cmd:te??"",args:re};let ce=Ep(te,K);if(!/\.(?:bat|cmd)$/i.test(ce))return{cmd:ce,args:re};return{cmd:xo(K,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",Os(ce),...re.map(Os)].join(" ")]}}var xn=async(j,K=Sp)=>{let te=await Dp(j,{timeoutMs:K});if(te.code!==0)return null;return $s(te.stdout).trim()||$s(te.stderr).trim()||null};function Dp(j,K){let[te,...re]=j;if(!te)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((oe)=>{try{let ce=cn([te,...re],process.env),de=wp(ce.cmd,ce.args,{stdio:["ignore","pipe","pipe"]}),we=!1,xe="",Ce="";de.stdout.on("data",(He)=>{xe+=He.toString()}),de.stderr.on("data",(He)=>{Ce+=He.toString()});let Se=(He)=>{if(we)return;we=!0,clearTimeout(Ne),oe(He)},Ne=setTimeout(()=>{de.kill(),Se({code:null,stdout:xe,stderr:Ce})},K.timeoutMs);de.on("close",(He)=>{Se({code:He,stdout:xe,stderr:Ce})}),de.on("error",()=>{Se({code:null,stdout:xe,stderr:Ce})})}catch{oe({code:null,stdout:"",stderr:""})}})}function br(j){if(!j)return null;let K=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(j);if(K)return K[1]??null;let te=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(j);if(te)return te[1]??null;return j.split(`
22
- `)[0]?.trim()||null}async function Hn(j=xn){let[K,te,re,oe,ce,de]=await Promise.all([Promise.all(Nt.map(async(we)=>[we.id,br(await j([...we.probeCommand]))])),j(["codex","plugin","list"],30000),j(["amp","plugins","list"],30000),j(["node","--version"]),j(["npm","--version"]),j(["bun","--version"])]);return{version:js,versions:Object.fromEntries(K),codexPluginListOutput:te,ampPluginListOutput:re,nodeVersion:br(oe),npmVersion:br(ce),bunVersion:br(de),platform:`${process.platform} ${process.arch}`}}function Co(j,K){if(K==="dev")return!1;let te=j.split(".").map(Number),re=K.split(".").map(Number),[oe=0,ce=0,de=0]=te,[we=0,xe=0,Ce=0]=re;if(oe!==we)return oe>we;if(ce!==xe)return ce>xe;return de>Ce}async function tn(){let j=Et(),K=new AbortController,te=setTimeout(()=>K.abort(),3000);try{let re=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:K.signal});if(!re.ok)return{currentVersion:j,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${re.status}`};let oe=await re.json(),ce=Co(oe.version,j);return{currentVersion:j,latestVersion:oe.version,updateAvailable:ce}}catch(re){return{currentVersion:j,latestVersion:null,updateAvailable:!1,error:re instanceof Error?re.message:"Network error"}}finally{clearTimeout(te)}}import*as qs from"node:readline";var Hs=(j)=>`\x1B[${j}B`,Ap=(j)=>`\x1B[${j}A`;var Fs=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function _p(j){return new Promise((K)=>setTimeout(K,j))}function Tp(j,K,te){if(!te)return K(j);if(te.aborted)return Promise.resolve();return new Promise((re,oe)=>{let ce=()=>te.removeEventListener("abort",de),de=()=>{ce(),re()};te.addEventListener("abort",de,{once:!0}),K(j).then(()=>{ce(),re()},(we)=>{ce(),oe(we)})})}function Un(j,K){return j&&j>0?j:K}function Lr(j){return Math.max(0,Math.min(1,j))}function Cn(j){return Math.max(0,Math.min(255,Math.round(j)))}function So(j){return j<=0.0031308?12.92*j:1.055*j**0.4166666666666667-0.055}function Ip(j,K,te){let re=te*Math.PI/180,oe=K*Math.cos(re),ce=K*Math.sin(re),de=(j+0.3963377774*oe+0.2158037573*ce)**3,we=(j-0.1055613458*oe-0.0638541728*ce)**3,xe=(j-0.0894841775*oe-1.291485548*ce)**3;return{blue:Cn(So(Lr(-0.0041960863*de-0.7034186147*we+1.707614701*xe))*255),green:Cn(So(Lr(-1.2684380046*de+2.6097574011*we-0.3413193965*xe))*255),red:Cn(So(Lr(4.0767416621*de-3.3077115913*we+0.2309699292*xe))*255)}}function Ro(j,K){let te=(K*j*180/Math.PI%360+360)%360;return Ip(0.72,0.15,te)}function Us(j,K=0.1){let te=Ro(K,j);return`\x1B[38;2;${te.red};${te.green};${te.blue}m`}function $p(j,K){return{blue:Cn(j.blue+(255-j.blue)*K),green:Cn(j.green+(255-j.green)*K),red:Cn(j.red+(255-j.red)*K)}}function Gs(j,K,te){let re=Math.imul(j+2654435769,2246822507)^Math.imul(K+3266489909,668265263)^Math.imul(te+374761393,2654435761),oe=re^re>>>15,ce=Math.imul(oe,739982445),de=ce^ce>>>12,we=Math.imul(de,695872825);return((we^we>>>15)>>>0)/4294967296}function Op(j,K,te){let re=Math.floor(Gs(j,K,te)*Fs.length);return Fs[re]??"░"}function Ns(j){let K=Lr(j);return K*K*K*(K*(K*6-15)+10)}function jp(j){if(j.length===0)return"";let K=[],te=!1,re="";for(let oe of j){let ce=`${oe.red};${oe.green};${oe.blue}`;if(oe.bold!==te)K.push(oe.bold?"\x1B[1m":"\x1B[22m"),te=oe.bold;if(ce!==re)K.push(`\x1B[38;2;${ce}m`),re=ce;K.push(oe.character)}return`${K.join("")}\x1B[22m\x1B[39m`}function Fp(j,K,te,re,oe){return j.map((ce,de)=>({...Ro(te,re+K+de/oe),bold:!1,character:ce}))}function Np(j,K,te,re,oe,ce,de,we){let xe=Math.max(1,re*0.75),Ce=Math.min(1,te/xe),Se=oe*Ns(Ce),Ne=Math.max(0,(te-xe)/Math.max(1,re-xe)),He=(1-Ns(te/re))*we*2,at=0.35*Math.max(0,1-Ne*2),mt=Ce>=1,it=Math.min(j.length,Math.ceil(Se+2+1));return j.slice(0,it).map((gt,ht)=>{let vt=Ro(ce,de+K+ht/we+He),yt=ht+Gs(K,ht,7919)*2-1;if(yt>Se+2)return{...vt,bold:!1,character:" "};let kt=Se-yt,Lt=0.8*Math.exp(-(kt*kt)/12.5),Ct=Math.min(0.9,Lt+at),sn=!mt&&yt>Se-4;return{...$p(vt,Ct),bold:Ct>0.3,character:sn?Op(K,ht,te):gt}})}function Ms(j){return`\x1B[?2026h${j.map((K,te)=>`\x1B8${te>0?Hs(te):""}${jp(K)}`).join("")}\x1B[?2026l`}async function Po(j,K={}){if(!j)return;let te=K.output??process.stdout,re=K.sleep??_p,oe=Un(K.frequency,0.1),ce=K.seed??0,de=Un(K.speed,40),we=Un(K.spread,3),xe=Un(K.frameRate,60),Ce=Math.max(1,Math.floor(Un(K.duration,12))),Se=j.split(`
21
+ ${j.findings.length} ${re}: ${te.join(", ")}.`;if(K.error>0)return bt.red(oe);if(K.warning>0)return bt.yellow(oe);return bt.blue(oe)}import{lstatSync as Lp}from"node:fs";import{dirname as wo}from"node:path";function ko(j,K){try{let te=Lp(K);if(te.isSymbolicLink())return{kind:j,path:K,status:"unsafe",issues:["symlink"]};if(!te.isDirectory())return{kind:j,path:K,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:j,path:K,status:"unknown",issues:[]};let re=[...te.uid!==process.getuid()?["ownership"]:[],...(te.mode&18)!==0?["permissions"]:[]];return{kind:j,path:K,status:re.length>0?"unsafe":"safe",issues:re}}catch(te){if(typeof te==="object"&&te!==null&&"code"in te&&te.code==="ENOENT")return{kind:j,path:K,status:"not-applicable",issues:[]};return{kind:j,path:K,status:"unknown",issues:[]}}}function $s(j,K){let te=M(j);return{directories:[ko("policy",wo(wo(K))),ko("config",wo(K)),...te?[ko("audit",te)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as wp}from"node:child_process";import{existsSync as Os}from"node:fs";import{delimiter as kp,extname as xp,join as Cp}from"node:path";import{stripVTControlCharacters as js}from"node:util";var Ns="2.4.1",Sp=5000,Rp="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function Et(){return Ns}function xo(j,K){let te=j[K];if(te)return te;let re=Object.keys(j).find((oe)=>oe.toLowerCase()===K.toLowerCase()&&!!j[oe]);return re?j[re]:te}function Pp(j){return(xo(j,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((K)=>K.length>0)}function Ep(j,K){let te=xp(j)?[j]:[...Pp(K).map((re)=>`${j}${re}`),j];if(j.includes("/")||j.includes("\\"))return te.find((re)=>Os(re))??j;return(xo(K,"PATH")??"").split(kp).flatMap((re)=>te.map((oe)=>Cp(re,oe))).find((re)=>Os(re))??j}function Fs(j){if(!/[\s"&|<>^]/.test(j))return j;return`"${j.replace(/"/g,'""')}"`}function cn(j,K){let[te,...re]=j,oe=K[Rp]==="win32"?"win32":process.platform;if(!te||oe!=="win32")return{cmd:te??"",args:re};let ce=Ep(te,K);if(!/\.(?:bat|cmd)$/i.test(ce))return{cmd:ce,args:re};return{cmd:xo(K,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",Fs(ce),...re.map(Fs)].join(" ")]}}var xn=async(j,K=Sp)=>{let te=await Dp(j,{timeoutMs:K});if(te.code!==0)return null;return js(te.stdout).trim()||js(te.stderr).trim()||null};function Dp(j,K){let[te,...re]=j;if(!te)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((oe)=>{try{let ce=cn([te,...re],process.env),de=wp(ce.cmd,ce.args,{stdio:["ignore","pipe","pipe"]}),we=!1,xe="",Ce="";de.stdout.on("data",(He)=>{xe+=He.toString()}),de.stderr.on("data",(He)=>{Ce+=He.toString()});let Se=(He)=>{if(we)return;we=!0,clearTimeout(Ne),oe(He)},Ne=setTimeout(()=>{de.kill(),Se({code:null,stdout:xe,stderr:Ce})},K.timeoutMs);de.on("close",(He)=>{Se({code:He,stdout:xe,stderr:Ce})}),de.on("error",()=>{Se({code:null,stdout:xe,stderr:Ce})})}catch{oe({code:null,stdout:"",stderr:""})}})}function br(j){if(!j)return null;let K=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(j);if(K)return K[1]??null;let te=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(j);if(te)return te[1]??null;return j.split(`
22
+ `)[0]?.trim()||null}async function Hn(j=xn){let[K,te,re,oe,ce,de]=await Promise.all([Promise.all(Nt.map(async(we)=>[we.id,br(await j([...we.probeCommand]))])),j(["codex","plugin","list"],30000),j(["amp","plugins","list"],30000),j(["node","--version"]),j(["npm","--version"]),j(["bun","--version"])]);return{version:Ns,versions:Object.fromEntries(K),codexPluginListOutput:te,ampPluginListOutput:re,nodeVersion:br(oe),npmVersion:br(ce),bunVersion:br(de),platform:`${process.platform} ${process.arch}`}}function Co(j,K){if(K==="dev")return!1;let te=j.split(".").map(Number),re=K.split(".").map(Number),[oe=0,ce=0,de=0]=te,[we=0,xe=0,Ce=0]=re;if(oe!==we)return oe>we;if(ce!==xe)return ce>xe;return de>Ce}async function nn(){let j=Et(),K=new AbortController,te=setTimeout(()=>K.abort(),3000);try{let re=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:K.signal});if(!re.ok)return{currentVersion:j,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${re.status}`};let oe=await re.json(),ce=Co(oe.version,j);return{currentVersion:j,latestVersion:oe.version,updateAvailable:ce}}catch(re){return{currentVersion:j,latestVersion:null,updateAvailable:!1,error:re instanceof Error?re.message:"Network error"}}finally{clearTimeout(te)}}import*as zs from"node:readline";var Gs=(j)=>`\x1B[${j}B`,Ap=(j)=>`\x1B[${j}A`;var Ms=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function _p(j){return new Promise((K)=>setTimeout(K,j))}function Tp(j,K,te){if(!te)return K(j);if(te.aborted)return Promise.resolve();return new Promise((re,oe)=>{let ce=()=>te.removeEventListener("abort",de),de=()=>{ce(),re()};te.addEventListener("abort",de,{once:!0}),K(j).then(()=>{ce(),re()},(we)=>{ce(),oe(we)})})}function Un(j,K){return j&&j>0?j:K}function Lr(j){return Math.max(0,Math.min(1,j))}function Cn(j){return Math.max(0,Math.min(255,Math.round(j)))}function So(j){return j<=0.0031308?12.92*j:1.055*j**0.4166666666666667-0.055}function Ip(j,K,te){let re=te*Math.PI/180,oe=K*Math.cos(re),ce=K*Math.sin(re),de=(j+0.3963377774*oe+0.2158037573*ce)**3,we=(j-0.1055613458*oe-0.0638541728*ce)**3,xe=(j-0.0894841775*oe-1.291485548*ce)**3;return{blue:Cn(So(Lr(-0.0041960863*de-0.7034186147*we+1.707614701*xe))*255),green:Cn(So(Lr(-1.2684380046*de+2.6097574011*we-0.3413193965*xe))*255),red:Cn(So(Lr(4.0767416621*de-3.3077115913*we+0.2309699292*xe))*255)}}function Ro(j,K){let te=(K*j*180/Math.PI%360+360)%360;return Ip(0.72,0.15,te)}function Bs(j,K=0.1){let te=Ro(K,j);return`\x1B[38;2;${te.red};${te.green};${te.blue}m`}function $p(j,K){return{blue:Cn(j.blue+(255-j.blue)*K),green:Cn(j.green+(255-j.green)*K),red:Cn(j.red+(255-j.red)*K)}}function qs(j,K,te){let re=Math.imul(j+2654435769,2246822507)^Math.imul(K+3266489909,668265263)^Math.imul(te+374761393,2654435761),oe=re^re>>>15,ce=Math.imul(oe,739982445),de=ce^ce>>>12,we=Math.imul(de,695872825);return((we^we>>>15)>>>0)/4294967296}function Op(j,K,te){let re=Math.floor(qs(j,K,te)*Ms.length);return Ms[re]??"░"}function Hs(j){let K=Lr(j);return K*K*K*(K*(K*6-15)+10)}function jp(j){if(j.length===0)return"";let K=[],te=!1,re="";for(let oe of j){let ce=`${oe.red};${oe.green};${oe.blue}`;if(oe.bold!==te)K.push(oe.bold?"\x1B[1m":"\x1B[22m"),te=oe.bold;if(ce!==re)K.push(`\x1B[38;2;${ce}m`),re=ce;K.push(oe.character)}return`${K.join("")}\x1B[22m\x1B[39m`}function Fp(j,K,te,re,oe){return j.map((ce,de)=>({...Ro(te,re+K+de/oe),bold:!1,character:ce}))}function Np(j,K,te,re,oe,ce,de,we){let xe=Math.max(1,re*0.75),Ce=Math.min(1,te/xe),Se=oe*Hs(Ce),Ne=Math.max(0,(te-xe)/Math.max(1,re-xe)),He=(1-Hs(te/re))*we*2,at=0.35*Math.max(0,1-Ne*2),mt=Ce>=1,it=Math.min(j.length,Math.ceil(Se+2+1));return j.slice(0,it).map((gt,ht)=>{let vt=Ro(ce,de+K+ht/we+He),yt=ht+qs(K,ht,7919)*2-1;if(yt>Se+2)return{...vt,bold:!1,character:" "};let kt=Se-yt,Lt=0.8*Math.exp(-(kt*kt)/12.5),Ct=Math.min(0.9,Lt+at),sn=!mt&&yt>Se-4;return{...$p(vt,Ct),bold:Ct>0.3,character:sn?Op(K,ht,te):gt}})}function Us(j){return`\x1B[?2026h${j.map((K,te)=>`\x1B8${te>0?Gs(te):""}${jp(K)}`).join("")}\x1B[?2026l`}async function Po(j,K={}){if(!j)return;let te=K.output??process.stdout,re=K.sleep??_p,oe=Un(K.frequency,0.1),ce=K.seed??0,de=Un(K.speed,40),we=Un(K.spread,3),xe=Un(K.frameRate,60),Ce=Math.max(1,Math.floor(Un(K.duration,12))),Se=j.split(`
23
23
  `).map((it)=>Array.from(it)),Ne=Math.max(...Se.map((it)=>it.length)),He=1000*Ce*Se.filter((it)=>it.length>0).length/de,at=Ne>0?Math.max(1,Math.ceil(He/(1000/xe))):0,mt=at>0?He/at:0;te.write(`\x1B[?25l${Se.length>1?`${`
24
- `.repeat(Se.length-1)}${Ap(Se.length-1)}`:""}\x1B7`);try{for(let it=1;it<=at;it+=1){if(K.signal?.aborted)break;te.write(Ms(Se.map((gt,ht)=>Np(gt,ht,it,at,Ne,oe,ce,we)))),await Tp(mt,re,K.signal)}}finally{if(te.write(Ms(Se.map((it,gt)=>Fp(it,gt,oe,ce,we)))),te.write("\x1B8"),Se.length>1)te.write(Hs(Se.length-1));te.write(`
25
- \x1B[0m\x1B[?25h`)}}var Bs=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
- `);function Mp(j){return Boolean(j.isTTY)}async function Gn(j={}){let K=j.output??process.stdout;if(!Mp(K))return;let te=j.input??process.stdin,re={duration:j.duration,frequency:j.frequency,output:K,seed:j.seed??Math.random()*8192,sleep:j.sleep,speed:j.speed,spread:j.spread};if(!te.isTTY||typeof te.setRawMode!=="function"){await Po(Bs,re);return}let oe=new AbortController,ce=te.readableFlowing===!0,de=te.isRaw===!0,we=!1,xe=(Ce,Se)=>{if(Se.ctrl&&Se.name==="c")we=!0;if(we||Se.name==="return"||Se.name==="enter")oe.abort()};qs.emitKeypressEvents(te),te.on("keypress",xe),te.setRawMode(!0),te.resume();try{await Po(Bs,{...re,signal:oe.signal})}finally{if(te.off("keypress",xe),te.setRawMode(de),!ce)te.pause()}if(!we)return;if(j.onInterrupt){j.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as qp}from"node:crypto";import{existsSync as Js}from"node:fs";import{dirname as wr,join as Ws}from"node:path";import{dirname as Vs,join as Hp,resolve as Up}from"node:path";var Gp="rule.lock";function Bp(j){return Hp(Vs(j),Gp)}function zs(j={}){return Up(j.cwd??process.cwd(),".safety-net.json")}function $t(j,K){let te=K.global?K.userConfigPath??T(j,K):K.projectConfigPath??A(K.cwd??process.cwd()),re=K.global?Qe(j,K):et(te,K.cwd??process.cwd()),oe=Bp(te);return{configDir:Vs(te),configPath:te,lockPath:oe,filesystemScope:re,configTarget:s(re,te),lockTarget:s(re,oe)}}var Vp="`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.",zp="cache",Jp="rulebooks";function Ks(j,K={}){let te=$t(j,K),re=s(te.filesystemScope,Zs(te.configDir)),oe=r(te.lockTarget);if(console.log(Vp),oe===null&&!Js(re.path))return console.log(`No v2 lock or cache leftovers found in ${wr(te.configDir)}; nothing to migrate.`),0;let ce=Xp(oe),de=m(te.configTarget);if(!de.config&&(r(te.configTarget)!==null||ce.size>0))return console.error(`Cannot migrate: the rules config in ${wr(te.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let we=de.config?.rules??[];for(let xe of we.flatMap((Ce)=>Wp(Ce,ce,te,re,K.global===!0)))console.log(xe);return G(te.lockTarget),lt(re),console.log(`Removed the v2 lock and cache under ${wr(te.configDir)}.`),0}function Ys(j,K){return[...new Set([{cwd:K},{cwd:K,global:!0}].flatMap((te)=>{let re=$t(j,te);return[re.lockPath,Zs(re.configDir)]}))].filter((te)=>Js(te))}function Wp(j,K,te,re,oe){if(!x(j))return[];let ce=O(j).name,de=s(te.filesystemScope,N(te.configDir,ce)),we=r(de);if(we!==null&&Kp(we,ce))return[];let xe=K.get(j),Ce=xe?Yp(xe,ce,re.path,te.filesystemScope):null;if(Ce===null)return[`Could not migrate ${j} from the v2 cache. Run \`cc-safety-net rule update ${j}${oe?" --global":""}\` to vendor it.`];if(y(de,Ce),we!==null)return[`Restored ${j} from the v2 cache over an invalid file.`];return[`Vendored ${j} from the v2 cache.`]}function Kp(j,K){let te=he(j);return!("problem"in te)&&te.rulebook.name===K}function Yp(j,K,te,re){let oe=Ws(te,Jp,`${Zp(j)}--${j.digest.replace("sha256:","").slice(0,12)}`,pe),ce=r(s(re,oe));if(ce===null||t2(ce)!==j.digest)return null;let de=he(ce);if("problem"in de||de.rulebook.name!==K)return null;return ce}function Zs(j){return Ws(wr(j),zp)}function Zp(j){return([j.owner,j.repo,j.display_ref,j.name].every((re)=>typeof re==="string"&&re!=="")?`${j.owner}/${j.repo}#${j.display_ref}/${j.name}`:j.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function Xp(j){let K=j===null?null:e2(j),te=Xs(K)&&Array.isArray(K.rulebooks)?K.rulebooks:[];return new Map(te.filter(Qp).map((re)=>[re.spec,re]))}function Qp(j){return Xs(j)&&typeof j.spec==="string"&&typeof j.digest==="string"}function Xs(j){return!!j&&typeof j==="object"}function e2(j){try{return JSON.parse(j)}catch{return null}}function t2(j){return`sha256:${qp("sha256").update(j).digest("hex")}`}var Qs="\r\x1B[2K",n2="\x1B[?25l",r2="\x1B[39m",o2="\x1B[?25h",i2=100,s2=0.55,a2=80,ea=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function l2(j){return new Promise((K)=>setTimeout(K,j))}async function kr(j,K={}){let te=K.output??process.stdout;if(!te.isTTY)return j;let re=K.sleep??l2,oe=!1,ce=j.then((we)=>(oe=!0,we),(we)=>{throw oe=!0,we});if(await Promise.race([ce.then(()=>!0),re(i2).then(()=>!1)]))return ce;te.write(n2);try{for(let we=0;!oe;we+=1)te.write(`${Qs}${Us(we*s2)}${ea[we%ea.length]}${r2} ${K.loadingMessage??"Loading…"}`),await Promise.race([ce,re(a2)]);return await ce}finally{te.write(`${Qs}${o2}`)}}async function Bn(j,K,te,re={}){let oe=K();if(j)await te();if(j&&oe.ready)await kr(oe.ready,re);return oe.finish()}import{stripVTControlCharacters as c2}from"node:util";var xr="amp plugins list",d2=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function ta(j){if(!j.ampPluginListOutput)return{platform:"amp",status:"n/a"};let K=c2(j.ampPluginListOutput).split(`
27
- `).map((te)=>d2.exec(te)?.[1]).find((te)=>te!==void 0);if(!K)return{platform:"amp",status:"n/a"};if(K!=="active")return{platform:"amp",status:"disabled",method:xr,configPath:xr,errors:[`Amp personal plugin cc-safety-net is ${K}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:xr,configPath:xr}}import{existsSync as f2,readFileSync as m2}from"node:fs";import{isAbsolute as vv,join as p2,relative as bv}from"node:path";function qn(j){return p2(j,".gemini","config","hooks.json")}var g2=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function y2(j){if(!j||typeof j!=="object"||Array.isArray(j))return[];return Object.values(j).flatMap((K)=>{if(!K||typeof K!=="object"||Array.isArray(K))return[];let te=K,re=te.PreToolUse;if(!Array.isArray(re))return[];return re.flatMap((oe)=>{if(!oe||typeof oe!=="object"||Array.isArray(oe))return[];let ce=oe.hooks;if(!Array.isArray(ce))return[];return ce.flatMap((de)=>{if(!de||typeof de!=="object"||Array.isArray(de))return[];let we=de.command;if(typeof we!=="string"||!g2.test(we))return[];return[{command:we,enabled:te.enabled!==!1}]})})})}function na(j){let K=qn(j.environment.home);if(!f2(K))return{platform:"antigravity-cli",status:"n/a",configPath:K};let te;try{te=y2(JSON.parse(m2(K,"utf-8")))}catch(re){return{platform:"antigravity-cli",status:"n/a",configPath:K,errors:[`Failed to parse Antigravity hooks config ${K}: ${re instanceof Error?re.message:String(re)}`]}}if(te.some((re)=>re.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:K};if(te.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:K};return{platform:"antigravity-cli",status:"n/a",configPath:K}}import{join as ra}from"node:path";import{existsSync as h2,lstatSync as v2,readFileSync as b2}from"node:fs";function qt(j,K=(te)=>te){if(!h2(j))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(K(b2(j,"utf-8")))}}catch{return{kind:"unreadable"}}}function Pt(j){try{return v2(j)}catch{return}}function Cr(j,K){let te=Pt(K);if(!te)return{platform:j,status:"n/a",configPath:K};if(!te.isSymbolicLink()&&te.isDirectory())return;return{platform:j,status:"n/a",configPath:K,errors:[`${K} is a symlink or not a directory; move or remove it before installing`]}}function wt(j,K){return typeof j==="object"&&j!==null?j[K]:void 0}var Eo="cc-safety-net@cc-marketplace";function oa(j){return ra(j.home,".claude","plugins","installed_plugins.json")}function ia(j,K){let te=wt(wt(j,"plugins"),K);return Array.isArray(te)&&te.length>0}function Sr(j,K){let te=qt(oa(j));return te.kind==="ok"&&ia(te.value,K)}function Do(j){let K=oa(j),te=qt(K);if(te.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(te.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!ia(te.value,Eo))return{platform:"claude-code",status:"n/a"};let re=ra(j.home,".claude","settings.json"),oe=qt(re);if(oe.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(oe.kind==="ok"&&wt(wt(oe.value,"enabledPlugins"),Eo)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:re,errors:[`${Eo} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:K}}function sa(j){return Do(j.environment)}function aa(j){if(!j.codexPluginListOutput)return{platform:"codex",status:"n/a"};let K=j.codexPluginListOutput.split(`
24
+ `.repeat(Se.length-1)}${Ap(Se.length-1)}`:""}\x1B7`);try{for(let it=1;it<=at;it+=1){if(K.signal?.aborted)break;te.write(Us(Se.map((gt,ht)=>Np(gt,ht,it,at,Ne,oe,ce,we)))),await Tp(mt,re,K.signal)}}finally{if(te.write(Us(Se.map((it,gt)=>Fp(it,gt,oe,ce,we)))),te.write("\x1B8"),Se.length>1)te.write(Gs(Se.length-1));te.write(`
25
+ \x1B[0m\x1B[?25h`)}}var Vs=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
+ `);function Mp(j){return Boolean(j.isTTY)}async function Gn(j={}){let K=j.output??process.stdout;if(!Mp(K))return;let te=j.input??process.stdin,re={duration:j.duration,frequency:j.frequency,output:K,seed:j.seed??Math.random()*8192,sleep:j.sleep,speed:j.speed,spread:j.spread};if(!te.isTTY||typeof te.setRawMode!=="function"){await Po(Vs,re);return}let oe=new AbortController,ce=te.readableFlowing===!0,de=te.isRaw===!0,we=!1,xe=(Ce,Se)=>{if(Se.ctrl&&Se.name==="c")we=!0;if(we||Se.name==="return"||Se.name==="enter")oe.abort()};zs.emitKeypressEvents(te),te.on("keypress",xe),te.setRawMode(!0),te.resume();try{await Po(Vs,{...re,signal:oe.signal})}finally{if(te.off("keypress",xe),te.setRawMode(de),!ce)te.pause()}if(!we)return;if(j.onInterrupt){j.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as qp}from"node:crypto";import{existsSync as Ks}from"node:fs";import{dirname as wr,join as Ys}from"node:path";import{dirname as Js,join as Hp,resolve as Up}from"node:path";var Gp="rule.lock";function Bp(j){return Hp(Js(j),Gp)}function Ws(j={}){return Up(j.cwd??process.cwd(),".safety-net.json")}function $t(j,K){let te=K.global?K.userConfigPath??T(j,K):K.projectConfigPath??A(K.cwd??process.cwd()),re=K.global?Qe(j,K):et(te,K.cwd??process.cwd()),oe=Bp(te);return{configDir:Js(te),configPath:te,lockPath:oe,filesystemScope:re,configTarget:s(re,te),lockTarget:s(re,oe)}}var Vp="`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.",zp="cache",Jp="rulebooks";function Zs(j,K={}){let te=$t(j,K),re=s(te.filesystemScope,Qs(te.configDir)),oe=r(te.lockTarget);if(console.log(Vp),oe===null&&!Ks(re.path))return console.log(`No v2 lock or cache leftovers found in ${wr(te.configDir)}; nothing to migrate.`),0;let ce=Xp(oe),de=m(te.configTarget);if(!de.config&&(r(te.configTarget)!==null||ce.size>0))return console.error(`Cannot migrate: the rules config in ${wr(te.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let we=de.config?.rules??[];for(let xe of we.flatMap((Ce)=>Wp(Ce,ce,te,re,K.global===!0)))console.log(xe);return G(te.lockTarget),lt(re),console.log(`Removed the v2 lock and cache under ${wr(te.configDir)}.`),0}function Xs(j,K){return[...new Set([{cwd:K},{cwd:K,global:!0}].flatMap((te)=>{let re=$t(j,te);return[re.lockPath,Qs(re.configDir)]}))].filter((te)=>Ks(te))}function Wp(j,K,te,re,oe){if(!x(j))return[];let ce=O(j).name,de=s(te.filesystemScope,N(te.configDir,ce)),we=r(de);if(we!==null&&Kp(we,ce))return[];let xe=K.get(j),Ce=xe?Yp(xe,ce,re.path,te.filesystemScope):null;if(Ce===null)return[`Could not migrate ${j} from the v2 cache. Run \`cc-safety-net rule update ${j}${oe?" --global":""}\` to vendor it.`];if(y(de,Ce),we!==null)return[`Restored ${j} from the v2 cache over an invalid file.`];return[`Vendored ${j} from the v2 cache.`]}function Kp(j,K){let te=he(j);return!("problem"in te)&&te.rulebook.name===K}function Yp(j,K,te,re){let oe=Ys(te,Jp,`${Zp(j)}--${j.digest.replace("sha256:","").slice(0,12)}`,pe),ce=r(s(re,oe));if(ce===null||t2(ce)!==j.digest)return null;let de=he(ce);if("problem"in de||de.rulebook.name!==K)return null;return ce}function Qs(j){return Ys(wr(j),zp)}function Zp(j){return([j.owner,j.repo,j.display_ref,j.name].every((re)=>typeof re==="string"&&re!=="")?`${j.owner}/${j.repo}#${j.display_ref}/${j.name}`:j.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function Xp(j){let K=j===null?null:e2(j),te=ea(K)&&Array.isArray(K.rulebooks)?K.rulebooks:[];return new Map(te.filter(Qp).map((re)=>[re.spec,re]))}function Qp(j){return ea(j)&&typeof j.spec==="string"&&typeof j.digest==="string"}function ea(j){return!!j&&typeof j==="object"}function e2(j){try{return JSON.parse(j)}catch{return null}}function t2(j){return`sha256:${qp("sha256").update(j).digest("hex")}`}var ta="\r\x1B[2K",n2="\x1B[?25l",r2="\x1B[39m",o2="\x1B[?25h",i2=100,s2=0.55,a2=80,na=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function l2(j){return new Promise((K)=>setTimeout(K,j))}async function kr(j,K={}){let te=K.output??process.stdout;if(!te.isTTY)return j;let re=K.sleep??l2,oe=!1,ce=j.then((we)=>(oe=!0,we),(we)=>{throw oe=!0,we});if(await Promise.race([ce.then(()=>!0),re(i2).then(()=>!1)]))return ce;te.write(n2);try{for(let we=0;!oe;we+=1)te.write(`${ta}${Bs(we*s2)}${na[we%na.length]}${r2} ${K.loadingMessage??"Loading…"}`),await Promise.race([ce,re(a2)]);return await ce}finally{te.write(`${ta}${o2}`)}}async function Bn(j,K,te,re={}){let oe=K();if(j)await te();if(j&&oe.ready)await kr(oe.ready,re);return oe.finish()}import{stripVTControlCharacters as c2}from"node:util";var xr="amp plugins list",d2=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function ra(j){if(!j.ampPluginListOutput)return{platform:"amp",status:"n/a"};let K=c2(j.ampPluginListOutput).split(`
27
+ `).map((te)=>d2.exec(te)?.[1]).find((te)=>te!==void 0);if(!K)return{platform:"amp",status:"n/a"};if(K!=="active")return{platform:"amp",status:"disabled",method:xr,configPath:xr,errors:[`Amp personal plugin cc-safety-net is ${K}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:xr,configPath:xr}}import{existsSync as f2,readFileSync as m2}from"node:fs";import{isAbsolute as vv,join as p2,relative as bv}from"node:path";function qn(j){return p2(j,".gemini","config","hooks.json")}var g2=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function y2(j){if(!j||typeof j!=="object"||Array.isArray(j))return[];return Object.values(j).flatMap((K)=>{if(!K||typeof K!=="object"||Array.isArray(K))return[];let te=K,re=te.PreToolUse;if(!Array.isArray(re))return[];return re.flatMap((oe)=>{if(!oe||typeof oe!=="object"||Array.isArray(oe))return[];let ce=oe.hooks;if(!Array.isArray(ce))return[];return ce.flatMap((de)=>{if(!de||typeof de!=="object"||Array.isArray(de))return[];let we=de.command;if(typeof we!=="string"||!g2.test(we))return[];return[{command:we,enabled:te.enabled!==!1}]})})})}function oa(j){let K=qn(j.environment.home);if(!f2(K))return{platform:"antigravity-cli",status:"n/a",configPath:K};let te;try{te=y2(JSON.parse(m2(K,"utf-8")))}catch(re){return{platform:"antigravity-cli",status:"n/a",configPath:K,errors:[`Failed to parse Antigravity hooks config ${K}: ${re instanceof Error?re.message:String(re)}`]}}if(te.some((re)=>re.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:K};if(te.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:K};return{platform:"antigravity-cli",status:"n/a",configPath:K}}import{join as ia}from"node:path";import{existsSync as h2,lstatSync as v2,readFileSync as b2}from"node:fs";function qt(j,K=(te)=>te){if(!h2(j))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(K(b2(j,"utf-8")))}}catch{return{kind:"unreadable"}}}function Pt(j){try{return v2(j)}catch{return}}function Cr(j,K){let te=Pt(K);if(!te)return{platform:j,status:"n/a",configPath:K};if(!te.isSymbolicLink()&&te.isDirectory())return;return{platform:j,status:"n/a",configPath:K,errors:[`${K} is a symlink or not a directory; move or remove it before installing`]}}function wt(j,K){return typeof j==="object"&&j!==null?j[K]:void 0}var Eo="cc-safety-net@cc-marketplace";function sa(j){return ia(j.home,".claude","plugins","installed_plugins.json")}function aa(j,K){let te=wt(wt(j,"plugins"),K);return Array.isArray(te)&&te.length>0}function Sr(j,K){let te=qt(sa(j));return te.kind==="ok"&&aa(te.value,K)}function Do(j){let K=sa(j),te=qt(K);if(te.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(te.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!aa(te.value,Eo))return{platform:"claude-code",status:"n/a"};let re=ia(j.home,".claude","settings.json"),oe=qt(re);if(oe.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(oe.kind==="ok"&&wt(wt(oe.value,"enabledPlugins"),Eo)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:re,errors:[`${Eo} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:K}}function la(j){return Do(j.environment)}function ca(j){if(!j.codexPluginListOutput)return{platform:"codex",status:"n/a"};let K=j.codexPluginListOutput.split(`
28
28
  `).find((te)=>te.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!K)return{platform:"codex",status:"n/a"};if(!K.includes("installed,"))return{platform:"codex",status:"n/a"};if(!K.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 _r,readdirSync as L2,readFileSync as w2}from"node:fs";import{join as Tt}from"node:path";function jt(j){let K="",te=0,re=!1,oe=!1,ce=-1;while(te<j.length){let de=j[te],we=j[te+1];if(oe){K+=de,oe=!1,te++;continue}if(de==='"'&&!re){re=!0,ce=-1,K+=de,te++;continue}if(de==='"'&&re){re=!1,K+=de,te++;continue}if(de==="\\"&&re){oe=!0,K+=de,te++;continue}if(re){K+=de,te++;continue}if(de==="/"&&we==="/"){while(te<j.length&&j[te]!==`
29
- `)te++;continue}if(de==="/"&&we==="*"){te+=2;while(te<j.length-1){if(j[te]==="*"&&j[te+1]==="/"){te+=2;break}te++}continue}if(de===","){ce=K.length,K+=de,te++;continue}if(de==="}"||de==="]"){if(ce!==-1){let xe=K.slice(ce+1);if(/^\s*$/.test(xe))K=K.slice(0,ce)+xe}ce=-1,K+=de,te++;continue}if(!/\s/.test(de))ce=-1;K+=de,te++}return K}function Ao(j,K,te){let re=K+1,oe=!1;while(re<j.length){if(oe){oe=!1,re++;continue}if(j[re]==="\\"){oe=!0,re++;continue}if(j[re]==='"')return re+1;re++}throw Error(te)}function _o(j,K,te){let re=j[K],oe=re==="["?"]":"}",ce=0,de=K;while(de<j.length){let we=te.skipComment?.(j,de)??de;if(we!==de){de=we;continue}if(j[de]==='"'){de=Ao(j,de,te.stringError);continue}if(j[de]===re)ce++;if(j[de]===oe){if(ce--,ce===0)return de}de++}throw Error(te.bracketError)}function ca(j,K){let te=j.lastIndexOf(`
29
+ `)te++;continue}if(de==="/"&&we==="*"){te+=2;while(te<j.length-1){if(j[te]==="*"&&j[te+1]==="/"){te+=2;break}te++}continue}if(de===","){ce=K.length,K+=de,te++;continue}if(de==="}"||de==="]"){if(ce!==-1){let xe=K.slice(ce+1);if(/^\s*$/.test(xe))K=K.slice(0,ce)+xe}ce=-1,K+=de,te++;continue}if(!/\s/.test(de))ce=-1;K+=de,te++}return K}function Ao(j,K,te){let re=K+1,oe=!1;while(re<j.length){if(oe){oe=!1,re++;continue}if(j[re]==="\\"){oe=!0,re++;continue}if(j[re]==='"')return re+1;re++}throw Error(te)}function _o(j,K,te){let re=j[K],oe=re==="["?"]":"}",ce=0,de=K;while(de<j.length){let we=te.skipComment?.(j,de)??de;if(we!==de){de=we;continue}if(j[de]==='"'){de=Ao(j,de,te.stringError);continue}if(j[de]===re)ce++;if(j[de]===oe){if(ce--,ce===0)return de}de++}throw Error(te.bracketError)}function ua(j,K){let te=j.lastIndexOf(`
30
30
  `,K)+1;return/^[ \t]*/.exec(j.slice(te))?.[0]??""}function Pr(j,K){let te=K.end+(/^\s*/.exec(j.slice(K.end))?.[0].length??0);if(j[te]===","){let de=j[te+1]===`
31
31
  `?te+2:te+1;return`${j.slice(0,K.start)}${j.slice(de)}`}let re=j.slice(0,K.start).search(/\s*$/)-1;if(j[re]!==",")return`${j.slice(0,K.start)}${j.slice(K.end)}`;let oe=j.lastIndexOf(`
32
32
  `,re-1),ce=oe!==-1&&/^\s*$/.test(j.slice(oe+1,re))?oe:re;return`${j.slice(0,ce)}${j.slice(K.end)}`}function Rr(j,K){if(j.startsWith("//",K)){let te=j.indexOf(`
33
- `,K+2);return te===-1?j.length:te+1}if(j.startsWith("/*",K)){let te=j.indexOf("*/",K+2);return te===-1?j.length:te+2}return K}function la(j,K){let te=K;while(te<j.length){if(/\s/.test(j[te]??"")){te++;continue}let re=Rr(j,te);if(re===te)return te;te=re}return te}function da(j,K,te){let re=0,oe=0;while(oe<j.length){let ce=Rr(j,oe);if(ce!==oe){oe=ce;continue}if(j[oe]==='"'){let de=Ao(j,oe,te.stringError);if(re===1&&JSON.parse(j.slice(oe,de))===K){let we=la(j,de),xe=la(j,we+1);if(j[we]===":"&&j[xe]==="[")return{start:xe,end:_o(j,xe,{skipComment:Rr,...te})}}oe=de;continue}if(j[oe]==="{"||j[oe]==="[")re++;if(j[oe]==="}"||j[oe]==="]")re--;oe++}return}function ua(j,K,te){let re=[],oe=K.start+1;while(oe<K.end){let ce=Rr(j,oe);if(ce!==oe){oe=ce;continue}if(j[oe]==='"'){let de=Ao(j,oe,te),we=JSON.parse(j.slice(oe,de));if(typeof we==="string")re.push({range:{start:oe,end:de},value:we});oe=de;continue}oe++}return re}var Vt="cc-safety-net@cc-marketplace",Er=["cc-marketplace","cc-safety-net"],pa=["_direct","copilot-safety-net"],fa=["cc-marketplace","safety-net"],ma="safety-net@cc-marketplace";function Dr(j,K){let te=K.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${te}([^a-z0-9-]|$)`,"m").test(j??"")}function ga(j){return Dr(j,"cc-safety-net@cc-marketplace")}function ya(j){return Dr(j,"cc-marketplace")}function ha(j){return Dr(j,"copilot-safety-net")}function va(j){return Dr(j,"safety-net@cc-marketplace")}function To(j){if(!j?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(j)}function La(j,K){if(!j)return null;let te=j.match(/(\d+)\.(\d+)\.(\d+)/);if(!te)return null;let re=[Number(te[1]),Number(te[2]),Number(te[3])];for(let oe=0;oe<K.length;oe++){let ce=re[oe]??0,de=K[oe]??0;if(ce!==de)return ce>de}return!0}function k2(j){return La(j,[0,0,422])}function x2(j){return La(j,[1,0,8])}function Vn(j){return j.env.get("COPILOT_HOME")||Tt(j.home,".copilot")}function Io(j){return(j.hooks?.preToolUse??[]).some((te)=>{if(te.type!=="command")return!1;return To(te.command)||To(te.bash)||To(te.powershell)})}function Ar(j){return j===void 0||typeof j==="string"}function C2(j){if(!j||typeof j!=="object"||Array.isArray(j))return!1;let K=j;if(K.disableAllHooks!==void 0&&typeof K.disableAllHooks!=="boolean")return!1;if(K.hooks===void 0)return!0;if(!K.hooks||typeof K.hooks!=="object"||Array.isArray(K.hooks))return!1;let te=K.hooks.preToolUse;if(te===void 0)return!0;return Array.isArray(te)&&te.every((re)=>re!==null&&typeof re==="object"&&!Array.isArray(re)&&Ar(re.type)&&Ar(re.command)&&Ar(re.bash)&&Ar(re.powershell))}function $o(j,K){try{let te=JSON.parse(jt(w2(j,"utf-8")));if(!C2(te)){K?.push(`Invalid hook config ${j}: hooks.preToolUse must be an array of hook objects`);return}return te}catch(te){K?.push(`Failed to parse ${j}: ${te instanceof Error?te.message:String(te)}`);return}}function wa(j,K){try{return L2(j).filter((te)=>te.endsWith(".json")).sort((te,re)=>te.localeCompare(re))}catch(te){return K?.push(`Failed to read ${j}: ${te instanceof Error?te.message:String(te)}`),[]}}function S2(j,K){if(!_r(j))return[];let te=[];for(let re of wa(j,K)){let oe=Tt(j,re),ce=$o(oe,K);if(ce&&Io(ce))te.push(oe)}return te}function Sn(j,K){if(!_r(j))return;let te=$o(j,K);if(!te)return;return{path:j,config:te}}function ba(j,K,te,re){if(K){j.push(`GitHub Copilot CLI ${K} does not support ${te}; requires ${re}+`);return}j.push(`GitHub Copilot CLI version unavailable; skipping ${te} because it requires ${re}+`)}function R2(j){for(let K of j){if(K?.config.disableAllHooks===!0)return K.path;if(K?.config.disableAllHooks===!1)return}return}function P2(j,K,te,re){let oe=Vn(j),ce=Tt(K,".github","hooks"),de=Tt(oe,"hooks"),we=Tt(K,".github","copilot"),xe=Tt(K,".claude"),Ce=x2(te),Se=Ce===!0?re:void 0,Ne=[Sn(Tt(we,"settings.local.json"),Se),Sn(Tt(we,"settings.json"),Se),Sn(Tt(xe,"settings.local.json"),Se),Sn(Tt(xe,"settings.json"),Se)],He=[Sn(Tt(oe,"settings.json"),Se),Sn(Tt(oe,"config.json"),Se)];if(Ce!==!1){let kt=R2([...Ne,...He]);if(kt){if(Ce===null)re.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${kt} as active`);return{activeConfigPaths:[],disabledBy:kt}}}let at=S2(ce,re),mt=k2(te),it=mt===!0?re:void 0,gt=_r(de)?wa(de,it):[],ht=[];for(let kt of gt){let Lt=Tt(de,kt),Ct=$o(Lt,it);if(Ct&&Io(Ct))ht.push(Lt)}if(mt!==!0&&ht.length>0)ba(re,te,`user hook files in ${de}`,"0.0.422"),ht.length=0;let vt=[];for(let kt of[...Ne,...He]){if(!kt)continue;if(!Io(kt.config))continue;if(Ce===!0){vt.push(kt);continue}ba(re,te,"inline hook definitions in Copilot config files","1.0.8");break}let yt=(kt)=>kt.filter((Lt)=>!!Lt&&vt.includes(Lt)).map((Lt)=>Lt.path);return{activeConfigPaths:[...yt(Ne),...at,...yt(He),...ht]}}function ka(j){let K=[],te=P2(j.environment,j.cwd,j.copilotCliVersion,K);if(te.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:te.disabledBy,configPaths:[te.disabledBy],errors:K.length>0?K:void 0};let re=Vn(j.environment),oe=Tt(re,"installed-plugins",...Er),ce=_r(oe),de=Tt(re,"settings.json"),we=qt(de,jt);if(ce&&we.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(ce&&we.kind==="ok"&&wt(wt(we.value,"enabledPlugins"),Vt)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:de,errors:[`${Vt} is installed but not enabled in Copilot CLI`]};if(ce||te.activeConfigPaths.length>0){let xe=ce,Ce=te.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:xe?"plugin config":"hook config",configPath:Ce??(xe?oe:void 0),configPaths:te.activeConfigPaths.length>0?te.activeConfigPaths:void 0,errors:K.length>0?K:void 0}}return{platform:"copilot-cli",status:"n/a",errors:K.length>0?K:void 0}}import{existsSync as F2,readFileSync as N2}from"node:fs";import{existsSync as xa,mkdirSync as A2,readFileSync as _2}from"node:fs";import{dirname as T2,join as I2}from"node:path";import{renameSync as E2,writeFileSync as D2}from"node:fs";function Dt(j,K){let te=`${j}.${process.pid}.tmp`;D2(te,K),E2(te,j)}var zt=Object.fromEntries(Mn.map((j)=>[j.id,`npx -y cc-safety-net hook ${j.flags[1]}`]));var zn=zt.cursor,Ca=30;function Ir(j){return I2(j.home,".cursor","hooks.json")}function dn(j){return typeof j==="object"&&j!==null&&!Array.isArray(j)}function Oo(){return{command:zn,timeout:Ca,failClosed:!0}}function Tr(j){return dn(j)&&j.command===zn}function $2(j){return Object.keys(j).length===3&&j.command===zn&&j.timeout===Ca&&j.failClosed===!0}function O2(j){try{return JSON.parse(_2(j,"utf-8"))}catch(K){if(K instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${j}: ${K.message}`);throw K}}function Sa(j){let K=O2(j);if(!dn(K))throw Error(`Cursor hooks config ${j} must be a JSON object`);if(K.version!==1)throw Error(`Cursor hooks config ${j} must set "version": 1`);if(K.hooks!==void 0&&!dn(K.hooks))throw Error(`Cursor hooks config ${j} "hooks" must be an object`);let te=dn(K.hooks)?K.hooks.preToolUse:void 0;if(te!==void 0&&!Array.isArray(te))throw Error(`Cursor hooks config ${j} "hooks.preToolUse" must be an array`);return K}function Ra(j){let K=dn(j.hooks)?j.hooks.preToolUse:void 0;return Array.isArray(K)?K:[]}function j2(j){if(!j.some(Tr))return[...j,Oo()];return j.reduce((K,te)=>{if(!Tr(te))return K.result.push(te),K;if(!K.inserted)K.result.push(Oo()),K.inserted=!0;return K},{result:[],inserted:!1}).result}function Pa(j,K,te){let re=dn(K.hooks)?K.hooks:{},oe={...K,hooks:{...re,preToolUse:te}};Dt(j,`${JSON.stringify(oe,null,2)}
34
- `)}function Ea(j){let K=Ir(j);if(!xa(K))return A2(T2(K),{recursive:!0}),Dt(K,`${JSON.stringify({version:1,hooks:{preToolUse:[Oo()]}},null,2)}
35
- `),{path:K,alreadyInstalled:!1};let te=Sa(K),re=Ra(te),oe=re.filter(Tr);if(dn(te.hooks)&&Array.isArray(te.hooks.preToolUse)&&oe.length===1&&oe[0]!==void 0&&$2(oe[0]))return{path:K,alreadyInstalled:!0};return Pa(K,te,j2(re)),{path:K,alreadyInstalled:!1}}function Da(j){let K=Ir(j);if(!xa(K))return{path:K,alreadyInstalled:!1};let te=Sa(K),re=Ra(te),oe=re.filter((ce)=>!Tr(ce));if(oe.length===re.length)return{path:K,alreadyInstalled:!1};return Pa(K,te,oe),{path:K,alreadyInstalled:!0}}function M2(j){if(!j||typeof j!=="object"||Array.isArray(j))return[];let K=j.hooks;if(!K||typeof K!=="object"||Array.isArray(K))return[];let te=K.preToolUse;if(!Array.isArray(te))return[];return te.filter((re)=>!!re&&typeof re==="object"&&!Array.isArray(re)&&re.command===zn)}function H2(j){let K=[];if(j.length>1)K.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let te=j[0];if(te&&te.failClosed!==!0)K.push('Managed hook is missing "failClosed": true; reinstall to repair');if(te&&te.timeout!==30)K.push('Managed hook "timeout" is not 30; reinstall to repair');return K}function Aa(j){let K=Ir(j.environment);if(!F2(K))return{platform:"cursor",status:"n/a",configPath:K};let te;try{te=JSON.parse(N2(K,"utf-8"))}catch(ce){return{platform:"cursor",status:"n/a",configPath:K,errors:[`Failed to parse Cursor hooks config ${K}: ${ce instanceof Error?ce.message:String(ce)}`]}}let re=M2(te);if(re.length===0)return{platform:"cursor",status:"n/a",configPath:K};let oe=H2(re);return{platform:"cursor",status:"configured",method:"hook config",configPath:K,errors:oe.length>0?oe:void 0}}import{existsSync as U2}from"node:fs";import{join as jo}from"node:path";var Fo="gemini-safety-net";function No(j){let K=jo(j.home,".gemini","extensions"),te=jo(K,Fo);if(!U2(te))return{platform:"gemini-cli",status:"n/a"};let re=jo(K,"extension-enablement.json"),oe=qt(re);if(oe.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let ce=oe.kind==="ok"?wt(wt(oe.value,Fo),"overrides"):void 0;if(Array.isArray(ce)&&ce.some((we)=>typeof we==="string"&&we.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:re,errors:[`${Fo} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:te}}function _a(j){return No(j.environment)}import{existsSync as V2,readFileSync as z2}from"node:fs";import{existsSync as Ia,mkdirSync as G2,readFileSync as $a,rmSync as B2}from"node:fs";import{dirname as q2,join as Ta}from"node:path";var Jn=zt["grok-build"],jr=30;function Fr(j){return Ta(j.env.get("GROK_HOME")??Ta(j.home,".grok"),"hooks","cc-safety-net.json")}function un(j){return typeof j==="object"&&j!==null&&!Array.isArray(j)}function $r(){return{hooks:[{type:"command",command:Jn,timeout:jr}]}}function Oa(j){return un(j)&&j.command===Jn}function ja(j){return j.flatMap((K)=>{if(!un(K)||!Array.isArray(K.hooks))return[K];let te=K.hooks.filter((re)=>!Oa(re));if(te.length===K.hooks.length)return[K];return te.length===0?[]:[{...K,hooks:te}]})}function Fa(j){try{let K=JSON.parse(j);return un(K)?K:null}catch{return null}}function Na(j){let K=un(j.hooks)?j.hooks.PreToolUse:void 0;return Array.isArray(K)?K:[]}function Or(j,K,te){let re=un(K.hooks)?K.hooks:{};Dt(j,`${JSON.stringify({...K,hooks:{...re,PreToolUse:te}},null,2)}
36
- `)}function Ma(j){let K=Fr(j);if(!Ia(K))return G2(q2(K),{recursive:!0}),Or(K,{},[$r()]),{path:K,alreadyInstalled:!1};let te=Fa($a(K,"utf-8"));if(!te)return Or(K,{},[$r()]),{path:K,alreadyInstalled:!1};let re=Na(te),oe=re.filter((ce)=>un(ce)&&Array.isArray(ce.hooks)&&ce.hooks.some(Oa));if(oe.length===1&&JSON.stringify(oe[0])===JSON.stringify($r()))return{path:K,alreadyInstalled:!0};return Or(K,te,[...ja(re),$r()]),{path:K,alreadyInstalled:!1}}function Ha(j){let K=Fr(j);if(!Ia(K))return{path:K,alreadyInstalled:!1};let te=Fa($a(K,"utf-8"));if(!te)return{path:K,alreadyInstalled:!1};let re=Na(te),oe=ja(re);if(JSON.stringify(oe)===JSON.stringify(re))return{path:K,alreadyInstalled:!1};let ce=un(te.hooks)?te.hooks:{};if(oe.length===0&&Object.keys(te).length===1&&Object.keys(ce).length===1)return B2(K),{path:K,alreadyInstalled:!0};return Or(K,te,oe),{path:K,alreadyInstalled:!0}}function Wn(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function J2(j){if(!Wn(j)||!Wn(j.hooks))return[];let K=j.hooks.PreToolUse;if(!Array.isArray(K))return[];return K.filter((te)=>Wn(te)&&Array.isArray(te.hooks)&&te.hooks.some((re)=>Wn(re)&&re.command===Jn))}function W2(j){let te=(Array.isArray(j.hooks)?j.hooks.filter(Wn):[]).find((re)=>re.command===Jn);return[...j.matcher===void 0||j.matcher===""||j.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...te?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...te?.timeout===jr?[]:[`Managed hook "timeout" is not ${jr}; reinstall to repair`]]}function Ua(j){let K=Fr(j.environment);if(!V2(K))return{platform:"grok-build",status:"n/a",configPath:K};let te;try{te=JSON.parse(z2(K,"utf-8"))}catch(ce){return{platform:"grok-build",status:"n/a",configPath:K,errors:[`Failed to parse Grok Build hooks config ${K}: ${ce instanceof Error?ce.message:String(ce)}`]}}let re=J2(te)[0];if(!re)return{platform:"grok-build",status:"n/a",configPath:K};let oe=W2(re);return{platform:"grok-build",status:"configured",method:"hook config",configPath:K,errors:oe.length>0?oe:void 0}}import{readFileSync as Ka}from"node:fs";import{join as Ya}from"node:path";var Ft="cc-safety-net",Mo="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",K2=30;function Ga(j){return`${Mo}
33
+ `,K+2);return te===-1?j.length:te+1}if(j.startsWith("/*",K)){let te=j.indexOf("*/",K+2);return te===-1?j.length:te+2}return K}function da(j,K){let te=K;while(te<j.length){if(/\s/.test(j[te]??"")){te++;continue}let re=Rr(j,te);if(re===te)return te;te=re}return te}function pa(j,K,te){let re=0,oe=0;while(oe<j.length){let ce=Rr(j,oe);if(ce!==oe){oe=ce;continue}if(j[oe]==='"'){let de=Ao(j,oe,te.stringError);if(re===1&&JSON.parse(j.slice(oe,de))===K){let we=da(j,de),xe=da(j,we+1);if(j[we]===":"&&j[xe]==="[")return{start:xe,end:_o(j,xe,{skipComment:Rr,...te})}}oe=de;continue}if(j[oe]==="{"||j[oe]==="[")re++;if(j[oe]==="}"||j[oe]==="]")re--;oe++}return}function fa(j,K,te){let re=[],oe=K.start+1;while(oe<K.end){let ce=Rr(j,oe);if(ce!==oe){oe=ce;continue}if(j[oe]==='"'){let de=Ao(j,oe,te),we=JSON.parse(j.slice(oe,de));if(typeof we==="string")re.push({range:{start:oe,end:de},value:we});oe=de;continue}oe++}return re}var Vt="cc-safety-net@cc-marketplace",Er=["cc-marketplace","cc-safety-net"],ma=["_direct","copilot-safety-net"],ga=["cc-marketplace","safety-net"],ya="safety-net@cc-marketplace";function Dr(j,K){let te=K.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${te}([^a-z0-9-]|$)`,"m").test(j??"")}function ha(j){return Dr(j,"cc-safety-net@cc-marketplace")}function va(j){return Dr(j,"cc-marketplace")}function ba(j){return Dr(j,"copilot-safety-net")}function La(j){return Dr(j,"safety-net@cc-marketplace")}function To(j){if(!j?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(j)}function ka(j,K){if(!j)return null;let te=j.match(/(\d+)\.(\d+)\.(\d+)/);if(!te)return null;let re=[Number(te[1]),Number(te[2]),Number(te[3])];for(let oe=0;oe<K.length;oe++){let ce=re[oe]??0,de=K[oe]??0;if(ce!==de)return ce>de}return!0}function k2(j){return ka(j,[0,0,422])}function x2(j){return ka(j,[1,0,8])}function Vn(j){return j.env.get("COPILOT_HOME")||Tt(j.home,".copilot")}function Io(j){return(j.hooks?.preToolUse??[]).some((te)=>{if(te.type!=="command")return!1;return To(te.command)||To(te.bash)||To(te.powershell)})}function Ar(j){return j===void 0||typeof j==="string"}function C2(j){if(!j||typeof j!=="object"||Array.isArray(j))return!1;let K=j;if(K.disableAllHooks!==void 0&&typeof K.disableAllHooks!=="boolean")return!1;if(K.hooks===void 0)return!0;if(!K.hooks||typeof K.hooks!=="object"||Array.isArray(K.hooks))return!1;let te=K.hooks.preToolUse;if(te===void 0)return!0;return Array.isArray(te)&&te.every((re)=>re!==null&&typeof re==="object"&&!Array.isArray(re)&&Ar(re.type)&&Ar(re.command)&&Ar(re.bash)&&Ar(re.powershell))}function $o(j,K){try{let te=JSON.parse(jt(w2(j,"utf-8")));if(!C2(te)){K?.push(`Invalid hook config ${j}: hooks.preToolUse must be an array of hook objects`);return}return te}catch(te){K?.push(`Failed to parse ${j}: ${te instanceof Error?te.message:String(te)}`);return}}function xa(j,K){try{return L2(j).filter((te)=>te.endsWith(".json")).sort((te,re)=>te.localeCompare(re))}catch(te){return K?.push(`Failed to read ${j}: ${te instanceof Error?te.message:String(te)}`),[]}}function S2(j,K){if(!_r(j))return[];let te=[];for(let re of xa(j,K)){let oe=Tt(j,re),ce=$o(oe,K);if(ce&&Io(ce))te.push(oe)}return te}function Sn(j,K){if(!_r(j))return;let te=$o(j,K);if(!te)return;return{path:j,config:te}}function wa(j,K,te,re){if(K){j.push(`GitHub Copilot CLI ${K} does not support ${te}; requires ${re}+`);return}j.push(`GitHub Copilot CLI version unavailable; skipping ${te} because it requires ${re}+`)}function R2(j){for(let K of j){if(K?.config.disableAllHooks===!0)return K.path;if(K?.config.disableAllHooks===!1)return}return}function P2(j,K,te,re){let oe=Vn(j),ce=Tt(K,".github","hooks"),de=Tt(oe,"hooks"),we=Tt(K,".github","copilot"),xe=Tt(K,".claude"),Ce=x2(te),Se=Ce===!0?re:void 0,Ne=[Sn(Tt(we,"settings.local.json"),Se),Sn(Tt(we,"settings.json"),Se),Sn(Tt(xe,"settings.local.json"),Se),Sn(Tt(xe,"settings.json"),Se)],He=[Sn(Tt(oe,"settings.json"),Se),Sn(Tt(oe,"config.json"),Se)];if(Ce!==!1){let kt=R2([...Ne,...He]);if(kt){if(Ce===null)re.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${kt} as active`);return{activeConfigPaths:[],disabledBy:kt}}}let at=S2(ce,re),mt=k2(te),it=mt===!0?re:void 0,gt=_r(de)?xa(de,it):[],ht=[];for(let kt of gt){let Lt=Tt(de,kt),Ct=$o(Lt,it);if(Ct&&Io(Ct))ht.push(Lt)}if(mt!==!0&&ht.length>0)wa(re,te,`user hook files in ${de}`,"0.0.422"),ht.length=0;let vt=[];for(let kt of[...Ne,...He]){if(!kt)continue;if(!Io(kt.config))continue;if(Ce===!0){vt.push(kt);continue}wa(re,te,"inline hook definitions in Copilot config files","1.0.8");break}let yt=(kt)=>kt.filter((Lt)=>!!Lt&&vt.includes(Lt)).map((Lt)=>Lt.path);return{activeConfigPaths:[...yt(Ne),...at,...yt(He),...ht]}}function Ca(j){let K=[],te=P2(j.environment,j.cwd,j.copilotCliVersion,K);if(te.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:te.disabledBy,configPaths:[te.disabledBy],errors:K.length>0?K:void 0};let re=Vn(j.environment),oe=Tt(re,"installed-plugins",...Er),ce=_r(oe),de=Tt(re,"settings.json"),we=qt(de,jt);if(ce&&we.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(ce&&we.kind==="ok"&&wt(wt(we.value,"enabledPlugins"),Vt)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:de,errors:[`${Vt} is installed but not enabled in Copilot CLI`]};if(ce||te.activeConfigPaths.length>0){let xe=ce,Ce=te.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:xe?"plugin config":"hook config",configPath:Ce??(xe?oe:void 0),configPaths:te.activeConfigPaths.length>0?te.activeConfigPaths:void 0,errors:K.length>0?K:void 0}}return{platform:"copilot-cli",status:"n/a",errors:K.length>0?K:void 0}}import{existsSync as F2,readFileSync as N2}from"node:fs";import{existsSync as Sa,mkdirSync as A2,readFileSync as _2}from"node:fs";import{dirname as T2,join as I2}from"node:path";import{renameSync as E2,writeFileSync as D2}from"node:fs";function Dt(j,K){let te=`${j}.${process.pid}.tmp`;D2(te,K),E2(te,j)}var zt=Object.fromEntries(Mn.map((j)=>[j.id,`npx -y cc-safety-net hook ${j.flags[1]}`]));var zn=zt.cursor,Ra=30;function Ir(j){return I2(j.home,".cursor","hooks.json")}function dn(j){return typeof j==="object"&&j!==null&&!Array.isArray(j)}function Oo(){return{command:zn,timeout:Ra,failClosed:!0}}function Tr(j){return dn(j)&&j.command===zn}function $2(j){return Object.keys(j).length===3&&j.command===zn&&j.timeout===Ra&&j.failClosed===!0}function O2(j){try{return JSON.parse(_2(j,"utf-8"))}catch(K){if(K instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${j}: ${K.message}`);throw K}}function Pa(j){let K=O2(j);if(!dn(K))throw Error(`Cursor hooks config ${j} must be a JSON object`);if(K.version!==1)throw Error(`Cursor hooks config ${j} must set "version": 1`);if(K.hooks!==void 0&&!dn(K.hooks))throw Error(`Cursor hooks config ${j} "hooks" must be an object`);let te=dn(K.hooks)?K.hooks.preToolUse:void 0;if(te!==void 0&&!Array.isArray(te))throw Error(`Cursor hooks config ${j} "hooks.preToolUse" must be an array`);return K}function Ea(j){let K=dn(j.hooks)?j.hooks.preToolUse:void 0;return Array.isArray(K)?K:[]}function j2(j){if(!j.some(Tr))return[...j,Oo()];return j.reduce((K,te)=>{if(!Tr(te))return K.result.push(te),K;if(!K.inserted)K.result.push(Oo()),K.inserted=!0;return K},{result:[],inserted:!1}).result}function Da(j,K,te){let re=dn(K.hooks)?K.hooks:{},oe={...K,hooks:{...re,preToolUse:te}};Dt(j,`${JSON.stringify(oe,null,2)}
34
+ `)}function Aa(j){let K=Ir(j);if(!Sa(K))return A2(T2(K),{recursive:!0}),Dt(K,`${JSON.stringify({version:1,hooks:{preToolUse:[Oo()]}},null,2)}
35
+ `),{path:K,alreadyInstalled:!1};let te=Pa(K),re=Ea(te),oe=re.filter(Tr);if(dn(te.hooks)&&Array.isArray(te.hooks.preToolUse)&&oe.length===1&&oe[0]!==void 0&&$2(oe[0]))return{path:K,alreadyInstalled:!0};return Da(K,te,j2(re)),{path:K,alreadyInstalled:!1}}function _a(j){let K=Ir(j);if(!Sa(K))return{path:K,alreadyInstalled:!1};let te=Pa(K),re=Ea(te),oe=re.filter((ce)=>!Tr(ce));if(oe.length===re.length)return{path:K,alreadyInstalled:!1};return Da(K,te,oe),{path:K,alreadyInstalled:!0}}function M2(j){if(!j||typeof j!=="object"||Array.isArray(j))return[];let K=j.hooks;if(!K||typeof K!=="object"||Array.isArray(K))return[];let te=K.preToolUse;if(!Array.isArray(te))return[];return te.filter((re)=>!!re&&typeof re==="object"&&!Array.isArray(re)&&re.command===zn)}function H2(j){let K=[];if(j.length>1)K.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let te=j[0];if(te&&te.failClosed!==!0)K.push('Managed hook is missing "failClosed": true; reinstall to repair');if(te&&te.timeout!==30)K.push('Managed hook "timeout" is not 30; reinstall to repair');return K}function Ta(j){let K=Ir(j.environment);if(!F2(K))return{platform:"cursor",status:"n/a",configPath:K};let te;try{te=JSON.parse(N2(K,"utf-8"))}catch(ce){return{platform:"cursor",status:"n/a",configPath:K,errors:[`Failed to parse Cursor hooks config ${K}: ${ce instanceof Error?ce.message:String(ce)}`]}}let re=M2(te);if(re.length===0)return{platform:"cursor",status:"n/a",configPath:K};let oe=H2(re);return{platform:"cursor",status:"configured",method:"hook config",configPath:K,errors:oe.length>0?oe:void 0}}import{existsSync as U2}from"node:fs";import{join as jo}from"node:path";var Fo="gemini-safety-net";function No(j){let K=jo(j.home,".gemini","extensions"),te=jo(K,Fo);if(!U2(te))return{platform:"gemini-cli",status:"n/a"};let re=jo(K,"extension-enablement.json"),oe=qt(re);if(oe.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let ce=oe.kind==="ok"?wt(wt(oe.value,Fo),"overrides"):void 0;if(Array.isArray(ce)&&ce.some((we)=>typeof we==="string"&&we.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:re,errors:[`${Fo} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:te}}function Ia(j){return No(j.environment)}import{existsSync as V2,readFileSync as z2}from"node:fs";import{existsSync as Oa,mkdirSync as G2,readFileSync as ja,rmSync as B2}from"node:fs";import{dirname as q2,join as $a}from"node:path";var Jn=zt["grok-build"],jr=30;function Fr(j){return $a(j.env.get("GROK_HOME")??$a(j.home,".grok"),"hooks","cc-safety-net.json")}function un(j){return typeof j==="object"&&j!==null&&!Array.isArray(j)}function $r(){return{hooks:[{type:"command",command:Jn,timeout:jr}]}}function Fa(j){return un(j)&&j.command===Jn}function Na(j){return j.flatMap((K)=>{if(!un(K)||!Array.isArray(K.hooks))return[K];let te=K.hooks.filter((re)=>!Fa(re));if(te.length===K.hooks.length)return[K];return te.length===0?[]:[{...K,hooks:te}]})}function Ma(j){try{let K=JSON.parse(j);return un(K)?K:null}catch{return null}}function Ha(j){let K=un(j.hooks)?j.hooks.PreToolUse:void 0;return Array.isArray(K)?K:[]}function Or(j,K,te){let re=un(K.hooks)?K.hooks:{};Dt(j,`${JSON.stringify({...K,hooks:{...re,PreToolUse:te}},null,2)}
36
+ `)}function Ua(j){let K=Fr(j);if(!Oa(K))return G2(q2(K),{recursive:!0}),Or(K,{},[$r()]),{path:K,alreadyInstalled:!1};let te=Ma(ja(K,"utf-8"));if(!te)return Or(K,{},[$r()]),{path:K,alreadyInstalled:!1};let re=Ha(te),oe=re.filter((ce)=>un(ce)&&Array.isArray(ce.hooks)&&ce.hooks.some(Fa));if(oe.length===1&&JSON.stringify(oe[0])===JSON.stringify($r()))return{path:K,alreadyInstalled:!0};return Or(K,te,[...Na(re),$r()]),{path:K,alreadyInstalled:!1}}function Ga(j){let K=Fr(j);if(!Oa(K))return{path:K,alreadyInstalled:!1};let te=Ma(ja(K,"utf-8"));if(!te)return{path:K,alreadyInstalled:!1};let re=Ha(te),oe=Na(re);if(JSON.stringify(oe)===JSON.stringify(re))return{path:K,alreadyInstalled:!1};let ce=un(te.hooks)?te.hooks:{};if(oe.length===0&&Object.keys(te).length===1&&Object.keys(ce).length===1)return B2(K),{path:K,alreadyInstalled:!0};return Or(K,te,oe),{path:K,alreadyInstalled:!0}}function Wn(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function J2(j){if(!Wn(j)||!Wn(j.hooks))return[];let K=j.hooks.PreToolUse;if(!Array.isArray(K))return[];return K.filter((te)=>Wn(te)&&Array.isArray(te.hooks)&&te.hooks.some((re)=>Wn(re)&&re.command===Jn))}function W2(j){let te=(Array.isArray(j.hooks)?j.hooks.filter(Wn):[]).find((re)=>re.command===Jn);return[...j.matcher===void 0||j.matcher===""||j.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...te?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...te?.timeout===jr?[]:[`Managed hook "timeout" is not ${jr}; reinstall to repair`]]}function Ba(j){let K=Fr(j.environment);if(!V2(K))return{platform:"grok-build",status:"n/a",configPath:K};let te;try{te=JSON.parse(z2(K,"utf-8"))}catch(ce){return{platform:"grok-build",status:"n/a",configPath:K,errors:[`Failed to parse Grok Build hooks config ${K}: ${ce instanceof Error?ce.message:String(ce)}`]}}let re=J2(te)[0];if(!re)return{platform:"grok-build",status:"n/a",configPath:K};let oe=W2(re);return{platform:"grok-build",status:"configured",method:"hook config",configPath:K,errors:oe.length>0?oe:void 0}}import{readFileSync as Za}from"node:fs";import{join as Xa}from"node:path";var Ft="cc-safety-net",Mo="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",K2=30;function qa(j){return`${Mo}
37
37
  # version: ${j}
38
- `}function Y2(j){return`${Ga(j)}name: ${Ft}
38
+ `}function Y2(j){return`${qa(j)}name: ${Ft}
39
39
  version: "${j}"
40
40
  description: "Block destructive commands and secret-file access before Hermes runs a tool."
41
41
  author: "cc-safety-net"
42
42
  provides_hooks:
43
43
  - pre_tool_call
44
- `}function Z2(j){return`${Ga(j)}"""CC Safety Net guard for Hermes Agent.
44
+ `}function Z2(j){return`${qa(j)}"""CC Safety Net guard for Hermes Agent.
45
45
 
46
46
  Registers pre_tool_call and forwards the tool call to the packaged CC Safety Net
47
47
  adapter (cc-safety-net hook --hermes-agent) over JSON stdin. The adapter prints nothing
@@ -203,66 +203,66 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
203
203
 
204
204
  def register(ctx):
205
205
  ctx.register_hook("pre_tool_call", _pre_tool_call)
206
- `}function Kn(j){return[{name:"__init__.py",content:Z2(j)},{name:"plugin.yaml",content:Y2(j)}]}import{mkdirSync as X2,readdirSync as Q2,readFileSync as ef,rmSync as Ho}from"node:fs";import{join as pn}from"node:path";var tf="__pycache__";function Uo(j){let K=j.env.get("HERMES_HOME")?.trim();return K?K:pn(j.home,".hermes")}function Go(j){return pn(Uo(j),"plugins",Ft)}function Bo(j){return j.startsWith(Mo)}function qo(j,K){let te=Go(j),re=Pt(te);if(re&&(re.isSymbolicLink()||!re.isDirectory()))throw Error(`Refusing to ${K} ${te}: not a regular directory. Move or remove it and rerun ${K==="install"?"install":"uninstall"} --hermes-agent.`);return te}function Ba(j,K){let te=Pt(j);if(!te)return;if(te.isSymbolicLink()||!te.isFile())throw Error(`Refusing to ${K} ${j}: not a regular file. Move or remove it.`);let re=ef(j,"utf-8");if(!Bo(re))throw Error(`Refusing to ${K} unmanaged file at ${j}. Move or remove it.`);return re}function qa(j){let K=qo(j,"install"),te=Kn(Et());if(te.map((oe)=>Ba(pn(K,oe.name),"overwrite")).every((oe,ce)=>oe===te[ce]?.content))return{path:K,alreadyInstalled:!0};return X2(K,{recursive:!0}),te.forEach((oe)=>{Dt(pn(K,oe.name),oe.content)}),{path:K,alreadyInstalled:!1}}function Vo(j){let K=qo(j,"remove");if(!Pt(K))return[];return Kn(Et()).filter((te)=>Ba(pn(K,te.name),"remove")!==void 0)}function Va(j){let K=qo(j,"remove");if(!Pt(K))return{path:K,alreadyInstalled:!1};let te=Vo(j);if(te.forEach((re)=>{Ho(pn(K,re.name))}),Ho(pn(K,tf),{recursive:!0,force:!0}),Q2(K).length===0)Ho(K,{recursive:!0});return{path:K,alreadyInstalled:te.length>0}}var Nr="hermes-agent",za=/^([^\s#][^:]*):/,nf=/^\s+([A-Za-z_][\w-]*):/,Ja=/^\s+-\s*(.*)$/;function rf(j){return j.trim().replace(/^(["'])(.*)\1$/,"$2")}function of(j){let K=j.split(/\r?\n/),te=K.findIndex((ce)=>za.exec(ce)?.[1]?.trim()==="plugins");if(te===-1)return[];let re=K.slice(te+1),oe=re.findIndex((ce)=>za.test(ce));return oe===-1?re:re.slice(0,oe)}function Wa(j,K){let te=of(j),re=te.findIndex((de)=>nf.exec(de)?.[1]===K);if(re===-1)return[];let oe=te.slice(re+1),ce=oe.findIndex((de)=>!Ja.test(de));return(ce===-1?oe:oe.slice(0,ce)).map((de)=>rf(Ja.exec(de)?.[1]??""))}function sf(j){try{return Ka(Ya(Uo(j),"config.yaml"),"utf-8")}catch{return}}function zo(j){let K=sf(j)??"";return Wa(K,"enabled").includes(Ft)&&!Wa(K,"disabled").includes(Ft)}function Za(j){return/^# version:\s*(.+)$/m.exec(j)?.[1]?.trim()}function af(j,K){let te=Pt(j);if(!te)return{error:`${K.name} is missing from ${j}; run install --hermes-agent`};if(te.isSymbolicLink()||!te.isFile())return{error:`${j} is a symlink or not a regular file; move or remove it`};try{let re=Ka(j,"utf-8");if(!Bo(re))return{error:`Unmanaged ${K.name} occupies ${j}; move or remove it`};if(Za(re)===Et()&&re!==K.content)return{error:`Modified ${K.name} occupies ${j}; run install --hermes-agent to restore it`};return{content:re}}catch(re){return{error:`Failed to read ${j}: ${re instanceof Error?re.message:String(re)}`}}}function Xa(j){let K=Go(j.environment),te=Cr(Nr,K);if(te)return te;let re=Kn(Et()).map((we)=>af(Ya(K,we.name),we)),oe=re.flatMap((we)=>("error"in we)?[we.error]:[]);if(oe.length>0)return{platform:Nr,status:"n/a",configPath:K,errors:oe};let ce=re.some((we)=>("content"in we)&&Za(we.content)!==Et()),de=ce?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!zo(j.environment))return{platform:Nr,status:"disabled",method:"plugin directory",configPath:K,errors:[`${Ft} is not enabled in Hermes; run \`hermes plugins enable ${Ft}\``,...de]};return{platform:Nr,status:"configured",method:"plugin directory",configPath:K,errors:ce?de:void 0}}import{existsSync as lf,readFileSync as cf}from"node:fs";import{join as Qa}from"node:path";var df=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function uf(j){return Qa(j.env.get("KIMI_CODE_HOME")||Qa(j.home,".kimi-code"),"config.toml")}function Yn(j){let K=uf(j.environment);if(!lf(K))return{platform:"kimi-code",status:"n/a",configPath:K};try{if(!df.test(cf(K,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:K}}catch(te){return{platform:"kimi-code",status:"n/a",configPath:K,errors:[`Failed to read ${K}: ${te instanceof Error?te.message:String(te)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:K}}import{readFileSync as cl}from"node:fs";import{join as Xn}from"node:path";var Rt="cc-safety-net",Mt="index.js",Rn="openclaw.plugin.json",Pn="package.json";var Mr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as mf,lstatSync as gf,readdirSync as yf,readFileSync as hf}from"node:fs";import{dirname as nl,join as nn}from"node:path";import{fileURLToPath as vf}from"node:url";import{spawn as pf}from"node:child_process";function ff(j){return j.join(" ")}function Jo(j,K,te){return[`Failed to run ${ff(j)}${K===null?"":` (exit ${K})`}.`,te.trim()].filter(Boolean).join(`
206
+ `}function Kn(j){return[{name:"__init__.py",content:Z2(j)},{name:"plugin.yaml",content:Y2(j)}]}import{mkdirSync as X2,readdirSync as Q2,readFileSync as ef,rmSync as Ho}from"node:fs";import{join as pn}from"node:path";var tf="__pycache__";function Uo(j){let K=j.env.get("HERMES_HOME")?.trim();return K?K:pn(j.home,".hermes")}function Go(j){return pn(Uo(j),"plugins",Ft)}function Bo(j){return j.startsWith(Mo)}function qo(j,K){let te=Go(j),re=Pt(te);if(re&&(re.isSymbolicLink()||!re.isDirectory()))throw Error(`Refusing to ${K} ${te}: not a regular directory. Move or remove it and rerun ${K==="install"?"install":"uninstall"} --hermes-agent.`);return te}function Va(j,K){let te=Pt(j);if(!te)return;if(te.isSymbolicLink()||!te.isFile())throw Error(`Refusing to ${K} ${j}: not a regular file. Move or remove it.`);let re=ef(j,"utf-8");if(!Bo(re))throw Error(`Refusing to ${K} unmanaged file at ${j}. Move or remove it.`);return re}function za(j){let K=qo(j,"install"),te=Kn(Et());if(te.map((oe)=>Va(pn(K,oe.name),"overwrite")).every((oe,ce)=>oe===te[ce]?.content))return{path:K,alreadyInstalled:!0};return X2(K,{recursive:!0}),te.forEach((oe)=>{Dt(pn(K,oe.name),oe.content)}),{path:K,alreadyInstalled:!1}}function Vo(j){let K=qo(j,"remove");if(!Pt(K))return[];return Kn(Et()).filter((te)=>Va(pn(K,te.name),"remove")!==void 0)}function Ja(j){let K=qo(j,"remove");if(!Pt(K))return{path:K,alreadyInstalled:!1};let te=Vo(j);if(te.forEach((re)=>{Ho(pn(K,re.name))}),Ho(pn(K,tf),{recursive:!0,force:!0}),Q2(K).length===0)Ho(K,{recursive:!0});return{path:K,alreadyInstalled:te.length>0}}var Nr="hermes-agent",Wa=/^([^\s#][^:]*):/,nf=/^\s+([A-Za-z_][\w-]*):/,Ka=/^\s+-\s*(.*)$/;function rf(j){return j.trim().replace(/^(["'])(.*)\1$/,"$2")}function of(j){let K=j.split(/\r?\n/),te=K.findIndex((ce)=>Wa.exec(ce)?.[1]?.trim()==="plugins");if(te===-1)return[];let re=K.slice(te+1),oe=re.findIndex((ce)=>Wa.test(ce));return oe===-1?re:re.slice(0,oe)}function Ya(j,K){let te=of(j),re=te.findIndex((de)=>nf.exec(de)?.[1]===K);if(re===-1)return[];let oe=te.slice(re+1),ce=oe.findIndex((de)=>!Ka.test(de));return(ce===-1?oe:oe.slice(0,ce)).map((de)=>rf(Ka.exec(de)?.[1]??""))}function sf(j){try{return Za(Xa(Uo(j),"config.yaml"),"utf-8")}catch{return}}function zo(j){let K=sf(j)??"";return Ya(K,"enabled").includes(Ft)&&!Ya(K,"disabled").includes(Ft)}function Qa(j){return/^# version:\s*(.+)$/m.exec(j)?.[1]?.trim()}function af(j,K){let te=Pt(j);if(!te)return{error:`${K.name} is missing from ${j}; run install --hermes-agent`};if(te.isSymbolicLink()||!te.isFile())return{error:`${j} is a symlink or not a regular file; move or remove it`};try{let re=Za(j,"utf-8");if(!Bo(re))return{error:`Unmanaged ${K.name} occupies ${j}; move or remove it`};if(Qa(re)===Et()&&re!==K.content)return{error:`Modified ${K.name} occupies ${j}; run install --hermes-agent to restore it`};return{content:re}}catch(re){return{error:`Failed to read ${j}: ${re instanceof Error?re.message:String(re)}`}}}function el(j){let K=Go(j.environment),te=Cr(Nr,K);if(te)return te;let re=Kn(Et()).map((we)=>af(Xa(K,we.name),we)),oe=re.flatMap((we)=>("error"in we)?[we.error]:[]);if(oe.length>0)return{platform:Nr,status:"n/a",configPath:K,errors:oe};let ce=re.some((we)=>("content"in we)&&Qa(we.content)!==Et()),de=ce?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!zo(j.environment))return{platform:Nr,status:"disabled",method:"plugin directory",configPath:K,errors:[`${Ft} is not enabled in Hermes; run \`hermes plugins enable ${Ft}\``,...de]};return{platform:Nr,status:"configured",method:"plugin directory",configPath:K,errors:ce?de:void 0}}import{existsSync as lf,readFileSync as cf}from"node:fs";import{join as tl}from"node:path";var df=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function uf(j){return tl(j.env.get("KIMI_CODE_HOME")||tl(j.home,".kimi-code"),"config.toml")}function Yn(j){let K=uf(j.environment);if(!lf(K))return{platform:"kimi-code",status:"n/a",configPath:K};try{if(!df.test(cf(K,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:K}}catch(te){return{platform:"kimi-code",status:"n/a",configPath:K,errors:[`Failed to read ${K}: ${te instanceof Error?te.message:String(te)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:K}}import{readFileSync as dl}from"node:fs";import{join as Xn}from"node:path";var Rt="cc-safety-net",Mt="index.js",Rn="openclaw.plugin.json",Pn="package.json";var Mr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as mf,lstatSync as gf,readdirSync as yf,readFileSync as hf}from"node:fs";import{dirname as rl,join as Yt}from"node:path";import{fileURLToPath as vf}from"node:url";import{spawn as pf}from"node:child_process";function ff(j){return j.join(" ")}function Jo(j,K,te){return[`Failed to run ${ff(j)}${K===null?"":` (exit ${K})`}.`,te.trim()].filter(Boolean).join(`
207
207
  `)}function Wo(j){let K={stdout:"",stderr:""};return j.stdout.setEncoding("utf-8"),j.stderr.setEncoding("utf-8"),j.stdout.on("data",(te)=>{K.stdout+=te}),j.stderr.on("data",(te)=>{K.stderr+=te}),K}function Jt(j,K){return new Promise((te,re)=>{let oe=cn([...j],process.env),ce=pf(oe.cmd,oe.args,{stdio:["ignore","pipe","pipe"]}),de=Wo(ce),we=()=>[de.stdout,de.stderr].filter(Boolean).join(`
208
208
  `),xe=K?.timeoutMs??120000,Ce=setTimeout(()=>{ce.kill(),re(Error(Jo(j,null,`Timed out after ${xe}ms.
209
209
  ${we()}`.trim())))},xe);ce.on("error",(Se)=>{clearTimeout(Ce),re(Error(Jo(j,null,`${Se.message}
210
- ${we()}`.trim())))}),ce.on("close",(Se)=>{if(clearTimeout(Ce),Se!==0){re(Error(Jo(j,Se,we())));return}te(K?.stdoutOnly?de.stdout:we())})})}async function Ko(j){for(let K of j)await Jt(K)}async function el(j){for(let K of j)try{await Jt(K)}catch(te){console.warn(te instanceof Error?te.message:String(te))}}var tl=nn("openclaw",Rt),bf=[Mt,Rn,Pn];function Yo(j,K){if(j==="~")return K;if(j.startsWith("~/")||j.startsWith("~\\"))return nn(K,j.slice(2));return j}function rl(j){let K=j.env.get("OPENCLAW_STATE_DIR")?.trim();if(K)return Yo(K,j.home);let te=j.env.get("OPENCLAW_CONFIG_PATH")?.trim();return te?nl(Yo(te,j.home)):nn(j.home,".openclaw")}function ol(j){let K=j.env.get("OPENCLAW_CONFIG_PATH")?.trim();return K?Yo(K,j.home):nn(rl(j),"openclaw.json")}function Zo(j){return nn(rl(j),"extensions",Rt)}function Lf(j){let K=yf(j);if(K.length===0)return!0;if(K.some((oe)=>!bf.includes(oe)))return!1;let te=nn(j,Mt),re=Pt(te);return re!==void 0&&!re.isSymbolicLink()&&re.isFile()&&hf(te,"utf-8").startsWith(Mr)}function Xo(j){let K=Zo(j),te=Pt(K);if(!te)return;if(!te.isSymbolicLink()&&te.isDirectory()&&Lf(K))return;throw Error(`Refusing to modify ${K}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function il(){let j=nl(vf(import.meta.url));return[nn(j,"..",tl),nn(j,"..","..","..","dist",tl)]}function Qo(j=il()){return j.find((K)=>mf(K)&&gf(K).isDirectory())}function wf(j=il()){let K=Qo(j);if(!K)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return K}function sl(j=wf()){return[["openclaw","plugins","install",j,"--force"],["openclaw","plugins","enable",Rt]]}function kf(j){let K=(()=>{try{return JSON.parse(j)}catch{return}})(),te=wt(wt(K,"plugin"),"status");return typeof te==="string"?te:void 0}async function al(){let j=kf(await Jt(["openclaw","plugins","inspect",Rt,"--runtime","--json"],{stdoutOnly:!0}));if(j==="loaded")return;throw Error(`${j===void 0?`The ${Rt} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${Rt} plugin with status "${j}".`} Run \`openclaw plugins inspect ${Rt} --runtime\` for details.`)}var Hr="openclaw",Zn=`run \`openclaw plugins enable ${Rt}\``;function En(j,K){let te=Xn(j,K),re=Pt(te);if(!re)return{error:`${K} is missing from ${te}; run install --openclaw`};if(re.isSymbolicLink()||!re.isFile())return{error:`${te} is a symlink or not a regular file; move or remove it`};try{return{content:cl(te,"utf-8")}}catch(oe){return{error:`Failed to read ${te}: ${oe instanceof Error?oe.message:String(oe)}`}}}function dl(j){try{return JSON.parse(jt(j))}catch{return}}function xf(j){let K=En(j,Rn);if("error"in K)return K.error;if(wt(dl(K.content),"id")===Rt)return;return`${Xn(j,Rn)} is not a valid ${Rt} manifest; run install --openclaw`}function Cf(j){let K=En(j,Pn);if("error"in K)return K.error;let te=wt(wt(dl(K.content),"openclaw"),"extensions");if(Array.isArray(te)&&te.includes(`./${Mt}`))return;return`${Xn(j,Pn)} does not point OpenClaw at ${Mt}; run install --openclaw`}function ll(j){return Array.isArray(j)?j.filter((K)=>typeof K==="string"):[]}function Sf(j){let K=ol(j);if(!Pt(K))return`${Rt} is not enabled; ${Zn}`;let te=(()=>{try{return JSON.parse(jt(cl(K,"utf-8")))}catch{return}})();if(te===void 0)return`Failed to read ${K}; fix it, then ${Zn}`;let re=wt(te,"plugins");if(wt(re,"enabled")===!1)return`plugins.enabled is false in ${K}; no OpenClaw plugin loads`;let oe=wt(wt(wt(re,"entries"),Rt),"enabled");if(ll(wt(re,"deny")).includes(Rt)||oe===!1)return`${Rt} is disabled in ${K}; ${Zn}`;let ce=ll(wt(re,"allow"));if(ce.length>0&&!ce.includes(Rt))return`plugins.allow in ${K} does not list ${Rt}; add it, then ${Zn}`;if(ce.includes(Rt)||oe===!0)return;return`${Rt} is not enabled; ${Zn}`}function ul(j){return/^\/\/ version:\s*(.+)$/m.exec(j)?.[1]?.trim()}function Rf(j,K,te){if(te===void 0)return[];let re=En(te,Mt);if("error"in re||ul(re.content)!==K)return[];return[Mt,Rn,Pn].flatMap((oe)=>{let ce=En(j,oe),de=En(te,oe);if("error"in ce||"error"in de||ce.content===de.content)return[];return[`Modified ${oe} occupies ${Xn(j,oe)}; run install --openclaw to restore it`]})}function pl(j){let K=Zo(j.environment),te=Cr(Hr,K);if(te)return te;let re=En(K,Mt),ce=["error"in re?re.error:re.content.startsWith(Mr)?void 0:`Unmanaged ${Mt} occupies ${Xn(K,Mt)}; move or remove it`,xf(K),Cf(K)].filter((Se)=>Se!==void 0),de="content"in re?ul(re.content):void 0,we=ce.length>0?ce:Rf(K,de,Qo());if(we.length>0)return{platform:Hr,status:"n/a",configPath:K,errors:we};let xe=de===Et()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],Ce=Sf(j.environment);if(Ce)return{platform:Hr,status:"disabled",method:"plugin directory",configPath:K,errors:[Ce,...xe]};return{platform:Hr,status:"configured",method:"plugin directory",configPath:K,errors:xe.length>0?xe:void 0}}import{existsSync as If,readFileSync as $f}from"node:fs";import{join as Of}from"node:path";import{existsSync as ei,readFileSync as gl,rmSync as Pf}from"node:fs";import{join as Yt}from"node:path";import{pathToFileURL as Ef}from"node:url";var Ur="cc-safety-net",yl=`${Ur}@latest`,hl=["opencode.json","opencode.jsonc"],fl="CCSafetyNetPlugin",ml={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function Gr(j){return Yt(j.env.get("XDG_CONFIG_HOME")||Yt(j.home,".config"),"opencode")}function Df(j){return Yt(Gr(j),hl[0])}function Af(j){return hl.map((K)=>Yt(Gr(j),K))}function vl(j){return Yt(j.env.get("XDG_CACHE_HOME")||Yt(j.home,".cache"),"opencode","packages",yl)}function ti(j){Pf(vl(j),{recursive:!0,force:!0})}async function bl(j){let K=Yt(vl(j),"node_modules",Ur),te=Yt(K,"package.json");if(!ei(te))throw Error(`The OpenCode plugin cache at ${K} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${yl}\` for details.`);let re=wt(JSON.parse(gl(te,"utf-8")),"main");if(typeof re!=="string")throw Error(`The cached OpenCode plugin at ${K} declares no "main" entry.`);let oe=Yt(K,re);if(typeof(await import(Ef(oe).href))[fl]==="function")return;throw Error(`The cached OpenCode plugin at ${oe} does not export a callable ${fl}, so OpenCode would load nothing and fail open.`)}function Ll(j,K){try{return JSON.parse(jt(j))}catch(te){if(te instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${K}: ${te.message}`);throw te}}function _f(j){if(!j||typeof j!=="object"||Array.isArray(j))return!1;let K=j.plugin;if(!Array.isArray(K))return!1;return K.some((te)=>typeof te==="string"&&te.includes(Ur))}function Tf(j,K){let te=da(j,"plugin",ml);if(!te)throw Error(`Failed to locate OpenCode plugin array in ${K}`);let re=ua(j,te,ml.stringError).filter((oe)=>oe.value.includes(Ur)).map((oe)=>oe.range).reverse().reduce(Pr,j);return Ll(re,K),re}function wl(j){ti(j);let K=Af(j),te=K.find((oe)=>ei(oe)),re=[];for(let oe of K){if(!ei(oe))continue;try{let ce=gl(oe,"utf-8");if(!_f(Ll(ce,oe)))continue;return Dt(oe,Tf(ce,oe)),{path:oe,alreadyInstalled:!0}}catch(ce){re.push(ce instanceof Error?ce.message:String(ce))}}if(re.length>0)throw Error(re.join(`
211
- `));return{path:te??Df(j),alreadyInstalled:!1}}function kl(j){let K=[],te=Gr(j.environment),re=["opencode.json","opencode.jsonc"];for(let oe of re){let ce=Of(te,oe);if(If(ce))try{let de=$f(ce,"utf-8"),we=jt(de);if((JSON.parse(we).plugin??[]).some((Ne)=>Ne.includes("cc-safety-net")))return{platform:"opencode",status:"configured",method:"plugin array",configPath:ce,errors:K.length>0?K:void 0}}catch(de){K.push(`Failed to parse ${oe}: ${de instanceof Error?de.message:String(de)}`)}}return{platform:"opencode",status:"n/a",errors:K.length>0?K:void 0}}import{join as jf}from"node:path";function ni(j){return jf(j.home,".pi","agent","settings.json")}function ri(j){if(typeof j!=="string")return!1;return j==="npm:cc-safety-net"||j.startsWith("npm:cc-safety-net@")}function xl(j){let K=ni(j.environment),te=qt(K);if(te.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(te.kind==="missing")return{platform:"pi",status:"n/a"};let re=wt(te.value,"packages");if(!Array.isArray(re))return{platform:"pi",status:"n/a"};let oe=re.find((we)=>ri(typeof we==="string"?we:wt(we,"source")));if(oe===void 0)return{platform:"pi",status:"n/a"};let ce=wt(oe,"extensions");if(Array.isArray(ce)&&ce.some((we)=>typeof we==="string"&&we.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:K,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:K}}var Ff={amp:ta,"antigravity-cli":na,"claude-code":sa,codex:aa,"copilot-cli":ka,cursor:Aa,"gemini-cli":_a,"grok-build":Ua,"hermes-agent":Xa,"kimi-code":Yn,openclaw:pl,opencode:kl,pi:xl};function Dn(j,K,te){let re={...te,cwd:K,environment:j};return ur.map((oe)=>Nf(Ff[oe](re)))}function Nf(j){if(j.status==="not-inspected")return{platform:j.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:j.platform,detected:j.status!=="n/a",configured:j.status==="configured",inspectionStatus:j.status!=="n/a"?"verified":j.errors&&j.errors.length>0?"failed":"not-applicable",method:j.method,configPath:j.configPath,configPaths:j.configPaths,errors:j.errors}}import{join as Mf}from"node:path";var Hf=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}]),Uf=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([])})})}),Gf={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 Cl(j){let K=Mf(j.tmpdir,"cc-safety-net-self-test"),te=Hf.map((re)=>{let oe=F(j,u("self-test",{command:re.command},{kind:"command",shell:"auto"},{configCwd:K,executionCwd:K},re.command),{guard:{dependencies:{loadPolicySnapshot:()=>Uf,getModes:()=>Gf,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),ce=re.expectBlocked?"blocked":"allowed",de=oe.decision.kind==="deny"?"blocked":"allowed";return{command:re.command,description:re.description,expected:ce,actual:de,passed:ce===de,reason:oe.decision.kind==="deny"?oe.decision.reason:void 0,ruleId:oe.decision.kind==="deny"?oe.decision.ruleId:void 0}});return{passed:te.filter((re)=>re.passed).length,failed:te.filter((re)=>!re.passed).length,total:te.length,results:te}}function oi(j){let K=At({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},j);if(Kt(K.errors))return null;return{json:K.flags.json,skipUpdateCheck:K.flags.skipUpdateCheck}}async function Sl(j,K={}){let te=await Bn(!K.json,()=>{let re=Bf(j,K);return{ready:re,finish:()=>re}},()=>Gn(),{loadingMessage:"Checking system status…"});if(K.json)console.log(JSON.stringify(te,null,2));else qf(te);return te.engineSelfTest.failed>0||te.findings.some((re)=>re.severity==="error")?1:0}async function Bf(j,K){let te=K.cwd??process.cwd(),re=await Hn(),oe=Dn(j,te,{ampPluginListOutput:re.ampPluginListOutput,codexPluginListOutput:re.codexPluginListOutput,copilotCliVersion:re.versions["copilot-cli"]}),ce=hs(j,te),de=vs(j),we=k(j,{cwd:te}),xe=we.policy,Ce=P(xe,j.env),Se=B(xe,Ce.capabilities),Ne=gr(j,7),He=Ys(j,te),at=K.skipUpdateCheck?{currentVersion:Et(),latestVersion:null,updateAvailable:!1}:await tn(),mt={hooks:oe,engineSelfTest:Cl(j),userConfig:ce.userConfig,projectConfig:ce.projectConfig,configState:Be(we),effectiveRules:ce.effectiveRules,shadowedRules:ce.shadowedRules,environment:de,effectiveSafety:{selectedPreset:xe.safety.level??"standard",level:Ce.effectiveLevel,capabilities:Ce.capabilities,ruleOverrides:xe.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(Se).filter(([,it])=>it.source==="rule_override"&&it.override==="off"&&it.inheritedEnabled&&it.changesInherited).map(([it])=>it),ruleCounts:{stored:Object.keys(xe.destructiveCommandRuleOverrides).length,effective:Object.values(Se).filter((it)=>it.changesInherited).length},...we.policyScopes?{policyScopes:we.policyScopes}:{}},...He.length>0?{v2Leftovers:He}:{},posture:Ts(j,ce.userConfig.path),activity:Ne,update:at,system:re};return{...mt,findings:Ls(mt)}}function qf(j){console.log(),console.log(ks(j.hooks)),console.log(),console.log(xs(j.engineSelfTest)),console.log(),console.log(Cs(j)),console.log(),console.log(Ss(j.environment)),console.log(),console.log(Rs(j)),console.log(),console.log(Ps(j.findings)),console.log(),console.log(Es(j.activity)),console.log(),console.log(As(j.system)),console.log(),console.log(Ds(j.update)),console.log(_s(j))}import{existsSync as Vf}from"node:fs";var zf=/^[A-Za-z0-9_@%+=:,./-]+$/,Rl="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function ii(j){let K=At({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},j);if(Kt(K.errors))return console.error(Rl),console.error("Pass -- before a command that starts with dashes."),null;if(K.values.cwd!==void 0&&!Vf(K.values.cwd))return console.error(`Error: --cwd path does not exist: ${K.values.cwd}`),null;let te=K.positionals.length===1?K.positionals[0]:K.positionals.map((re)=>zf.test(re)?re:`'${re.replaceAll("'","'\\''")}'`).join(" ");if(!te)return console.error("Error: No command provided"),console.error(Rl),null;return{json:K.flags.json,cwd:K.values.cwd,command:te}}function Pl(j){if(j)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 El(j,K){let re=K-18;return[`${j.dtl}${j.dh.repeat(K)}${j.dtr}`,`${j.dv} Command Analysis${" ".repeat(re)}${j.dv}`,`${j.dbl}${j.dh.repeat(K)}${j.dbr}`]}function si(j){return JSON.stringify(j)}function Dl(j,K=0){return`[${j.map((re,oe)=>ws(re,oe,K)).join(",")}]`}function Qn(j,K,te=70){let re=j.split(" "),oe=[],ce="";for(let de of re)if(ce&&ce.length+de.length+1>te)oe.push(ce),ce=de;else ce=ce?`${ce} ${de}`:de;if(ce)oe.push(ce);return oe.map((de,we)=>we===0?de:`${K}${de}`)}function Al(j,K,te){let re=[];switch(j.type){case"parse":return null;case"env-strip":return re.push(""),re.push(`STEP ${K} ${te.h} Strip environment variables`),re.push(` Removed: ${j.envVars.map((oe)=>`${oe}=<redacted>`).join(", ")}`),re.push(` Tokens: ${si(j.output)}`),{lines:re,incrementStep:!0};case"leading-tokens-stripped":return re.push(""),re.push(`STEP ${K} ${te.h} Strip wrappers`),re.push(` Removed: ${j.removed.join(", ")}`),re.push(` Tokens: ${si(j.output)}`),{lines:re,incrementStep:!0};case"shell-wrapper":return re.push(""),re.push(`STEP ${K} ${te.h} Detect shell wrapper`),re.push(` Wrapper: ${j.wrapper} -c`),re.push(` Inner: ${j.innerCommand}`),{lines:re,incrementStep:!0};case"interpreter":{if(re.push(""),re.push(`STEP ${K} ${te.h} Detect interpreter`),re.push(` Interpreter: ${j.interpreter}`),re.push(` Code: ${j.codeArg}`),j.paranoidBlocked)re.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:re,incrementStep:!0}}case"busybox":return re.push(""),re.push(`STEP ${K} ${te.h} Busybox wrapper`),re.push(` Subcommand: ${j.subcommand}`),{lines:re,incrementStep:!0};case"transparent-wrapper":return re.push(""),re.push(`STEP ${K} ${te.h} Transparent wrapper`),re.push(` Wrapper: ${j.wrapper}`),re.push(` Tokens: ${si(j.output)}`),{lines:re,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(re.push(""),re.push(`STEP ${K} ${te.h} Match rules`),re.push(` Rule: ${j.rule}()`),j.matched)re.push(" Result: MATCHED");else re.push(" Result: No match");return{lines:re,incrementStep:!0}}case"worktree-relaxation":return re.push(""),re.push(`STEP ${K} ${te.h} Worktree relaxation`),re.push(` Mode: ${i.worktree.name}`),re.push(` Git cwd: ${j.gitCwd}`),re.push(" Result: Allowed local discard in linked worktree"),{lines:re,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(j.embeddedCommandFound)return re.push(""),re.push(`STEP ${K} ${te.h} Fallback scan`),re.push(` Found: ${j.embeddedCommandFound}`),{lines:re,incrementStep:!0};return null}case"custom-rules-check":{if(j.rulesChecked){if(re.push(""),re.push(`STEP ${K} ${te.h} Custom rules`),j.matched)re.push(" Result: MATCHED");else re.push(" Result: No match");return{lines:re,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(j.matched)return re.push(""),re.push(`STEP ${K} ${te.h} Dangerous text check`),re.push(` Token: ${j.token}`),re.push(" Result: MATCHED"),{lines:re,incrementStep:!0};return null}case"strict-unparseable":return re.push(""),re.push(`STEP ${K} ${te.h} Strict mode check`),re.push(` Command: ${j.rawCommand}`),re.push(" Result: ✗ UNPARSEABLE"),{lines:re,incrementStep:!0};case"segment-skipped":return null;case"error":return re.push(""),re.push(`ERROR: ${j.message}`),{lines:re,incrementStep:!1};default:return j}}function ai(j,K){let te=Pl(K?.asciiOnly??!1),re=58,oe=[],ce=1;oe.push(...El(te,58)),oe.push("");let de=j.trace.steps.find((mt)=>mt.type==="error");if(de&&de.type==="error"){oe.push("ERROR"),oe.push(` ${de.message}`),oe.push(""),oe.push("RESULT"),oe.push(` Status: ${j.result==="blocked"?bt.red("BLOCKED"):bt.green("ALLOWED")}`),oe.push(""),oe.push("CONFIG");let mt=j.configSource??"none";return oe.push(` Path: ${mt}`),oe.join(`
212
- `)}let we=j.trace.steps.find((mt)=>mt.type==="parse");if(we&&we.type==="parse"){oe.push("INPUT"),oe.push(` ${we.input}`),oe.push(""),oe.push(`STEP ${ce} ${te.h} Split shell commands`),ce++;for(let mt=0;mt<we.segments.length;mt++){let it=we.segments[mt];if(it){let gt=Math.random();oe.push(` Segment ${mt+1}: ${Dl(it,gt)}`)}}}let xe=j.trace.segments,Ce=xe.length>1;for(let mt of xe){if(Ce){oe.push("");let vt="";if(we&&we.type==="parse"){let mo=we.segments[mt.index];if(mo)vt=mo.join(" ")}let yt=54,kt=vt,Lt=` Segment ${mt.index+1}: `,Ct=" ";if(vt){if(Lt.length+vt.length+Ct.length>yt){let iu=yt-Lt.length-Ct.length;kt=`${vt.substring(0,iu-1)}…`}}let sn=vt?`${Lt}${kt}${Ct}`:` Segment ${mt.index+1} `,Gt=vt?`${Lt}${bt.cyan(kt)}${Ct}`:sn,zi=58-sn.length,Ji=Math.floor(zi/2),ou=zi-Ji;oe.push(`${te.sh.repeat(Ji)}${Gt}${te.sh.repeat(ou)}`)}if(mt.steps.find((vt)=>vt.type==="segment-skipped")){oe.push(""),oe.push(" (skipped — prior segment blocked)");continue}let gt=!1,ht=!1;for(let vt of mt.steps){let yt=Al(vt,ce,te);if(yt){if(ht=!0,vt.type==="recurse"){oe.push("");let kt=" RECURSING ",Lt=58-kt.length-4;oe.push(` ${te.tl}${te.h}${kt}${te.h.repeat(Lt)}`),oe.push(` ${te.v}`),gt=!0;continue}for(let kt of yt.lines)if(gt)oe.push(` ${te.v} ${kt}`);else oe.push(kt);if(yt.incrementStep)ce++}}if(gt)oe.push(` ${te.v}`),oe.push(` ${te.bl}${te.h.repeat(56)}`),gt=!1;if(!ht)oe.push(""),oe.push(` ${bt.green("✓")} Allowed (no matching rules)`)}if(oe.push(""),oe.push("RESULT"),j.result==="blocked"){if(oe.push(` Status: ${bt.red("BLOCKED")}`),j.customRule){if(oe.push(` Rule: ${j.customRule.id}`),j.customRule.rulebook)oe.push(` Rulebook: ${j.customRule.rulebook.name} ${j.customRule.rulebook.version}`);if(j.customRule.source)oe.push(` Source: ${j.customRule.source}`);if(j.customRule.override)oe.push(` Override: reason ${j.customRule.override.reason}`)}if(j.reason){let mt=Qn(j.reason," ");oe.push(` Reason: ${mt[0]}`);for(let it=1;it<mt.length;it++)oe.push(mt[it]??"")}}else oe.push(` Status: ${bt.green("ALLOWED")}`);oe.push(""),oe.push("CONFIG");let Se=j.configSource??"none",Ne=j.configValid?"":" (invalid)";oe.push(` Path: ${Se}${Ne}`);let He=j.safetyPresetScope;oe.push(` Safety preset: ${j.selectedPreset??"standard"}${He?` (${hr(He)})`:""}`),oe.push(` Effective capabilities: ${j.effectiveLevel}`);let at=Object.entries(j.destructiveCommandRuleOverrides??{});if(oe.push(` Rule customizations: ${at.length}`),j.ruleActivation)oe.push(` Rule activation: ${j.ruleActivation.id} — ${j.ruleActivation.enabled?"on":"off"} via ${j.ruleActivation.source}`);return oe.join(`
213
- `)}function li(j){return JSON.stringify(j,null,2)}import{resolve as Xf}from"node:path";var Jf=["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 _l(j){let K=0,te={allocateSegment(){return K++},getNextSegmentIndex(){return K},recordGlobal(re){j.record({kind:"step",scope:"global",step:re})},recordSegment(re,oe=te.currentSegmentIndex){if(oe===void 0)return;j.record({kind:"step",scope:"segment",segmentIndex:oe,step:re})}};return te}function Tl(j={}){let K=[],te=j.maxEvents??512,re={maxTextLength:j.maxTextLength??2048,maxListLength:j.maxListLength??128,maxObjectProperties:j.maxObjectProperties??j.maxListLength??128,maxDepth:j.maxDepth??16},oe=0,ce,de=new Set;return{record(we){if(ce)return;try{if(!we||K.length>=te){oe++;return}K.push(di(Wf(we,re,de)))}catch{oe++}},finish(we){if(ce)return ce;try{ce=di({events:Object.freeze(K),droppedEvents:oe,terminal:Kf(we,re,de)})}catch{oe++,ce=Object.freeze({events:Object.freeze(K),droppedEvents:oe,terminal:Object.freeze({result:"blocked",reason:"trace unavailable".slice(0,re.maxTextLength),segment:"trace unavailable".slice(0,re.maxTextLength)})})}return ce}}}function Wf(j,K,te){if(j.kind!=="step")throw TypeError("invalid trace event");let{scope:re,step:oe}=j;Br(oe,te,K);let ce=An(oe,K,te);if(re==="global")return{kind:"step",scope:"global",step:ce};if(re!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:j.segmentIndex,step:ce}}function Kf(j,K,te){let re=j.result;if(re==="allowed")return Object.freeze({result:"allowed"});if(re!=="blocked")throw TypeError("invalid trace terminal");let oe=j.ruleId;return Object.freeze({result:"blocked",reason:An(j.reason,K,te),segment:An(j.segment,K,te),...oe?{ruleId:An(oe,K,te)}:{}})}function Br(j,K,te,re=0,oe=new WeakSet){if(typeof j==="string"){let we=j.slice(0,te.maxTextLength);if(!Je(we))return;for(let xe of ot(we))for(let Ce of xe.match(/[^\s"'()$]+/g)??[])K.add(Il(Ce));return}if(!j||typeof j!=="object"||re>=te.maxDepth||oe.has(j))return;if(oe.add(j),Array.isArray(j)){let we=Math.min(j.length,te.maxListLength);for(let xe=0;xe<we;xe++)Br(j[xe],K,te,re+1,oe);return}let ce=0,de=new Set;for(let we in j){if(!Object.hasOwn(j,we))continue;if(ce>=te.maxObjectProperties)break;ce++,Br(we,K,te);let xe=ci(we,te,K);if(de.has(xe))continue;de.add(xe),Br(j[we],K,te,re+1,oe)}}function An(j,K,te,re=0,oe=new WeakSet){if(typeof j==="string")return ci(j,K,te);if(!j||typeof j!=="object")return j;if(re>=K.maxDepth)return;if(oe.has(j))return;if(oe.add(j),Array.isArray(j)){let we=[],xe=Math.min(j.length,K.maxListLength);for(let Ce=0;Ce<xe;Ce++)we.push(An(j[Ce],K,te,re+1,oe));return we}let ce={},de=0;for(let we in j){if(!Object.hasOwn(j,we))continue;if(de>=K.maxObjectProperties)break;de++;let xe=ci(we,K,te);if(Object.hasOwn(ce,xe))continue;Object.defineProperty(ce,xe,{value:An(j[we],K,te,re+1,oe),enumerable:!0,configurable:!0,writable:!0})}return ce}function ci(j,K,te){let re=j.slice(0,K.maxTextLength),oe=Je(re)?Ye(re):re,ce=te.size>0?Zf(oe,te):oe;return(Yf(ce)?Oe(ce):ce).slice(0,K.maxTextLength)}function Yf(j){return j.includes("PRIVATE KEY")||j.includes("://")||j.includes("eyJ")||j.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(j)||j.length>=14&&Jf.some((K)=>j.includes(K))||j.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(j)}function Zf(j,K){return j.replace(/[^\s"'()$]+/g,(te)=>K.has(Il(te))?"<redacted>":te)}function Il(j){let K=2166136261,te=2166136261;for(let re=0;re<j.length;re++)K=Math.imul(K^j.charCodeAt(re),16777619),te=Math.imul(te^j.charCodeAt(j.length-re-1),16777619);return`${K>>>0}:${te>>>0}:${j.length}`}function di(j){if(j&&typeof j==="object"&&!Object.isFrozen(j)){for(let K of Object.values(j))di(K);Object.freeze(j)}return j}function er(j,K={},te){let re=Xf(K.cwd??process.cwd()),oe=K.policySnapshot??k(te,{cwd:re,userConfigDir:K.userConfigDir}),ce=P(oe.policy,te.env),de=K.strict,we=ze({policySnapshot:oe,effectiveCapabilities:ce.capabilities,strict:de??ce.strict,paranoidRm:ce.paranoidRm,paranoidInterpreters:ce.paranoidInterpreters,worktreeMode:ce.worktreeMode}),xe={effectiveLevel:we.effectiveLevel,selectedPreset:oe.policy.safety.level??"standard",...oe.policyScopes?{safetyPresetScope:oe.policyScopes.levelScope}:{},effectiveCapabilities:we.effectiveCapabilities,destructiveCommandRuleOverrides:oe.policy.destructiveCommandRuleOverrides},{configSource:Ce,configValid:Se}=em(te,{cwd:re,userConfigDir:K.userConfigDir});if(!j||!j.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:Ce,configValid:Se,...xe};let Ne=v(j,"auto");if(Ne.status==="limited")throw new b;let He=Ne.dialect==="powershell"?v(j,"posix"):Ne,at=ft(He),mt=Tl(),it=_l(mt);it.recordGlobal({type:"parse",input:j,segments:at.map((Gt)=>[...Gt])});let gt=u("Bash",{command:j},{kind:"command",shell:"auto"},{configCwd:re,executionCwd:re},j),ht=V(gt,{environment:te,trace:it,dependencies:{loadPolicySnapshot:()=>oe,...de===void 0?{}:{getModes:()=>({...ce,strict:de})}}}),vt=ht.decision.kind==="deny"?ht.decision:null;if(vt&&(ht.stage==="policy-protection"||ht.stage==="secret-protection")){let Gt=Qf(vt);return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Gt.rule,matched:!0,reason:vt.reason}]}]},result:"blocked",reason:R(vt.reason),segment:R(ui(vt,j)),...Gt.ruleId?{ruleId:R(Gt.ruleId)}:{},configSource:Ce,configValid:Se,...xe}}let yt=it.getNextSegmentIndex();if(vt&&yt>0&&yt<at.length)it.recordSegment({type:"segment-skipped",index:yt,reason:"prior-segment-blocked"},yt);let kt=mt.finish(vt?{result:"blocked",reason:vt.reason,segment:ui(vt,j),...vt.ruleId?{ruleId:vt.ruleId}:{}}:{result:"allowed"}),Lt=vt?.ruleId??tm(gt,oe,ce,te),Ct=U.find((Gt)=>Gt.id===Lt&&Gt.activationCapability),sn=Ct?we.policy.effectiveDestructiveCommandRules[Ct.id]:void 0;return{trace:rm(kt),result:vt?"blocked":"allowed",reason:vt?R(vt.reason):void 0,segment:vt?R(ui(vt,j)):void 0,ruleId:vt?.ruleId?R(vt.ruleId):void 0,customRule:nm(om(vt?.ruleId,oe)),configSource:Ce,configValid:Se,...xe,...Ct&&sn?{ruleActivation:{id:Ct.id,...sn}}:{}}}function ui(j,K){return j.evidence.find((te)=>te.kind==="command")?.segment??K}function Qf(j){if(j.reason===qe)return{ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};if(j.reason===Ve)return{ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};if(j.reason===C)return{ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};return{ruleId:j.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"}}function em(j,K){let te=A(K.cwd),re=K.userConfigPath??T(j,K),oe=H(j,{cwd:K.cwd,userConfigDir:K.userConfigDir,userConfigPath:K.userConfigPath});try{if(r(oe.projectConfigTarget)!==null){if(en(oe.projectConfigTarget).errors.length===0)return{configSource:te,configValid:!0};return{configSource:te,configValid:!1}}}catch(ce){if(ce instanceof o)return{configSource:te,configValid:!1};throw ce}try{if(r(oe.userConfigTarget)!==null){let ce=en(oe.userConfigTarget);return{configSource:re,configValid:ce.errors.length===0}}return{configSource:null,configValid:!0}}catch(ce){if(ce instanceof o)return{configSource:re,configValid:!1};throw ce}}function tm(j,K,te,re){let oe=K.policy,ce=De({...oe,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...oe.destructiveCommandRuleOverrides,...Object.fromEntries(U.flatMap((we)=>we.activationCapability?[[we.id,"on"]]:[]))}},K.state==="degraded"?{diagnostics:K.diagnostics,reason:K.reason}:void 0),de=V(j,{environment:re,dependencies:{loadPolicySnapshot:()=>ce,getModes:()=>({...te,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return de.decision.kind==="deny"?de.decision.ruleId:void 0}function nm(j){if(!j)return;return{id:R(j.id),...j.rulebook?{rulebook:{name:R(j.rulebook.name),version:R(j.rulebook.version)}}:{},...j.source?{source:R(j.source)}:{},...j.override?{override:{type:"reason",reason:R(j.override.reason)}}:{}}}function rm(j){let K=j.events.flatMap((re)=>re.kind==="step"&&re.scope==="global"?[re.step]:[]),te=new Map;for(let re of j.events){if(re.kind!=="step"||re.scope!=="segment")continue;let oe=te.get(re.segmentIndex)??{index:re.segmentIndex,steps:[]};oe.steps.push(re.step),te.set(re.segmentIndex,oe)}return{steps:K,segments:[...te.values()]}}function om(j,K){let te=j?.replace(/^custom\./,"");if(!te||!K.policy.rules.some((re)=>re.name===te))return;return K.ruleMetadata[te]??Object.freeze({id:te})}function $l(j){return new Promise((K)=>{process.stdout.write(`${j}
214
- `,()=>K())})}async function Ol(j,K){let te=ii(K);if(!te)return 1;try{let re=er(te.command,{cwd:te.cwd},j),oe=!!process.env.NO_COLOR||!process.stdout.isTTY;return await $l(te.json?li(re):ai(re,{asciiOnly:oe})),0}catch(re){let oe=im(re instanceof p?re.cause:re);if(oe===void 0)throw re;if(te.json)return await $l(JSON.stringify({error:oe})),1;return console.error(oe),1}}function im(j){if(j instanceof b)return j.message;if(j instanceof f)return j.message;if(j instanceof a&&n[j.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var jl="2.4.0",Ht=" ",fn="cc-safety-net";function Fl(j){return j.argument?`${j.flags} ${j.argument}`:j.flags}function sm(j){return Math.max(...j.map((K)=>Fl(K).length))}function am(j){return Math.max(...j.map((K)=>K.usage.length))}function lm(j){return Math.max(...j.map((K)=>`${fn} ${K.usage}`.length))}function cm(j,K){let te=`${fn} ${j.usage}`;return`${Ht}${te.padEnd(K+2)}${j.description}`}function Zt(j,K){return`${Ht}${j.padEnd(Math.max(40,j.length+2))}${K}`}function _n(j,K=console.log){let te=[];if(te.push(`${fn} ${j.name}`),te.push(""),te.push(`${Ht}${j.description}`),te.push(""),te.push("USAGE:"),te.push(`${Ht}${fn} ${j.usage}`),te.push(""),j.subcommands&&j.subcommands.length>0){te.push("SUBCOMMANDS:");let re=am(j.subcommands);for(let oe of j.subcommands)te.push(`${Ht}${oe.usage.padEnd(re+2)}${oe.description}`);te.push("")}if(j.options.length>0){te.push("OPTIONS:");let re=sm(j.options);for(let oe of j.options){let ce=Fl(oe),de=oe.default?`${oe.description} (default: ${oe.default})`:oe.description;te.push(`${Ht}${ce.padEnd(re+2)}${de}`)}te.push("")}if(j.examples&&j.examples.length>0){te.push("EXAMPLES:");for(let re of j.examples)te.push(`${Ht}${re}`)}K(te.join(`
215
- `))}function pi(){let j=lm(fr),K=[];K.push(`${fn} v${jl}`),K.push(""),K.push("Blocks destructive commands and secret access."),K.push(""),K.push("COMMANDS:");for(let te of fr)K.push(cm(te,j));K.push(""),K.push("GLOBAL OPTIONS:"),K.push(`${Ht}-h, --help Show help (use with command for command-specific help)`),K.push(`${Ht}-V, --version Show version`),K.push(""),K.push("HELP:"),K.push(`${Ht}${fn} help <command> Show help for a specific command`),K.push(`${Ht}${fn} <command> --help Show help for a specific command`),K.push(""),K.push("ENVIRONMENT VARIABLES:"),K.push(Zt(`${i.level.name}=standard|strict|paranoid`,"Set session safety level")),K.push(Zt(`${i.worktree.name}=1`,"Allow local git discards in linked worktrees")),K.push(Zt(`${i.debug.name}=1`,"Print diagnostic messages to stderr")),K.push(Zt(`${i.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),K.push(Zt("CC_SAFETY_NET_HOME","Override rule config home directory")),K.push(""),K.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),K.push(Zt(`${i.strict.name}=1`,"Force safety.overrides.fail_closed on")),K.push(Zt(`${i.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),K.push(Zt(`${i.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),K.push(Zt(`${i.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),K.push(""),K.push("Documentation: https://ccsafetynet.com/docs"),console.log(K.join(`
216
- `))}function Nl(){console.log(jl)}function tr(j,K=console.log){let te=mr(j);if(!te)return!1;if(te.name.toLowerCase()!==j.toLowerCase())return!1;return _n(te,K),!0}import{existsSync as Ci,readFileSync as Oc}from"node:fs";import{join as ki}from"node:path";import*as rn from"node:readline";function dm(j){return j==="install"?"Install":"Uninstall"}function um(j){return j==="install"?"Installing":"Uninstalling"}function pm(j){return j==="install"?"into":"from"}function Ul(j){return j?.available===!0}function fm(j,K){let te=new Set(K);return j.filter((re)=>te.has(re.target)).map((re)=>re.target)}function Ml(j,K,te){if(j.length===0||j.every((re)=>!re.available))return K;return Array.from({length:j.length},(re,oe)=>oe+1).map((re)=>(K+re*te+j.length)%j.length).find((re)=>Ul(j[re]))}function mm(j,K,te){if(te.ctrl&&te.name==="c")return"interrupt";if(te.name==="escape"||K==="q")return"abort";if(j==="install"&&(K==="u"||K==="U"))return"update";if(te.name==="up"||K==="k")return"up";if(te.name==="down"||K==="j")return"down";if(te.name==="space"||K===" ")return"toggle";if(te.name==="return"||te.name==="enter")return"confirm";return null}function gm(j){return{cursor:j.findIndex((K)=>K.available),selected:[]}}function ym(j,K,te){if(te==="confirm"||te==="update"||te==="abort"||te==="interrupt")return{state:j,done:te};if(te==="up")return{state:{...j,cursor:Ml(K,j.cursor,-1)}};if(te==="down")return{state:{...j,cursor:Ml(K,j.cursor,1)}};let re=K[j.cursor];if(!Ul(re))return{state:j};let oe=j.selected.includes(re.target)?j.selected.filter((ce)=>ce!==re.target):fm(K,[...j.selected,re.target]);return{state:{...j,selected:oe}}}var Gl="◉",Bl="◯",ql=">",Vl=" ";function hm(j,K,te,re={}){let oe=re.color!==!1,ce=oe?bt.dim:(xe)=>xe,de=oe?bt.green:(xe)=>xe,we=oe?bt.bold:(xe)=>xe;return["",`${dm(j)} CC Safety Net ${pm(j)}:`,"",...K.map((xe,Ce)=>{let Se=te.selected.includes(xe.target),Ne=Ce===te.cursor,He=Se?Gl:Bl,at=Ne?ql:Vl,mt=xe.available?"":` (${xe.unavailableReason??"not installed"})`,it=`${He} ${xe.label}${mt}`,gt=!xe.available?ce(it):Se?de(it):Ne?we(it):it;return`${at} ${gt}`}),"",j==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":K.some((xe)=>xe.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${j}. q/Esc: close`].join(`
217
- `)}var Hl=["global-hook","plugin"];function vm(j,K,te={}){let re=te.color!==!1?bt.bold:(ce)=>ce;return["","Install the Kimi Code integration as:","",...[`Global hook — ${K?"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((ce,de)=>{let we=de===j,xe=`${we?Gl:Bl} ${ce}`;return`${we?ql:Vl} ${we?re(xe):xe}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
218
- `)}function zl(j){let{input:K,output:te}=j;rn.emitKeypressEvents(K);let re=K.isRaw===!0;K.setRawMode(!0),K.resume();let oe=0,ce=()=>{if(oe===0)return;rn.moveCursor(te,0,-oe),rn.cursorTo(te,0),rn.clearScreenDown(te)},de=()=>{ce();let we=j.render();te.write(`${we}
210
+ ${we()}`.trim())))}),ce.on("close",(Se)=>{if(clearTimeout(Ce),Se!==0){re(Error(Jo(j,Se,we())));return}te(K?.stdoutOnly?de.stdout:we())})})}async function Ko(j){for(let K of j)await Jt(K)}async function nl(j){for(let K of j)try{await Jt(K)}catch(te){console.warn(te instanceof Error?te.message:String(te))}}var Yo=Yt("openclaw",Rt),bf=[Mt,Rn,Pn];function Zo(j,K){if(j==="~")return K;if(j.startsWith("~/")||j.startsWith("~\\"))return Yt(K,j.slice(2));return j}function ol(j){let K=j.env.get("OPENCLAW_STATE_DIR")?.trim();if(K)return Zo(K,j.home);let te=j.env.get("OPENCLAW_CONFIG_PATH")?.trim();return te?rl(Zo(te,j.home)):Yt(j.home,".openclaw")}function il(j){let K=j.env.get("OPENCLAW_CONFIG_PATH")?.trim();return K?Zo(K,j.home):Yt(ol(j),"openclaw.json")}function Xo(j){return Yt(ol(j),"extensions",Rt)}function Lf(j){let K=yf(j);if(K.length===0)return!0;if(K.some((oe)=>!bf.includes(oe)))return!1;let te=Yt(j,Mt),re=Pt(te);return re!==void 0&&!re.isSymbolicLink()&&re.isFile()&&hf(te,"utf-8").startsWith(Mr)}function Qo(j){let K=Xo(j),te=Pt(K);if(!te)return;if(!te.isSymbolicLink()&&te.isDirectory()&&Lf(K))return;throw Error(`Refusing to modify ${K}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function sl(){let j=rl(vf(import.meta.url));return[Yt(j,Yo),Yt(j,"..",Yo),Yt(j,"..","..","..","dist",Yo)]}function ei(j=sl()){return j.find((K)=>mf(K)&&gf(K).isDirectory())}function wf(j=sl()){let K=ei(j);if(!K)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return K}function al(j=wf()){return[["openclaw","plugins","install",j,"--force"],["openclaw","plugins","enable",Rt]]}function kf(j){let K=(()=>{try{return JSON.parse(j)}catch{return}})(),te=wt(wt(K,"plugin"),"status");return typeof te==="string"?te:void 0}async function ll(){let j=kf(await Jt(["openclaw","plugins","inspect",Rt,"--runtime","--json"],{stdoutOnly:!0}));if(j==="loaded")return;throw Error(`${j===void 0?`The ${Rt} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${Rt} plugin with status "${j}".`} Run \`openclaw plugins inspect ${Rt} --runtime\` for details.`)}var Hr="openclaw",Zn=`run \`openclaw plugins enable ${Rt}\``;function En(j,K){let te=Xn(j,K),re=Pt(te);if(!re)return{error:`${K} is missing from ${te}; run install --openclaw`};if(re.isSymbolicLink()||!re.isFile())return{error:`${te} is a symlink or not a regular file; move or remove it`};try{return{content:dl(te,"utf-8")}}catch(oe){return{error:`Failed to read ${te}: ${oe instanceof Error?oe.message:String(oe)}`}}}function ul(j){try{return JSON.parse(jt(j))}catch{return}}function xf(j){let K=En(j,Rn);if("error"in K)return K.error;if(wt(ul(K.content),"id")===Rt)return;return`${Xn(j,Rn)} is not a valid ${Rt} manifest; run install --openclaw`}function Cf(j){let K=En(j,Pn);if("error"in K)return K.error;let te=wt(wt(ul(K.content),"openclaw"),"extensions");if(Array.isArray(te)&&te.includes(`./${Mt}`))return;return`${Xn(j,Pn)} does not point OpenClaw at ${Mt}; run install --openclaw`}function cl(j){return Array.isArray(j)?j.filter((K)=>typeof K==="string"):[]}function Sf(j){let K=il(j);if(!Pt(K))return`${Rt} is not enabled; ${Zn}`;let te=(()=>{try{return JSON.parse(jt(dl(K,"utf-8")))}catch{return}})();if(te===void 0)return`Failed to read ${K}; fix it, then ${Zn}`;let re=wt(te,"plugins");if(wt(re,"enabled")===!1)return`plugins.enabled is false in ${K}; no OpenClaw plugin loads`;let oe=wt(wt(wt(re,"entries"),Rt),"enabled");if(cl(wt(re,"deny")).includes(Rt)||oe===!1)return`${Rt} is disabled in ${K}; ${Zn}`;let ce=cl(wt(re,"allow"));if(ce.length>0&&!ce.includes(Rt))return`plugins.allow in ${K} does not list ${Rt}; add it, then ${Zn}`;if(ce.includes(Rt)||oe===!0)return;return`${Rt} is not enabled; ${Zn}`}function pl(j){return/^\/\/ version:\s*(.+)$/m.exec(j)?.[1]?.trim()}function Rf(j,K,te){if(te===void 0)return[];let re=En(te,Mt);if("error"in re||pl(re.content)!==K)return[];return[Mt,Rn,Pn].flatMap((oe)=>{let ce=En(j,oe),de=En(te,oe);if("error"in ce||"error"in de||ce.content===de.content)return[];return[`Modified ${oe} occupies ${Xn(j,oe)}; run install --openclaw to restore it`]})}function fl(j){let K=Xo(j.environment),te=Cr(Hr,K);if(te)return te;let re=En(K,Mt),ce=["error"in re?re.error:re.content.startsWith(Mr)?void 0:`Unmanaged ${Mt} occupies ${Xn(K,Mt)}; move or remove it`,xf(K),Cf(K)].filter((Se)=>Se!==void 0),de="content"in re?pl(re.content):void 0,we=ce.length>0?ce:Rf(K,de,ei());if(we.length>0)return{platform:Hr,status:"n/a",configPath:K,errors:we};let xe=de===Et()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],Ce=Sf(j.environment);if(Ce)return{platform:Hr,status:"disabled",method:"plugin directory",configPath:K,errors:[Ce,...xe]};return{platform:Hr,status:"configured",method:"plugin directory",configPath:K,errors:xe.length>0?xe:void 0}}import{existsSync as If,readFileSync as $f}from"node:fs";import{join as Of}from"node:path";import{existsSync as ti,readFileSync as yl,rmSync as Pf}from"node:fs";import{join as Zt}from"node:path";import{pathToFileURL as Ef}from"node:url";var Ur="cc-safety-net",hl=`${Ur}@latest`,vl=["opencode.json","opencode.jsonc"],ml="CCSafetyNetPlugin",gl={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function Gr(j){return Zt(j.env.get("XDG_CONFIG_HOME")||Zt(j.home,".config"),"opencode")}function Df(j){return Zt(Gr(j),vl[0])}function Af(j){return vl.map((K)=>Zt(Gr(j),K))}function bl(j){return Zt(j.env.get("XDG_CACHE_HOME")||Zt(j.home,".cache"),"opencode","packages",hl)}function ni(j){Pf(bl(j),{recursive:!0,force:!0})}async function Ll(j){let K=Zt(bl(j),"node_modules",Ur),te=Zt(K,"package.json");if(!ti(te))throw Error(`The OpenCode plugin cache at ${K} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${hl}\` for details.`);let re=wt(JSON.parse(yl(te,"utf-8")),"main");if(typeof re!=="string")throw Error(`The cached OpenCode plugin at ${K} declares no "main" entry.`);let oe=Zt(K,re);if(typeof(await import(Ef(oe).href))[ml]==="function")return;throw Error(`The cached OpenCode plugin at ${oe} does not export a callable ${ml}, so OpenCode would load nothing and fail open.`)}function wl(j,K){try{return JSON.parse(jt(j))}catch(te){if(te instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${K}: ${te.message}`);throw te}}function _f(j){if(!j||typeof j!=="object"||Array.isArray(j))return!1;let K=j.plugin;if(!Array.isArray(K))return!1;return K.some((te)=>typeof te==="string"&&te.includes(Ur))}function Tf(j,K){let te=pa(j,"plugin",gl);if(!te)throw Error(`Failed to locate OpenCode plugin array in ${K}`);let re=fa(j,te,gl.stringError).filter((oe)=>oe.value.includes(Ur)).map((oe)=>oe.range).reverse().reduce(Pr,j);return wl(re,K),re}function kl(j){ni(j);let K=Af(j),te=K.find((oe)=>ti(oe)),re=[];for(let oe of K){if(!ti(oe))continue;try{let ce=yl(oe,"utf-8");if(!_f(wl(ce,oe)))continue;return Dt(oe,Tf(ce,oe)),{path:oe,alreadyInstalled:!0}}catch(ce){re.push(ce instanceof Error?ce.message:String(ce))}}if(re.length>0)throw Error(re.join(`
211
+ `));return{path:te??Df(j),alreadyInstalled:!1}}function xl(j){let K=[],te=Gr(j.environment),re=["opencode.json","opencode.jsonc"];for(let oe of re){let ce=Of(te,oe);if(If(ce))try{let de=$f(ce,"utf-8"),we=jt(de);if((JSON.parse(we).plugin??[]).some((Ne)=>Ne.includes("cc-safety-net")))return{platform:"opencode",status:"configured",method:"plugin array",configPath:ce,errors:K.length>0?K:void 0}}catch(de){K.push(`Failed to parse ${oe}: ${de instanceof Error?de.message:String(de)}`)}}return{platform:"opencode",status:"n/a",errors:K.length>0?K:void 0}}import{join as jf}from"node:path";function ri(j){return jf(j.home,".pi","agent","settings.json")}function oi(j){if(typeof j!=="string")return!1;return j==="npm:cc-safety-net"||j.startsWith("npm:cc-safety-net@")}function Cl(j){let K=ri(j.environment),te=qt(K);if(te.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(te.kind==="missing")return{platform:"pi",status:"n/a"};let re=wt(te.value,"packages");if(!Array.isArray(re))return{platform:"pi",status:"n/a"};let oe=re.find((we)=>oi(typeof we==="string"?we:wt(we,"source")));if(oe===void 0)return{platform:"pi",status:"n/a"};let ce=wt(oe,"extensions");if(Array.isArray(ce)&&ce.some((we)=>typeof we==="string"&&we.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:K,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:K}}var Ff={amp:ra,"antigravity-cli":oa,"claude-code":la,codex:ca,"copilot-cli":Ca,cursor:Ta,"gemini-cli":Ia,"grok-build":Ba,"hermes-agent":el,"kimi-code":Yn,openclaw:fl,opencode:xl,pi:Cl};function Dn(j,K,te){let re={...te,cwd:K,environment:j};return ur.map((oe)=>Nf(Ff[oe](re)))}function Nf(j){if(j.status==="not-inspected")return{platform:j.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:j.platform,detected:j.status!=="n/a",configured:j.status==="configured",inspectionStatus:j.status!=="n/a"?"verified":j.errors&&j.errors.length>0?"failed":"not-applicable",method:j.method,configPath:j.configPath,configPaths:j.configPaths,errors:j.errors}}import{join as Mf}from"node:path";var Hf=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}]),Uf=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([])})})}),Gf={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 Sl(j){let K=Mf(j.tmpdir,"cc-safety-net-self-test"),te=Hf.map((re)=>{let oe=F(j,u("self-test",{command:re.command},{kind:"command",shell:"auto"},{configCwd:K,executionCwd:K},re.command),{guard:{dependencies:{loadPolicySnapshot:()=>Uf,getModes:()=>Gf,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),ce=re.expectBlocked?"blocked":"allowed",de=oe.decision.kind==="deny"?"blocked":"allowed";return{command:re.command,description:re.description,expected:ce,actual:de,passed:ce===de,reason:oe.decision.kind==="deny"?oe.decision.reason:void 0,ruleId:oe.decision.kind==="deny"?oe.decision.ruleId:void 0}});return{passed:te.filter((re)=>re.passed).length,failed:te.filter((re)=>!re.passed).length,total:te.length,results:te}}function ii(j){let K=At({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},j);if(Kt(K.errors))return null;return{json:K.flags.json,skipUpdateCheck:K.flags.skipUpdateCheck}}async function Rl(j,K={}){let te=await Bn(!K.json,()=>{let re=Bf(j,K);return{ready:re,finish:()=>re}},()=>Gn(),{loadingMessage:"Checking system status…"});if(K.json)console.log(JSON.stringify(te,null,2));else qf(te);return te.engineSelfTest.failed>0||te.findings.some((re)=>re.severity==="error")?1:0}async function Bf(j,K){let te=K.cwd??process.cwd(),re=await Hn(),oe=Dn(j,te,{ampPluginListOutput:re.ampPluginListOutput,codexPluginListOutput:re.codexPluginListOutput,copilotCliVersion:re.versions["copilot-cli"]}),ce=bs(j,te),de=Ls(j),we=k(j,{cwd:te}),xe=we.policy,Ce=P(xe,j.env),Se=B(xe,Ce.capabilities),Ne=gr(j,7),He=Xs(j,te),at=K.skipUpdateCheck?{currentVersion:Et(),latestVersion:null,updateAvailable:!1}:await nn(),mt={hooks:oe,engineSelfTest:Sl(j),userConfig:ce.userConfig,projectConfig:ce.projectConfig,configState:Be(we),effectiveRules:ce.effectiveRules,shadowedRules:ce.shadowedRules,environment:de,effectiveSafety:{selectedPreset:xe.safety.level??"standard",level:Ce.effectiveLevel,capabilities:Ce.capabilities,ruleOverrides:xe.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(Se).filter(([,it])=>it.source==="rule_override"&&it.override==="off"&&it.inheritedEnabled&&it.changesInherited).map(([it])=>it),ruleCounts:{stored:Object.keys(xe.destructiveCommandRuleOverrides).length,effective:Object.values(Se).filter((it)=>it.changesInherited).length},...we.policyScopes?{policyScopes:we.policyScopes}:{}},...He.length>0?{v2Leftovers:He}:{},posture:$s(j,ce.userConfig.path),activity:Ne,update:at,system:re};return{...mt,findings:ks(mt)}}function qf(j){console.log(),console.log(Cs(j.hooks)),console.log(),console.log(Ss(j.engineSelfTest)),console.log(),console.log(Rs(j)),console.log(),console.log(Ps(j.environment)),console.log(),console.log(Es(j)),console.log(),console.log(Ds(j.findings)),console.log(),console.log(As(j.activity)),console.log(),console.log(Ts(j.system)),console.log(),console.log(_s(j.update)),console.log(Is(j))}import{existsSync as Vf}from"node:fs";var zf=/^[A-Za-z0-9_@%+=:,./-]+$/,Pl="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function si(j){let K=At({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},j);if(Kt(K.errors))return console.error(Pl),console.error("Pass -- before a command that starts with dashes."),null;if(K.values.cwd!==void 0&&!Vf(K.values.cwd))return console.error(`Error: --cwd path does not exist: ${K.values.cwd}`),null;let te=K.positionals.length===1?K.positionals[0]:K.positionals.map((re)=>zf.test(re)?re:`'${re.replaceAll("'","'\\''")}'`).join(" ");if(!te)return console.error("Error: No command provided"),console.error(Pl),null;return{json:K.flags.json,cwd:K.values.cwd,command:te}}function El(j){if(j)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 Dl(j,K){let re=K-18;return[`${j.dtl}${j.dh.repeat(K)}${j.dtr}`,`${j.dv} Command Analysis${" ".repeat(re)}${j.dv}`,`${j.dbl}${j.dh.repeat(K)}${j.dbr}`]}function ai(j){return JSON.stringify(j)}function Al(j,K=0){return`[${j.map((re,oe)=>xs(re,oe,K)).join(",")}]`}function Qn(j,K,te=70){let re=j.split(" "),oe=[],ce="";for(let de of re)if(ce&&ce.length+de.length+1>te)oe.push(ce),ce=de;else ce=ce?`${ce} ${de}`:de;if(ce)oe.push(ce);return oe.map((de,we)=>we===0?de:`${K}${de}`)}function _l(j,K,te){let re=[];switch(j.type){case"parse":return null;case"env-strip":return re.push(""),re.push(`STEP ${K} ${te.h} Strip environment variables`),re.push(` Removed: ${j.envVars.map((oe)=>`${oe}=<redacted>`).join(", ")}`),re.push(` Tokens: ${ai(j.output)}`),{lines:re,incrementStep:!0};case"leading-tokens-stripped":return re.push(""),re.push(`STEP ${K} ${te.h} Strip wrappers`),re.push(` Removed: ${j.removed.join(", ")}`),re.push(` Tokens: ${ai(j.output)}`),{lines:re,incrementStep:!0};case"shell-wrapper":return re.push(""),re.push(`STEP ${K} ${te.h} Detect shell wrapper`),re.push(` Wrapper: ${j.wrapper} -c`),re.push(` Inner: ${j.innerCommand}`),{lines:re,incrementStep:!0};case"interpreter":{if(re.push(""),re.push(`STEP ${K} ${te.h} Detect interpreter`),re.push(` Interpreter: ${j.interpreter}`),re.push(` Code: ${j.codeArg}`),j.paranoidBlocked)re.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:re,incrementStep:!0}}case"busybox":return re.push(""),re.push(`STEP ${K} ${te.h} Busybox wrapper`),re.push(` Subcommand: ${j.subcommand}`),{lines:re,incrementStep:!0};case"transparent-wrapper":return re.push(""),re.push(`STEP ${K} ${te.h} Transparent wrapper`),re.push(` Wrapper: ${j.wrapper}`),re.push(` Tokens: ${ai(j.output)}`),{lines:re,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(re.push(""),re.push(`STEP ${K} ${te.h} Match rules`),re.push(` Rule: ${j.rule}()`),j.matched)re.push(" Result: MATCHED");else re.push(" Result: No match");return{lines:re,incrementStep:!0}}case"worktree-relaxation":return re.push(""),re.push(`STEP ${K} ${te.h} Worktree relaxation`),re.push(` Mode: ${i.worktree.name}`),re.push(` Git cwd: ${j.gitCwd}`),re.push(" Result: Allowed local discard in linked worktree"),{lines:re,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(j.embeddedCommandFound)return re.push(""),re.push(`STEP ${K} ${te.h} Fallback scan`),re.push(` Found: ${j.embeddedCommandFound}`),{lines:re,incrementStep:!0};return null}case"custom-rules-check":{if(j.rulesChecked){if(re.push(""),re.push(`STEP ${K} ${te.h} Custom rules`),j.matched)re.push(" Result: MATCHED");else re.push(" Result: No match");return{lines:re,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(j.matched)return re.push(""),re.push(`STEP ${K} ${te.h} Dangerous text check`),re.push(` Token: ${j.token}`),re.push(" Result: MATCHED"),{lines:re,incrementStep:!0};return null}case"strict-unparseable":return re.push(""),re.push(`STEP ${K} ${te.h} Strict mode check`),re.push(` Command: ${j.rawCommand}`),re.push(" Result: ✗ UNPARSEABLE"),{lines:re,incrementStep:!0};case"segment-skipped":return null;case"error":return re.push(""),re.push(`ERROR: ${j.message}`),{lines:re,incrementStep:!1};default:return j}}function li(j,K){let te=El(K?.asciiOnly??!1),re=58,oe=[],ce=1;oe.push(...Dl(te,58)),oe.push("");let de=j.trace.steps.find((mt)=>mt.type==="error");if(de&&de.type==="error"){oe.push("ERROR"),oe.push(` ${de.message}`),oe.push(""),oe.push("RESULT"),oe.push(` Status: ${j.result==="blocked"?bt.red("BLOCKED"):bt.green("ALLOWED")}`),oe.push(""),oe.push("CONFIG");let mt=j.configSource??"none";return oe.push(` Path: ${mt}`),oe.join(`
212
+ `)}let we=j.trace.steps.find((mt)=>mt.type==="parse");if(we&&we.type==="parse"){oe.push("INPUT"),oe.push(` ${we.input}`),oe.push(""),oe.push(`STEP ${ce} ${te.h} Split shell commands`),ce++;for(let mt=0;mt<we.segments.length;mt++){let it=we.segments[mt];if(it){let gt=Math.random();oe.push(` Segment ${mt+1}: ${Al(it,gt)}`)}}}let xe=j.trace.segments,Ce=xe.length>1;for(let mt of xe){if(Ce){oe.push("");let vt="";if(we&&we.type==="parse"){let mo=we.segments[mt.index];if(mo)vt=mo.join(" ")}let yt=54,kt=vt,Lt=` Segment ${mt.index+1}: `,Ct=" ";if(vt){if(Lt.length+vt.length+Ct.length>yt){let iu=yt-Lt.length-Ct.length;kt=`${vt.substring(0,iu-1)}…`}}let sn=vt?`${Lt}${kt}${Ct}`:` Segment ${mt.index+1} `,Gt=vt?`${Lt}${bt.cyan(kt)}${Ct}`:sn,Wi=58-sn.length,Ki=Math.floor(Wi/2),ou=Wi-Ki;oe.push(`${te.sh.repeat(Ki)}${Gt}${te.sh.repeat(ou)}`)}if(mt.steps.find((vt)=>vt.type==="segment-skipped")){oe.push(""),oe.push(" (skipped — prior segment blocked)");continue}let gt=!1,ht=!1;for(let vt of mt.steps){let yt=_l(vt,ce,te);if(yt){if(ht=!0,vt.type==="recurse"){oe.push("");let kt=" RECURSING ",Lt=58-kt.length-4;oe.push(` ${te.tl}${te.h}${kt}${te.h.repeat(Lt)}`),oe.push(` ${te.v}`),gt=!0;continue}for(let kt of yt.lines)if(gt)oe.push(` ${te.v} ${kt}`);else oe.push(kt);if(yt.incrementStep)ce++}}if(gt)oe.push(` ${te.v}`),oe.push(` ${te.bl}${te.h.repeat(56)}`),gt=!1;if(!ht)oe.push(""),oe.push(` ${bt.green("✓")} Allowed (no matching rules)`)}if(oe.push(""),oe.push("RESULT"),j.result==="blocked"){if(oe.push(` Status: ${bt.red("BLOCKED")}`),j.customRule){if(oe.push(` Rule: ${j.customRule.id}`),j.customRule.rulebook)oe.push(` Rulebook: ${j.customRule.rulebook.name} ${j.customRule.rulebook.version}`);if(j.customRule.source)oe.push(` Source: ${j.customRule.source}`);if(j.customRule.override)oe.push(` Override: reason ${j.customRule.override.reason}`)}if(j.reason){let mt=Qn(j.reason," ");oe.push(` Reason: ${mt[0]}`);for(let it=1;it<mt.length;it++)oe.push(mt[it]??"")}}else oe.push(` Status: ${bt.green("ALLOWED")}`);oe.push(""),oe.push("CONFIG");let Se=j.configSource??"none",Ne=j.configValid?"":" (invalid)";oe.push(` Path: ${Se}${Ne}`);let He=j.safetyPresetScope;oe.push(` Safety preset: ${j.selectedPreset??"standard"}${He?` (${hr(He)})`:""}`),oe.push(` Effective capabilities: ${j.effectiveLevel}`);let at=Object.entries(j.destructiveCommandRuleOverrides??{});if(oe.push(` Rule customizations: ${at.length}`),j.ruleActivation)oe.push(` Rule activation: ${j.ruleActivation.id} — ${j.ruleActivation.enabled?"on":"off"} via ${j.ruleActivation.source}`);return oe.join(`
213
+ `)}function ci(j){return JSON.stringify(j,null,2)}import{resolve as Xf}from"node:path";var Jf=["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 Tl(j){let K=0,te={allocateSegment(){return K++},getNextSegmentIndex(){return K},recordGlobal(re){j.record({kind:"step",scope:"global",step:re})},recordSegment(re,oe=te.currentSegmentIndex){if(oe===void 0)return;j.record({kind:"step",scope:"segment",segmentIndex:oe,step:re})}};return te}function Il(j={}){let K=[],te=j.maxEvents??512,re={maxTextLength:j.maxTextLength??2048,maxListLength:j.maxListLength??128,maxObjectProperties:j.maxObjectProperties??j.maxListLength??128,maxDepth:j.maxDepth??16},oe=0,ce,de=new Set;return{record(we){if(ce)return;try{if(!we||K.length>=te){oe++;return}K.push(ui(Wf(we,re,de)))}catch{oe++}},finish(we){if(ce)return ce;try{ce=ui({events:Object.freeze(K),droppedEvents:oe,terminal:Kf(we,re,de)})}catch{oe++,ce=Object.freeze({events:Object.freeze(K),droppedEvents:oe,terminal:Object.freeze({result:"blocked",reason:"trace unavailable".slice(0,re.maxTextLength),segment:"trace unavailable".slice(0,re.maxTextLength)})})}return ce}}}function Wf(j,K,te){if(j.kind!=="step")throw TypeError("invalid trace event");let{scope:re,step:oe}=j;Br(oe,te,K);let ce=An(oe,K,te);if(re==="global")return{kind:"step",scope:"global",step:ce};if(re!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:j.segmentIndex,step:ce}}function Kf(j,K,te){let re=j.result;if(re==="allowed")return Object.freeze({result:"allowed"});if(re!=="blocked")throw TypeError("invalid trace terminal");let oe=j.ruleId;return Object.freeze({result:"blocked",reason:An(j.reason,K,te),segment:An(j.segment,K,te),...oe?{ruleId:An(oe,K,te)}:{}})}function Br(j,K,te,re=0,oe=new WeakSet){if(typeof j==="string"){let we=j.slice(0,te.maxTextLength);if(!Je(we))return;for(let xe of ot(we))for(let Ce of xe.match(/[^\s"'()$]+/g)??[])K.add($l(Ce));return}if(!j||typeof j!=="object"||re>=te.maxDepth||oe.has(j))return;if(oe.add(j),Array.isArray(j)){let we=Math.min(j.length,te.maxListLength);for(let xe=0;xe<we;xe++)Br(j[xe],K,te,re+1,oe);return}let ce=0,de=new Set;for(let we in j){if(!Object.hasOwn(j,we))continue;if(ce>=te.maxObjectProperties)break;ce++,Br(we,K,te);let xe=di(we,te,K);if(de.has(xe))continue;de.add(xe),Br(j[we],K,te,re+1,oe)}}function An(j,K,te,re=0,oe=new WeakSet){if(typeof j==="string")return di(j,K,te);if(!j||typeof j!=="object")return j;if(re>=K.maxDepth)return;if(oe.has(j))return;if(oe.add(j),Array.isArray(j)){let we=[],xe=Math.min(j.length,K.maxListLength);for(let Ce=0;Ce<xe;Ce++)we.push(An(j[Ce],K,te,re+1,oe));return we}let ce={},de=0;for(let we in j){if(!Object.hasOwn(j,we))continue;if(de>=K.maxObjectProperties)break;de++;let xe=di(we,K,te);if(Object.hasOwn(ce,xe))continue;Object.defineProperty(ce,xe,{value:An(j[we],K,te,re+1,oe),enumerable:!0,configurable:!0,writable:!0})}return ce}function di(j,K,te){let re=j.slice(0,K.maxTextLength),oe=Je(re)?Ye(re):re,ce=te.size>0?Zf(oe,te):oe;return(Yf(ce)?Oe(ce):ce).slice(0,K.maxTextLength)}function Yf(j){return j.includes("PRIVATE KEY")||j.includes("://")||j.includes("eyJ")||j.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(j)||j.length>=14&&Jf.some((K)=>j.includes(K))||j.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(j)}function Zf(j,K){return j.replace(/[^\s"'()$]+/g,(te)=>K.has($l(te))?"<redacted>":te)}function $l(j){let K=2166136261,te=2166136261;for(let re=0;re<j.length;re++)K=Math.imul(K^j.charCodeAt(re),16777619),te=Math.imul(te^j.charCodeAt(j.length-re-1),16777619);return`${K>>>0}:${te>>>0}:${j.length}`}function ui(j){if(j&&typeof j==="object"&&!Object.isFrozen(j)){for(let K of Object.values(j))ui(K);Object.freeze(j)}return j}function er(j,K={},te){let re=Xf(K.cwd??process.cwd()),oe=K.policySnapshot??k(te,{cwd:re,userConfigDir:K.userConfigDir}),ce=P(oe.policy,te.env),de=K.strict,we=ze({policySnapshot:oe,effectiveCapabilities:ce.capabilities,strict:de??ce.strict,paranoidRm:ce.paranoidRm,paranoidInterpreters:ce.paranoidInterpreters,worktreeMode:ce.worktreeMode}),xe={effectiveLevel:we.effectiveLevel,selectedPreset:oe.policy.safety.level??"standard",...oe.policyScopes?{safetyPresetScope:oe.policyScopes.levelScope}:{},effectiveCapabilities:we.effectiveCapabilities,destructiveCommandRuleOverrides:oe.policy.destructiveCommandRuleOverrides},{configSource:Ce,configValid:Se}=em(te,{cwd:re,userConfigDir:K.userConfigDir});if(!j||!j.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:Ce,configValid:Se,...xe};let Ne=v(j,"auto");if(Ne.status==="limited")throw new b;let He=Ne.dialect==="powershell"?v(j,"posix"):Ne,at=ft(He),mt=Il(),it=Tl(mt);it.recordGlobal({type:"parse",input:j,segments:at.map((Gt)=>[...Gt])});let gt=u("Bash",{command:j},{kind:"command",shell:"auto"},{configCwd:re,executionCwd:re},j),ht=V(gt,{environment:te,trace:it,dependencies:{loadPolicySnapshot:()=>oe,...de===void 0?{}:{getModes:()=>({...ce,strict:de})}}}),vt=ht.decision.kind==="deny"?ht.decision:null;if(vt&&(ht.stage==="policy-protection"||ht.stage==="secret-protection")){let Gt=Qf(vt);return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Gt.rule,matched:!0,reason:vt.reason}]}]},result:"blocked",reason:R(vt.reason),segment:R(pi(vt,j)),...Gt.ruleId?{ruleId:R(Gt.ruleId)}:{},configSource:Ce,configValid:Se,...xe}}let yt=it.getNextSegmentIndex();if(vt&&yt>0&&yt<at.length)it.recordSegment({type:"segment-skipped",index:yt,reason:"prior-segment-blocked"},yt);let kt=mt.finish(vt?{result:"blocked",reason:vt.reason,segment:pi(vt,j),...vt.ruleId?{ruleId:vt.ruleId}:{}}:{result:"allowed"}),Lt=vt?.ruleId??tm(gt,oe,ce,te),Ct=U.find((Gt)=>Gt.id===Lt&&Gt.activationCapability),sn=Ct?we.policy.effectiveDestructiveCommandRules[Ct.id]:void 0;return{trace:rm(kt),result:vt?"blocked":"allowed",reason:vt?R(vt.reason):void 0,segment:vt?R(pi(vt,j)):void 0,ruleId:vt?.ruleId?R(vt.ruleId):void 0,customRule:nm(om(vt?.ruleId,oe)),configSource:Ce,configValid:Se,...xe,...Ct&&sn?{ruleActivation:{id:Ct.id,...sn}}:{}}}function pi(j,K){return j.evidence.find((te)=>te.kind==="command")?.segment??K}function Qf(j){if(j.reason===qe)return{ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};if(j.reason===Ve)return{ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};if(j.reason===C)return{ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};return{ruleId:j.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"}}function em(j,K){let te=A(K.cwd),re=K.userConfigPath??T(j,K),oe=H(j,{cwd:K.cwd,userConfigDir:K.userConfigDir,userConfigPath:K.userConfigPath});try{if(r(oe.projectConfigTarget)!==null){if(tn(oe.projectConfigTarget).errors.length===0)return{configSource:te,configValid:!0};return{configSource:te,configValid:!1}}}catch(ce){if(ce instanceof o)return{configSource:te,configValid:!1};throw ce}try{if(r(oe.userConfigTarget)!==null){let ce=tn(oe.userConfigTarget);return{configSource:re,configValid:ce.errors.length===0}}return{configSource:null,configValid:!0}}catch(ce){if(ce instanceof o)return{configSource:re,configValid:!1};throw ce}}function tm(j,K,te,re){let oe=K.policy,ce=De({...oe,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...oe.destructiveCommandRuleOverrides,...Object.fromEntries(U.flatMap((we)=>we.activationCapability?[[we.id,"on"]]:[]))}},K.state==="degraded"?{diagnostics:K.diagnostics,reason:K.reason}:void 0),de=V(j,{environment:re,dependencies:{loadPolicySnapshot:()=>ce,getModes:()=>({...te,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return de.decision.kind==="deny"?de.decision.ruleId:void 0}function nm(j){if(!j)return;return{id:R(j.id),...j.rulebook?{rulebook:{name:R(j.rulebook.name),version:R(j.rulebook.version)}}:{},...j.source?{source:R(j.source)}:{},...j.override?{override:{type:"reason",reason:R(j.override.reason)}}:{}}}function rm(j){let K=j.events.flatMap((re)=>re.kind==="step"&&re.scope==="global"?[re.step]:[]),te=new Map;for(let re of j.events){if(re.kind!=="step"||re.scope!=="segment")continue;let oe=te.get(re.segmentIndex)??{index:re.segmentIndex,steps:[]};oe.steps.push(re.step),te.set(re.segmentIndex,oe)}return{steps:K,segments:[...te.values()]}}function om(j,K){let te=j?.replace(/^custom\./,"");if(!te||!K.policy.rules.some((re)=>re.name===te))return;return K.ruleMetadata[te]??Object.freeze({id:te})}function Ol(j){return new Promise((K)=>{process.stdout.write(`${j}
214
+ `,()=>K())})}async function jl(j,K){let te=si(K);if(!te)return 1;try{let re=er(te.command,{cwd:te.cwd},j),oe=!!process.env.NO_COLOR||!process.stdout.isTTY;return await Ol(te.json?ci(re):li(re,{asciiOnly:oe})),0}catch(re){let oe=im(re instanceof p?re.cause:re);if(oe===void 0)throw re;if(te.json)return await Ol(JSON.stringify({error:oe})),1;return console.error(oe),1}}function im(j){if(j instanceof b)return j.message;if(j instanceof f)return j.message;if(j instanceof a&&n[j.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var Fl="2.4.1",Ht=" ",fn="cc-safety-net";function Nl(j){return j.argument?`${j.flags} ${j.argument}`:j.flags}function sm(j){return Math.max(...j.map((K)=>Nl(K).length))}function am(j){return Math.max(...j.map((K)=>K.usage.length))}function lm(j){return Math.max(...j.map((K)=>`${fn} ${K.usage}`.length))}function cm(j,K){let te=`${fn} ${j.usage}`;return`${Ht}${te.padEnd(K+2)}${j.description}`}function Xt(j,K){return`${Ht}${j.padEnd(Math.max(40,j.length+2))}${K}`}function _n(j,K=console.log){let te=[];if(te.push(`${fn} ${j.name}`),te.push(""),te.push(`${Ht}${j.description}`),te.push(""),te.push("USAGE:"),te.push(`${Ht}${fn} ${j.usage}`),te.push(""),j.subcommands&&j.subcommands.length>0){te.push("SUBCOMMANDS:");let re=am(j.subcommands);for(let oe of j.subcommands)te.push(`${Ht}${oe.usage.padEnd(re+2)}${oe.description}`);te.push("")}if(j.options.length>0){te.push("OPTIONS:");let re=sm(j.options);for(let oe of j.options){let ce=Nl(oe),de=oe.default?`${oe.description} (default: ${oe.default})`:oe.description;te.push(`${Ht}${ce.padEnd(re+2)}${de}`)}te.push("")}if(j.examples&&j.examples.length>0){te.push("EXAMPLES:");for(let re of j.examples)te.push(`${Ht}${re}`)}K(te.join(`
215
+ `))}function fi(){let j=lm(fr),K=[];K.push(`${fn} v${Fl}`),K.push(""),K.push("Blocks destructive commands and secret access."),K.push(""),K.push("COMMANDS:");for(let te of fr)K.push(cm(te,j));K.push(""),K.push("GLOBAL OPTIONS:"),K.push(`${Ht}-h, --help Show help (use with command for command-specific help)`),K.push(`${Ht}-V, --version Show version`),K.push(""),K.push("HELP:"),K.push(`${Ht}${fn} help <command> Show help for a specific command`),K.push(`${Ht}${fn} <command> --help Show help for a specific command`),K.push(""),K.push("ENVIRONMENT VARIABLES:"),K.push(Xt(`${i.level.name}=standard|strict|paranoid`,"Set session safety level")),K.push(Xt(`${i.worktree.name}=1`,"Allow local git discards in linked worktrees")),K.push(Xt(`${i.debug.name}=1`,"Print diagnostic messages to stderr")),K.push(Xt(`${i.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),K.push(Xt("CC_SAFETY_NET_HOME","Override rule config home directory")),K.push(""),K.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),K.push(Xt(`${i.strict.name}=1`,"Force safety.overrides.fail_closed on")),K.push(Xt(`${i.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),K.push(Xt(`${i.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),K.push(Xt(`${i.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),K.push(""),K.push("Documentation: https://ccsafetynet.com/docs"),console.log(K.join(`
216
+ `))}function Ml(){console.log(Fl)}function tr(j,K=console.log){let te=mr(j);if(!te)return!1;if(te.name.toLowerCase()!==j.toLowerCase())return!1;return _n(te,K),!0}import{existsSync as Ri,readFileSync as Oc}from"node:fs";import{join as Ci}from"node:path";import*as rn from"node:readline";function dm(j){return j==="install"?"Install":"Uninstall"}function um(j){return j==="install"?"Installing":"Uninstalling"}function pm(j){return j==="install"?"into":"from"}function Gl(j){return j?.available===!0}function fm(j,K){let te=new Set(K);return j.filter((re)=>te.has(re.target)).map((re)=>re.target)}function Hl(j,K,te){if(j.length===0||j.every((re)=>!re.available))return K;return Array.from({length:j.length},(re,oe)=>oe+1).map((re)=>(K+re*te+j.length)%j.length).find((re)=>Gl(j[re]))}function mm(j,K,te){if(te.ctrl&&te.name==="c")return"interrupt";if(te.name==="escape"||K==="q")return"abort";if(j==="install"&&(K==="u"||K==="U"))return"update";if(te.name==="up"||K==="k")return"up";if(te.name==="down"||K==="j")return"down";if(te.name==="space"||K===" ")return"toggle";if(te.name==="return"||te.name==="enter")return"confirm";return null}function gm(j){return{cursor:j.findIndex((K)=>K.available),selected:[]}}function ym(j,K,te){if(te==="confirm"||te==="update"||te==="abort"||te==="interrupt")return{state:j,done:te};if(te==="up")return{state:{...j,cursor:Hl(K,j.cursor,-1)}};if(te==="down")return{state:{...j,cursor:Hl(K,j.cursor,1)}};let re=K[j.cursor];if(!Gl(re))return{state:j};let oe=j.selected.includes(re.target)?j.selected.filter((ce)=>ce!==re.target):fm(K,[...j.selected,re.target]);return{state:{...j,selected:oe}}}var Bl="◉",ql="◯",Vl=">",zl=" ";function hm(j,K,te,re={}){let oe=re.color!==!1,ce=oe?bt.dim:(xe)=>xe,de=oe?bt.green:(xe)=>xe,we=oe?bt.bold:(xe)=>xe;return["",`${dm(j)} CC Safety Net ${pm(j)}:`,"",...K.map((xe,Ce)=>{let Se=te.selected.includes(xe.target),Ne=Ce===te.cursor,He=Se?Bl:ql,at=Ne?Vl:zl,mt=xe.available?"":` (${xe.unavailableReason??"not installed"})`,it=`${He} ${xe.label}${mt}`,gt=!xe.available?ce(it):Se?de(it):Ne?we(it):it;return`${at} ${gt}`}),"",j==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":K.some((xe)=>xe.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${j}. q/Esc: close`].join(`
217
+ `)}var Ul=["global-hook","plugin"];function vm(j,K,te={}){let re=te.color!==!1?bt.bold:(ce)=>ce;return["","Install the Kimi Code integration as:","",...[`Global hook — ${K?"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((ce,de)=>{let we=de===j,xe=`${we?Bl:ql} ${ce}`;return`${we?Vl:zl} ${we?re(xe):xe}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
218
+ `)}function Jl(j){let{input:K,output:te}=j;rn.emitKeypressEvents(K);let re=K.isRaw===!0;K.setRawMode(!0),K.resume();let oe=0,ce=()=>{if(oe===0)return;rn.moveCursor(te,0,-oe),rn.cursorTo(te,0),rn.clearScreenDown(te)},de=()=>{ce();let we=j.render();te.write(`${we}
219
219
  `),oe=we.split(`
220
- `).length};return new Promise((we)=>{let xe=(Se)=>{K.off("keypress",Ce),K.setRawMode(re),K.pause(),ce(),we(Se)};function Ce(Se,Ne){j.onKey(Se,Ne,{finish:xe,draw:de})}K.on("keypress",Ce),de()})}function Jl(j={}){let K=0;return zl({input:j.input??process.stdin,output:j.output??process.stdout,render:()=>vm(K,j.globalHookInstalled===!0),onKey:(te,re,oe)=>{if(re.ctrl&&re.name==="c"){oe.finish(null),(j.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(re.name==="escape"||te==="q")return oe.finish(null);if(re.name==="return"||re.name==="enter")return oe.finish(Hl[K]);if(re.name==="up"||re.name==="down"||te==="k"||te==="j")K=(K+1)%Hl.length,oe.draw()}})}function fi(j=process.stdin,K=process.stdout){return Boolean(j.isTTY&&K.isTTY&&typeof j.setRawMode==="function")}function Wl(j,K,te={}){let re=te.output??process.stdout,oe=gm(K);return zl({input:te.input??process.stdin,output:re,render:()=>hm(j,K,oe),onKey:(ce,de,we)=>{let xe=mm(j,ce,de);if(!xe)return;let Ce=ym(oe,K,xe);if(oe=Ce.state,Ce.done==="interrupt"){we.finish(null),(te.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(Ce.done==="abort")return we.finish(null);if(Ce.done==="update")return we.finish("update");if(Ce.done==="confirm"){if(oe.selected.length===0){re.write("\x07"),we.draw();return}we.finish([...oe.selected]),re.write(`${um(j)} selected integrations...
221
- `);return}we.draw()}})}import{existsSync as Yl,lstatSync as Lm,mkdirSync as wm,mkdtempSync as km,readdirSync as xm,readFileSync as In,rmSync as Vr}from"node:fs";import{basename as Cm,dirname as Sm,join as Ot}from"node:path";import{fileURLToPath as Rm}from"node:url";var mi="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",mn="cc-safety-net",gn="cc-safety-net/index.ts";import{spawn as bm}from"node:child_process";var gi=(j,K)=>{let te=cn([...j],process.env);return new Promise((re)=>{let oe=bm(te.cmd,te.args,{cwd:K,stdio:["ignore","pipe","pipe"]}),ce=Wo(oe),de=!1,we=setTimeout(()=>{de=!0,oe.kill()},120000);oe.on("error",(xe)=>{clearTimeout(we),re({status:null,errorCode:xe.code,stdout:ce.stdout,stderr:[xe.message,ce.stderr].filter(Boolean).join(`
222
- `)})}),oe.on("close",(xe)=>{clearTimeout(we),re({status:de?null:xe,errorCode:de?"ETIMEDOUT":void 0,stdout:ce.stdout,stderr:ce.stderr})})})};var Tn="cc-safety-net.ts",Kl=Ot("amp",gn);function Pm(j){return Ot(j.home,".config","amp","plugins","cc-safety-net.ts")}function Em(){let j=Sm(Rm(import.meta.url));return[Ot(j,"..",Kl),Ot(j,"..","..","..","dist",Kl)]}function Dm(j=Em()){let K=j.find((te)=>Yl(te)&&Lm(te).isFile());if(!K)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return K}function Zl(j){try{return JSON.parse(j)}catch{return}}function zr(j){return j.subarray(0,Buffer.byteLength(mi)).toString("utf-8")===mi}async function nr(j,K,te){let re=await j(K,te);if(re.status===0)return re;throw Error([`Failed to run ${K.join(" ")}${re.status===null?"":` (exit ${re.status})`}.`,[re.stdout,re.stderr].filter(Boolean).join(`
220
+ `).length};return new Promise((we)=>{let xe=(Se)=>{K.off("keypress",Ce),K.setRawMode(re),K.pause(),ce(),we(Se)};function Ce(Se,Ne){j.onKey(Se,Ne,{finish:xe,draw:de})}K.on("keypress",Ce),de()})}function Wl(j={}){let K=0;return Jl({input:j.input??process.stdin,output:j.output??process.stdout,render:()=>vm(K,j.globalHookInstalled===!0),onKey:(te,re,oe)=>{if(re.ctrl&&re.name==="c"){oe.finish(null),(j.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(re.name==="escape"||te==="q")return oe.finish(null);if(re.name==="return"||re.name==="enter")return oe.finish(Ul[K]);if(re.name==="up"||re.name==="down"||te==="k"||te==="j")K=(K+1)%Ul.length,oe.draw()}})}function mi(j=process.stdin,K=process.stdout){return Boolean(j.isTTY&&K.isTTY&&typeof j.setRawMode==="function")}function Kl(j,K,te={}){let re=te.output??process.stdout,oe=gm(K);return Jl({input:te.input??process.stdin,output:re,render:()=>hm(j,K,oe),onKey:(ce,de,we)=>{let xe=mm(j,ce,de);if(!xe)return;let Ce=ym(oe,K,xe);if(oe=Ce.state,Ce.done==="interrupt"){we.finish(null),(te.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(Ce.done==="abort")return we.finish(null);if(Ce.done==="update")return we.finish("update");if(Ce.done==="confirm"){if(oe.selected.length===0){re.write("\x07"),we.draw();return}we.finish([...oe.selected]),re.write(`${um(j)} selected integrations...
221
+ `);return}we.draw()}})}import{existsSync as Yl,lstatSync as Lm,mkdirSync as wm,mkdtempSync as km,readdirSync as xm,readFileSync as In,rmSync as Vr}from"node:fs";import{basename as Cm,dirname as Sm,join as Ot}from"node:path";import{fileURLToPath as Rm}from"node:url";var gi="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",mn="cc-safety-net",gn="cc-safety-net/index.ts";import{spawn as bm}from"node:child_process";var yi=(j,K)=>{let te=cn([...j],process.env);return new Promise((re)=>{let oe=bm(te.cmd,te.args,{cwd:K,stdio:["ignore","pipe","pipe"]}),ce=Wo(oe),de=!1,we=setTimeout(()=>{de=!0,oe.kill()},120000);oe.on("error",(xe)=>{clearTimeout(we),re({status:null,errorCode:xe.code,stdout:ce.stdout,stderr:[xe.message,ce.stderr].filter(Boolean).join(`
222
+ `)})}),oe.on("close",(xe)=>{clearTimeout(we),re({status:de?null:xe,errorCode:de?"ETIMEDOUT":void 0,stdout:ce.stdout,stderr:ce.stderr})})})};var Tn="cc-safety-net.ts",hi=Ot("amp",gn);function Pm(j){return Ot(j.home,".config","amp","plugins","cc-safety-net.ts")}function Em(){let j=Sm(Rm(import.meta.url));return[Ot(j,hi),Ot(j,"..",hi),Ot(j,"..","..","..","dist",hi)]}function Dm(j=Em()){let K=j.find((te)=>Yl(te)&&Lm(te).isFile());if(!K)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return K}function Zl(j){try{return JSON.parse(j)}catch{return}}function zr(j){return j.subarray(0,Buffer.byteLength(gi)).toString("utf-8")===gi}async function nr(j,K,te){let re=await j(K,te);if(re.status===0)return re;throw Error([`Failed to run ${K.join(" ")}${re.status===null?"":` (exit ${re.status})`}.`,[re.stdout,re.stderr].filter(Boolean).join(`
223
223
  `).trim()].filter(Boolean).join(`
224
224
  `))}async function Xl(j){let K=await j(["amp","plugins","repositories","--json"]);if(K.status===null)throw Error(`${K.errorCode==="ENOENT"?'Amp CLI not found. Install the amp CLI, sign in with "amp login", and rerun install --amp.':`amp plugins repositories --json did not finish (${K.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
225
225
  ${K.stderr}`.trim());if(K.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${K.status}). Sign in with "amp login" and rerun install --amp.
226
226
  ${[K.stdout,K.stderr].filter(Boolean).join(`
227
- `)}`.trim());let te=Zl(K.stdout),re=(Array.isArray(te)?te:[]).filter((oe)=>wt(oe,"scope")==="user"&&wt(oe,"exists")===!0&&wt(oe,"viewerCanWrite")===!0).map((oe)=>wt(oe,"cloneRef")).find((oe)=>typeof oe==="string"&&oe.length>0);if(!re)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return re}async function Ql(j,K,te){let re=km(Ot(K.tmpdir,"cc-safety-net-amp-"));try{return await nr(j,["amp","clone","user-plugins",re]),await te(re)}finally{Vr(re,{recursive:!0,force:!0})}}function yi(j){return`rerun ${j==="overwrite"?"install":"uninstall"} --amp`}function ec(j,K,te){let re=Ot(j,K),oe=Pt(re);if(!oe)return;if(oe.isSymbolicLink()||!oe.isFile())throw Error(`Refusing to ${te} ${K} in your Amp personal plugins repository: not a regular file. Remove it there and ${yi(te)}.`);let ce=In(re);if(zr(ce))return ce;throw Error(`Refusing to ${te} unmanaged file ${K} in your Amp personal plugins repository. Remove it there and ${yi(te)}.`)}function tc(j,K){let te=Ot(j,mn),re=Pt(te);if(!re)return;if(re.isSymbolicLink()||!re.isDirectory())throw Error(`Refusing to ${K} ${mn} in your Amp personal plugins repository: not a regular directory. Remove it there and ${yi(K)}.`);return ec(j,gn,K)}function Am(j){let K=Ot(j,Tn),te=Pt(K);if(!te||te.isSymbolicLink()||!te.isFile())return;let re=In(K);return zr(re)?re:void 0}async function nc(j,K,te,re){if(await nr(j,te,K),(await nr(j,["git","status","--porcelain"],K)).stdout.trim()==="")return!1;return await nr(j,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",re],K),await nr(j,["git","push","origin","HEAD"],K),!0}function qr(j,K){_m(j,K),Tm(j,K)}function rc(j,K){if(K==="keep")return;throw Error(`Local Amp plugin ${j} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function _m(j,K){let te=Pm(j),re=Pt(te);if(!re)return;if(!re.isSymbolicLink()&&re.isFile()&&zr(In(te))){Vr(te);return}rc(te,K)}function Tm(j,K){let te=Ot(j.home,".config","amp","plugins",mn),re=Pt(te);if(!re)return;if(!re.isSymbolicLink()&&re.isDirectory()&&Im(te)){Vr(te,{recursive:!0});return}rc(te,K)}function Im(j){let K=Cm(gn);if(xm(j).join("\x00")!==K)return!1;let te=Ot(j,K),re=Pt(te);return!!re&&!re.isSymbolicLink()&&re.isFile()&&zr(In(te))}function $m(j){let K=d(j);if(!Yl(K))return"";let te=Zl(In(K,"utf-8"));if(!te||typeof te!=="object"||Array.isArray(te))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(h(te,j.home))};
228
- `}async function oc(j,K=Dm(),te=gi){let re=Buffer.concat([In(K),Buffer.from($m(j),"utf-8")]),oe=await Xl(te);return Ql(te,j,async(ce)=>{let de=`${oe}/${mn}`,we=tc(ce,"overwrite"),xe=ec(ce,Tn,"overwrite");if(we?.equals(re)&&!xe)return qr(j,"fail"),{path:de,alreadyInstalled:!0};if(wm(Ot(ce,mn),{recursive:!0}),Dt(Ot(ce,gn),re),xe)Vr(Ot(ce,Tn));let Ce=await nc(te,ce,["git","add","--",gn,...xe?[Tn]:[]],`chore: update cc-safety-net plugin to v${Et()}`);return qr(j,"fail"),{path:de,alreadyInstalled:!Ce}})}async function ic(j,K=gi){let te=await Xl(K);return Ql(K,j,async(re)=>{let oe=tc(re,"remove"),ce=Am(re),de=`${te}/${ce&&!oe?Tn:mn}`;if(!oe&&!ce)return qr(j,"keep"),{path:de,alreadyInstalled:!1};return await nc(K,re,["git","rm","--",...oe?[gn]:[],...ce?[Tn]:[]],`chore: remove cc-safety-net plugin v${Et()}`),qr(j,"keep"),{path:de,alreadyInstalled:!0}})}import{existsSync as sc,mkdirSync as Om,readFileSync as jm}from"node:fs";import{dirname as Fm}from"node:path";var hi=zt["antigravity-cli"],yn="cc-safety-net";function hn(j){return Boolean(j)&&typeof j==="object"&&!Array.isArray(j)}function Wr(){return{PreToolUse:[{hooks:[{type:"command",command:hi,timeout:30}]}]}}function ac(j){try{let K=JSON.parse(jm(j,"utf-8"));if(!K||typeof K!=="object"||Array.isArray(K))throw Error("Antigravity hooks config must be a JSON object");return K}catch(K){if(K instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${j}: ${K.message}`);throw K}}function lc(j){let K=j[yn];if(K===void 0){let re=Wr();return j[yn]=re,{definition:re,preToolUse:re.PreToolUse??[]}}if(!hn(K))throw Error(`Antigravity hooks config entry "${yn}" must be an object`);let te=Array.isArray(K.PreToolUse)?K.PreToolUse:[];return K.PreToolUse=te,{definition:K,preToolUse:te}}function cc(j){if(!Array.isArray(j.PreToolUse))return!1;return j.PreToolUse.some((K)=>hn(K)&&Array.isArray(K.hooks)&&K.hooks.some((te)=>hn(te)&&te.command===hi))}function Nm(j){return Object.values(j).some((K)=>hn(K)&&K.enabled!==!1&&cc(K))}function Mm(j){if(j[yn]===void 0)return!1;let K=lc(j);if(K.definition.enabled!==!1||!cc(K.definition))return!1;return K.definition.enabled=!0,!0}function Hm(j){if(j[yn]===void 0){j[yn]=Wr();return}let K=lc(j);K.definition.enabled=!0,K.preToolUse.push(Wr().PreToolUse?.[0]??{hooks:[]})}function Um(j){let K=!1;for(let te of Object.values(j)){if(!hn(te)||!Array.isArray(te.PreToolUse))continue;te.PreToolUse=te.PreToolUse.flatMap((re)=>{if(!hn(re)||!Array.isArray(re.hooks))return[re];let oe=re.hooks.filter((ce)=>!hn(ce)||ce.command!==hi);if(oe.length!==re.hooks.length)K=!0;return oe.length===0?[]:[{...re,hooks:oe}]})}return K}function Jr(j,K){Dt(j,`${JSON.stringify(K,null,2)}
229
- `)}function dc(j){let K=qn(j.home);if(Om(Fm(K),{recursive:!0}),!sc(K))return Jr(K,{[yn]:Wr()}),{path:K,alreadyInstalled:!1};let te=ac(K);if(Nm(te))return{path:K,alreadyInstalled:!0};if(Mm(te))return Jr(K,te),{path:K,alreadyInstalled:!1};return Hm(te),Jr(K,te),{path:K,alreadyInstalled:!1}}function uc(j){let K=qn(j.home);if(!sc(K))return{path:K,alreadyInstalled:!1};let te=ac(K);if(!Um(te))return{path:K,alreadyInstalled:!1};return Jr(K,te),{path:K,alreadyInstalled:!0}}import{existsSync as Gm,readdirSync as Bm,rmSync as qm}from"node:fs";import{join as Vm}from"node:path";function pc(j,K=process.platform,te){if(!Gm(j))return;let re=K==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);Bm(j).filter((oe)=>oe!==te&&re.test(oe)).forEach((oe)=>{qm(Vm(j,oe),{recursive:!0,force:!0})})}import{spawn as zm}from"node:child_process";var Wt=Nt.map((j)=>({target:j.id,flag:j.flag,label:St(j.id),probeCommand:j.probeCommand}));function vi(j){let K=new Set(j);return Wt.map((te)=>te.target).filter((te)=>K.has(te))}async function fc(j,K){for(let te of j)await K(te)}var Jm=5000;function bi(j,K=Jm){return new Promise((te)=>{let re=cn([...j],process.env),oe=zm(re.cmd,re.args,{env:process.env,stdio:"ignore"}),ce=!1,de=(xe)=>{if(ce)return;ce=!0,clearTimeout(we),te(xe)},we=setTimeout(()=>{oe.kill(),de(!1)},K);oe.on("error",()=>de(!1)),oe.on("close",(xe)=>de(xe===0))})}function mc(j=bi,K={}){let te=new Set(K.configuredTargets??[]);return Promise.all(Wt.map(async(re)=>({target:re.target,flag:re.flag,label:re.label,...yc(K.action,await j(re.probeCommand),te.has(re.target))})))}function gc(j,K){let te=new Set(K.configuredTargets??[]);return j.map((re)=>({...re,...yc(K.action,re.available,te.has(re.target))}))}function yc(j,K,te){if(j==="uninstall")return te?{available:!0}:{available:!1,unavailableReason:"not installed"};if(j==="install"&&te)return{available:!1,unavailableReason:"already installed"};if(!K)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}import{existsSync as hc,readdirSync as Wm,rmSync as Km}from"node:fs";import{join as $n}from"node:path";function Kr(j,K=process.platform){let te=$n(j.env.get("npm_config_cache")||(K==="win32"?$n(j.env.get("LOCALAPPDATA")||$n(j.home,"AppData","Local"),"npm-cache"):$n(j.home,".npm")),"_npx");if(!hc(te))return;Wm(te).filter((re)=>hc($n(te,re,"node_modules","cc-safety-net"))).forEach((re)=>{Km($n(te,re),{recursive:!0,force:!0})})}import{existsSync as xc,mkdirSync as Zm,readFileSync as Cc}from"node:fs";import{dirname as Xm,join as kc}from"node:path";function Ym(j,K){if(j[K]!=="#")return K;let te=j.indexOf(`
230
- `,K+1);return te===-1?j.length:te+1}function Li(j,K,te){let re=new RegExp(`^(\\s*)${K}\\s*=\\s*\\[`),oe=0;for(let ce of j.split(`
231
- `)){if(/^\s*\[/.test(ce))return;let de=re.exec(ce);if(de){let we=oe+de[0].lastIndexOf("[");return{start:we,end:_o(j,we,{skipComment:Ym,...te})}}oe+=ce.length+1}return}function vc(j,K,te){let re=j.slice(0,K.end).trimEnd(),oe=ca(j,K.end),ce=oe===""?" ":`${oe} `,de=!re.endsWith("[")&&!re.endsWith(",");return`${re}${de?",":""}
227
+ `)}`.trim());let te=Zl(K.stdout),re=(Array.isArray(te)?te:[]).filter((oe)=>wt(oe,"scope")==="user"&&wt(oe,"exists")===!0&&wt(oe,"viewerCanWrite")===!0).map((oe)=>wt(oe,"cloneRef")).find((oe)=>typeof oe==="string"&&oe.length>0);if(!re)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return re}async function Ql(j,K,te){let re=km(Ot(K.tmpdir,"cc-safety-net-amp-"));try{return await nr(j,["amp","clone","user-plugins",re]),await te(re)}finally{Vr(re,{recursive:!0,force:!0})}}function vi(j){return`rerun ${j==="overwrite"?"install":"uninstall"} --amp`}function ec(j,K,te){let re=Ot(j,K),oe=Pt(re);if(!oe)return;if(oe.isSymbolicLink()||!oe.isFile())throw Error(`Refusing to ${te} ${K} in your Amp personal plugins repository: not a regular file. Remove it there and ${vi(te)}.`);let ce=In(re);if(zr(ce))return ce;throw Error(`Refusing to ${te} unmanaged file ${K} in your Amp personal plugins repository. Remove it there and ${vi(te)}.`)}function tc(j,K){let te=Ot(j,mn),re=Pt(te);if(!re)return;if(re.isSymbolicLink()||!re.isDirectory())throw Error(`Refusing to ${K} ${mn} in your Amp personal plugins repository: not a regular directory. Remove it there and ${vi(K)}.`);return ec(j,gn,K)}function Am(j){let K=Ot(j,Tn),te=Pt(K);if(!te||te.isSymbolicLink()||!te.isFile())return;let re=In(K);return zr(re)?re:void 0}async function nc(j,K,te,re){if(await nr(j,te,K),(await nr(j,["git","status","--porcelain"],K)).stdout.trim()==="")return!1;return await nr(j,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",re],K),await nr(j,["git","push","origin","HEAD"],K),!0}function qr(j,K){_m(j,K),Tm(j,K)}function rc(j,K){if(K==="keep")return;throw Error(`Local Amp plugin ${j} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function _m(j,K){let te=Pm(j),re=Pt(te);if(!re)return;if(!re.isSymbolicLink()&&re.isFile()&&zr(In(te))){Vr(te);return}rc(te,K)}function Tm(j,K){let te=Ot(j.home,".config","amp","plugins",mn),re=Pt(te);if(!re)return;if(!re.isSymbolicLink()&&re.isDirectory()&&Im(te)){Vr(te,{recursive:!0});return}rc(te,K)}function Im(j){let K=Cm(gn);if(xm(j).join("\x00")!==K)return!1;let te=Ot(j,K),re=Pt(te);return!!re&&!re.isSymbolicLink()&&re.isFile()&&zr(In(te))}function $m(j){let K=d(j);if(!Yl(K))return"";let te=Zl(In(K,"utf-8"));if(!te||typeof te!=="object"||Array.isArray(te))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(h(te,j.home))};
228
+ `}async function oc(j,K=Dm(),te=yi){let re=Buffer.concat([In(K),Buffer.from($m(j),"utf-8")]),oe=await Xl(te);return Ql(te,j,async(ce)=>{let de=`${oe}/${mn}`,we=tc(ce,"overwrite"),xe=ec(ce,Tn,"overwrite");if(we?.equals(re)&&!xe)return qr(j,"fail"),{path:de,alreadyInstalled:!0};if(wm(Ot(ce,mn),{recursive:!0}),Dt(Ot(ce,gn),re),xe)Vr(Ot(ce,Tn));let Ce=await nc(te,ce,["git","add","--",gn,...xe?[Tn]:[]],`chore: update cc-safety-net plugin to v${Et()}`);return qr(j,"fail"),{path:de,alreadyInstalled:!Ce}})}async function ic(j,K=yi){let te=await Xl(K);return Ql(K,j,async(re)=>{let oe=tc(re,"remove"),ce=Am(re),de=`${te}/${ce&&!oe?Tn:mn}`;if(!oe&&!ce)return qr(j,"keep"),{path:de,alreadyInstalled:!1};return await nc(K,re,["git","rm","--",...oe?[gn]:[],...ce?[Tn]:[]],`chore: remove cc-safety-net plugin v${Et()}`),qr(j,"keep"),{path:de,alreadyInstalled:!0}})}import{existsSync as sc,mkdirSync as Om,readFileSync as jm}from"node:fs";import{dirname as Fm}from"node:path";var bi=zt["antigravity-cli"],yn="cc-safety-net";function hn(j){return Boolean(j)&&typeof j==="object"&&!Array.isArray(j)}function Wr(){return{PreToolUse:[{hooks:[{type:"command",command:bi,timeout:30}]}]}}function ac(j){try{let K=JSON.parse(jm(j,"utf-8"));if(!K||typeof K!=="object"||Array.isArray(K))throw Error("Antigravity hooks config must be a JSON object");return K}catch(K){if(K instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${j}: ${K.message}`);throw K}}function lc(j){let K=j[yn];if(K===void 0){let re=Wr();return j[yn]=re,{definition:re,preToolUse:re.PreToolUse??[]}}if(!hn(K))throw Error(`Antigravity hooks config entry "${yn}" must be an object`);let te=Array.isArray(K.PreToolUse)?K.PreToolUse:[];return K.PreToolUse=te,{definition:K,preToolUse:te}}function cc(j){if(!Array.isArray(j.PreToolUse))return!1;return j.PreToolUse.some((K)=>hn(K)&&Array.isArray(K.hooks)&&K.hooks.some((te)=>hn(te)&&te.command===bi))}function Nm(j){return Object.values(j).some((K)=>hn(K)&&K.enabled!==!1&&cc(K))}function Mm(j){if(j[yn]===void 0)return!1;let K=lc(j);if(K.definition.enabled!==!1||!cc(K.definition))return!1;return K.definition.enabled=!0,!0}function Hm(j){if(j[yn]===void 0){j[yn]=Wr();return}let K=lc(j);K.definition.enabled=!0,K.preToolUse.push(Wr().PreToolUse?.[0]??{hooks:[]})}function Um(j){let K=!1;for(let te of Object.values(j)){if(!hn(te)||!Array.isArray(te.PreToolUse))continue;te.PreToolUse=te.PreToolUse.flatMap((re)=>{if(!hn(re)||!Array.isArray(re.hooks))return[re];let oe=re.hooks.filter((ce)=>!hn(ce)||ce.command!==bi);if(oe.length!==re.hooks.length)K=!0;return oe.length===0?[]:[{...re,hooks:oe}]})}return K}function Jr(j,K){Dt(j,`${JSON.stringify(K,null,2)}
229
+ `)}function dc(j){let K=qn(j.home);if(Om(Fm(K),{recursive:!0}),!sc(K))return Jr(K,{[yn]:Wr()}),{path:K,alreadyInstalled:!1};let te=ac(K);if(Nm(te))return{path:K,alreadyInstalled:!0};if(Mm(te))return Jr(K,te),{path:K,alreadyInstalled:!1};return Hm(te),Jr(K,te),{path:K,alreadyInstalled:!1}}function uc(j){let K=qn(j.home);if(!sc(K))return{path:K,alreadyInstalled:!1};let te=ac(K);if(!Um(te))return{path:K,alreadyInstalled:!1};return Jr(K,te),{path:K,alreadyInstalled:!0}}import{existsSync as Gm,readdirSync as Bm,rmSync as qm}from"node:fs";import{join as Vm}from"node:path";function pc(j,K=process.platform,te){if(!Gm(j))return;let re=K==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);Bm(j).filter((oe)=>oe!==te&&re.test(oe)).forEach((oe)=>{qm(Vm(j,oe),{recursive:!0,force:!0})})}import{spawn as zm}from"node:child_process";var Wt=Nt.map((j)=>({target:j.id,flag:j.flag,label:St(j.id),probeCommand:j.probeCommand}));function Li(j){let K=new Set(j);return Wt.map((te)=>te.target).filter((te)=>K.has(te))}async function fc(j,K){for(let te of j)await K(te)}var Jm=5000;function wi(j,K=Jm){return new Promise((te)=>{let re=cn([...j],process.env),oe=zm(re.cmd,re.args,{env:process.env,stdio:"ignore"}),ce=!1,de=(xe)=>{if(ce)return;ce=!0,clearTimeout(we),te(xe)},we=setTimeout(()=>{oe.kill(),de(!1)},K);oe.on("error",()=>de(!1)),oe.on("close",(xe)=>de(xe===0))})}function mc(j=wi,K={}){let te=new Set(K.configuredTargets??[]);return Promise.all(Wt.map(async(re)=>({target:re.target,flag:re.flag,label:re.label,...yc(K.action,await j(re.probeCommand),te.has(re.target))})))}function gc(j,K){let te=new Set(K.configuredTargets??[]);return j.map((re)=>({...re,...yc(K.action,re.available,te.has(re.target))}))}function yc(j,K,te){if(j==="uninstall")return te?{available:!0}:{available:!1,unavailableReason:"not installed"};if(j==="install"&&te)return{available:!1,unavailableReason:"already installed"};if(!K)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}import{existsSync as hc,readdirSync as Wm,rmSync as Km}from"node:fs";import{join as $n}from"node:path";function Kr(j,K=process.platform){let te=$n(j.env.get("npm_config_cache")||(K==="win32"?$n(j.env.get("LOCALAPPDATA")||$n(j.home,"AppData","Local"),"npm-cache"):$n(j.home,".npm")),"_npx");if(!hc(te))return;Wm(te).filter((re)=>hc($n(te,re,"node_modules","cc-safety-net"))).forEach((re)=>{Km($n(te,re),{recursive:!0,force:!0})})}import{existsSync as xc,mkdirSync as Zm,readFileSync as Cc}from"node:fs";import{dirname as Xm,join as kc}from"node:path";function Ym(j,K){if(j[K]!=="#")return K;let te=j.indexOf(`
230
+ `,K+1);return te===-1?j.length:te+1}function ki(j,K,te){let re=new RegExp(`^(\\s*)${K}\\s*=\\s*\\[`),oe=0;for(let ce of j.split(`
231
+ `)){if(/^\s*\[/.test(ce))return;let de=re.exec(ce);if(de){let we=oe+de[0].lastIndexOf("[");return{start:we,end:_o(j,we,{skipComment:Ym,...te})}}oe+=ce.length+1}return}function vc(j,K,te){let re=j.slice(0,K.end).trimEnd(),oe=ua(j,K.end),ce=oe===""?" ":`${oe} `,de=!re.endsWith("[")&&!re.endsWith(",");return`${re}${de?",":""}
232
232
  ${ce}${te}${j.slice(K.end)}`}function bc(j,K,te){let re=j.indexOf(te,K.start);if(re===-1||re>K.end)return j;return Pr(j,{start:re,end:re+te.length})}function Lc(j,K){let te=new RegExp(`^\\s*${K}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),re=j.split(`
233
233
  `),oe=re.findIndex((we)=>/^\s*\[/.test(we)),ce=oe===-1?re:re.slice(0,oe),de=oe===-1?[]:re.slice(oe);return[...ce.filter((we)=>!te.test(we)),...de].join(`
234
- `)}function wc(j,K,te){let re=new RegExp(`^\\s*\\[\\[${K}]]\\s*$`,"m");return j.split(/(?=^\s*\[)/m).filter((oe)=>!re.test(oe)||!oe.includes(te)).join("").trimEnd()}var rr=zt["kimi-code"],wi=`[[hooks]]
234
+ `)}function wc(j,K,te){let re=new RegExp(`^\\s*\\[\\[${K}]]\\s*$`,"m");return j.split(/(?=^\s*\[)/m).filter((oe)=>!re.test(oe)||!oe.includes(te)).join("").trimEnd()}var rr=zt["kimi-code"],xi=`[[hooks]]
235
235
  event = "PreToolUse"
236
- command = "${rr}"`,Sc=`{ event = "PreToolUse", command = "${rr}" }`,Rc={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function Pc(j){return kc(j.env.get("KIMI_CODE_HOME")??kc(j.home,".kimi-code"),"config.toml")}function Qm(j){let K=Li(j,"hooks",Rc);if(K&&j.slice(K.start+1,K.end).trim())return vc(j,K,Sc);let te=Lc(j,"hooks").trimEnd();if(te==="")return`${wi}
236
+ command = "${rr}"`,Sc=`{ event = "PreToolUse", command = "${rr}" }`,Rc={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function Pc(j){return kc(j.env.get("KIMI_CODE_HOME")??kc(j.home,".kimi-code"),"config.toml")}function Qm(j){let K=ki(j,"hooks",Rc);if(K&&j.slice(K.start+1,K.end).trim())return vc(j,K,Sc);let te=Lc(j,"hooks").trimEnd();if(te==="")return`${xi}
237
237
  `;return`${te}
238
238
 
239
- ${wi}
240
- `}function Ec(j){let K=Pc(j);if(Zm(Xm(K),{recursive:!0}),!xc(K))return Dt(K,`${wi}
241
- `),{path:K,alreadyInstalled:!1};let te=Cc(K,"utf-8");if(te.includes(rr))return{path:K,alreadyInstalled:!0};return Dt(K,Qm(te)),{path:K,alreadyInstalled:!1}}function Dc(j){let K=Pc(j);if(!xc(K))return{path:K,alreadyInstalled:!1};let te=Cc(K,"utf-8");if(!te.includes(rr))return{path:K,alreadyInstalled:!1};let re=Li(te,"hooks",Rc),oe=re?bc(te,re,Sc):`${wc(te,"hooks",rr)}
242
- `;return Dt(K,oe),{path:K,alreadyInstalled:!0}}var xi="safety-net@cc-marketplace",Ac=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),_c=new Set(["antigravity-cli","cursor","grok-build","hermes-agent","kimi-code"]);function Si(j){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(j??"")}function jc(j){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(j??"")}function eg(j){return/^Marketplace `cc-marketplace`\s*$/m.test(j??"")}var Fc={"claude-code":{installCommands:(j)=>{let K=Sr(j,"cc-safety-net@cc-marketplace");return{commands:[...K?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...Do(j).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Sr(j,xi)?[["claude","plugin","uninstall",xi]]:[],update:K}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(j,K)=>{let te=K??await Jt(["codex","plugin","list"]),re=jc(te);return{commands:[re||eg(te)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:Si(te)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:re}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:"Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."},"copilot-cli":{installCommands:async()=>{let j=await Jt(["copilot","plugin","list"]),K=[...ha(j)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...va(j)?[["copilot","plugin","uninstall",ma]]:[]];if(ga(j))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",Vt]],cleanupCommands:K,update:!0};return{commands:[ya(await Jt(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",Vt]],cleanupCommands:K}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(j)=>{let K=No(j);if(K.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(K.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:Xo,installCommands:()=>({commands:sl()}),uninstallCommands:[["openclaw","plugins","uninstall",Rt,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
243
- `)},opencode:{beforeInstall:ti,installCommands:[["opencode","plugin","-g","-f","cc-safety-net@latest"]]},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]}};function Nc(j,K=(te)=>te){try{let te=JSON.parse(K(Oc(j,"utf-8")));if(!te||typeof te!=="object"||Array.isArray(te))throw Error(`Settings file ${j} must be a JSON object`);return te}catch(te){if(te instanceof SyntaxError)throw Error(`Failed to parse ${j}: ${te.message}`);throw te}}function tg(j){let K=ki(Vn(j),"settings.json");if(!Ci(K))return;let te=Nc(K,jt),re=te.enabledPlugins;if(!re||typeof re!=="object"||Array.isArray(re))return;if(re[Vt]!==!1)return;let oe=Oc(K,"utf-8"),ce=oe.replace(new RegExp(`("${Vt}"\\s*:\\s*)false`),"$1true");return re[Vt]=!0,Dt(K,ce!==oe?ce:`${JSON.stringify(te,null,2)}
244
- `),`Enabled ${Vt} plugin in ${K}`}function ng(j){let K=ni(j);if(!Ci(K))return;let te=Nc(K);if(!Array.isArray(te.packages))return;let re=te.packages.find((oe)=>!!oe&&typeof oe==="object"&&!Array.isArray(oe)&&ri(oe.source)&&("extensions"in oe));if(!re)return;return delete re.extensions,Dt(K,`${JSON.stringify(te,null,2)}
245
- `),`Enabled npm:cc-safety-net extensions in ${K}`}function Tc(j,K){let te=At({label:K,booleans:Object.fromEntries(Wt.map((ce)=>[ce.target,[ce.flag]]))},j),re=te.errors[0];if(re)throw Error(re);let oe=Wt.filter((ce)=>te.flags[ce.target]).map((ce)=>ce.target);if(oe.length!==1)throw Error(`Choose exactly one ${K} target: ${Wt.map((ce)=>ce.flag).join(", ")}`);return oe[0]}async function Mc(j,K=xn){let[te,re,oe]=await Promise.all([K(["amp","plugins","list"],30000),K(["codex","plugin","list"],30000),K(["copilot","--binary-version"])]);return{codexPluginListOutput:re,hooks:Dn(j,process.cwd(),{ampPluginListOutput:te,codexPluginListOutput:re,copilotCliVersion:oe})}}async function rg(j,K,te=xn){let re=await Mc(j,te);return re.hooks.filter((oe)=>K==="install"?oe.configured:oe.detected||oe.inspectionStatus==="not-inspected").filter((oe)=>oe.platform!=="codex"||!Si(re.codexPluginListOutput)||jc(re.codexPluginListOutput)).map((oe)=>oe.platform)}function og(j,K,te,re){if(te.length>0)return{finish:async()=>[Tc(te,K)]};if(!re.selectTargets&&!fi(re.input,re.output))return{finish:async()=>[Tc(te,K)]};let oe=re.detectConfiguredTargets??(()=>rg(j,K,re.fetchVersion)),ce=Promise.all([mc(re.probeTargets),oe()]);return{ready:ce,finish:async()=>{let[de,we]=await ce,xe=gc(de,{action:K,configuredTargets:we}),Ce=re.selectTargets?await re.selectTargets(K,$c(K,xe)):await Wl(K,$c(K,xe),{input:re.input,output:re.output});if(Ce==="update")return Ce;if(!Ce||Ce.length===0)return null;return vi(Ce)}}}async function vn(j,K,te=!1,re){let oe=Fc[j];oe.beforeInstall?.(K);let ce=typeof oe.installCommands==="function"?await oe.installCommands(K,re):{commands:oe.installCommands};return await Ko(ce.commands),await el(ce.cleanupCommands??[]),[`${ce.update||te?"Updated":"Installed"} ${St(j)} integration`,oe.postInstallMessage].filter(Boolean).join(`
246
- `)}async function On(j){let K=Fc[j];if(!K.uninstallCommands)throw Error(`${St(j)} uninstall is not supported`);return await Ko(K.uninstallCommands),`Uninstalled ${St(j)} integration`}function ig(j){let K=wl(j);return K.alreadyInstalled?`Uninstalled OpenCode plugin from ${K.path}`:`OpenCode plugin not installed in ${K.path}`}var sg={"antigravity-cli":{install:dc,uninstall:uc},cursor:{install:Ea,uninstall:Da},"grok-build":{install:Ma,uninstall:Ha},"kimi-code":{install:Ec,uninstall:Dc}};function on(j,K,te,re=!1){if(j==="install"&&!re)Kr(te);let oe=sg[K][j](te),ce=St(K),de=j!=="install"?"Uninstalled":re?"Updated":"Installed";return j==="install"&&oe.alreadyInstalled?re?`${ce} hook up to date in ${oe.path}`:`${ce} hook already installed in ${oe.path}`:j==="uninstall"&&!oe.alreadyInstalled?`${ce} hook not installed in ${oe.path}`:`${de} ${ce} hook ${j==="install"?"in":"from"} ${oe.path}`}var ag={amp:{install:oc,uninstall:ic,restartNote:'Amp personal plugins apply to every Amp session, including Orb threads. Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:qa,uninstall:Va,afterInstall:async(j)=>{let K=zo(j);return await Jt(["hermes","plugins","enable",Ft,"--no-allow-tool-override"]),!K},beforeUninstall:async(j)=>{Vo(j);try{await Jt(["hermes","plugins","disable",Ft])}catch(K){console.warn(`${K instanceof Error?K.message:String(K)}
239
+ ${xi}
240
+ `}function Ec(j){let K=Pc(j);if(Zm(Xm(K),{recursive:!0}),!xc(K))return Dt(K,`${xi}
241
+ `),{path:K,alreadyInstalled:!1};let te=Cc(K,"utf-8");if(te.includes(rr))return{path:K,alreadyInstalled:!0};return Dt(K,Qm(te)),{path:K,alreadyInstalled:!1}}function Dc(j){let K=Pc(j);if(!xc(K))return{path:K,alreadyInstalled:!1};let te=Cc(K,"utf-8");if(!te.includes(rr))return{path:K,alreadyInstalled:!1};let re=ki(te,"hooks",Rc),oe=re?bc(te,re,Sc):`${wc(te,"hooks",rr)}
242
+ `;return Dt(K,oe),{path:K,alreadyInstalled:!0}}var Si="safety-net@cc-marketplace",Ac=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),_c=new Set(["antigravity-cli","cursor","grok-build","hermes-agent","kimi-code"]);function Pi(j){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(j??"")}function jc(j){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(j??"")}function eg(j){return/^Marketplace `cc-marketplace`\s*$/m.test(j??"")}var Fc={"claude-code":{installCommands:(j)=>{let K=Sr(j,"cc-safety-net@cc-marketplace");return{commands:[...K?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...Do(j).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Sr(j,Si)?[["claude","plugin","uninstall",Si]]:[],update:K}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(j,K)=>{let te=K??await Jt(["codex","plugin","list"]),re=jc(te);return{commands:[re||eg(te)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:Pi(te)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:re}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:"Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."},"copilot-cli":{installCommands:async()=>{let j=await Jt(["copilot","plugin","list"]),K=[...ba(j)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...La(j)?[["copilot","plugin","uninstall",ya]]:[]];if(ha(j))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",Vt]],cleanupCommands:K,update:!0};return{commands:[va(await Jt(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",Vt]],cleanupCommands:K}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(j)=>{let K=No(j);if(K.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(K.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:Qo,installCommands:()=>({commands:al()}),uninstallCommands:[["openclaw","plugins","uninstall",Rt,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
243
+ `)},opencode:{beforeInstall:ni,installCommands:[["opencode","plugin","-g","-f","cc-safety-net@latest"]]},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]}};function Nc(j,K=(te)=>te){try{let te=JSON.parse(K(Oc(j,"utf-8")));if(!te||typeof te!=="object"||Array.isArray(te))throw Error(`Settings file ${j} must be a JSON object`);return te}catch(te){if(te instanceof SyntaxError)throw Error(`Failed to parse ${j}: ${te.message}`);throw te}}function tg(j){let K=Ci(Vn(j),"settings.json");if(!Ri(K))return;let te=Nc(K,jt),re=te.enabledPlugins;if(!re||typeof re!=="object"||Array.isArray(re))return;if(re[Vt]!==!1)return;let oe=Oc(K,"utf-8"),ce=oe.replace(new RegExp(`("${Vt}"\\s*:\\s*)false`),"$1true");return re[Vt]=!0,Dt(K,ce!==oe?ce:`${JSON.stringify(te,null,2)}
244
+ `),`Enabled ${Vt} plugin in ${K}`}function ng(j){let K=ri(j);if(!Ri(K))return;let te=Nc(K);if(!Array.isArray(te.packages))return;let re=te.packages.find((oe)=>!!oe&&typeof oe==="object"&&!Array.isArray(oe)&&oi(oe.source)&&("extensions"in oe));if(!re)return;return delete re.extensions,Dt(K,`${JSON.stringify(te,null,2)}
245
+ `),`Enabled npm:cc-safety-net extensions in ${K}`}function Tc(j,K){let te=At({label:K,booleans:Object.fromEntries(Wt.map((ce)=>[ce.target,[ce.flag]]))},j),re=te.errors[0];if(re)throw Error(re);let oe=Wt.filter((ce)=>te.flags[ce.target]).map((ce)=>ce.target);if(oe.length!==1)throw Error(`Choose exactly one ${K} target: ${Wt.map((ce)=>ce.flag).join(", ")}`);return oe[0]}async function Mc(j,K=xn){let[te,re,oe]=await Promise.all([K(["amp","plugins","list"],30000),K(["codex","plugin","list"],30000),K(["copilot","--binary-version"])]);return{codexPluginListOutput:re,hooks:Dn(j,process.cwd(),{ampPluginListOutput:te,codexPluginListOutput:re,copilotCliVersion:oe})}}async function rg(j,K,te=xn){let re=await Mc(j,te);return re.hooks.filter((oe)=>K==="install"?oe.configured:oe.detected||oe.inspectionStatus==="not-inspected").filter((oe)=>oe.platform!=="codex"||!Pi(re.codexPluginListOutput)||jc(re.codexPluginListOutput)).map((oe)=>oe.platform)}function og(j,K,te,re){if(te.length>0)return{finish:async()=>[Tc(te,K)]};if(!re.selectTargets&&!mi(re.input,re.output))return{finish:async()=>[Tc(te,K)]};let oe=re.detectConfiguredTargets??(()=>rg(j,K,re.fetchVersion)),ce=Promise.all([mc(re.probeTargets),oe()]);return{ready:ce,finish:async()=>{let[de,we]=await ce,xe=gc(de,{action:K,configuredTargets:we}),Ce=re.selectTargets?await re.selectTargets(K,$c(K,xe)):await Kl(K,$c(K,xe),{input:re.input,output:re.output});if(Ce==="update")return Ce;if(!Ce||Ce.length===0)return null;return Li(Ce)}}}async function vn(j,K,te=!1,re){let oe=Fc[j];oe.beforeInstall?.(K);let ce=typeof oe.installCommands==="function"?await oe.installCommands(K,re):{commands:oe.installCommands};return await Ko(ce.commands),await nl(ce.cleanupCommands??[]),[`${ce.update||te?"Updated":"Installed"} ${St(j)} integration`,oe.postInstallMessage].filter(Boolean).join(`
246
+ `)}async function On(j){let K=Fc[j];if(!K.uninstallCommands)throw Error(`${St(j)} uninstall is not supported`);return await Ko(K.uninstallCommands),`Uninstalled ${St(j)} integration`}function ig(j){let K=kl(j);return K.alreadyInstalled?`Uninstalled OpenCode plugin from ${K.path}`:`OpenCode plugin not installed in ${K.path}`}var sg={"antigravity-cli":{install:dc,uninstall:uc},cursor:{install:Aa,uninstall:_a},"grok-build":{install:Ua,uninstall:Ga},"kimi-code":{install:Ec,uninstall:Dc}};function on(j,K,te,re=!1){if(j==="install"&&!re)Kr(te);let oe=sg[K][j](te),ce=St(K),de=j!=="install"?"Uninstalled":re?"Updated":"Installed";return j==="install"&&oe.alreadyInstalled?re?`${ce} hook up to date in ${oe.path}`:`${ce} hook already installed in ${oe.path}`:j==="uninstall"&&!oe.alreadyInstalled?`${ce} hook not installed in ${oe.path}`:`${de} ${ce} hook ${j==="install"?"in":"from"} ${oe.path}`}var ag={amp:{install:oc,uninstall:ic,restartNote:'Amp personal plugins apply to every Amp session, including Orb threads. Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:za,uninstall:Ja,afterInstall:async(j)=>{let K=zo(j);return await Jt(["hermes","plugins","enable",Ft,"--no-allow-tool-override"]),!K},beforeUninstall:async(j)=>{Vo(j);try{await Jt(["hermes","plugins","disable",Ft])}catch(K){console.warn(`${K instanceof Error?K.message:String(K)}
247
247
  Removing the plugin files anyway; ${Ft} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function Yr(j,K,te,re=!1){let oe=ag[K];if(j==="uninstall")await oe.beforeUninstall?.(te);let ce=j==="install"?await oe.install(te):await oe.uninstall(te),de=j==="install"&&await oe.afterInstall?.(te),we=St(K),xe=!de&&(j==="install"&&ce.alreadyInstalled||j==="uninstall"&&!ce.alreadyInstalled);return[xe?j==="install"?`${we} plugin ${re?"up to date":"already installed"} at ${ce.path}`:`${we} plugin not installed at ${ce.path}`:`${j!=="install"?"Uninstalled":re?"Updated":"Installed"} ${we} plugin ${j==="install"?"at":"from"} ${ce.path}`,xe?void 0:oe.restartNote].filter(Boolean).join(`
248
248
  `)}var lg={amp:{install:(j,K)=>Yr("install","amp",j,K),uninstall:(j)=>Yr("uninstall","amp",j)},"antigravity-cli":{install:(j,K)=>on("install","antigravity-cli",j,K),uninstall:(j)=>on("uninstall","antigravity-cli",j)},"claude-code":{install:(j,K)=>vn("claude-code",j,K),uninstall:()=>On("claude-code")},codex:{install:(j,K,te)=>vn("codex",j,K,te),uninstall:()=>On("codex")},"copilot-cli":{install:async(j,K)=>[await vn("copilot-cli",j,K),tg(j)].filter(Boolean).join(`
249
- `),uninstall:()=>On("copilot-cli")},cursor:{install:(j,K)=>on("install","cursor",j,K),uninstall:(j)=>on("uninstall","cursor",j)},"gemini-cli":{install:(j,K)=>vn("gemini-cli",j,K),uninstall:()=>On("gemini-cli")},"grok-build":{install:(j,K)=>on("install","grok-build",j,K),uninstall:(j)=>on("uninstall","grok-build",j)},"hermes-agent":{install:(j,K)=>{if(!K)Kr(j);return Yr("install","hermes-agent",j,K)},uninstall:(j)=>Yr("uninstall","hermes-agent",j)},"kimi-code":{install:(j,K)=>on("install","kimi-code",j,K),uninstall:(j)=>on("uninstall","kimi-code",j)},openclaw:{install:async(j,K)=>{let te=await vn("openclaw",j,K);return await al(),te},uninstall:(j)=>(Xo(j),On("openclaw"))},opencode:{install:async(j,K)=>{let te=await vn("opencode",j,K);return await bl(j),te},uninstall:(j)=>ig(j)},pi:{install:async(j,K)=>[await vn("pi",j,K),ng(j)].filter(Boolean).join(`
249
+ `),uninstall:()=>On("copilot-cli")},cursor:{install:(j,K)=>on("install","cursor",j,K),uninstall:(j)=>on("uninstall","cursor",j)},"gemini-cli":{install:(j,K)=>vn("gemini-cli",j,K),uninstall:()=>On("gemini-cli")},"grok-build":{install:(j,K)=>on("install","grok-build",j,K),uninstall:(j)=>on("uninstall","grok-build",j)},"hermes-agent":{install:(j,K)=>{if(!K)Kr(j);return Yr("install","hermes-agent",j,K)},uninstall:(j)=>Yr("uninstall","hermes-agent",j)},"kimi-code":{install:(j,K)=>on("install","kimi-code",j,K),uninstall:(j)=>on("uninstall","kimi-code",j)},openclaw:{install:async(j,K)=>{let te=await vn("openclaw",j,K);return await ll(),te},uninstall:(j)=>(Qo(j),On("openclaw"))},opencode:{install:async(j,K)=>{let te=await vn("opencode",j,K);return await Ll(j),te},uninstall:(j)=>ig(j)},pi:{install:async(j,K)=>[await vn("pi",j,K),ng(j)].filter(Boolean).join(`
250
250
  `),uninstall:()=>On("pi")}},Ic=["Install CC Safety Net as a native Kimi Code plugin:",""," 1. Start Kimi Code and run: /plugins install https://github.com/kenryu42/cc-safety-net"," Confirm the trust prompt; it defaults to cancel."," 2. Run /reload, or start a new session.","","Note: Kimi Code hooks are fail-open. When the hook process cannot start, crashes, or times","out, Kimi Code allows the tool call."].join(`
251
251
  `);function cg(j){if(Yn({environment:j,cwd:process.cwd()}).status!=="configured")return Ic;return[Ic,"",bt.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
252
252
  `))].join(`
253
- `)}function $c(j,K){return K.map((te)=>j==="install"&&te.target==="kimi-code"&&te.unavailableReason==="already installed"?{...te,available:!0,unavailableReason:void 0,label:`${te.label} (global hook installed)`}:te)}function dg(j,K){if(j.selectKimiInstallMethod)return j.selectKimiInstallMethod();if(!fi(j.input,j.output))return Promise.resolve("global-hook");return Jl({input:j.input,output:j.output,globalHookInstalled:Yn({environment:K,cwd:process.cwd()}).status==="configured"})}async function Hc(j,K,te,re=!1,oe){return lg[K][j](te,re,oe)}function ug(j){let K=At({label:"update"},j).errors[0];if(K)throw Error(K)}async function pg(j,K=xn){let te=await Mc(j,K),re=ki(Vn(j),"installed-plugins");return{targets:vi([...te.hooks.filter((ce)=>ce.platform!=="copilot-cli"&&ce.detected).map((ce)=>ce.platform),...[Er,fa,pa].flatMap((ce)=>Ci(ki(re,...ce))?["copilot-cli"]:[]),...Sr(j,xi)?["claude-code"]:[],...Si(te.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:te.codexPluginListOutput}}async function fg(j){let K=l(),te=j.output??process.stdout,re=(j.scriptPath??process.argv[1]??"").split(/[\\/]/),oe=re.find((at)=>/^bunx-\d+-/.test(at)),ce=oe!==void 0||re.includes("_npx")?null:(j.checkLatestVersion??tn)(),de=async()=>{let at=ce&&await ce;if(at?.updateAvailable)te.write(`
253
+ `)}function $c(j,K){return K.map((te)=>j==="install"&&te.target==="kimi-code"&&te.unavailableReason==="already installed"?{...te,available:!0,unavailableReason:void 0,label:`${te.label} (global hook installed)`}:te)}function dg(j,K){if(j.selectKimiInstallMethod)return j.selectKimiInstallMethod();if(!mi(j.input,j.output))return Promise.resolve("global-hook");return Wl({input:j.input,output:j.output,globalHookInstalled:Yn({environment:K,cwd:process.cwd()}).status==="configured"})}async function Hc(j,K,te,re=!1,oe){return lg[K][j](te,re,oe)}function ug(j){let K=At({label:"update"},j).errors[0];if(K)throw Error(K)}async function pg(j,K=xn){let te=await Mc(j,K),re=Ci(Vn(j),"installed-plugins");return{targets:Li([...te.hooks.filter((ce)=>ce.platform!=="copilot-cli"&&ce.detected).map((ce)=>ce.platform),...[Er,ga,ma].flatMap((ce)=>Ri(Ci(re,...ce))?["copilot-cli"]:[]),...Sr(j,Si)?["claude-code"]:[],...Pi(te.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:te.codexPluginListOutput}}async function fg(j){let K=l(),te=j.output??process.stdout,re=(j.scriptPath??process.argv[1]??"").split(/[\\/]/),oe=re.find((at)=>/^bunx-\d+-/.test(at)),ce=oe!==void 0||re.includes("_npx")?null:(j.checkLatestVersion??nn)(),de=async()=>{let at=ce&&await ce;if(at?.updateAvailable)te.write(`
254
254
  Update available: cc-safety-net ${at.currentVersion} → ${at.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
255
- `)},we=pg(K,j.fetchVersion??xn).then(async(at)=>{let mt=new Set(at.targets);return{targets:at.targets,codexPluginListOutput:at.codexPluginListOutput,available:new Map(await Promise.all(Wt.filter((it)=>mt.has(it.target)&&Ac.has(it.target)).map(async(it)=>[it.target,await bi(it.probeCommand)])))}}),xe=await Bn(j.showBanner??!0,()=>({ready:we,finish:()=>we}),()=>Gn({input:j.input??process.stdin,output:te}),{loadingMessage:"Checking installed integrations…",output:te}),Ce=await Promise.resolve().then(()=>(pc(K.tmpdir,process.platform,oe),null)).catch((at)=>or(at));if(xe.targets.length===0){if(te.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),Ce!==null)console.error(Ce);return await de(),Ce===null?0:1}let Se=xe.targets.some((at)=>_c.has(at))?await Promise.resolve().then(()=>(Kr(K),null)).catch((at)=>or(at)):null,Ne=await kr(Promise.all(xe.targets.map((at)=>{if(Ac.has(at)&&!xe.available.get(at))return Promise.resolve({message:`${St(at)} not found; skipped`,failed:!1});if(Se!==null&&_c.has(at))return Promise.resolve({message:Se,failed:!0});return Hc("install",at,K,!0,xe.codexPluginListOutput).then((mt)=>({message:mt,failed:!1}),(mt)=>({message:or(mt),failed:!0}))})),{loadingMessage:`Updating ${xe.targets.length} integration${xe.targets.length===1?"":"s"}…`,output:te}),He=Ce===null?Ne:[...Ne,{message:Ce,failed:!0}];return He.forEach((at)=>{at.failed?console.error(at.message):te.write(`${at.message}
256
- `)}),await de(),He.some((at)=>at.failed)?1:0}function Ri(j,K={}){return Promise.resolve().then(()=>ug(j)).then(()=>fg(K)).catch((te)=>(console.error(or(te)),1))}async function ir(j,K,te={}){try{let re=l(),oe=await Bn(!0,()=>og(re,j,K,te),()=>Gn({input:te.input??process.stdin,output:te.output??process.stdout}),{loadingMessage:j==="install"?"Checking available integrations…":"Checking installed integrations…",output:te.output??process.stdout});if(!oe)return(te.output??process.stdout).write(`Cancelled: nothing was ${j}ed.
257
- `),0;if(oe==="update")return(te.runUpdate??(()=>Ri([],{fetchVersion:te.fetchVersion,input:te.input,output:te.output,showBanner:!1})))();let ce=te.output??process.stdout;return await fc(oe,async(de)=>{if(de==="kimi-code"&&j==="install"){let xe=await dg(te,re);if(xe===null){ce.write(`Cancelled: Kimi Code integration was not installed.
255
+ `)},we=pg(K,j.fetchVersion??xn).then(async(at)=>{let mt=new Set(at.targets);return{targets:at.targets,codexPluginListOutput:at.codexPluginListOutput,available:new Map(await Promise.all(Wt.filter((it)=>mt.has(it.target)&&Ac.has(it.target)).map(async(it)=>[it.target,await wi(it.probeCommand)])))}}),xe=await Bn(j.showBanner??!0,()=>({ready:we,finish:()=>we}),()=>Gn({input:j.input??process.stdin,output:te}),{loadingMessage:"Checking installed integrations…",output:te}),Ce=await Promise.resolve().then(()=>(pc(K.tmpdir,process.platform,oe),null)).catch((at)=>or(at));if(xe.targets.length===0){if(te.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),Ce!==null)console.error(Ce);return await de(),Ce===null?0:1}let Se=xe.targets.some((at)=>_c.has(at))?await Promise.resolve().then(()=>(Kr(K),null)).catch((at)=>or(at)):null,Ne=await kr(Promise.all(xe.targets.map((at)=>{if(Ac.has(at)&&!xe.available.get(at))return Promise.resolve({message:`${St(at)} not found; skipped`,failed:!1});if(Se!==null&&_c.has(at))return Promise.resolve({message:Se,failed:!0});return Hc("install",at,K,!0,xe.codexPluginListOutput).then((mt)=>({message:mt,failed:!1}),(mt)=>({message:or(mt),failed:!0}))})),{loadingMessage:`Updating ${xe.targets.length} integration${xe.targets.length===1?"":"s"}…`,output:te}),He=Ce===null?Ne:[...Ne,{message:Ce,failed:!0}];return He.forEach((at)=>{at.failed?console.error(at.message):te.write(`${at.message}
256
+ `)}),await de(),He.some((at)=>at.failed)?1:0}function Ei(j,K={}){return Promise.resolve().then(()=>ug(j)).then(()=>fg(K)).catch((te)=>(console.error(or(te)),1))}async function ir(j,K,te={}){try{let re=l(),oe=await Bn(!0,()=>og(re,j,K,te),()=>Gn({input:te.input??process.stdin,output:te.output??process.stdout}),{loadingMessage:j==="install"?"Checking available integrations…":"Checking installed integrations…",output:te.output??process.stdout});if(!oe)return(te.output??process.stdout).write(`Cancelled: nothing was ${j}ed.
257
+ `),0;if(oe==="update")return(te.runUpdate??(()=>Ei([],{fetchVersion:te.fetchVersion,input:te.input,output:te.output,showBanner:!1})))();let ce=te.output??process.stdout;return await fc(oe,async(de)=>{if(de==="kimi-code"&&j==="install"){let xe=await dg(te,re);if(xe===null){ce.write(`Cancelled: Kimi Code integration was not installed.
258
258
  `);return}if(xe==="plugin"){ce.write(`${cg(re)}
259
259
  `);return}}let we=await kr(Hc(j,de,re),{loadingMessage:`${j==="install"?"Installing":"Uninstalling"} ${St(de)} integration…`,output:ce});ce.write(`${we}
260
260
  `)}),0}catch(re){return console.error(or(re)),1}}function or(j){let K=j instanceof Error?j.message:String(j),te=typeof j==="object"&&j!==null&&"code"in j?j.code:null;if(te==="EACCES"||te==="EPERM")return`${K}
261
261
  Check file permissions for the target config file and parent directory.`;if(te==="ENOENT")return`${K}
262
262
  Check that the target config path and parent directory exist.`;if(te==="ENOTDIR")return`${K}
263
- Check that every parent path component is a directory.`;return K}import{mkdirSync as xg}from"node:fs";import{dirname as Cg}from"node:path";import{createInterface as Sg}from"node:readline";import{existsSync as Jc,readFileSync as vg}from"node:fs";var Bc=["version","safety","workflow","destructive_command_protection","secret_protection","audit"],mg=["standard","strict","paranoid"],qc="must be an object if provided",gg=`must be an integer between ${ye} and ${ve}`;function Ut(j,K){return se(nt(yg(j,K),Bc,(te)=>te.kind==="custom")," "," ")}function yg(j,K){if(!Ei(j))return[e([],"Config must be an object")];return[...j.version===1?[]:[e(["version"],"must be 1")],...jn(j.safety,["safety"],["level","overrides"],(te)=>[...te.level===void 0||typeof te.level==="string"&&mg.includes(te.level)?[]:[e(["safety","level"],'must be "standard", "strict", or "paranoid"')],...jn(te.overrides,["safety","overrides"],Uc,(re)=>Uc.flatMap((oe)=>Zr(re[oe],["safety","overrides",oe])))]),...jn(j.workflow,["workflow"],["worktree_mode"],(te)=>Zr(te.worktree_mode,["workflow","worktree_mode"])),...jn(j.destructive_command_protection,["destructive_command_protection"],["enabled","overrides","allow_paths"],(te)=>[...Zr(te.enabled,["destructive_command_protection","enabled"]),...Gc(te.overrides,["destructive_command_protection","overrides"],Pe,"destructive command"),...Pi(te.allow_paths,["destructive_command_protection","allow_paths"],Ae,K)]),...jn(j.secret_protection,["secret_protection"],["enabled","overrides","deny_paths","allow_paths"],(te)=>[...Zr(te.enabled,["secret_protection","enabled"]),...Gc(te.overrides,["secret_protection","overrides"],_e,"secret protection"),...Pi(te.deny_paths,["secret_protection","deny_paths"],Te,K),...Pi(te.allow_paths,["secret_protection","allow_paths"],Ie,K)]),...jn(j.audit,["audit"],["retention_days"],(te)=>hg(te.retention_days)?[]:[e(["audit","retention_days"],gg)]),...Object.keys(j).filter((te)=>!Bc.includes(te)).map((te)=>Vc([],te))]}var Uc=["fail_closed","paranoid_rm","paranoid_interpreters"];function jn(j,K,te,re){if(j===void 0)return[];if(!Ei(j))return[e(K,qc)];return[...re(j),...Object.keys(j).filter((oe)=>!te.includes(oe)).map((oe)=>Vc(K,oe))]}function Zr(j,K){return j===void 0||typeof j==="boolean"?[]:[e(K,"must be a boolean")]}function Gc(j,K,te,re){if(j===void 0)return[];if(!Ei(j))return[e(K,qc)];return[...Object.keys(j).filter((oe)=>!te.has(oe)).map((oe)=>({path:[...K,oe],message:`unknown ${re} rule id "${oe}"`,kind:"key"})),...Object.keys(j).filter((oe)=>j[oe]!=="on"&&j[oe]!=="off").map((oe)=>e([...K,oe],'must be "on" or "off"'))]}function Pi(j,K,te,re){if(j===void 0)return[];if(!Array.isArray(j))return[e(K,"must be an array of paths")];return j.flatMap((oe,ce)=>{if(typeof oe!=="string")return[e([...K,ce],"must be a non-empty path string")];let de=te(oe,re);return de===null?[]:[g([...K,ce],de)]})}function hg(j){if(j===void 0)return!0;if(typeof j!=="number"||!Number.isInteger(j))return!1;return j>=ye&&j<=ve}var Vc=(j,K)=>({path:j,message:K,kind:"unknownKeys"});function Ei(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function zc(j,K){return{"safety.level":j.safety.level,...Di("safety.overrides",j.safety.overrides),"workflow.worktree_mode":String(j.workflow.worktree_mode),"destructive_command_protection.enabled":String(j.destructive_command_protection.enabled),...Di("destructive_command_protection.overrides",j.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Ai(j.destructive_command_protection.allow_paths),"secret_protection.enabled":String(j.secret_protection.enabled),...Di("secret_protection.overrides",j.secret_protection.overrides),"secret_protection.deny_paths":Ai(j.secret_protection.deny_paths),"secret_protection.allow_paths":Ai(j.secret_protection.allow_paths),...K?{"audit.retention_days":String(j.audit.retention_days)}:{}}}function Xr(j,K,te){let re=zc(j,te),oe=zc(K,te);return[...new Set([...Object.keys(re),...Object.keys(oe)])].flatMap((ce)=>re[ce]===oe[ce]?[]:[{field:ce,before:re[ce],after:oe[ce]}])}function sr(j,K){let te=d(j,K);if(!Jc(te))return{baseline:h(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,j.home),diagnostics:[]};let re=bn(te);return{baseline:h(re.value,j.home),diagnostics:re.errors.length>0?re.errors:Ut(re.value,j.home)}}function bn(j){if(!Jc(j))return{errors:[`${j}: file not found`]};try{return{value:JSON.parse(vg(j,"utf-8")),errors:[]}}catch(K){let te=K instanceof Error?K.message:String(K);return{errors:[`${j}: ${K instanceof SyntaxError?`Invalid JSON: ${te}`:te}`]}}}function Qr(j,K){let te=bg(j)?j:{};return{version:K.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((re)=>te[re]!==void 0).map((re)=>[re,te[re]]))}}function Di(j,K){return Object.fromEntries(Object.entries(K).flatMap(([te,re])=>re===void 0?[]:[[`${j}.${te}`,String(re)]]))}function Ai(j){return j.length===0?"(none)":j.join(", ")}function bg(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}import{chmodSync as Lg,existsSync as Wc,mkdirSync as wg,readFileSync as Kc}from"node:fs";import{dirname as kg}from"node:path";function Yc(j,K={}){let te=d(j,K);if(!Wc(te))return{path:te,exists:!1,raw:"",policy:z(),errors:[]};let re=Kc(te,"utf-8");if(!re.trim())return{path:te,exists:!0,raw:re,policy:z(),errors:["Config file is empty"]};try{let oe=JSON.parse(re),ce=Ut(oe,j.home);return{path:te,exists:!0,raw:re,policy:h(oe,j.home),errors:ce}}catch(oe){return{path:te,exists:!0,raw:re,policy:z(),errors:[`Invalid JSON: ${oe instanceof Error?oe.message:String(oe)}`]}}}function Xt(j,K,te={}){let re=d(j,te),oe=Ut(K,j.home),ce=oe.length>0?z():h(K,j.home);if(oe.length>0)return{path:re,policy:ce,errors:oe};return wg(kg(re),{recursive:!0,mode:448}),y(D(re),`${JSON.stringify(ce,null,2)}
264
- `,384),Lg(re,384),{path:re,policy:ce,errors:[]}}function Zc(j,K){let te=Ut(K,j.home);if(te.length>0)return{errors:te};return{preview:Ge(h(K,j.home),j.env),errors:[]}}function Xc(j,K={}){let te=d(j,K);if(!Wc(te))return Xt(j,Q,K);let re=Kc(te,"utf-8");if(!re.trim())return Xt(j,Q,K);try{return Xt(j,h(JSON.parse(re),j.home),K)}catch{return Xt(j,Q,K)}}var Qc=new Set(["check","apply"]),ed="(unset)";async function nd(j,K,te={}){let re=At({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},K),oe=re.positionals[0],ce=[...re.errors,...oe&&!Qc.has(oe)?[`Unknown policy subcommand: ${oe}`]:[],...oe&&Qc.has(oe)&&!re.positionals[1]?[`policy ${oe} requires a file`]:[],...re.positionals.slice(2).map((mt)=>`Unexpected policy argument: ${mt}`)];if(ce.length>0){for(let mt of ce)console.error(mt);return 1}let de=re.positionals[1];if(!oe||!de)return _n(pr,console.error),1;let we=re.flags.global?d(j):w(te.cwd??process.cwd()),xe=bn(de),Ce=[...xe.errors,...Ut(xe.value,j.home).map((mt)=>`${de}: ${mt}`),...!re.flags.global&&Eg(xe.value)&&xe.value.audit!==void 0?[`${de}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(Ce.length>0){for(let mt of Ce)console.error(mt);return 1}let Se=h(xe.value,j.home);if(console.log(`Scope: ${re.flags.global?"user":"project"} (${we})`),console.log(`Proposal: ${de}`),re.flags.global)td(h(bn(we).value,j.home),Se,!0);if(!re.flags.global){let mt=sr(j).baseline;console.log("Effective policy (user + project merged):"),td(X(mt,le(bn(we).value,j.home).policy).policy,X(mt,le(xe.value,j.home).policy).policy,!1)}if(oe==="check")return 0;let Ne=te.input??process.stdin,He=te.output??process.stdout;if(!Ne.isTTY||!He.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${de}${re.flags.global?" --global":""}`),1;if(!await Rg(`Apply this policy to ${we}? [y/N] `,Ne,He))return console.log("Cancelled; nothing was written."),0;return Pg(j,we,xe.value,Se,re.flags.global),console.log(`Policy applied: ${we}`),0}function Rg(j,K,te){let re=Sg({input:K,output:te,terminal:!1});return new Promise((oe)=>{re.once("close",()=>oe(!1)),re.question(j,(ce)=>{oe(/^y(es)?$/i.test(ce.trim())),re.close()})})}function Pg(j,K,te,re,oe){if(oe){Xt(j,re);return}xg(Cg(K),{recursive:!0}),It(K,Qr(te,re))}function td(j,K,te){let re=Xr(j,K,te);if(re.length===0){console.log("No changes.");return}console.log(`Changes (${re.length}):`);for(let oe of re)console.log(` ${oe.field}: ${oe.before??ed} -> ${oe.after??ed}`)}function Eg(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}import{join as Gy}from"node:path";var rd="# 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 eo(j,K){if(!j.ok){ld(j);return}sd(j,K)}function id(j,K,te){if(j.ok)console.log(te);if(!j.add){eo(j,`Added rulebook source: ${K}`);return}if(!j.ok){ld(j);return}if(j.add.added.length>0)console.log(`Added ${j.add.added.length} ${j.add.added.length===1?"rulebook":"rulebooks"} from ${j.add.source} at ${j.add.ref}:`),j.add.added.forEach((re)=>{console.log(` - ${re}`)});if(j.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${j.add.source} at ${j.add.ref}: ${j.add.alreadyConfigured.join(", ")}`);if(j.add.commits.length>0)console.log(`Vendored at ${j.add.commits.map((re)=>re.slice(0,7)).join(", ")}.`);sd(j,"Rule config updated.")}function sd(j,K){for(let te of j.changes??[])console.log(te);console.log(K),console.log(""),Dg(j.entries)}function Dg(j){if(j.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${j.length}):`);for(let K of j)console.log(` - ${K.name} ${K.version} (${Ag(K.ruleCount)})`),console.log(` Source: ${K.spec}`)}function Ag(j){return`${j} ${j===1?"rule":"rules"}`}function ad(j){Ln("Active sources",j.rulebooks,(K)=>[`[${K.source}] ${K.name} ${K.version}`,` Source: ${K.spec}`]),Ln("Active rules",j.rules,(K)=>[`[${Tg(j,K.name)}] ${K.name}`,..._g(K),` Reason: ${K.reason}`]),Ln("Disabled rules",od(j,"off"),(K)=>[K.key]),Ln("Reason overrides",od(j,"reason"),(K)=>[K.key,` Reason: ${K.value.reason}`]),Ln("Transparent wrappers",j.transparent_wrappers,(K)=>[K]),Ln("Issues",j.errors,(K)=>[K]),Ln("Warnings",j.warnings,(K)=>[K])}function Ln(j,K,te){if(K.length===0){console.log(`${j}: (none)`);return}console.log(`${j} (${K.length}):`);for(let re of K){let[oe,...ce]=te(re);console.log(` - ${oe}`);for(let de of ce)console.log(` ${de}`)}}function _g(j){if(!j.match)return[` Command: ${j.subcommand?`${j.command} ${j.subcommand}`:j.command}`,` Block args: ${j.block_args.join(", ")}`];return[` Command: ${[j.command,...j.match.command_path].join(" ")}`,...j.match.any_args?[` Any args: ${j.match.any_args.join(", ")}`]:[],...j.match.exclude_args?[` Exclude args: ${j.match.exclude_args.join(", ")}`]:[]]}function Tg(j,K){return j.rulebooks.find((te)=>te.rules.includes(K))?.source??"project"}function od(j,K){return Object.entries({...j.userConfig?.overrides??{},...j.projectConfig?.overrides??{}}).filter((te)=>{if(K==="off")return te[1]==="off";return!!te[1]&&typeof te[1]==="object"}).map(([te,re])=>({key:te,value:re}))}function ld(j){for(let K of j.errors)console.error(K)}import{dirname as _d,join as lo}from"node:path";import{join as ji,resolve as qg}from"node:path";function _i(j){let K=m(j);if(K.errors.length>0)return{ok:!1,result:{ok:!1,errors:K.errors,entries:[]}};return{ok:!0,config:K.config??pt}}function cd(j,K=[]){It(j,{version:1,rules:K,overrides:{},transparent_wrappers:[]})}function dd(j,K="project-rules"){It(j,{rulebook_version:1,name:K,version:"1.0.0",description:K==="project-rules"?"Project-specific CC Safety Net rules.":"User-specific CC Safety Net rules.",author:K==="project-rules"?"project":"user",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 oo}from"node:path";var Ig="custom.";function to(j){if(j.rulebook_version!==2)return[];let K=j.rules.map((te)=>({name:te.name,command:te.command,block_args:[],match:te.match,reason:te.reason,intent:te.intent}));return(j.tests??[]).flatMap((te,re)=>{let oe=Ti(v(te.command));if(oe.length===0)return[`tests[${re}]: could not parse fixture command: ${te.command}`];let ce=oe.reduce((de,we)=>de??E(we,K)?.id.slice(Ig.length),void 0);if(te.expect==="blocked"){if(ce===te.rule)return[];let de=ce?`"${ce}" matched first`:"no rule matched";return[`tests[${re}]: expected "${te.rule}" to block "${te.command}" but ${de}`]}return ce?[`tests[${re}]: expected "${te.command}" to be allowed but "${ce}" matched`]:[]})}function Ti(j){return j.nodes.flatMap((K)=>{if(K.kind==="group"||K.kind==="function")return Ti(K.body);if(K.kind!=="command")return[];let te=be(ee(K.dialect,K.words)).words.map(t);return[...te.length>0?[te]:[],...K.nested.flatMap((re)=>Ti(re))]})}var Ii="Rule synchronization exceeds CC Safety Net's safe resource limits.",no=Object.freeze({maxSources:J,concurrency:4,maxRequests:131,maxResponseBytes:67108864});function ro(j={}){return{requests:0,responseBytes:0,maxRequests:j.maxRequests??no.maxRequests,maxResponseBytes:j.maxResponseBytes??no.maxResponseBytes}}function Qt(j){return{controller:new AbortController,budget:ro(),resolveUrl:j}}function ud(j){return j instanceof Error&&j.message===Ii}function pd(j){if(j.requests>=j.maxRequests)throw Error(Ii);j.requests++}function fd(j,K){if(K>j.maxResponseBytes-j.responseBytes)throw j.responseBytes+=K,Error(Ii);j.responseBytes+=K}var yd=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function md(j,K,te=S(oo(oo(K)),"rules policy"),re=Qt()){if(x(j))return Fg(j,re);return jg(j,K,te)}async function hd(j,K,te,re,oe,ce){if(!x(j))return md(j,K,te,re);let de=oe?null:$g(j,K,te);if(de)return de;if(!oe&&!ce)throw Error(`${j} is not vendored; run rule update ${j} to vendor it`);return md(j,K,te,re)}function $g(j,K,te=S(oo(oo(K)),"rules policy")){let re=O(j),oe=N(K,re.name),ce=r(s(te,oe));if(ce===null)return null;let de=ae($i(ce,`Invalid rulebook ${oe}.`));if(de.name!==re.name)throw Error(`rulebook name "${de.name}" in ${oe} must match "${re.name}"`);return{spec:j,rulebook:de,content:ce}}async function vd(j,K={}){if(!Y(j))throw Error(`Invalid GitHub repository source: ${j}`);let[te,re]=j.split("/");if(!te||!re)throw Error(`Invalid GitHub repository source: ${j}`);if(K.ref!==void 0&&!ie(K.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${K.ref}`);let oe=K.operation??Qt(),ce=K.ref??await Og(te,re,j,oe),de=await Ld(te,re,ce,j,oe),we=await io(`https://api.github.com/repos/${te}/${re}/git/trees/${de}?recursive=1`,"tree",oe),xe=we.response;if(!xe.ok)throw Error(`Failed to inspect ${j}: GitHub tree returned ${xe.status}`);let Ce=JSON.parse(we.content);if(!Array.isArray(Ce?.tree))throw Error(`Failed to inspect ${j}: unexpected GitHub tree response`);let Se=Ce.tree,Ne=[...new Set(Se.flatMap((He)=>{if(!He||typeof He!=="object")return[];let at=He;if(at.type!=="blob"||typeof at.path!=="string")return[];let mt=at.path.match(dt);return mt?.[1]?[mt[1]]:[]}))].sort();if(Ne.length===0)throw Error(`No rulebooks found in ${j} under ${fe}/`);return{source:j,owner:te,repo:re,ref:ce,commit:de,names:Ne}}async function Og(j,K,te,re){let oe=await io(`https://api.github.com/repos/${j}/${K}`,"metadata",re),ce=oe.response;if(!ce.ok)throw Error(`Failed to inspect ${te}: GitHub returned ${ce.status}`);let we=JSON.parse(oe.content)?.default_branch;if(typeof we!=="string"||we==="")throw Error(`Failed to inspect ${te}: missing default branch`);if(!ie(we))throw Error(`GitHub returned an invalid default branch: ${we}`);return we}function jg(j,K,te){ut(j);let re=N(K,j),oe=r(s(te,re));if(oe===null)throw Error(`Rulebook source not found: ${j}`);let ce=bd($i(oe,"Invalid local rulebook source."));if(ce.name!==j)throw Error(`rulebook name "${ce.name}" must match local source "${j}"`);return{spec:j,rulebook:ce,content:oe}}async function Fg(j,K){let te=O(j),re=await Ld(te.owner,te.repo,te.ref,j,K),oe=await io(`https://raw.githubusercontent.com/${te.owner}/${te.repo}/${re}/${te.path}`,"raw",K),ce=oe.response;if(!ce.ok)throw Error(`Failed to fetch ${j}: GitHub raw returned ${ce.status}`);let de=oe.content,we=bd($i(de,"Invalid GitHub rulebook response."));if(we.name!==te.name)throw Error(`rulebook name "${we.name}" must match GitHub source "${te.name}"`);return{spec:j,rulebook:we,content:de}}function bd(j){let K=ae(j),te=to(K);if(te.length>0)throw Error(te.join("; "));return K}function $i(j,K){try{return JSON.parse(j)}catch{throw Error(K)}}async function Ld(j,K,te,re,oe){let ce=await io(`https://api.github.com/repos/${j}/${K}/commits/${encodeURIComponent(te)}`,"commit",oe),de=ce.response;if(!de.ok)throw Error(`Failed to resolve ${re}: GitHub returned ${de.status}`);let we=JSON.parse(ce.content);if(typeof we?.sha!=="string"||we.sha==="")throw Error(`Failed to resolve commit for ${re}`);return we.sha}async function Ng(j,K,te={}){if(te.signal?.aborted)throw te.signal.reason;let re=te.budget??ro(),oe=new AbortController,ce=()=>oe.abort(te.signal?.reason);te.signal?.addEventListener("abort",ce,{once:!0});let de=!1,we=setTimeout(()=>{if(oe.signal.aborted)return;de=!0,oe.abort()},te.timeoutMs??yd.timeoutMs);try{if(te.signal?.aborted)throw te.signal.reason;pd(re);let xe=await(te.fetch??fetch)(j,{signal:oe.signal,redirect:"error"});if(!xe.ok)return wd(xe),{response:xe,content:""};return{response:xe,content:await Mg(xe,K,re,()=>oe.abort())}}catch(xe){if(de)throw Error("GitHub request timed out",{cause:xe});if(te.signal?.aborted)throw te.signal.reason;throw xe}finally{clearTimeout(we),te.signal?.removeEventListener("abort",ce)}}function io(j,K,te){return Ng(te.resolveUrl?.(j)??j,K,{budget:te.budget,signal:te.controller.signal})}async function Mg(j,K,te=ro(),re){let oe=yd[`${K}Bytes`],ce=Number(j.headers.get("content-length"));if(Number.isFinite(ce)&&ce>oe)throw wd(j),Error(`GitHub ${K} response exceeds ${oe} bytes`);if(!j.body)return"";let de=j.body.getReader(),we=[],xe=0;while(!0){let Ce=await de.read();if(Ce.done)break;try{fd(te,Ce.value.byteLength)}catch(Se){throw re?.(),gd(de),Se}if(xe+=Ce.value.byteLength,xe>oe)throw re?.(),gd(de),Error(`GitHub ${K} response exceeds ${oe} bytes`);we.push(Buffer.from(Ce.value))}return Buffer.concat(we,xe).toString("utf-8")}function wd(j){if(!j.body)return;kd(()=>j.body?.cancel())}function gd(j){kd(()=>j.cancel())}function kd(j){try{Promise.resolve(j()).catch(()=>{})}catch{}}var Hg=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function xd(j,K){let te=Rd(j.rules,K);if(te.length>0)return{ok:!0,specs:te};return Sd(j.rules,K)}function Cd(j,K){let te=Rd(j,K);if(te.length>0)return{ok:!0,specs:te};let re=Gg(j,K);if(re.length>0)return{ok:!0,specs:re};let oe=Bg(j,K);if(!oe.ok)return oe;if(oe.specs.length>0)return{ok:!0,specs:oe.specs};return Sd(j,K)}function Sd(j,K){let te=j.filter((re)=>Oi(re)?.name===K);if(te.length===1)return{ok:!0,specs:te};return Ug(K,te)}function Ug(j,K){return{ok:!1,result:{ok:!1,errors:K.length===0?[`No configured rulebook matches ${j}`]:[`Ambiguous rulebook match ${j}: ${K.join(", ")}`],entries:[]}}}function Rd(j,K){return j.filter((te)=>te===K)}function Gg(j,K){let te=K.match(Hg),re=te?.[1],oe=te?.[2],ce=te?.[3];if(!re||!oe||!ce||!ie(ce))return[];return Pd(j,(de)=>de.owner===re&&de.repo===oe&&de.ref===ce)}function Bg(j,K){if(!Y(K))return{ok:!0,specs:[]};let[te,re]=K.split("/"),oe=Pd(j,(de)=>de.owner===te&&de.repo===re);if(new Set(oe.map((de)=>Oi(de)?.ref).filter((de)=>!!de)).size<2)return{ok:!0,specs:oe};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${K}. Use an explicit ref:`,` cc-safety-net rule remove ${K}#<ref>`],entries:[]}}}function Oi(j){try{return O(j)}catch{return null}}function Pd(j,K){return j.filter((te)=>{let re=Oi(te);return re?K(re):!1})}async function ao(j,K={}){let te=Fi(K);return Vg(j,te,await so(j,te,Qt()))}function Vg(j,K,te){if(!te.ok)return te;let re=$t(j,K),oe=[...new Set(W(re.configPath,re.filesystemScope))];if(oe.length===0)return te;return{ok:!1,errors:oe,entries:te.entries}}async function so(j,K,te,re={},oe=new Set,ce=new Set){try{let de=$t(j,K),we=_i(de.configTarget);if(!we.ok)return we.result;let xe=we.config;if(K.check)return ay(xe,de,K);let Ce=K.only?xd(xe,K.only):{ok:!0,specs:xe.rules};if(!Ce.ok)return Ce.result;let Se=new Set([...K.refresh?Ce.specs:[],...oe]),Ne=(Lt)=>hd(Lt,de.configDir,de.filesystemScope,te,Se.has(Lt),!K.refresh||Se.has(Lt)),He=await ny(xe.rules,K.refresh?(Lt)=>Ne(Lt).then((Ct)=>({ok:!0,item:Ct})).catch((Ct)=>{if(ud(Ct))throw Ct;return{ok:!1,spec:Lt,message:Ct instanceof Error?Ct.message:String(Ct)}}):async(Lt)=>({ok:!0,item:await Ne(Lt)}),te),at=He.filter((Lt)=>!Lt.ok),mt=He.filter((Lt)=>Lt.ok).map((Lt)=>Lt.item),it=mt.flatMap((Lt)=>zg(Lt,xe.rules)),gt=mt.flatMap((Lt)=>Jg(Lt,ce,de)),ht=new Set([...it,...gt].map((Lt)=>Lt.spec)),vt=[...at,...it,...gt],yt=[],kt=Kg(yt,()=>mt.flatMap((Lt)=>ht.has(Lt.spec)||vt.length>0&&ce.has(Lt.spec)?[]:Wg(Lt,de,re,yt)));return{ok:vt.length===0,errors:vt.map((Lt)=>`Failed to update ${Lt.spec}: ${Lt.message}`),entries:mt.map(Zg),changes:kt}}catch(de){return lr(de)}}function zg(j,K){if(!x(j.spec))return[];let te=je(j.spec),re=K.filter((oe)=>oe!==j.spec&&je(oe).toLowerCase()===te.toLowerCase());if(re.length===0)return[];return[{ok:!1,spec:j.spec,message:`rulebook name "${te}" is also claimed by ${re.join(", ")}; rename one of them`}]}function Jg(j,K,te){if(!K.has(j.spec)||!x(j.spec))return[];let re=N(te.configDir,j.rulebook.name),oe=r(s(te.filesystemScope,re));if(oe===null||oe===j.content)return[];return[{ok:!1,spec:j.spec,message:`${re} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Wg(j,K,te,re){if(!x(j.spec))return[];let oe=N(K.configDir,j.rulebook.name),ce=s(K.filesystemScope,oe),de=r(ce);if(de===j.content)return[];return re?.push({target:ce,previous:de}),y(ce,j.content,void 0,te._testAfterPolicyRename),Yg(j,de)}function Kg(j,K){try{return K()}catch(te){for(let re of[...j].reverse()){if(re.previous===null){G(re.target);continue}y(re.target,re.previous)}throw te}}function Yg(j,K){if(K===null)return[`Vendored ${j.spec} (${j.rulebook.version})`];let te=he(K),re="problem"in te?null:te.rulebook,oe=new Map(re?.rules.map((de)=>[de.name,JSON.stringify(de)])??[]),ce=new Set(j.rulebook.rules.map((de)=>de.name));return[`Updated ${j.spec} (${re?.version??"unreadable"} -> ${j.rulebook.version})`,...[...ce].filter((de)=>!oe.has(de)).map((de)=>` + ${de}`),...[...oe.keys()].filter((de)=>!ce.has(de)).map((de)=>` - ${de}`),...j.rulebook.rules.filter((de)=>{let we=oe.get(de.name);return we!==void 0&&we!==JSON.stringify(de)}).map((de)=>` ~ ${de.name}`)]}function Zg(j){return{spec:j.spec,name:j.rulebook.name,version:j.rulebook.version,ruleCount:j.rulebook.rules.length}}async function Ed(j,K,te={}){return Xg(j,K,oy(te),Qt())}async function Xg(j,K,te,re,oe={}){let ce=null,de=!1;try{let we=$t(j,te),xe=r(we.configTarget);ce={target:we.configTarget,content:xe};let Ce=_i(we.configTarget);if(!Ce.ok)return Ce.result;let Se=Ce.config,Ne=Y(K);Qg(K,te,Ne);let He=Ne?await vd(K,{ref:te.ref,operation:re}):null,at=He?ey(He,te.rulebooks):[],mt=He?at.map((yt)=>ty(Se.rules,He,yt)??`${K}#${He.ref}/${yt}`):[K],it=mt.filter((yt)=>!Se.rules.includes(yt)),gt=[...Se.rules,...it];if(gt.length>J)return ry();if(gt.length!==Se.rules.length)de=!0,It(we.configTarget,{version:1,rules:gt,overrides:Se.overrides??{},transparent_wrappers:Se.transparent_wrappers??[]},void 0,oe._testAfterPolicyRename);let ht=await so(j,te,re,oe,new Set(it),new Set(it));if(!ht.ok)ar(we.configTarget,xe);if(!ht.ok||!He)return ht;let vt=at.filter((yt,kt)=>it.includes(mt[kt]??""));return{...ht,add:{source:K,ref:He.ref,selected:at,added:vt,alreadyConfigured:at.filter((yt)=>!vt.includes(yt)),commits:it.length>0?[He.commit]:[]}}}catch(we){if(de&&ce)try{ar(ce.target,ce.content)}catch(xe){return lr(xe)}return lr(we)}}function Qg(j,K,te){if(!te&&K.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!te&&K.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${j}`);if(K.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let re=K.rulebooks?.filter((oe)=>!c.test(oe))??[];if(re.length>0)throw Error(`Invalid rulebook names: ${re.join(", ")}`)}function ey(j,K){let te=K?[...new Set(K)]:j.names,re=te.filter((oe)=>!j.names.includes(oe));if(re.length>0)throw Error(`Rulebooks not found in ${j.source} at ${j.ref}: ${re.join(", ")}
265
- Available rulebooks: ${j.names.join(", ")}`);return te}function ty(j,K,te){let re=`${K.source}#${K.ref}/${te}`;if(j.includes(re))return re;let oe=`${K.source}#${K.commit}/${te}`;return j.find((ce)=>ce===oe)}async function ny(j,K,te=Qt()){if(j.length>J)throw Error(ge);let re=Array(j.length),oe=0,ce,de=Array.from({length:Math.min(j.length,no.concurrency)},async()=>{while(!ce){let we=oe;if(we>=j.length)return;oe++;try{re[we]=await K(j[we],we,te.controller.signal)}catch(xe){if(!ce)ce={value:xe},oe=j.length,te.controller.abort(xe);return}}});if(await Promise.all(de),ce)throw ce.value;return re}function ry(){return{ok:!1,errors:[ge],entries:[]}}function Fi(j){return{cwd:j.cwd,userConfigDir:j.userConfigDir,userConfigPath:j.userConfigPath,projectConfigPath:j.projectConfigPath,global:j.global,check:j.check,only:j.only,refresh:j.refresh}}function oy(j){return{...Fi(j),ref:j.ref,rulebooks:j.rulebooks}}function iy(j){return{...Fi(j),deleteSource:j.deleteSource}}async function Dd(j,K,te={}){try{return await sy(j,K,iy(te),{})}catch(re){return lr(re)}}async function sy(j,K,te,re){let oe=$t(j,te),ce=m(oe.configTarget);if(ce.errors.length>0)return{ok:!1,errors:ce.errors,entries:[]};if(!ce.config)return{ok:!1,errors:[`No config found at ${oe.configPath}`],entries:[]};let de=Cd(ce.config.rules,K);if(!de.ok)return de.result;let we=te.deleteSource?ly(oe.configDir,de.specs,oe.filesystemScope):{ok:!0,dirs:[]};if(!we.ok)return we.result;let xe=r(oe.configTarget);if(xe===null)return lr(Error("Rules config is unavailable."));try{It(oe.configTarget,{version:1,rules:ce.config.rules.filter((Ne)=>!de.specs.includes(Ne)),overrides:ce.config.overrides??{},transparent_wrappers:ce.config.transparent_wrappers??[]},void 0,re._testAfterPolicyRename)}catch(Ne){throw ar(oe.configTarget,xe),Ne}let Ce=await so(j,te,Qt(),re);if(!Ce.ok)return ar(oe.configTarget,xe),Ce;let Se=cy(we.dirs,re,oe.filesystemScope);if(!Se.ok){ar(oe.configTarget,xe);let Ne=await so(j,te,Qt(),re);if(!Ne.ok)return{ok:!1,errors:[...Se.result.errors,...Ne.errors],entries:Ne.entries};return Se.result}return Ce}async function ay(j,K,te){let re=Re(j,K.configDir,te.global?"user":"project",K.filesystemScope);return{ok:re.errors.length===0&&re.warnings.length===0,errors:[...re.errors,...re.warnings],entries:re.entries}}function ly(j,K,te){let re=K.flatMap((we)=>c.test(we)?[]:["--delete-source can only delete local rulebook sources"]),oe=K.map((we)=>ji(j,we)),ce=re.length>0?[]:oe.flatMap((we)=>Ad(we,te)),de=[...re,...ce];return de.length>0?{ok:!1,result:{ok:!1,errors:de,entries:[]}}:{ok:!0,dirs:oe}}function Ad(j,K){let te=qg(j),re=s(K,te),oe=ue(re);if(!oe)return[`Local rulebook source directory not found: ${j}`];let ce=oe.find((de)=>de.name==="rulebook.json");if(!ce)return[`Local rulebook source directory is missing rulebook.json: ${j}`];if(ce.kind!=="file")throw new o(K.label);if(r(s(K,ji(te,"rulebook.json"))),oe.length>1)return[`Local rulebook source directory contains extra files: ${j}. delete manually if you really want to remove the directory.`];return[]}function cy(j,K,te){let re=j.flatMap((oe)=>{try{if(!ue(s(te,oe)))return[];let ce=Ad(oe,te);if(ce.length>0)return ce;return dy(oe,K,te),[]}catch(ce){return[`Failed to delete local rulebook source ${oe}: ${ce instanceof Error?ce.message:String(ce)}`]}});return re.length>0?{ok:!1,result:{ok:!1,errors:re,entries:[]}}:{ok:!0}}function dy(j,K,te){if(K._testDeleteLocalSourceDir){K._testDeleteLocalSourceDir(j);return}G(s(te,ji(j,pe))),ct(s(te,j))}function ar(j,K){if(K===null){G(j);return}y(j,K)}function lr(j){return{ok:!1,errors:[j instanceof Error?j.message:String(j)],entries:[]}}var uy=".safety-net.json",py="~/.cc-safety-net/config.json";async function $d(j,K){return[await Td(j,{legacyPath:zs({cwd:K.cwd}),configPath:A(K.cwd),defaultRulebookName:"project-rules",migratedFrom:uy,cleanup:K.cleanup,syncOptions:{cwd:K.cwd}}),await Td(j,{legacyPath:yr(j),configPath:T(j),defaultRulebookName:"user-rules",migratedFrom:py,cleanup:K.cleanup,syncOptions:{cwd:K.cwd,global:!0}})].every((re)=>re)?0:1}async function Td(j,K){let te=$t(j,K.syncOptions),re=s(te.filesystemScope,K.legacyPath),oe=r(re);if(oe===null)return console.log(`No legacy config found at ${K.legacyPath}`),!0;let ce=my(oe);if(!ce.ok){for(let at of ce.errors)console.error(at);return!1}let de=m(te.configTarget);if(de.errors.length>0){for(let at of de.errors)console.error(at);return!1}let we=de.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},xe=gy(_d(K.configPath),we.rules,K.defaultRulebookName,K.migratedFrom,te.filesystemScope),Ce=lo(_d(K.configPath),xe,"rulebook.json"),Se=s(te.filesystemScope,Ce),Ne=[Id(te.configTarget),Id(Se)],He=await fy(j,K,te.configTarget,Se,xe,ce.config.rules,we.rules.includes(xe)?we.rules:[...we.rules,xe],we.overrides??{},we.transparent_wrappers??[]);if(!He.ok){vy(Ne);for(let at of He.errors)console.error(at);return!1}if(!K.cleanup)return console.log(`Migrated legacy config at ${K.legacyPath}. Legacy file is no longer used.`),!0;if(!hy(te.configTarget,Se,xe,K.migratedFrom,ce.config.rules))return console.error(`Migration cleanup verification failed for ${K.legacyPath}`),!1;return G(re),console.log(`Deleted legacy config at ${K.legacyPath}`),!0}async function fy(j,K,te,re,oe,ce,de,we,xe){try{return It(te,{version:1,rules:de,overrides:we,transparent_wrappers:xe}),It(re,yy(oe,K.migratedFrom,ce)),await ao(j,K.syncOptions)}catch(Ce){return{ok:!1,errors:[Ce instanceof Error?Ce.message:String(Ce)]}}}function my(j){try{let K=JSON.parse(j),te=vo(K);if(te.errors.length>0)return{ok:!1,errors:te.errors};return{ok:!0,config:{version:1,rules:K.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function gy(j,K,te,re,oe){let ce=K.find((de)=>by(s(oe,lo(j,de,"rulebook.json")))===re);if(ce)return ce;if(r(s(oe,lo(j,te,"rulebook.json")))===null)return te;for(let de=2;;de++){let we=`${te}-${de}`;if(r(s(oe,lo(j,we,"rulebook.json")))===null)return we}}function yy(j,K,te){return{rulebook_version:1,name:j,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:K,allowed_commands:[...new Set(te.map((re)=>re.command))],rules:te,tests:te.map((re)=>({command:[re.command,re.subcommand,re.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:re.name}))}}function hy(j,K,te,re,oe){if(!m(j).config?.rules.includes(te))return!1;try{let de=r(K);if(de===null)return!1;let we=JSON.parse(de);return we.migrated_from===re&&JSON.stringify(we.rules)===JSON.stringify(oe)}catch{return!1}}function Id(j){return{target:j,content:r(j)}}function vy(j){for(let K of j){if(K.content===null){G(K.target);continue}y(K.target,K.content)}}function by(j){let K=r(j);if(K===null)return null;try{let te=JSON.parse(K);return typeof te.migrated_from==="string"?te.migrated_from:null}catch{return null}}import{mkdir as Ly,readFile as wy,writeFile as ky}from"node:fs/promises";import{dirname as xy,join as Cy}from"node:path";var Sy=86400000,Ry=604800000;async function jd(j,K=Date.now()){if(j.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let te=Ke(j);if(!te)return null;let re=Cy(te,".cc-safety-net","update-check.json"),oe=await Py(re,K);if(!oe.lastCheck||K-oe.lastCheck>Sy){let we=await tn();if(oe.lastCheck=K,we.latestVersion)oe.latestVersion=we.latestVersion;if(!await Od(re,oe))return null;if(we.error)return null}let ce=oe.latestVersion,de=Et();if(!ce||!Co(ce,de))return null;if(oe.notifiedVersion===ce&&oe.notifiedAt!==void 0&&K-oe.notifiedAt<Ry)return null;if(oe.notifiedVersion=ce,oe.notifiedAt=K,!await Od(re,oe))return null;return`UPDATE_AVAILABLE: cc-safety-net v${ce} is available (running v${de}). 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 Py(j,K){let te=await wy(j,"utf8").then((ce)=>JSON.parse(ce)).catch(()=>{return});if(!te||typeof te!=="object"||Array.isArray(te))return{};let re=te,oe=(ce)=>typeof ce==="number"&&Number.isFinite(ce)&&ce<=K?ce:void 0;return{lastCheck:oe(re.lastCheck),latestVersion:typeof re.latestVersion==="string"?re.latestVersion:void 0,notifiedVersion:typeof re.notifiedVersion==="string"?re.notifiedVersion:void 0,notifiedAt:oe(re.notifiedAt)}}async function Od(j,K){return Ly(xy(j),{recursive:!0,mode:448}).then(()=>ky(j,JSON.stringify(K),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as Ey,resolve as Ni}from"node:path";var Fd="CC Safety Net Config",Dy="═".repeat(Fd.length),Ay="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",_y=new Set(["rule.json","rule.lock","cache"]);function Nd(j,K={}){try{return Ty(j,K)}catch(te){if(te instanceof o)return console.error(te.message),1;throw te}}function Ty(j,K){let te=K.cwd??process.cwd(),re=K.userConfigPath??T(j),oe=K.projectConfigPath??A(te),ce=K.legacyUserConfigPath??yr(j),de=K.legacyProjectConfigPath??gs(te),we=Ni(te,fe),xe=H(j,{cwd:te,userConfigPath:re,projectConfigPath:oe}),Ce=H(j,{cwd:te}),Se=s(xe.userScope,re),Ne=s(xe.projectScope,oe),He=K.legacyUserConfigPath?D(K.legacyUserConfigPath,"user policy"):s(Ce.userScope,ce),at=K.legacyProjectConfigPath?D(K.legacyProjectConfigPath,"project policy"):s(Ce.projectScope,de),mt=!1,it=!1,gt=[],ht=[],vt=Iy(s(Ce.projectScope,we));if(Oy(),r(Se)!==null){let yt=en(Se);if(yt.errors.push(...W(re,xe.userScope)),gt.push({scope:"User",path:re,result:yt,schema:"rules",target:Se}),yt.errors.length>0)mt=!0}if(r(He)!==null)if(it=!0,r(Se)!==null)ht.push(co("user","cleanup"));else{let yt=bo(He);if(gt.push({scope:"User",path:ce,result:yt,schema:"legacy",inactive:!0,target:He}),ht.push(co("user",yt.errors.length>0?"fix-or-delete":"migrate")),yt.errors.length>0)mt=!0}if(r(Ne)!==null){let yt=en(Ne);if(yt.errors.push(...W(oe,xe.projectScope)),gt.push({scope:"Project",path:Ni(oe),result:yt,schema:"rules",target:Ne}),yt.errors.length>0)mt=!0;if(r(at)!==null)it=!0,ht.push(co("project","cleanup"))}else if(r(at)!==null){it=!0,mt=!0;let yt=bo(at);gt.push({scope:"Project",path:Ni(de),result:yt,schema:"legacy",inactive:!0,target:at}),ht.push(co("project",yt.errors.length>0?"fix-or-delete":"migrate"))}if(vt?.result.errors.length)mt=!0;if(gt.length===0&&!vt)return console.log(`
263
+ Check that every parent path component is a directory.`;return K}import{mkdirSync as xg}from"node:fs";import{dirname as Cg}from"node:path";import{createInterface as Sg}from"node:readline";import{existsSync as Jc,readFileSync as vg}from"node:fs";var Bc=["version","safety","workflow","destructive_command_protection","secret_protection","audit"],mg=["standard","strict","paranoid"],qc="must be an object if provided",gg=`must be an integer between ${ye} and ${ve}`;function Ut(j,K){return se(nt(yg(j,K),Bc,(te)=>te.kind==="custom")," "," ")}function yg(j,K){if(!Ai(j))return[e([],"Config must be an object")];return[...j.version===1?[]:[e(["version"],"must be 1")],...jn(j.safety,["safety"],["level","overrides"],(te)=>[...te.level===void 0||typeof te.level==="string"&&mg.includes(te.level)?[]:[e(["safety","level"],'must be "standard", "strict", or "paranoid"')],...jn(te.overrides,["safety","overrides"],Uc,(re)=>Uc.flatMap((oe)=>Zr(re[oe],["safety","overrides",oe])))]),...jn(j.workflow,["workflow"],["worktree_mode"],(te)=>Zr(te.worktree_mode,["workflow","worktree_mode"])),...jn(j.destructive_command_protection,["destructive_command_protection"],["enabled","overrides","allow_paths"],(te)=>[...Zr(te.enabled,["destructive_command_protection","enabled"]),...Gc(te.overrides,["destructive_command_protection","overrides"],Pe,"destructive command"),...Di(te.allow_paths,["destructive_command_protection","allow_paths"],Ae,K)]),...jn(j.secret_protection,["secret_protection"],["enabled","overrides","deny_paths","allow_paths"],(te)=>[...Zr(te.enabled,["secret_protection","enabled"]),...Gc(te.overrides,["secret_protection","overrides"],_e,"secret protection"),...Di(te.deny_paths,["secret_protection","deny_paths"],Te,K),...Di(te.allow_paths,["secret_protection","allow_paths"],Ie,K)]),...jn(j.audit,["audit"],["retention_days"],(te)=>hg(te.retention_days)?[]:[e(["audit","retention_days"],gg)]),...Object.keys(j).filter((te)=>!Bc.includes(te)).map((te)=>Vc([],te))]}var Uc=["fail_closed","paranoid_rm","paranoid_interpreters"];function jn(j,K,te,re){if(j===void 0)return[];if(!Ai(j))return[e(K,qc)];return[...re(j),...Object.keys(j).filter((oe)=>!te.includes(oe)).map((oe)=>Vc(K,oe))]}function Zr(j,K){return j===void 0||typeof j==="boolean"?[]:[e(K,"must be a boolean")]}function Gc(j,K,te,re){if(j===void 0)return[];if(!Ai(j))return[e(K,qc)];return[...Object.keys(j).filter((oe)=>!te.has(oe)).map((oe)=>({path:[...K,oe],message:`unknown ${re} rule id "${oe}"`,kind:"key"})),...Object.keys(j).filter((oe)=>j[oe]!=="on"&&j[oe]!=="off").map((oe)=>e([...K,oe],'must be "on" or "off"'))]}function Di(j,K,te,re){if(j===void 0)return[];if(!Array.isArray(j))return[e(K,"must be an array of paths")];return j.flatMap((oe,ce)=>{if(typeof oe!=="string")return[e([...K,ce],"must be a non-empty path string")];let de=te(oe,re);return de===null?[]:[g([...K,ce],de)]})}function hg(j){if(j===void 0)return!0;if(typeof j!=="number"||!Number.isInteger(j))return!1;return j>=ye&&j<=ve}var Vc=(j,K)=>({path:j,message:K,kind:"unknownKeys"});function Ai(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function zc(j,K){return{"safety.level":j.safety.level,..._i("safety.overrides",j.safety.overrides),"workflow.worktree_mode":String(j.workflow.worktree_mode),"destructive_command_protection.enabled":String(j.destructive_command_protection.enabled),..._i("destructive_command_protection.overrides",j.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Ti(j.destructive_command_protection.allow_paths),"secret_protection.enabled":String(j.secret_protection.enabled),..._i("secret_protection.overrides",j.secret_protection.overrides),"secret_protection.deny_paths":Ti(j.secret_protection.deny_paths),"secret_protection.allow_paths":Ti(j.secret_protection.allow_paths),...K?{"audit.retention_days":String(j.audit.retention_days)}:{}}}function Xr(j,K,te){let re=zc(j,te),oe=zc(K,te);return[...new Set([...Object.keys(re),...Object.keys(oe)])].flatMap((ce)=>re[ce]===oe[ce]?[]:[{field:ce,before:re[ce],after:oe[ce]}])}function sr(j,K){let te=d(j,K);if(!Jc(te))return{baseline:h(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,j.home),diagnostics:[]};let re=bn(te);return{baseline:h(re.value,j.home),diagnostics:re.errors.length>0?re.errors:Ut(re.value,j.home)}}function bn(j){if(!Jc(j))return{errors:[`${j}: file not found`]};try{return{value:JSON.parse(vg(j,"utf-8")),errors:[]}}catch(K){let te=K instanceof Error?K.message:String(K);return{errors:[`${j}: ${K instanceof SyntaxError?`Invalid JSON: ${te}`:te}`]}}}function Qr(j,K){let te=bg(j)?j:{};return{version:K.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((re)=>te[re]!==void 0).map((re)=>[re,te[re]]))}}function _i(j,K){return Object.fromEntries(Object.entries(K).flatMap(([te,re])=>re===void 0?[]:[[`${j}.${te}`,String(re)]]))}function Ti(j){return j.length===0?"(none)":j.join(", ")}function bg(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}import{chmodSync as Lg,existsSync as Wc,mkdirSync as wg,readFileSync as Kc}from"node:fs";import{dirname as kg}from"node:path";function Yc(j,K={}){let te=d(j,K);if(!Wc(te))return{path:te,exists:!1,raw:"",policy:z(),errors:[]};let re=Kc(te,"utf-8");if(!re.trim())return{path:te,exists:!0,raw:re,policy:z(),errors:["Config file is empty"]};try{let oe=JSON.parse(re),ce=Ut(oe,j.home);return{path:te,exists:!0,raw:re,policy:h(oe,j.home),errors:ce}}catch(oe){return{path:te,exists:!0,raw:re,policy:z(),errors:[`Invalid JSON: ${oe instanceof Error?oe.message:String(oe)}`]}}}function Qt(j,K,te={}){let re=d(j,te),oe=Ut(K,j.home),ce=oe.length>0?z():h(K,j.home);if(oe.length>0)return{path:re,policy:ce,errors:oe};return wg(kg(re),{recursive:!0,mode:448}),y(D(re),`${JSON.stringify(ce,null,2)}
264
+ `,384),Lg(re,384),{path:re,policy:ce,errors:[]}}function Zc(j,K){let te=Ut(K,j.home);if(te.length>0)return{errors:te};return{preview:Ge(h(K,j.home),j.env),errors:[]}}function Xc(j,K={}){let te=d(j,K);if(!Wc(te))return Qt(j,Q,K);let re=Kc(te,"utf-8");if(!re.trim())return Qt(j,Q,K);try{return Qt(j,h(JSON.parse(re),j.home),K)}catch{return Qt(j,Q,K)}}var Qc=new Set(["check","apply"]),ed="(unset)";async function nd(j,K,te={}){let re=At({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},K),oe=re.positionals[0],ce=[...re.errors,...oe&&!Qc.has(oe)?[`Unknown policy subcommand: ${oe}`]:[],...oe&&Qc.has(oe)&&!re.positionals[1]?[`policy ${oe} requires a file`]:[],...re.positionals.slice(2).map((mt)=>`Unexpected policy argument: ${mt}`)];if(ce.length>0){for(let mt of ce)console.error(mt);return 1}let de=re.positionals[1];if(!oe||!de)return _n(pr,console.error),1;let we=re.flags.global?d(j):w(te.cwd??process.cwd()),xe=bn(de),Ce=[...xe.errors,...Ut(xe.value,j.home).map((mt)=>`${de}: ${mt}`),...!re.flags.global&&Eg(xe.value)&&xe.value.audit!==void 0?[`${de}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(Ce.length>0){for(let mt of Ce)console.error(mt);return 1}let Se=h(xe.value,j.home);if(console.log(`Scope: ${re.flags.global?"user":"project"} (${we})`),console.log(`Proposal: ${de}`),re.flags.global)td(h(bn(we).value,j.home),Se,!0);if(!re.flags.global){let mt=sr(j).baseline;console.log("Effective policy (user + project merged):"),td(X(mt,le(bn(we).value,j.home).policy).policy,X(mt,le(xe.value,j.home).policy).policy,!1)}if(oe==="check")return 0;let Ne=te.input??process.stdin,He=te.output??process.stdout;if(!Ne.isTTY||!He.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${de}${re.flags.global?" --global":""}`),1;if(!await Rg(`Apply this policy to ${we}? [y/N] `,Ne,He))return console.log("Cancelled; nothing was written."),0;return Pg(j,we,xe.value,Se,re.flags.global),console.log(`Policy applied: ${we}`),0}function Rg(j,K,te){let re=Sg({input:K,output:te,terminal:!1});return new Promise((oe)=>{re.once("close",()=>oe(!1)),re.question(j,(ce)=>{oe(/^y(es)?$/i.test(ce.trim())),re.close()})})}function Pg(j,K,te,re,oe){if(oe){Qt(j,re);return}xg(Cg(K),{recursive:!0}),It(K,Qr(te,re))}function td(j,K,te){let re=Xr(j,K,te);if(re.length===0){console.log("No changes.");return}console.log(`Changes (${re.length}):`);for(let oe of re)console.log(` ${oe.field}: ${oe.before??ed} -> ${oe.after??ed}`)}function Eg(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}import{join as Gy}from"node:path";var rd="# 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 eo(j,K){if(!j.ok){ld(j);return}sd(j,K)}function id(j,K,te){if(j.ok)console.log(te);if(!j.add){eo(j,`Added rulebook source: ${K}`);return}if(!j.ok){ld(j);return}if(j.add.added.length>0)console.log(`Added ${j.add.added.length} ${j.add.added.length===1?"rulebook":"rulebooks"} from ${j.add.source} at ${j.add.ref}:`),j.add.added.forEach((re)=>{console.log(` - ${re}`)});if(j.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${j.add.source} at ${j.add.ref}: ${j.add.alreadyConfigured.join(", ")}`);if(j.add.commits.length>0)console.log(`Vendored at ${j.add.commits.map((re)=>re.slice(0,7)).join(", ")}.`);sd(j,"Rule config updated.")}function sd(j,K){for(let te of j.changes??[])console.log(te);console.log(K),console.log(""),Dg(j.entries)}function Dg(j){if(j.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${j.length}):`);for(let K of j)console.log(` - ${K.name} ${K.version} (${Ag(K.ruleCount)})`),console.log(` Source: ${K.spec}`)}function Ag(j){return`${j} ${j===1?"rule":"rules"}`}function ad(j){Ln("Active sources",j.rulebooks,(K)=>[`[${K.source}] ${K.name} ${K.version}`,` Source: ${K.spec}`]),Ln("Active rules",j.rules,(K)=>[`[${Tg(j,K.name)}] ${K.name}`,..._g(K),` Reason: ${K.reason}`]),Ln("Disabled rules",od(j,"off"),(K)=>[K.key]),Ln("Reason overrides",od(j,"reason"),(K)=>[K.key,` Reason: ${K.value.reason}`]),Ln("Transparent wrappers",j.transparent_wrappers,(K)=>[K]),Ln("Issues",j.errors,(K)=>[K]),Ln("Warnings",j.warnings,(K)=>[K])}function Ln(j,K,te){if(K.length===0){console.log(`${j}: (none)`);return}console.log(`${j} (${K.length}):`);for(let re of K){let[oe,...ce]=te(re);console.log(` - ${oe}`);for(let de of ce)console.log(` ${de}`)}}function _g(j){if(!j.match)return[` Command: ${j.subcommand?`${j.command} ${j.subcommand}`:j.command}`,` Block args: ${j.block_args.join(", ")}`];return[` Command: ${[j.command,...j.match.command_path].join(" ")}`,...j.match.any_args?[` Any args: ${j.match.any_args.join(", ")}`]:[],...j.match.exclude_args?[` Exclude args: ${j.match.exclude_args.join(", ")}`]:[]]}function Tg(j,K){return j.rulebooks.find((te)=>te.rules.includes(K))?.source??"project"}function od(j,K){return Object.entries({...j.userConfig?.overrides??{},...j.projectConfig?.overrides??{}}).filter((te)=>{if(K==="off")return te[1]==="off";return!!te[1]&&typeof te[1]==="object"}).map(([te,re])=>({key:te,value:re}))}function ld(j){for(let K of j.errors)console.error(K)}import{dirname as _d,join as lo}from"node:path";import{join as Ni,resolve as qg}from"node:path";function Ii(j){let K=m(j);if(K.errors.length>0)return{ok:!1,result:{ok:!1,errors:K.errors,entries:[]}};return{ok:!0,config:K.config??pt}}function cd(j,K=[]){It(j,{version:1,rules:K,overrides:{},transparent_wrappers:[]})}function dd(j,K="project-rules"){It(j,{rulebook_version:1,name:K,version:"1.0.0",description:K==="project-rules"?"Project-specific CC Safety Net rules.":"User-specific CC Safety Net rules.",author:K==="project-rules"?"project":"user",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 oo}from"node:path";var Ig="custom.";function to(j){if(j.rulebook_version!==2)return[];let K=j.rules.map((te)=>({name:te.name,command:te.command,block_args:[],match:te.match,reason:te.reason,intent:te.intent}));return(j.tests??[]).flatMap((te,re)=>{let oe=$i(v(te.command));if(oe.length===0)return[`tests[${re}]: could not parse fixture command: ${te.command}`];let ce=oe.reduce((de,we)=>de??E(we,K)?.id.slice(Ig.length),void 0);if(te.expect==="blocked"){if(ce===te.rule)return[];let de=ce?`"${ce}" matched first`:"no rule matched";return[`tests[${re}]: expected "${te.rule}" to block "${te.command}" but ${de}`]}return ce?[`tests[${re}]: expected "${te.command}" to be allowed but "${ce}" matched`]:[]})}function $i(j){return j.nodes.flatMap((K)=>{if(K.kind==="group"||K.kind==="function")return $i(K.body);if(K.kind!=="command")return[];let te=be(ee(K.dialect,K.words)).words.map(t);return[...te.length>0?[te]:[],...K.nested.flatMap((re)=>$i(re))]})}var Oi="Rule synchronization exceeds CC Safety Net's safe resource limits.",no=Object.freeze({maxSources:J,concurrency:4,maxRequests:131,maxResponseBytes:67108864});function ro(j={}){return{requests:0,responseBytes:0,maxRequests:j.maxRequests??no.maxRequests,maxResponseBytes:j.maxResponseBytes??no.maxResponseBytes}}function en(j){return{controller:new AbortController,budget:ro(),resolveUrl:j}}function ud(j){return j instanceof Error&&j.message===Oi}function pd(j){if(j.requests>=j.maxRequests)throw Error(Oi);j.requests++}function fd(j,K){if(K>j.maxResponseBytes-j.responseBytes)throw j.responseBytes+=K,Error(Oi);j.responseBytes+=K}var yd=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function md(j,K,te=S(oo(oo(K)),"rules policy"),re=en()){if(x(j))return Fg(j,re);return jg(j,K,te)}async function hd(j,K,te,re,oe,ce){if(!x(j))return md(j,K,te,re);let de=oe?null:$g(j,K,te);if(de)return de;if(!oe&&!ce)throw Error(`${j} is not vendored; run rule update ${j} to vendor it`);return md(j,K,te,re)}function $g(j,K,te=S(oo(oo(K)),"rules policy")){let re=O(j),oe=N(K,re.name),ce=r(s(te,oe));if(ce===null)return null;let de=ae(ji(ce,`Invalid rulebook ${oe}.`));if(de.name!==re.name)throw Error(`rulebook name "${de.name}" in ${oe} must match "${re.name}"`);return{spec:j,rulebook:de,content:ce}}async function vd(j,K={}){if(!Y(j))throw Error(`Invalid GitHub repository source: ${j}`);let[te,re]=j.split("/");if(!te||!re)throw Error(`Invalid GitHub repository source: ${j}`);if(K.ref!==void 0&&!ie(K.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${K.ref}`);let oe=K.operation??en(),ce=K.ref??await Og(te,re,j,oe),de=await Ld(te,re,ce,j,oe),we=await io(`https://api.github.com/repos/${te}/${re}/git/trees/${de}?recursive=1`,"tree",oe),xe=we.response;if(!xe.ok)throw Error(`Failed to inspect ${j}: GitHub tree returned ${xe.status}`);let Ce=JSON.parse(we.content);if(!Array.isArray(Ce?.tree))throw Error(`Failed to inspect ${j}: unexpected GitHub tree response`);let Se=Ce.tree,Ne=[...new Set(Se.flatMap((He)=>{if(!He||typeof He!=="object")return[];let at=He;if(at.type!=="blob"||typeof at.path!=="string")return[];let mt=at.path.match(dt);return mt?.[1]?[mt[1]]:[]}))].sort();if(Ne.length===0)throw Error(`No rulebooks found in ${j} under ${fe}/`);return{source:j,owner:te,repo:re,ref:ce,commit:de,names:Ne}}async function Og(j,K,te,re){let oe=await io(`https://api.github.com/repos/${j}/${K}`,"metadata",re),ce=oe.response;if(!ce.ok)throw Error(`Failed to inspect ${te}: GitHub returned ${ce.status}`);let we=JSON.parse(oe.content)?.default_branch;if(typeof we!=="string"||we==="")throw Error(`Failed to inspect ${te}: missing default branch`);if(!ie(we))throw Error(`GitHub returned an invalid default branch: ${we}`);return we}function jg(j,K,te){ut(j);let re=N(K,j),oe=r(s(te,re));if(oe===null)throw Error(`Rulebook source not found: ${j}`);let ce=bd(ji(oe,"Invalid local rulebook source."));if(ce.name!==j)throw Error(`rulebook name "${ce.name}" must match local source "${j}"`);return{spec:j,rulebook:ce,content:oe}}async function Fg(j,K){let te=O(j),re=await Ld(te.owner,te.repo,te.ref,j,K),oe=await io(`https://raw.githubusercontent.com/${te.owner}/${te.repo}/${re}/${te.path}`,"raw",K),ce=oe.response;if(!ce.ok)throw Error(`Failed to fetch ${j}: GitHub raw returned ${ce.status}`);let de=oe.content,we=bd(ji(de,"Invalid GitHub rulebook response."));if(we.name!==te.name)throw Error(`rulebook name "${we.name}" must match GitHub source "${te.name}"`);return{spec:j,rulebook:we,content:de}}function bd(j){let K=ae(j),te=to(K);if(te.length>0)throw Error(te.join("; "));return K}function ji(j,K){try{return JSON.parse(j)}catch{throw Error(K)}}async function Ld(j,K,te,re,oe){let ce=await io(`https://api.github.com/repos/${j}/${K}/commits/${encodeURIComponent(te)}`,"commit",oe),de=ce.response;if(!de.ok)throw Error(`Failed to resolve ${re}: GitHub returned ${de.status}`);let we=JSON.parse(ce.content);if(typeof we?.sha!=="string"||we.sha==="")throw Error(`Failed to resolve commit for ${re}`);return we.sha}async function Ng(j,K,te={}){if(te.signal?.aborted)throw te.signal.reason;let re=te.budget??ro(),oe=new AbortController,ce=()=>oe.abort(te.signal?.reason);te.signal?.addEventListener("abort",ce,{once:!0});let de=!1,we=setTimeout(()=>{if(oe.signal.aborted)return;de=!0,oe.abort()},te.timeoutMs??yd.timeoutMs);try{if(te.signal?.aborted)throw te.signal.reason;pd(re);let xe=await(te.fetch??fetch)(j,{signal:oe.signal,redirect:"error"});if(!xe.ok)return wd(xe),{response:xe,content:""};return{response:xe,content:await Mg(xe,K,re,()=>oe.abort())}}catch(xe){if(de)throw Error("GitHub request timed out",{cause:xe});if(te.signal?.aborted)throw te.signal.reason;throw xe}finally{clearTimeout(we),te.signal?.removeEventListener("abort",ce)}}function io(j,K,te){return Ng(te.resolveUrl?.(j)??j,K,{budget:te.budget,signal:te.controller.signal})}async function Mg(j,K,te=ro(),re){let oe=yd[`${K}Bytes`],ce=Number(j.headers.get("content-length"));if(Number.isFinite(ce)&&ce>oe)throw wd(j),Error(`GitHub ${K} response exceeds ${oe} bytes`);if(!j.body)return"";let de=j.body.getReader(),we=[],xe=0;while(!0){let Ce=await de.read();if(Ce.done)break;try{fd(te,Ce.value.byteLength)}catch(Se){throw re?.(),gd(de),Se}if(xe+=Ce.value.byteLength,xe>oe)throw re?.(),gd(de),Error(`GitHub ${K} response exceeds ${oe} bytes`);we.push(Buffer.from(Ce.value))}return Buffer.concat(we,xe).toString("utf-8")}function wd(j){if(!j.body)return;kd(()=>j.body?.cancel())}function gd(j){kd(()=>j.cancel())}function kd(j){try{Promise.resolve(j()).catch(()=>{})}catch{}}var Hg=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function xd(j,K){let te=Rd(j.rules,K);if(te.length>0)return{ok:!0,specs:te};return Sd(j.rules,K)}function Cd(j,K){let te=Rd(j,K);if(te.length>0)return{ok:!0,specs:te};let re=Gg(j,K);if(re.length>0)return{ok:!0,specs:re};let oe=Bg(j,K);if(!oe.ok)return oe;if(oe.specs.length>0)return{ok:!0,specs:oe.specs};return Sd(j,K)}function Sd(j,K){let te=j.filter((re)=>Fi(re)?.name===K);if(te.length===1)return{ok:!0,specs:te};return Ug(K,te)}function Ug(j,K){return{ok:!1,result:{ok:!1,errors:K.length===0?[`No configured rulebook matches ${j}`]:[`Ambiguous rulebook match ${j}: ${K.join(", ")}`],entries:[]}}}function Rd(j,K){return j.filter((te)=>te===K)}function Gg(j,K){let te=K.match(Hg),re=te?.[1],oe=te?.[2],ce=te?.[3];if(!re||!oe||!ce||!ie(ce))return[];return Pd(j,(de)=>de.owner===re&&de.repo===oe&&de.ref===ce)}function Bg(j,K){if(!Y(K))return{ok:!0,specs:[]};let[te,re]=K.split("/"),oe=Pd(j,(de)=>de.owner===te&&de.repo===re);if(new Set(oe.map((de)=>Fi(de)?.ref).filter((de)=>!!de)).size<2)return{ok:!0,specs:oe};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${K}. Use an explicit ref:`,` cc-safety-net rule remove ${K}#<ref>`],entries:[]}}}function Fi(j){try{return O(j)}catch{return null}}function Pd(j,K){return j.filter((te)=>{let re=Fi(te);return re?K(re):!1})}async function ao(j,K={}){let te=Mi(K);return Vg(j,te,await so(j,te,en()))}function Vg(j,K,te){if(!te.ok)return te;let re=$t(j,K),oe=[...new Set(W(re.configPath,re.filesystemScope))];if(oe.length===0)return te;return{ok:!1,errors:oe,entries:te.entries}}async function so(j,K,te,re={},oe=new Set,ce=new Set){try{let de=$t(j,K),we=Ii(de.configTarget);if(!we.ok)return we.result;let xe=we.config;if(K.check)return ay(xe,de,K);let Ce=K.only?xd(xe,K.only):{ok:!0,specs:xe.rules};if(!Ce.ok)return Ce.result;let Se=new Set([...K.refresh?Ce.specs:[],...oe]),Ne=(Lt)=>hd(Lt,de.configDir,de.filesystemScope,te,Se.has(Lt),!K.refresh||Se.has(Lt)),He=await ny(xe.rules,K.refresh?(Lt)=>Ne(Lt).then((Ct)=>({ok:!0,item:Ct})).catch((Ct)=>{if(ud(Ct))throw Ct;return{ok:!1,spec:Lt,message:Ct instanceof Error?Ct.message:String(Ct)}}):async(Lt)=>({ok:!0,item:await Ne(Lt)}),te),at=He.filter((Lt)=>!Lt.ok),mt=He.filter((Lt)=>Lt.ok).map((Lt)=>Lt.item),it=mt.flatMap((Lt)=>zg(Lt,xe.rules)),gt=mt.flatMap((Lt)=>Jg(Lt,ce,de)),ht=new Set([...it,...gt].map((Lt)=>Lt.spec)),vt=[...at,...it,...gt],yt=[],kt=Kg(yt,()=>mt.flatMap((Lt)=>ht.has(Lt.spec)||vt.length>0&&ce.has(Lt.spec)?[]:Wg(Lt,de,re,yt)));return{ok:vt.length===0,errors:vt.map((Lt)=>`Failed to update ${Lt.spec}: ${Lt.message}`),entries:mt.map(Zg),changes:kt}}catch(de){return lr(de)}}function zg(j,K){if(!x(j.spec))return[];let te=je(j.spec),re=K.filter((oe)=>oe!==j.spec&&je(oe).toLowerCase()===te.toLowerCase());if(re.length===0)return[];return[{ok:!1,spec:j.spec,message:`rulebook name "${te}" is also claimed by ${re.join(", ")}; rename one of them`}]}function Jg(j,K,te){if(!K.has(j.spec)||!x(j.spec))return[];let re=N(te.configDir,j.rulebook.name),oe=r(s(te.filesystemScope,re));if(oe===null||oe===j.content)return[];return[{ok:!1,spec:j.spec,message:`${re} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Wg(j,K,te,re){if(!x(j.spec))return[];let oe=N(K.configDir,j.rulebook.name),ce=s(K.filesystemScope,oe),de=r(ce);if(de===j.content)return[];return re?.push({target:ce,previous:de}),y(ce,j.content,void 0,te._testAfterPolicyRename),Yg(j,de)}function Kg(j,K){try{return K()}catch(te){for(let re of[...j].reverse()){if(re.previous===null){G(re.target);continue}y(re.target,re.previous)}throw te}}function Yg(j,K){if(K===null)return[`Vendored ${j.spec} (${j.rulebook.version})`];let te=he(K),re="problem"in te?null:te.rulebook,oe=new Map(re?.rules.map((de)=>[de.name,JSON.stringify(de)])??[]),ce=new Set(j.rulebook.rules.map((de)=>de.name));return[`Updated ${j.spec} (${re?.version??"unreadable"} -> ${j.rulebook.version})`,...[...ce].filter((de)=>!oe.has(de)).map((de)=>` + ${de}`),...[...oe.keys()].filter((de)=>!ce.has(de)).map((de)=>` - ${de}`),...j.rulebook.rules.filter((de)=>{let we=oe.get(de.name);return we!==void 0&&we!==JSON.stringify(de)}).map((de)=>` ~ ${de.name}`)]}function Zg(j){return{spec:j.spec,name:j.rulebook.name,version:j.rulebook.version,ruleCount:j.rulebook.rules.length}}async function Ed(j,K,te={}){return Xg(j,K,oy(te),en())}async function Xg(j,K,te,re,oe={}){let ce=null,de=!1;try{let we=$t(j,te),xe=r(we.configTarget);ce={target:we.configTarget,content:xe};let Ce=Ii(we.configTarget);if(!Ce.ok)return Ce.result;let Se=Ce.config,Ne=Y(K);Qg(K,te,Ne);let He=Ne?await vd(K,{ref:te.ref,operation:re}):null,at=He?ey(He,te.rulebooks):[],mt=He?at.map((yt)=>ty(Se.rules,He,yt)??`${K}#${He.ref}/${yt}`):[K],it=mt.filter((yt)=>!Se.rules.includes(yt)),gt=[...Se.rules,...it];if(gt.length>J)return ry();if(gt.length!==Se.rules.length)de=!0,It(we.configTarget,{version:1,rules:gt,overrides:Se.overrides??{},transparent_wrappers:Se.transparent_wrappers??[]},void 0,oe._testAfterPolicyRename);let ht=await so(j,te,re,oe,new Set(it),new Set(it));if(!ht.ok)ar(we.configTarget,xe);if(!ht.ok||!He)return ht;let vt=at.filter((yt,kt)=>it.includes(mt[kt]??""));return{...ht,add:{source:K,ref:He.ref,selected:at,added:vt,alreadyConfigured:at.filter((yt)=>!vt.includes(yt)),commits:it.length>0?[He.commit]:[]}}}catch(we){if(de&&ce)try{ar(ce.target,ce.content)}catch(xe){return lr(xe)}return lr(we)}}function Qg(j,K,te){if(!te&&K.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!te&&K.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${j}`);if(K.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let re=K.rulebooks?.filter((oe)=>!c.test(oe))??[];if(re.length>0)throw Error(`Invalid rulebook names: ${re.join(", ")}`)}function ey(j,K){let te=K?[...new Set(K)]:j.names,re=te.filter((oe)=>!j.names.includes(oe));if(re.length>0)throw Error(`Rulebooks not found in ${j.source} at ${j.ref}: ${re.join(", ")}
265
+ Available rulebooks: ${j.names.join(", ")}`);return te}function ty(j,K,te){let re=`${K.source}#${K.ref}/${te}`;if(j.includes(re))return re;let oe=`${K.source}#${K.commit}/${te}`;return j.find((ce)=>ce===oe)}async function ny(j,K,te=en()){if(j.length>J)throw Error(ge);let re=Array(j.length),oe=0,ce,de=Array.from({length:Math.min(j.length,no.concurrency)},async()=>{while(!ce){let we=oe;if(we>=j.length)return;oe++;try{re[we]=await K(j[we],we,te.controller.signal)}catch(xe){if(!ce)ce={value:xe},oe=j.length,te.controller.abort(xe);return}}});if(await Promise.all(de),ce)throw ce.value;return re}function ry(){return{ok:!1,errors:[ge],entries:[]}}function Mi(j){return{cwd:j.cwd,userConfigDir:j.userConfigDir,userConfigPath:j.userConfigPath,projectConfigPath:j.projectConfigPath,global:j.global,check:j.check,only:j.only,refresh:j.refresh}}function oy(j){return{...Mi(j),ref:j.ref,rulebooks:j.rulebooks}}function iy(j){return{...Mi(j),deleteSource:j.deleteSource}}async function Dd(j,K,te={}){try{return await sy(j,K,iy(te),{})}catch(re){return lr(re)}}async function sy(j,K,te,re){let oe=$t(j,te),ce=m(oe.configTarget);if(ce.errors.length>0)return{ok:!1,errors:ce.errors,entries:[]};if(!ce.config)return{ok:!1,errors:[`No config found at ${oe.configPath}`],entries:[]};let de=Cd(ce.config.rules,K);if(!de.ok)return de.result;let we=te.deleteSource?ly(oe.configDir,de.specs,oe.filesystemScope):{ok:!0,dirs:[]};if(!we.ok)return we.result;let xe=r(oe.configTarget);if(xe===null)return lr(Error("Rules config is unavailable."));try{It(oe.configTarget,{version:1,rules:ce.config.rules.filter((Ne)=>!de.specs.includes(Ne)),overrides:ce.config.overrides??{},transparent_wrappers:ce.config.transparent_wrappers??[]},void 0,re._testAfterPolicyRename)}catch(Ne){throw ar(oe.configTarget,xe),Ne}let Ce=await so(j,te,en(),re);if(!Ce.ok)return ar(oe.configTarget,xe),Ce;let Se=cy(we.dirs,re,oe.filesystemScope);if(!Se.ok){ar(oe.configTarget,xe);let Ne=await so(j,te,en(),re);if(!Ne.ok)return{ok:!1,errors:[...Se.result.errors,...Ne.errors],entries:Ne.entries};return Se.result}return Ce}async function ay(j,K,te){let re=Re(j,K.configDir,te.global?"user":"project",K.filesystemScope);return{ok:re.errors.length===0&&re.warnings.length===0,errors:[...re.errors,...re.warnings],entries:re.entries}}function ly(j,K,te){let re=K.flatMap((we)=>c.test(we)?[]:["--delete-source can only delete local rulebook sources"]),oe=K.map((we)=>Ni(j,we)),ce=re.length>0?[]:oe.flatMap((we)=>Ad(we,te)),de=[...re,...ce];return de.length>0?{ok:!1,result:{ok:!1,errors:de,entries:[]}}:{ok:!0,dirs:oe}}function Ad(j,K){let te=qg(j),re=s(K,te),oe=ue(re);if(!oe)return[`Local rulebook source directory not found: ${j}`];let ce=oe.find((de)=>de.name==="rulebook.json");if(!ce)return[`Local rulebook source directory is missing rulebook.json: ${j}`];if(ce.kind!=="file")throw new o(K.label);if(r(s(K,Ni(te,"rulebook.json"))),oe.length>1)return[`Local rulebook source directory contains extra files: ${j}. delete manually if you really want to remove the directory.`];return[]}function cy(j,K,te){let re=j.flatMap((oe)=>{try{if(!ue(s(te,oe)))return[];let ce=Ad(oe,te);if(ce.length>0)return ce;return dy(oe,K,te),[]}catch(ce){return[`Failed to delete local rulebook source ${oe}: ${ce instanceof Error?ce.message:String(ce)}`]}});return re.length>0?{ok:!1,result:{ok:!1,errors:re,entries:[]}}:{ok:!0}}function dy(j,K,te){if(K._testDeleteLocalSourceDir){K._testDeleteLocalSourceDir(j);return}G(s(te,Ni(j,pe))),ct(s(te,j))}function ar(j,K){if(K===null){G(j);return}y(j,K)}function lr(j){return{ok:!1,errors:[j instanceof Error?j.message:String(j)],entries:[]}}var uy=".safety-net.json",py="~/.cc-safety-net/config.json";async function $d(j,K){return[await Td(j,{legacyPath:Ws({cwd:K.cwd}),configPath:A(K.cwd),defaultRulebookName:"project-rules",migratedFrom:uy,cleanup:K.cleanup,syncOptions:{cwd:K.cwd}}),await Td(j,{legacyPath:yr(j),configPath:T(j),defaultRulebookName:"user-rules",migratedFrom:py,cleanup:K.cleanup,syncOptions:{cwd:K.cwd,global:!0}})].every((re)=>re)?0:1}async function Td(j,K){let te=$t(j,K.syncOptions),re=s(te.filesystemScope,K.legacyPath),oe=r(re);if(oe===null)return console.log(`No legacy config found at ${K.legacyPath}`),!0;let ce=my(oe);if(!ce.ok){for(let at of ce.errors)console.error(at);return!1}let de=m(te.configTarget);if(de.errors.length>0){for(let at of de.errors)console.error(at);return!1}let we=de.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},xe=gy(_d(K.configPath),we.rules,K.defaultRulebookName,K.migratedFrom,te.filesystemScope),Ce=lo(_d(K.configPath),xe,"rulebook.json"),Se=s(te.filesystemScope,Ce),Ne=[Id(te.configTarget),Id(Se)],He=await fy(j,K,te.configTarget,Se,xe,ce.config.rules,we.rules.includes(xe)?we.rules:[...we.rules,xe],we.overrides??{},we.transparent_wrappers??[]);if(!He.ok){vy(Ne);for(let at of He.errors)console.error(at);return!1}if(!K.cleanup)return console.log(`Migrated legacy config at ${K.legacyPath}. Legacy file is no longer used.`),!0;if(!hy(te.configTarget,Se,xe,K.migratedFrom,ce.config.rules))return console.error(`Migration cleanup verification failed for ${K.legacyPath}`),!1;return G(re),console.log(`Deleted legacy config at ${K.legacyPath}`),!0}async function fy(j,K,te,re,oe,ce,de,we,xe){try{return It(te,{version:1,rules:de,overrides:we,transparent_wrappers:xe}),It(re,yy(oe,K.migratedFrom,ce)),await ao(j,K.syncOptions)}catch(Ce){return{ok:!1,errors:[Ce instanceof Error?Ce.message:String(Ce)]}}}function my(j){try{let K=JSON.parse(j),te=vo(K);if(te.errors.length>0)return{ok:!1,errors:te.errors};return{ok:!0,config:{version:1,rules:K.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function gy(j,K,te,re,oe){let ce=K.find((de)=>by(s(oe,lo(j,de,"rulebook.json")))===re);if(ce)return ce;if(r(s(oe,lo(j,te,"rulebook.json")))===null)return te;for(let de=2;;de++){let we=`${te}-${de}`;if(r(s(oe,lo(j,we,"rulebook.json")))===null)return we}}function yy(j,K,te){return{rulebook_version:1,name:j,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:K,allowed_commands:[...new Set(te.map((re)=>re.command))],rules:te,tests:te.map((re)=>({command:[re.command,re.subcommand,re.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:re.name}))}}function hy(j,K,te,re,oe){if(!m(j).config?.rules.includes(te))return!1;try{let de=r(K);if(de===null)return!1;let we=JSON.parse(de);return we.migrated_from===re&&JSON.stringify(we.rules)===JSON.stringify(oe)}catch{return!1}}function Id(j){return{target:j,content:r(j)}}function vy(j){for(let K of j){if(K.content===null){G(K.target);continue}y(K.target,K.content)}}function by(j){let K=r(j);if(K===null)return null;try{let te=JSON.parse(K);return typeof te.migrated_from==="string"?te.migrated_from:null}catch{return null}}import{mkdir as Ly,readFile as wy,writeFile as ky}from"node:fs/promises";import{dirname as xy,join as Cy}from"node:path";var Sy=86400000,Ry=604800000;async function jd(j,K=Date.now()){if(j.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let te=Ke(j);if(!te)return null;let re=Cy(te,".cc-safety-net","update-check.json"),oe=await Py(re,K);if(!oe.lastCheck||K-oe.lastCheck>Sy){let we=await nn();if(oe.lastCheck=K,we.latestVersion)oe.latestVersion=we.latestVersion;if(!await Od(re,oe))return null;if(we.error)return null}let ce=oe.latestVersion,de=Et();if(!ce||!Co(ce,de))return null;if(oe.notifiedVersion===ce&&oe.notifiedAt!==void 0&&K-oe.notifiedAt<Ry)return null;if(oe.notifiedVersion=ce,oe.notifiedAt=K,!await Od(re,oe))return null;return`UPDATE_AVAILABLE: cc-safety-net v${ce} is available (running v${de}). 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 Py(j,K){let te=await wy(j,"utf8").then((ce)=>JSON.parse(ce)).catch(()=>{return});if(!te||typeof te!=="object"||Array.isArray(te))return{};let re=te,oe=(ce)=>typeof ce==="number"&&Number.isFinite(ce)&&ce<=K?ce:void 0;return{lastCheck:oe(re.lastCheck),latestVersion:typeof re.latestVersion==="string"?re.latestVersion:void 0,notifiedVersion:typeof re.notifiedVersion==="string"?re.notifiedVersion:void 0,notifiedAt:oe(re.notifiedAt)}}async function Od(j,K){return Ly(xy(j),{recursive:!0,mode:448}).then(()=>ky(j,JSON.stringify(K),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as Ey,resolve as Hi}from"node:path";var Fd="CC Safety Net Config",Dy="═".repeat(Fd.length),Ay="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",_y=new Set(["rule.json","rule.lock","cache"]);function Nd(j,K={}){try{return Ty(j,K)}catch(te){if(te instanceof o)return console.error(te.message),1;throw te}}function Ty(j,K){let te=K.cwd??process.cwd(),re=K.userConfigPath??T(j),oe=K.projectConfigPath??A(te),ce=K.legacyUserConfigPath??yr(j),de=K.legacyProjectConfigPath??hs(te),we=Hi(te,fe),xe=H(j,{cwd:te,userConfigPath:re,projectConfigPath:oe}),Ce=H(j,{cwd:te}),Se=s(xe.userScope,re),Ne=s(xe.projectScope,oe),He=K.legacyUserConfigPath?D(K.legacyUserConfigPath,"user policy"):s(Ce.userScope,ce),at=K.legacyProjectConfigPath?D(K.legacyProjectConfigPath,"project policy"):s(Ce.projectScope,de),mt=!1,it=!1,gt=[],ht=[],vt=Iy(s(Ce.projectScope,we));if(Oy(),r(Se)!==null){let yt=tn(Se);if(yt.errors.push(...W(re,xe.userScope)),gt.push({scope:"User",path:re,result:yt,schema:"rules",target:Se}),yt.errors.length>0)mt=!0}if(r(He)!==null)if(it=!0,r(Se)!==null)ht.push(co("user","cleanup"));else{let yt=bo(He);if(gt.push({scope:"User",path:ce,result:yt,schema:"legacy",inactive:!0,target:He}),ht.push(co("user",yt.errors.length>0?"fix-or-delete":"migrate")),yt.errors.length>0)mt=!0}if(r(Ne)!==null){let yt=tn(Ne);if(yt.errors.push(...W(oe,xe.projectScope)),gt.push({scope:"Project",path:Hi(oe),result:yt,schema:"rules",target:Ne}),yt.errors.length>0)mt=!0;if(r(at)!==null)it=!0,ht.push(co("project","cleanup"))}else if(r(at)!==null){it=!0,mt=!0;let yt=bo(at);gt.push({scope:"Project",path:Hi(de),result:yt,schema:"legacy",inactive:!0,target:at}),ht.push(co("project",yt.errors.length>0?"fix-or-delete":"migrate"))}if(vt?.result.errors.length)mt=!0;if(gt.length===0&&!vt)return console.log(`
266
266
  No config files found. Using built-in rules only.`),0;for(let yt of gt)if(yt.inactive)Fy(yt.scope,yt.path,yt.result);else if(yt.result.errors.length>0)Ny(yt.scope,yt.path,yt.result.errors);else{if(yt.schema==="rules"&&Uy(yt.target))console.log(`
267
267
  Added $schema to ${yt.scope.toLowerCase()} config.`);jy(yt.scope,yt.path,yt.result,yt.schema)}for(let yt of ht)console.error(`
268
268
  ${bt.red(yt)}`);if(vt)if(vt.result.errors.length>0)Hy(vt.path,vt.result.errors);else My(vt.path,vt.result);if(mt)return console.error(`
@@ -272,7 +272,7 @@ All configs valid.`),0}function co(j,K){let te=`legacy ${j} config`;if(K==="clea
272
272
  ✓ ${j} config: ${K}`),console.log(` Schema: ${re==="rules"?"rulebook sources":"legacy inline rules"}`),te.ruleNames.size>0){console.log(` ${re==="rules"?"Sources":"Rules"}:`);let oe=1;for(let ce of te.ruleNames)console.log(` ${oe}. ${ce}`),oe++}else console.log(` ${re==="rules"?"Sources":"Rules"}: (none)`)}function Fy(j,K,te){if(console.error(`
273
273
  ✗ Legacy ${j.toLowerCase()} config: ${K}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),te.errors.length>0){console.error(" Errors:");let re=1;for(let oe of te.errors)for(let ce of oe.split("; "))console.error(` ${re}. ${ce}`),re++;return}if(te.ruleNames.size>0){console.error(" Rules:");let re=1;for(let oe of te.ruleNames)console.error(` ${re}. ${oe}`),re++;return}console.error(" Rules: (none)")}function Ny(j,K,te){Md(`${j} config`,K,te)}function My(j,K){console.log(`
274
274
  ✓ GitHub source rules: ${j}`),console.log(" Rulebooks:");let te=1;for(let re of K.ruleNames)console.log(` ${te}. ${re}`),te++}function Hy(j,K){Md("GitHub source rules",j,K)}function Md(j,K,te){console.error(`
275
- ✗ ${j}: ${K}`),console.error(" Errors:");let re=1;for(let oe of te)for(let ce of oe.split("; "))console.error(` ${re}. ${ce}`),re++}function Uy(j){try{let K=r(j);if(K===null)return!1;let te=JSON.parse(K);if(te.$schema)return!1;return y(j,JSON.stringify({$schema:Ay,...te},null,2)),!0}catch(K){if(K instanceof o)throw K;return!1}}var Hd=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),By=new Set(["add","remove","list"]),qy="cc-safety-net/rulebooks";async function Ud(j,K){try{return await Vy(j,K)}catch(te){if(te instanceof o)return console.error(te.message),1;throw te}}async function Vy(j,K){let te=Jy(K),re=te.help?zy(te.positionals):null;if(re)return _n(re),0;if(te.errors.length>0){for(let we of te.errors)console.error(we);return 1}let oe=te.positionals[0];if(!oe)return _n(kn,console.error),1;let ce=te.positionals[1],de={global:te.global};if(oe==="init"){let we=$t(j,de);Zy(we.configTarget);let xe=Gy(we.configDir,"example-rules","rulebook.json"),Ce=s(we.filesystemScope,xe);if(te.example&&r(Ce)===null)dd(Ce,"example-rules");let Se=W(we.configPath,we.filesystemScope);for(let Ne of Se)console.error(Ne);if(Se.length>0)return 1;return console.log("Rule config initialized."),0}if(oe==="add"){let we=Gd(te);if(!we)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let xe=$t(j,de),Ce=await Ed(j,we,{...de,ref:te.ref,rulebooks:te.only.length>0?te.only:void 0});return id(Ce,we,`Scope: ${te.global?"user":"project"} (${xe.configDir})`),Ce.ok?0:1}if(oe==="remove"){if(!ce)return console.error("rule remove requires a source"),1;let we=await Dd(j,ce,{...de,deleteSource:te.deleteSource});return eo(we,`Removed rulebook source: ${ce}`),we.ok?0:1}if(oe==="update"){let we=await ao(j,{...de,only:ce,refresh:!0});return eo(we,"Rule config updated."),we.ok?0:1}if(oe==="sync")return Ks(j,{global:te.global});if(oe==="list"){let we=Z(j,{cwd:process.cwd()});return ad(we),we.errors.length>0?1:0}if(oe==="wrapper")return Xy(j,te);if(oe==="migrate")return $d(j,{cleanup:te.cleanup,cwd:process.cwd()});if(oe==="doc"){console.log(rd);let we=await jd(j);if(we)console.error(we);return 0}if(oe==="verify")return Nd(j);return 1}function zy(j){if(j.length===0)return kn;let K=kn.subcommands.filter((re)=>re.usage.split(" ")[0]===j[0]);if(K.length===0)return null;if(j.length===1&&K.length>1)return{name:`rule ${j[0]}`,description:`Subcommands of rule ${j[0]}`,usage:`rule ${j[0]} <subcommand>`,subcommands:K,options:[]};let te=j.length===1?K[0]:K.find((re)=>re.usage.split(" ")[1]===j[1]);if(!te)return null;return{name:`rule ${j[0]}`,description:te.description,usage:`rule ${te.usage}`,options:j[0]==="add"?go:[],examples:j[0]==="add"?yo:void 0}}function Jy(j){let K=At({label:"rule",booleans:{global:["-g","--global"],check:["--check"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},j),te={...K.flags,ref:K.values.ref,only:K.lists.only??[],help:K.help,positionals:K.positionals,errors:K.errors};return Wy(te),te}function Wy(j){let[K]=j.positionals;if(K&&!Hd.has(K))j.errors.push(`Unknown rule subcommand: ${K}`);if(j.deleteSource&&K!=="remove")if(K&&Hd.has(K))j.errors.push(`Unknown option for rule ${K}: --delete-source`);else j.errors.push("--delete-source is only valid with 'rule remove'");if(j.check&&K)j.errors.push(Fn(K,"--check"));if(j.cleanup&&K!=="migrate")j.errors.push(Fn(K,"--cleanup"));if(j.example&&K!=="init")j.errors.push(Fn(K,"--example"));if(j.ref&&K!=="add")j.errors.push(Fn(K,"--ref"));if(j.only.length>0&&K!=="add")j.errors.push(Fn(K,"--only"));if(K==="add")Ky(j);if(K==="migrate"){if(j.global)j.errors.push(Fn(K,"--global"));if(j.positionals.length>1)j.errors.push(`Unexpected rule migrate argument: ${j.positionals[1]}`)}else if(K==="wrapper")Yy(j);else if(j.positionals.length>2)j.errors.push(`Unexpected rule argument: ${j.positionals[2]}`);if(K==="list"&&j.global)j.errors.push("Unknown option for rule list: --global")}function Gd(j){if(j.positionals[1])return j.positionals[1];if(j.ref||j.only.length>0)return qy;return}function Ky(j){let K=Gd(j);if(!K)return;if((j.ref||j.only.length>0)&&!Y(K)){if(j.ref)j.errors.push(`--ref can only select a ref for an owner/repo source: ${K}`);if(j.only.length>0)j.errors.push("--only can only select rulebooks from an owner/repo source");return}if(j.ref&&!ie(j.ref))j.errors.push(`--ref must use valid path segments: ${j.ref}`);let te=j.only.filter((re)=>!c.test(re));if(te.length>0)j.errors.push(`Invalid rulebook names: ${te.join(", ")}`)}function Fn(j,K){return j?`Unknown option for rule ${j}: ${K}`:`Unknown option for rule: ${K}`}function Yy(j){let K=j.positionals[1],te=j.positionals[2];if(!K){j.errors.push("rule wrapper requires add, remove, or list");return}if(!By.has(K)){j.errors.push(`Unknown rule wrapper action: ${K}`);return}if(K==="list"){if(te)j.errors.push(`Unexpected rule wrapper argument: ${te}`);return}if(!te){j.errors.push(`rule wrapper ${K} requires a command`);return}if(j.positionals.length>3)j.errors.push(`Unexpected rule wrapper argument: ${j.positionals[3]}`)}function Zy(j){if(r(j)===null){cd(j);return}let K=m(j);if(!K.config)return;It(j,{version:1,rules:K.config.rules,overrides:K.config.overrides??{},transparent_wrappers:K.config.transparent_wrappers??[]})}async function Xy(j,K){let te=K.positionals[1],re=K.positionals[2],oe=$t(j,{global:K.global}).configTarget;if(te==="list"){let xe=m(oe);if(xe.errors.length>0){for(let Ce of xe.errors)console.error(Ce);return 1}return Qy(xe.config?.transparent_wrappers??[]),0}if(!re||!L.test(re))return console.error("transparent wrapper must match command pattern"),1;if(Me(re))return console.error(`reserved command "${re}" cannot be a wrapper`),1;let ce=m(oe);if(ce.errors.length>0){for(let xe of ce.errors)console.error(xe);return 1}let de=ce.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},we=te==="add"?[...new Set([...de.transparent_wrappers??[],re])]:(de.transparent_wrappers??[]).filter((xe)=>xe!==re);return It(oe,{version:1,rules:de.rules,overrides:de.overrides??{},transparent_wrappers:we}),console.log(te==="add"?`Added transparent wrapper: ${re}`:`Removed transparent wrapper: ${re}`),0}function Qy(j){if(j.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${j.length}):`);for(let K of j)console.log(` - ${K}`)}import{sep as ih}from"node:path";import{existsSync as eh,readFileSync as th}from"node:fs";import{join as nh}from"node:path";async function rh(j){if(j.isTTY)return null;return(await Xe(j).catch(()=>null))?.trim()||null}function oh(j){let K=j.env.get("CLAUDE_SETTINGS_PATH");if(K)return K;return nh(j.home,".claude","settings.json")}function Mi(j){let K=oh(j);if(!eh(K))return!1;try{let te=th(K,"utf-8"),re=JSON.parse(te);if(!re.enabledPlugins)return!1;let oe="cc-safety-net@cc-marketplace";if(!(oe in re.enabledPlugins))return!1;return re.enabledPlugins[oe]===!0}catch(te){if(_(i.debug,j.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${K}: ${te instanceof Error?te.message:String(te)}`);return!1}}async function Hi(j,K=process.stdin){let te=Mi(j),re;if(!te)re="\uD83D\uDEE1️ CC Safety Net ❌";else{let ce=k(j,{cwd:process.cwd()}),de=ce.policy,we=P(de,j.env),xe=Object.values(B(de,we.capabilities)).some((Ne)=>Ne.changesInherited),Ce={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[xe?"custom":we.effectiveLevel],Se=(ce.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";re=`\uD83D\uDEE1️ CC Safety Net ${Ce}${we.worktreeMode?"\uD83C\uDF33":""}${Se}${ce.state==="degraded"?"⚠️":""}`}let oe=await rh(K);if(oe&&!oe.startsWith("{"))console.log(`${oe} | ${re}`);else console.log(re)}function Bd(j){let K=k(j,{cwd:process.cwd()}),te=K.policy,re=P(te,j.env),oe=!!process.env.NO_COLOR||!process.stdout.isTTY,ce=Math.min(process.stdout.columns||80,100),de=oe?"ok":"✔",we=oe?"OFF":"✘",xe=(it,gt)=>{let ht=` ${it.padEnd(13)}${gt}`;return(ht.length>ce?`${ht.slice(0,ce-1)}…`:ht).replaceAll(we,bt.red(we))},Ce=Object.values(B(te,re.capabilities)).some((it)=>it.changesInherited),Se=(it)=>it===j.home||it.startsWith(`${j.home}${ih}`)?`~${it.slice(j.home.length)}`:it,Ne={ready:bt.green,degraded:bt.yellow}[K.state],He=K.policyScopes?.weakenings??[],at=[...Mi(j)?[]:["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."],...K.diagnostics],mt=oe?"-":"·";console.log([`${oe?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ne(K.state)}`,"",xe("Protection",`destructive ${te.destructiveCommandProtectionEnabled?de:we} secrets ${te.secretProtection.enabled?de:we}`),xe("Level",Ce?`${re.effectiveLevel} (customised)`:re.effectiveLevel),xe("Rules",te.rules.length===0?"none active":`${te.rules.length} active`),xe("Policy",Se(d(j))),...K.policyScopes?[xe("Project",Se(w(process.cwd())))]:[],...re.worktreeMode?[xe("Worktree","relaxations active")]:[],"",...He.length===0?[]:[" Project policy",...He.flatMap((it)=>Qn(it," ",ce-6).map((gt,ht)=>ht===0?` ${gt}`:gt)),""],...at.length===0?[" Everything configured is active."]:[" Not active",...at.flatMap((it)=>Qn(it," ",ce-6).map((gt,ht)=>ht===0?` ${mt} ${gt}`:gt)),""," Full report: cc-safety-net doctor"]].join(`
275
+ ✗ ${j}: ${K}`),console.error(" Errors:");let re=1;for(let oe of te)for(let ce of oe.split("; "))console.error(` ${re}. ${ce}`),re++}function Uy(j){try{let K=r(j);if(K===null)return!1;let te=JSON.parse(K);if(te.$schema)return!1;return y(j,JSON.stringify({$schema:Ay,...te},null,2)),!0}catch(K){if(K instanceof o)throw K;return!1}}var Hd=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),By=new Set(["add","remove","list"]),qy="cc-safety-net/rulebooks";async function Ud(j,K){try{return await Vy(j,K)}catch(te){if(te instanceof o)return console.error(te.message),1;throw te}}async function Vy(j,K){let te=Jy(K),re=te.help?zy(te.positionals):null;if(re)return _n(re),0;if(te.errors.length>0){for(let we of te.errors)console.error(we);return 1}let oe=te.positionals[0];if(!oe)return _n(kn,console.error),1;let ce=te.positionals[1],de={global:te.global};if(oe==="init"){let we=$t(j,de);Zy(we.configTarget);let xe=Gy(we.configDir,"example-rules","rulebook.json"),Ce=s(we.filesystemScope,xe);if(te.example&&r(Ce)===null)dd(Ce,"example-rules");let Se=W(we.configPath,we.filesystemScope);for(let Ne of Se)console.error(Ne);if(Se.length>0)return 1;return console.log("Rule config initialized."),0}if(oe==="add"){let we=Gd(te);if(!we)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let xe=$t(j,de),Ce=await Ed(j,we,{...de,ref:te.ref,rulebooks:te.only.length>0?te.only:void 0});return id(Ce,we,`Scope: ${te.global?"user":"project"} (${xe.configDir})`),Ce.ok?0:1}if(oe==="remove"){if(!ce)return console.error("rule remove requires a source"),1;let we=await Dd(j,ce,{...de,deleteSource:te.deleteSource});return eo(we,`Removed rulebook source: ${ce}`),we.ok?0:1}if(oe==="update"){let we=await ao(j,{...de,only:ce,refresh:!0});return eo(we,"Rule config updated."),we.ok?0:1}if(oe==="sync")return Zs(j,{global:te.global});if(oe==="list"){let we=Z(j,{cwd:process.cwd()});return ad(we),we.errors.length>0?1:0}if(oe==="wrapper")return Xy(j,te);if(oe==="migrate")return $d(j,{cleanup:te.cleanup,cwd:process.cwd()});if(oe==="doc"){console.log(rd);let we=await jd(j);if(we)console.error(we);return 0}if(oe==="verify")return Nd(j);return 1}function zy(j){if(j.length===0)return kn;let K=kn.subcommands.filter((re)=>re.usage.split(" ")[0]===j[0]);if(K.length===0)return null;if(j.length===1&&K.length>1)return{name:`rule ${j[0]}`,description:`Subcommands of rule ${j[0]}`,usage:`rule ${j[0]} <subcommand>`,subcommands:K,options:[]};let te=j.length===1?K[0]:K.find((re)=>re.usage.split(" ")[1]===j[1]);if(!te)return null;return{name:`rule ${j[0]}`,description:te.description,usage:`rule ${te.usage}`,options:j[0]==="add"?go:[],examples:j[0]==="add"?yo:void 0}}function Jy(j){let K=At({label:"rule",booleans:{global:["-g","--global"],check:["--check"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},j),te={...K.flags,ref:K.values.ref,only:K.lists.only??[],help:K.help,positionals:K.positionals,errors:K.errors};return Wy(te),te}function Wy(j){let[K]=j.positionals;if(K&&!Hd.has(K))j.errors.push(`Unknown rule subcommand: ${K}`);if(j.deleteSource&&K!=="remove")if(K&&Hd.has(K))j.errors.push(`Unknown option for rule ${K}: --delete-source`);else j.errors.push("--delete-source is only valid with 'rule remove'");if(j.check&&K)j.errors.push(Fn(K,"--check"));if(j.cleanup&&K!=="migrate")j.errors.push(Fn(K,"--cleanup"));if(j.example&&K!=="init")j.errors.push(Fn(K,"--example"));if(j.ref&&K!=="add")j.errors.push(Fn(K,"--ref"));if(j.only.length>0&&K!=="add")j.errors.push(Fn(K,"--only"));if(K==="add")Ky(j);if(K==="migrate"){if(j.global)j.errors.push(Fn(K,"--global"));if(j.positionals.length>1)j.errors.push(`Unexpected rule migrate argument: ${j.positionals[1]}`)}else if(K==="wrapper")Yy(j);else if(j.positionals.length>2)j.errors.push(`Unexpected rule argument: ${j.positionals[2]}`);if(K==="list"&&j.global)j.errors.push("Unknown option for rule list: --global")}function Gd(j){if(j.positionals[1])return j.positionals[1];if(j.ref||j.only.length>0)return qy;return}function Ky(j){let K=Gd(j);if(!K)return;if((j.ref||j.only.length>0)&&!Y(K)){if(j.ref)j.errors.push(`--ref can only select a ref for an owner/repo source: ${K}`);if(j.only.length>0)j.errors.push("--only can only select rulebooks from an owner/repo source");return}if(j.ref&&!ie(j.ref))j.errors.push(`--ref must use valid path segments: ${j.ref}`);let te=j.only.filter((re)=>!c.test(re));if(te.length>0)j.errors.push(`Invalid rulebook names: ${te.join(", ")}`)}function Fn(j,K){return j?`Unknown option for rule ${j}: ${K}`:`Unknown option for rule: ${K}`}function Yy(j){let K=j.positionals[1],te=j.positionals[2];if(!K){j.errors.push("rule wrapper requires add, remove, or list");return}if(!By.has(K)){j.errors.push(`Unknown rule wrapper action: ${K}`);return}if(K==="list"){if(te)j.errors.push(`Unexpected rule wrapper argument: ${te}`);return}if(!te){j.errors.push(`rule wrapper ${K} requires a command`);return}if(j.positionals.length>3)j.errors.push(`Unexpected rule wrapper argument: ${j.positionals[3]}`)}function Zy(j){if(r(j)===null){cd(j);return}let K=m(j);if(!K.config)return;It(j,{version:1,rules:K.config.rules,overrides:K.config.overrides??{},transparent_wrappers:K.config.transparent_wrappers??[]})}async function Xy(j,K){let te=K.positionals[1],re=K.positionals[2],oe=$t(j,{global:K.global}).configTarget;if(te==="list"){let xe=m(oe);if(xe.errors.length>0){for(let Ce of xe.errors)console.error(Ce);return 1}return Qy(xe.config?.transparent_wrappers??[]),0}if(!re||!L.test(re))return console.error("transparent wrapper must match command pattern"),1;if(Me(re))return console.error(`reserved command "${re}" cannot be a wrapper`),1;let ce=m(oe);if(ce.errors.length>0){for(let xe of ce.errors)console.error(xe);return 1}let de=ce.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},we=te==="add"?[...new Set([...de.transparent_wrappers??[],re])]:(de.transparent_wrappers??[]).filter((xe)=>xe!==re);return It(oe,{version:1,rules:de.rules,overrides:de.overrides??{},transparent_wrappers:we}),console.log(te==="add"?`Added transparent wrapper: ${re}`:`Removed transparent wrapper: ${re}`),0}function Qy(j){if(j.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${j.length}):`);for(let K of j)console.log(` - ${K}`)}import{sep as ih}from"node:path";import{existsSync as eh,readFileSync as th}from"node:fs";import{join as nh}from"node:path";async function rh(j){if(j.isTTY)return null;return(await Xe(j).catch(()=>null))?.trim()||null}function oh(j){let K=j.env.get("CLAUDE_SETTINGS_PATH");if(K)return K;return nh(j.home,".claude","settings.json")}function Ui(j){let K=oh(j);if(!eh(K))return!1;try{let te=th(K,"utf-8"),re=JSON.parse(te);if(!re.enabledPlugins)return!1;let oe="cc-safety-net@cc-marketplace";if(!(oe in re.enabledPlugins))return!1;return re.enabledPlugins[oe]===!0}catch(te){if(_(i.debug,j.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${K}: ${te instanceof Error?te.message:String(te)}`);return!1}}async function Gi(j,K=process.stdin){let te=Ui(j),re;if(!te)re="\uD83D\uDEE1️ CC Safety Net ❌";else{let ce=k(j,{cwd:process.cwd()}),de=ce.policy,we=P(de,j.env),xe=Object.values(B(de,we.capabilities)).some((Ne)=>Ne.changesInherited),Ce={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[xe?"custom":we.effectiveLevel],Se=(ce.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";re=`\uD83D\uDEE1️ CC Safety Net ${Ce}${we.worktreeMode?"\uD83C\uDF33":""}${Se}${ce.state==="degraded"?"⚠️":""}`}let oe=await rh(K);if(oe&&!oe.startsWith("{"))console.log(`${oe} | ${re}`);else console.log(re)}function Bd(j){let K=k(j,{cwd:process.cwd()}),te=K.policy,re=P(te,j.env),oe=!!process.env.NO_COLOR||!process.stdout.isTTY,ce=Math.min(process.stdout.columns||80,100),de=oe?"ok":"✔",we=oe?"OFF":"✘",xe=(it,gt)=>{let ht=` ${it.padEnd(13)}${gt}`;return(ht.length>ce?`${ht.slice(0,ce-1)}…`:ht).replaceAll(we,bt.red(we))},Ce=Object.values(B(te,re.capabilities)).some((it)=>it.changesInherited),Se=(it)=>it===j.home||it.startsWith(`${j.home}${ih}`)?`~${it.slice(j.home.length)}`:it,Ne={ready:bt.green,degraded:bt.yellow}[K.state],He=K.policyScopes?.weakenings??[],at=[...Ui(j)?[]:["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."],...K.diagnostics],mt=oe?"-":"·";console.log([`${oe?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ne(K.state)}`,"",xe("Protection",`destructive ${te.destructiveCommandProtectionEnabled?de:we} secrets ${te.secretProtection.enabled?de:we}`),xe("Level",Ce?`${re.effectiveLevel} (customised)`:re.effectiveLevel),xe("Rules",te.rules.length===0?"none active":`${te.rules.length} active`),xe("Policy",Se(d(j))),...K.policyScopes?[xe("Project",Se(w(process.cwd())))]:[],...re.worktreeMode?[xe("Worktree","relaxations active")]:[],"",...He.length===0?[]:[" Project policy",...He.flatMap((it)=>Qn(it," ",ce-6).map((gt,ht)=>ht===0?` ${gt}`:gt)),""],...at.length===0?[" Everything configured is active."]:[" Not active",...at.flatMap((it)=>Qn(it," ",ce-6).map((gt,ht)=>ht===0?` ${mt} ${gt}`:gt)),""," Full report: cc-safety-net doctor"]].join(`
276
276
  `))}import{spawn as eu}from"node:child_process";import{randomBytes as gh}from"node:crypto";import{existsSync as yh}from"node:fs";import{createServer as hh}from"node:http";import{Writable as vh}from"node:stream";var uo=500;function sh(j){let K=j.filter((oe)=>oe.decision!=="allow"),te=j.filter((oe)=>oe.decision==="allow"),re=Math.min(K.length,Math.max(uo-te.length,Math.ceil(uo/2)));return[...K.slice(0,re),...te.slice(0,uo-re)]}function qd(j,K,te=M(j)){if(te)q(j,te);let re=(gt)=>new Date(gt.getFullYear(),gt.getMonth(),gt.getDate()).getTime(),oe=re(new Date),ce=new Date(oe);ce.setDate(ce.getDate()-(K-1));let de=ce.getTime(),we=[],xe={count:0};for(let gt of te?an(te,xe):[])for(let ht of wn(gt,xe)){if(!ht||typeof ht.ts!=="string"||typeof ht.command!=="string")continue;let vt=new Date(ht.ts).getTime();if(!Number.isFinite(vt))continue;if(vt>=de)we.push(ht)}we.sort((gt,ht)=>new Date(ht.ts).getTime()-new Date(gt.ts).getTime());let Ce=Array.from({length:K},()=>0),Se=Array.from({length:K},()=>0),Ne={},He={},at={},mt=0,it=0;for(let gt of we){let ht=gt.agent||"unknown";Ne[ht]=(Ne[ht]??0)+1;let vt=Math.round((oe-re(new Date(gt.ts)))/86400000),yt=K-1-vt,kt=vt>=0&&vt<K;if(kt)Se[yt]=(Se[yt]??0)+1;if(gt.decision!=="allow"){if(mt++,gt.ruleId)He[gt.ruleId]=(He[gt.ruleId]??0)+1;let Lt=dr(gt.segment||gt.command);if(Lt)at[Lt]=(at[Lt]??0)+1;if(gt.failureStage)it++;if(kt)Ce[yt]=(Ce[yt]??0)+1}}return{days:K,logsDir:te,homeDir:j.home,totalInWindow:we.length,truncated:we.length>uo,unreadable:xe.count,counts:{blocked:mt,allowed:we.length-mt,agents:Ne,blockedByDay:Ce,analyzedByDay:Se,rules:He,commands:at,errors:it},entries:sh(we).sort((gt,ht)=>new Date(ht.ts).getTime()-new Date(gt.ts).getTime())}}import{spawn as ah}from"node:child_process";import{existsSync as lh,statSync as Vd}from"node:fs";import{delimiter as ch,join as dh}from"node:path";var uh=120000,po="Choose the project folder",ph=`try
277
277
  return POSIX path of (choose folder with prompt "${po}")
278
278
  on error number -128
@@ -280,7 +280,7 @@ on error number -128
280
280
  end try`,fh=`Add-Type -AssemblyName System.Windows.Forms
281
281
  $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
282
282
  $dialog.Description = '${po}'
283
- if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,zd=[{binary:"zenity",args:["--file-selection","--directory",`--title=${po}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",po]}],Jd=(j,K)=>(K.PATH??"").split(ch).some((te)=>{if(te.length===0)return!1;try{let re=Vd(dh(te,j));return re.isFile()&&(re.mode&73)!==0}catch{return!1}});function Ui(j,K){if(j==="darwin"||j==="win32")return!0;if(j!=="linux")return!1;if(!K.DISPLAY&&!K.WAYLAND_DISPLAY)return!1;return zd.some((te)=>Jd(te.binary,K))}function mh(j,K){if(j==="darwin")return{cmd:"osascript",args:["-e",ph]};if(j==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",fh]};let te=zd.find((re)=>Jd(re.binary,K));return te?{cmd:te.binary,args:te.args}:null}function Gi(j=process.platform,K=process.env){let te=mh(j,K);if(!te)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((re)=>{let oe=ah(te.cmd,te.args,{env:K,stdio:["ignore","pipe","pipe"]}),ce="",de=!1,we=(Ce)=>{if(de)return;de=!0,clearTimeout(xe),re(Ce)},xe=setTimeout(()=>{oe.kill(),we({error:"The folder dialog timed out"})},uh);oe.stdout.on("data",(Ce)=>{ce+=Ce.toString()}),oe.on("error",()=>we({error:`Could not open the folder dialog (${te.cmd})`})),oe.on("close",()=>{let Ce=ce.trim().replace(/\/+$/,"");if(!Ce)return we({cancelled:!0});if(!lh(Ce)||!Vd(Ce).isDirectory())return we({error:"That selection is not a folder on disk"});we({path:Ce})})})}var Wd=`<!doctype html>
283
+ if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,zd=[{binary:"zenity",args:["--file-selection","--directory",`--title=${po}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",po]}],Jd=(j,K)=>(K.PATH??"").split(ch).some((te)=>{if(te.length===0)return!1;try{let re=Vd(dh(te,j));return re.isFile()&&(re.mode&73)!==0}catch{return!1}});function Bi(j,K){if(j==="darwin"||j==="win32")return!0;if(j!=="linux")return!1;if(!K.DISPLAY&&!K.WAYLAND_DISPLAY)return!1;return zd.some((te)=>Jd(te.binary,K))}function mh(j,K){if(j==="darwin")return{cmd:"osascript",args:["-e",ph]};if(j==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",fh]};let te=zd.find((re)=>Jd(re.binary,K));return te?{cmd:te.binary,args:te.args}:null}function qi(j=process.platform,K=process.env){let te=mh(j,K);if(!te)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((re)=>{let oe=ah(te.cmd,te.args,{env:K,stdio:["ignore","pipe","pipe"]}),ce="",de=!1,we=(Ce)=>{if(de)return;de=!0,clearTimeout(xe),re(Ce)},xe=setTimeout(()=>{oe.kill(),we({error:"The folder dialog timed out"})},uh);oe.stdout.on("data",(Ce)=>{ce+=Ce.toString()}),oe.on("error",()=>we({error:`Could not open the folder dialog (${te.cmd})`})),oe.on("close",()=>{let Ce=ce.trim().replace(/\/+$/,"");if(!Ce)return we({cancelled:!0});if(!lh(Ce)||!Vd(Ce).isDirectory())return we({error:"That selection is not a folder on disk"});we({path:Ce})})})}var Wd=`<!doctype html>
284
284
  <html lang="en">
285
285
  <head>
286
286
  <meta charset="utf-8">
@@ -5914,6 +5914,6 @@ load().then((loaded) => {
5914
5914
  </script>
5915
5915
  </body>
5916
5916
  </html>
5917
- `;var Kd='<script id="ccsn-data" type="application/json">';function Yd(j){return Wd.replace(Kd,()=>Kd+JSON.stringify({token:j}).replaceAll("<","\\u003c"))}var fo="kenryu42/cc-safety-net",bh=`https://github.com/${fo}`,Vi=1e4,Lh=7,wh="The project draft directory changed; reload the draft before applying.",kh="audit settings are user scope only; remove the audit section from a project proposal";async function tu(j,K={}){let te=At({label:"gui",booleans:{noOpen:["--no-open"]}},j),re=K.log??console.log,oe=K.error??console.error;if(te.errors.length>0){for(let de of te.errors)oe(de);return oe("Usage: cc-safety-net gui [--no-open]"),1}let ce=await xh(l,K);if(re(`CC Safety Net policy GUI: ${ce.url}`),!te.flags.noOpen)try{await(K.openBrowser??$h)(ce.url)}catch(de){oe(`Failed to open browser: ${de instanceof Error?de.message:String(de)}`),oe(`Open this URL manually: ${ce.url}`)}if(K.keepAlive===!1)return await ce.close(),0;return await Ih(ce),0}async function xh(j,K={}){let te=gh(24).toString("base64url"),re={dir:null,revision:0},oe=hh((we,xe)=>{Ch(j,we,xe,te,K,re)});await new Promise((we,xe)=>{oe.once("error",xe),oe.listen(0,"127.0.0.1",()=>{oe.off("error",xe),we()})});let de=`http://127.0.0.1:${oe.address().port}`;return{origin:de,token:te,url:`${de}/?token=${encodeURIComponent(te)}`,close:()=>Th(oe)}}async function Ch(j,K,te,re,oe,ce){let de=j(),we=new URL(K.url??"/","http://127.0.0.1");if(K.method==="GET"&&we.pathname==="/favicon.ico"){te.writeHead(204,{"cache-control":"no-store"}),te.end();return}if(!Dh(K,we,re)){xt(te,403,{error:"Forbidden"});return}if(K.method==="GET"&&we.pathname==="/"){_h(te,Yd(re));return}if(K.method==="GET"&&we.pathname==="/api/policy"){let xe=Yc(de,oe),Ce=k(de,Bi(oe));xt(te,200,{...xe,configState:Be(Ce),...Ce.policyScopes?{projectPolicy:{path:w(oe.cwd??process.cwd()),weakenings:Ce.policyScopes.weakenings}}:{},destructiveCommandRules:U,secretPatterns:rt,version:Et(),preview:xe.errors.length>0?null:Ge(xe.policy,de.env)});return}if(K.method==="POST"&&we.pathname==="/api/policy/preview"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=Zc(de,xe.value);xt(te,Ce.errors.length>0?400:200,Ce);return}if(K.method==="POST"&&we.pathname==="/api/policy/explain"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=xe.value;if(Ce===null||typeof Ce.command!=="string"){xt(te,400,{errors:["command must be a string"]});return}let Se=Ut(Ce.policy,de.home);if(Se.length>0){xt(te,400,{errors:Se});return}xt(te,200,Ph(de,Ce.command,Ce.policy,oe));return}if(K.method==="POST"&&we.pathname==="/api/policy"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=Xt(de,xe.value,oe);xt(te,Ce.errors.length>0?400:200,Ce);return}if(K.method==="POST"&&we.pathname==="/api/reset"){xt(te,200,Xt(de,Q,oe));return}if(K.method==="POST"&&we.pathname==="/api/repair"){xt(te,200,Xc(de,oe));return}if(K.method==="POST"&&we.pathname==="/api/policy/project/choose-directory"){let xe=await(oe.chooseDirectory??Gi)();if("path"in xe)ce.dir=xe.path,ce.revision+=1;xt(te,200,{cancelled:"cancelled"in xe,..."error"in xe?{error:xe.error}:{}});return}if(K.method==="GET"&&we.pathname==="/api/policy/project"){let xe=nu(ce,oe),Ce=Zd(xe,de.home),Se=sr(de,oe);xt(te,200,{dir:xe,path:w(xe),revision:ce.revision,baseline:Se.baseline,userPolicyDiagnostics:Se.diagnostics,projection:Ce.projection,projectionDiagnostics:Ce.diagnostics,canPickDirectory:Ui(process.platform,process.env)});return}if(K.method==="POST"&&we.pathname==="/api/policy/project/diff"){let xe=await Xd(de,K,te,ce,oe);if(!xe)return;let Ce=Zd(xe.dir,de.home),Se=sr(de,oe).baseline,Ne=X(Se,le(xe.proposal,de.home).policy);xt(te,200,{rows:Xr(X(Se,Ce.projection).policy,Ne.policy,!1),weakenings:Ne.weakenings,existingFileDiagnostics:Ce.diagnostics,errors:[]});return}if(K.method==="POST"&&we.pathname==="/api/policy/project/apply"){let xe=await Xd(de,K,te,ce,oe);if(!xe)return;let Ce=Rh(xe.dir,xe.proposal,de.home);xt(te,Ce.errors.length>0?500:200,Ce);return}if(K.method==="GET"&&we.pathname==="/api/activity"){let xe=ne(de,oe),Ce=Eh(we.searchParams.get("days"),xe);if(Ce===null){xt(te,400,{error:`days must be an integer between 1 and ${xe}`});return}xt(te,200,qd(de,Ce,oe.activityLogsDir));return}if(K.method==="POST"&&we.pathname==="/api/rules/choose-directory"){xt(te,200,await Gi());return}if(K.method==="GET"&&we.pathname==="/api/rules"){let xe=Z(de,Bi(oe)),Ce=new Map(xe.rules.map((Se)=>[Se.name,Se]));xt(te,200,{projectPath:oe.cwd??process.cwd(),canPickDirectory:Ui(process.platform,process.env),rulebooks:xe.rulebooks.map((Se)=>({source:Se.source,spec:Se.spec,name:Se.name,version:Se.version,rules:Se.rules.flatMap((Ne)=>{let He=Ce.get(Ne);if(!He)return[];return[{name:He.name,command:He.command,subcommand:He.subcommand,block_args:He.block_args,reason:He.reason}]})})),errors:xe.errors,warnings:xe.warnings});return}if(K.method==="GET"&&we.pathname==="/api/star/context"){xt(te,200,await(oe.fetchStarContext??(()=>Mh(de,{logsDir:oe.activityLogsDir})))());return}if(K.method==="POST"&&we.pathname==="/api/star"){let xe=await(oe.starRepo??Oh)();xt(te,200,xe.ok?{ok:!0}:{ok:!1,fallbackUrl:bh});return}if(K.method==="GET"&&we.pathname==="/api/integrations"){xt(te,200,await(oe.fetchIntegrations??(()=>jh(de)))());return}if(K.method==="GET"&&we.pathname==="/api/health"){xt(te,200,await(oe.fetchHealth??(()=>Fh(de)))());return}if(K.method==="POST"&&(we.pathname==="/api/install"||we.pathname==="/api/uninstall")){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=xe.value?.target;if(typeof Ce!=="string"||!Wt.some((Ne)=>Ne.target===Ce)){xt(te,400,{error:"unknown target"});return}let Se=we.pathname==="/api/install"?"install":"uninstall";xt(te,200,await(oe.runIntegration??Nh)(Se,Ce));return}xt(te,404,{error:"Not found"})}function Bi(j){return{...j,cwd:j.cwd??process.cwd()}}function nu(j,K){return j.dir??K.cwd??process.cwd()}function Zd(j,K){let te=w(j),re=yh(te)?bn(te):{value:void 0,errors:[]},oe=le(re.value,K);return{projection:oe.policy,diagnostics:[...re.errors,...oe.diagnostics]}}async function Xd(j,K,te,re,oe){let ce=nu(re,oe),de=re.revision,we=await cr(K);if(!we.ok)return xt(te,we.status,{errors:[we.error]}),null;let xe=we.value;if(typeof xe?.revision!=="number")return xt(te,400,{errors:["revision must be a number"]}),null;if(xe.revision!==de)return xt(te,409,{errors:[wh]}),null;let Ce=Sh(xe.proposal,j.home);if(Ce.length>0)return xt(te,400,{errors:Ce}),null;return{dir:ce,proposal:xe.proposal}}function Sh(j,K){let te=Ut(j,K);if(te.length>0)return te;return j?.audit===void 0?[]:[kh]}function Rh(j,K,te){let re=w(j),oe=Qr(K,h(K,te));try{return y(s(S(j,"project policy"),re),`${JSON.stringify(oe,null,2)}
5918
- `),{path:re,errors:[]}}catch(ce){return{path:re,errors:[ce instanceof Error?ce.message:String(ce)]}}}function Ph(j,K,te,re){let oe=h(te,j.home),ce=k(j,Bi(re)),de=De({rules:ce.policy.rules,transparentWrappers:ce.policy.transparentWrappers,safety:Ue(oe.safety),worktreeMode:oe.workflow.worktree_mode,destructiveCommandProtectionEnabled:oe.destructive_command_protection.enabled,destructiveCommandRuleOverrides:oe.destructive_command_protection.overrides,destructiveCommandAllowPaths:oe.destructive_command_protection.allow_paths,secretProtection:{enabled:oe.secret_protection.enabled,disabledRules:We(oe.secret_protection.overrides),denyPaths:oe.secret_protection.deny_paths,allowPaths:oe.secret_protection.allow_paths}});return er(K,{policySnapshot:de,cwd:re.cwd,userConfigDir:re.userConfigDir},j)}function Eh(j,K){if(j===null)return Math.min(Lh,K);let te=Number(j);if(!Number.isInteger(te)||te<1||te>K)return null;return te}function Dh(j,K,te){if(K.searchParams.get("token")!==te)return!1;if(j.method!=="POST")return!0;return j.headers["x-cc-safety-net-token"]===te}var Ah=1048576;async function cr(j){let K=[],te=0;for await(let re of j){let oe=re;if(te+=oe.byteLength,te>Ah)return{ok:!1,status:413,error:"Request body is too large"};K.push(oe)}try{return{ok:!0,value:JSON.parse(Buffer.concat(K).toString("utf-8")||"{}")}}catch(re){return{ok:!1,status:400,error:`Invalid JSON: ${re instanceof Error?re.message:String(re)}`}}}function _h(j,K){j.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),j.end(K)}function xt(j,K,te){j.writeHead(K,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),j.end(JSON.stringify(te))}function Th(j){return new Promise((K,te)=>{j.close((re)=>re?te(re):K())})}function Ih(j){return new Promise((K)=>{let te=()=>{process.off("SIGINT",re),process.off("SIGTERM",re)},re=()=>{te(),j.close().then(K)};process.once("SIGINT",re),process.once("SIGTERM",re)})}function $h(j){let K=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",te=process.platform==="win32"?["/c","start","",j]:[j];return new Promise((re,oe)=>{let ce=eu(K,te,{detached:!0,stdio:"ignore"}),de=(xe)=>{ce.off("spawn",we),oe(xe)},we=()=>{ce.off("error",de),ce.unref(),re()};ce.once("error",de),ce.once("spawn",we)})}async function Oh(j="gh",K=Vi){return{ok:await qi(j,["api","-X","PUT",`/user/starred/${fo}`],K)===0}}async function jh(j,K={}){let te=await Hn(K.fetcher),re=ru(j,te);return{targets:Nt.map((oe)=>{let ce=re.find((de)=>de.platform===oe.id);return{target:oe.id,label:St(oe.id),version:te.versions[oe.id]??null,status:ce?.configured?"active":ce?.detected?"disabled":ce?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:te.version,nodeVersion:te.nodeVersion,platform:te.platform}}}function ru(j,K){return Dn(j,process.cwd(),{ampPluginListOutput:K.ampPluginListOutput,codexPluginListOutput:K.codexPluginListOutput,copilotCliVersion:K.versions["copilot-cli"]})}async function Fh(j,K={}){let[te,re]=await Promise.all([Hn(K.fetcher),(K.checkUpdates??tn)()]);return{hooks:ru(j,te).filter((oe)=>oe.detected).map((oe)=>({platform:oe.platform,label:St(oe.platform),configured:oe.configured})),update:{currentVersion:re.currentVersion,latestVersion:re.latestVersion??null,updateAvailable:re.updateAvailable}}}var Qd=Promise.resolve();function Nh(j,K,te={}){let re=async()=>{let ce=[],{log:de,error:we}=console;console.log=(...xe)=>ce.push(xe.map(String).join(" ")),console.error=console.log;try{return{ok:await ir(j,[],{selectTargets:async()=>[K],output:new vh({write(Ce,Se,Ne){ce.push(String(Ce).replace(/\n$/,"")),Ne()}}),...te})===0,output:ce.join(`
5919
- `)}}finally{console.log=de,console.error=we}},oe=Qd.then(re);return Qd=oe.then(()=>{return},()=>{return}),oe}async function Mh(j,K={}){let[te,re,oe]=await Promise.all([Hh(K.command),Uh(K.fetchRepo),Promise.resolve(gr(j,ne(j),K.logsDir).totalBlocked)]);return{starred:te,starCount:re,blockedTotal:oe}}async function Hh(j="gh",K=Vi){if(await qi(j,["auth","status"],K)!==0)return null;let te=await qi(j,["api",`/user/starred/${fo}`],K);if(te===0)return!0;if(te===null)return null;return!1}function qi(j,K,te){return new Promise((re)=>{let oe=eu(j,K,{stdio:"ignore",windowsHide:!0}),ce=!1,de,we=(xe)=>{if(ce)return;if(ce=!0,de)clearTimeout(de);re(xe)};oe.once("error",()=>we(null)),oe.once("close",we),de=setTimeout(()=>{oe.kill(),we(null)},te)})}async function Uh(j=fetch){try{let K=await j(`https://api.github.com/repos/${fo}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(Vi)});if(!K.ok)return null;let te=await K.json();return typeof te.stargazers_count==="number"?te.stargazers_count:null}catch{return null}}function Gh(j){if(j[0]!=="help")return!1;let K=j[1];if(!K)pi(),process.exit(0);if(tr(K))process.exit(0);console.error(`Unknown command: ${K}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var Bh={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),tr("hook",console.error),process.exit(1)},install:async(j)=>{process.exit(await ir("install",j))},update:async(j)=>{process.exit(await Ri(j))},uninstall:async(j)=>{process.exit(await ir("uninstall",j))},rule:async(j)=>{process.exit(await Ud(l(),j))},policy:async(j)=>{process.exit(await nd(l(),j))},status:async(j)=>{if(Kt(At({label:"status"},j).errors))process.exit(1);Bd(l())},statusline:async(j)=>{let K=At({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},j);if(K.errors.length===0&&K.flags.claudeCode){await Hi(l());return}if(Kt(K.errors),!K.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");tr("statusline",console.error),process.exit(1)},doctor:async(j)=>{let K=oi(j);if(!K)process.exit(1);let te=await Sl(l(),{json:K.json,skipUpdateCheck:K.skipUpdateCheck});process.exit(te)},logs:async(j)=>{process.exit(await Qi(l(),j))},gui:async(j)=>{process.exit(await tu(j))},explain:async(j)=>{process.exit(await Ol(l(),j))}};async function qh(j){let K=At({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},j);if(Gh(j))return;let te=j[0],re=te?mr(te):void 0;if(K.help&&re&&re.name!=="rule")tr(re.name),process.exit(0);if(!te||K.help&&!re)pi(),process.exit(0);if(K.flags.version)Nl(),process.exit(0);if(re){await Bh[re.name](j.slice(1));return}if(te==="--statusline"){await Hi(l());return}console.error(te.startsWith("-")?`Unknown option: ${te}`:`Unknown command: ${te}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{qh as runCli};
5917
+ `;var Kd='<script id="ccsn-data" type="application/json">';function Yd(j){return Wd.replace(Kd,()=>Kd+JSON.stringify({token:j}).replaceAll("<","\\u003c"))}var fo="kenryu42/cc-safety-net",bh=`https://github.com/${fo}`,Ji=1e4,Lh=7,wh="The project draft directory changed; reload the draft before applying.",kh="audit settings are user scope only; remove the audit section from a project proposal";async function tu(j,K={}){let te=At({label:"gui",booleans:{noOpen:["--no-open"]}},j),re=K.log??console.log,oe=K.error??console.error;if(te.errors.length>0){for(let de of te.errors)oe(de);return oe("Usage: cc-safety-net gui [--no-open]"),1}let ce=await xh(l,K);if(re(`CC Safety Net policy GUI: ${ce.url}`),!te.flags.noOpen)try{await(K.openBrowser??$h)(ce.url)}catch(de){oe(`Failed to open browser: ${de instanceof Error?de.message:String(de)}`),oe(`Open this URL manually: ${ce.url}`)}if(K.keepAlive===!1)return await ce.close(),0;return await Ih(ce),0}async function xh(j,K={}){let te=gh(24).toString("base64url"),re={dir:null,revision:0},oe=hh((we,xe)=>{Ch(j,we,xe,te,K,re)});await new Promise((we,xe)=>{oe.once("error",xe),oe.listen(0,"127.0.0.1",()=>{oe.off("error",xe),we()})});let de=`http://127.0.0.1:${oe.address().port}`;return{origin:de,token:te,url:`${de}/?token=${encodeURIComponent(te)}`,close:()=>Th(oe)}}async function Ch(j,K,te,re,oe,ce){let de=j(),we=new URL(K.url??"/","http://127.0.0.1");if(K.method==="GET"&&we.pathname==="/favicon.ico"){te.writeHead(204,{"cache-control":"no-store"}),te.end();return}if(!Dh(K,we,re)){xt(te,403,{error:"Forbidden"});return}if(K.method==="GET"&&we.pathname==="/"){_h(te,Yd(re));return}if(K.method==="GET"&&we.pathname==="/api/policy"){let xe=Yc(de,oe),Ce=k(de,Vi(oe));xt(te,200,{...xe,configState:Be(Ce),...Ce.policyScopes?{projectPolicy:{path:w(oe.cwd??process.cwd()),weakenings:Ce.policyScopes.weakenings}}:{},destructiveCommandRules:U,secretPatterns:rt,version:Et(),preview:xe.errors.length>0?null:Ge(xe.policy,de.env)});return}if(K.method==="POST"&&we.pathname==="/api/policy/preview"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=Zc(de,xe.value);xt(te,Ce.errors.length>0?400:200,Ce);return}if(K.method==="POST"&&we.pathname==="/api/policy/explain"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=xe.value;if(Ce===null||typeof Ce.command!=="string"){xt(te,400,{errors:["command must be a string"]});return}let Se=Ut(Ce.policy,de.home);if(Se.length>0){xt(te,400,{errors:Se});return}xt(te,200,Ph(de,Ce.command,Ce.policy,oe));return}if(K.method==="POST"&&we.pathname==="/api/policy"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=Qt(de,xe.value,oe);xt(te,Ce.errors.length>0?400:200,Ce);return}if(K.method==="POST"&&we.pathname==="/api/reset"){xt(te,200,Qt(de,Q,oe));return}if(K.method==="POST"&&we.pathname==="/api/repair"){xt(te,200,Xc(de,oe));return}if(K.method==="POST"&&we.pathname==="/api/policy/project/choose-directory"){let xe=await(oe.chooseDirectory??qi)();if("path"in xe)ce.dir=xe.path,ce.revision+=1;xt(te,200,{cancelled:"cancelled"in xe,..."error"in xe?{error:xe.error}:{}});return}if(K.method==="GET"&&we.pathname==="/api/policy/project"){let xe=nu(ce,oe),Ce=Zd(xe,de.home),Se=sr(de,oe);xt(te,200,{dir:xe,path:w(xe),revision:ce.revision,baseline:Se.baseline,userPolicyDiagnostics:Se.diagnostics,projection:Ce.projection,projectionDiagnostics:Ce.diagnostics,canPickDirectory:Bi(process.platform,process.env)});return}if(K.method==="POST"&&we.pathname==="/api/policy/project/diff"){let xe=await Xd(de,K,te,ce,oe);if(!xe)return;let Ce=Zd(xe.dir,de.home),Se=sr(de,oe).baseline,Ne=X(Se,le(xe.proposal,de.home).policy);xt(te,200,{rows:Xr(X(Se,Ce.projection).policy,Ne.policy,!1),weakenings:Ne.weakenings,existingFileDiagnostics:Ce.diagnostics,errors:[]});return}if(K.method==="POST"&&we.pathname==="/api/policy/project/apply"){let xe=await Xd(de,K,te,ce,oe);if(!xe)return;let Ce=Rh(xe.dir,xe.proposal,de.home);xt(te,Ce.errors.length>0?500:200,Ce);return}if(K.method==="GET"&&we.pathname==="/api/activity"){let xe=ne(de,oe),Ce=Eh(we.searchParams.get("days"),xe);if(Ce===null){xt(te,400,{error:`days must be an integer between 1 and ${xe}`});return}xt(te,200,qd(de,Ce,oe.activityLogsDir));return}if(K.method==="POST"&&we.pathname==="/api/rules/choose-directory"){xt(te,200,await qi());return}if(K.method==="GET"&&we.pathname==="/api/rules"){let xe=Z(de,Vi(oe)),Ce=new Map(xe.rules.map((Se)=>[Se.name,Se]));xt(te,200,{projectPath:oe.cwd??process.cwd(),canPickDirectory:Bi(process.platform,process.env),rulebooks:xe.rulebooks.map((Se)=>({source:Se.source,spec:Se.spec,name:Se.name,version:Se.version,rules:Se.rules.flatMap((Ne)=>{let He=Ce.get(Ne);if(!He)return[];return[{name:He.name,command:He.command,subcommand:He.subcommand,block_args:He.block_args,reason:He.reason}]})})),errors:xe.errors,warnings:xe.warnings});return}if(K.method==="GET"&&we.pathname==="/api/star/context"){xt(te,200,await(oe.fetchStarContext??(()=>Mh(de,{logsDir:oe.activityLogsDir})))());return}if(K.method==="POST"&&we.pathname==="/api/star"){let xe=await(oe.starRepo??Oh)();xt(te,200,xe.ok?{ok:!0}:{ok:!1,fallbackUrl:bh});return}if(K.method==="GET"&&we.pathname==="/api/integrations"){xt(te,200,await(oe.fetchIntegrations??(()=>jh(de)))());return}if(K.method==="GET"&&we.pathname==="/api/health"){xt(te,200,await(oe.fetchHealth??(()=>Fh(de)))());return}if(K.method==="POST"&&(we.pathname==="/api/install"||we.pathname==="/api/uninstall")){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=xe.value?.target;if(typeof Ce!=="string"||!Wt.some((Ne)=>Ne.target===Ce)){xt(te,400,{error:"unknown target"});return}let Se=we.pathname==="/api/install"?"install":"uninstall";xt(te,200,await(oe.runIntegration??Nh)(Se,Ce));return}xt(te,404,{error:"Not found"})}function Vi(j){return{...j,cwd:j.cwd??process.cwd()}}function nu(j,K){return j.dir??K.cwd??process.cwd()}function Zd(j,K){let te=w(j),re=yh(te)?bn(te):{value:void 0,errors:[]},oe=le(re.value,K);return{projection:oe.policy,diagnostics:[...re.errors,...oe.diagnostics]}}async function Xd(j,K,te,re,oe){let ce=nu(re,oe),de=re.revision,we=await cr(K);if(!we.ok)return xt(te,we.status,{errors:[we.error]}),null;let xe=we.value;if(typeof xe?.revision!=="number")return xt(te,400,{errors:["revision must be a number"]}),null;if(xe.revision!==de)return xt(te,409,{errors:[wh]}),null;let Ce=Sh(xe.proposal,j.home);if(Ce.length>0)return xt(te,400,{errors:Ce}),null;return{dir:ce,proposal:xe.proposal}}function Sh(j,K){let te=Ut(j,K);if(te.length>0)return te;return j?.audit===void 0?[]:[kh]}function Rh(j,K,te){let re=w(j),oe=Qr(K,h(K,te));try{return y(s(S(j,"project policy"),re),`${JSON.stringify(oe,null,2)}
5918
+ `),{path:re,errors:[]}}catch(ce){return{path:re,errors:[ce instanceof Error?ce.message:String(ce)]}}}function Ph(j,K,te,re){let oe=h(te,j.home),ce=k(j,Vi(re)),de=De({rules:ce.policy.rules,transparentWrappers:ce.policy.transparentWrappers,safety:Ue(oe.safety),worktreeMode:oe.workflow.worktree_mode,destructiveCommandProtectionEnabled:oe.destructive_command_protection.enabled,destructiveCommandRuleOverrides:oe.destructive_command_protection.overrides,destructiveCommandAllowPaths:oe.destructive_command_protection.allow_paths,secretProtection:{enabled:oe.secret_protection.enabled,disabledRules:We(oe.secret_protection.overrides),denyPaths:oe.secret_protection.deny_paths,allowPaths:oe.secret_protection.allow_paths}});return er(K,{policySnapshot:de,cwd:re.cwd,userConfigDir:re.userConfigDir},j)}function Eh(j,K){if(j===null)return Math.min(Lh,K);let te=Number(j);if(!Number.isInteger(te)||te<1||te>K)return null;return te}function Dh(j,K,te){if(K.searchParams.get("token")!==te)return!1;if(j.method!=="POST")return!0;return j.headers["x-cc-safety-net-token"]===te}var Ah=1048576;async function cr(j){let K=[],te=0;for await(let re of j){let oe=re;if(te+=oe.byteLength,te>Ah)return{ok:!1,status:413,error:"Request body is too large"};K.push(oe)}try{return{ok:!0,value:JSON.parse(Buffer.concat(K).toString("utf-8")||"{}")}}catch(re){return{ok:!1,status:400,error:`Invalid JSON: ${re instanceof Error?re.message:String(re)}`}}}function _h(j,K){j.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),j.end(K)}function xt(j,K,te){j.writeHead(K,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),j.end(JSON.stringify(te))}function Th(j){return new Promise((K,te)=>{j.close((re)=>re?te(re):K())})}function Ih(j){return new Promise((K)=>{let te=()=>{process.off("SIGINT",re),process.off("SIGTERM",re)},re=()=>{te(),j.close().then(K)};process.once("SIGINT",re),process.once("SIGTERM",re)})}function $h(j){let K=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",te=process.platform==="win32"?["/c","start","",j]:[j];return new Promise((re,oe)=>{let ce=eu(K,te,{detached:!0,stdio:"ignore"}),de=(xe)=>{ce.off("spawn",we),oe(xe)},we=()=>{ce.off("error",de),ce.unref(),re()};ce.once("error",de),ce.once("spawn",we)})}async function Oh(j="gh",K=Ji){return{ok:await zi(j,["api","-X","PUT",`/user/starred/${fo}`],K)===0}}async function jh(j,K={}){let te=await Hn(K.fetcher),re=ru(j,te);return{targets:Nt.map((oe)=>{let ce=re.find((de)=>de.platform===oe.id);return{target:oe.id,label:St(oe.id),version:te.versions[oe.id]??null,status:ce?.configured?"active":ce?.detected?"disabled":ce?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:te.version,nodeVersion:te.nodeVersion,platform:te.platform}}}function ru(j,K){return Dn(j,process.cwd(),{ampPluginListOutput:K.ampPluginListOutput,codexPluginListOutput:K.codexPluginListOutput,copilotCliVersion:K.versions["copilot-cli"]})}async function Fh(j,K={}){let[te,re]=await Promise.all([Hn(K.fetcher),(K.checkUpdates??nn)()]);return{hooks:ru(j,te).filter((oe)=>oe.detected).map((oe)=>({platform:oe.platform,label:St(oe.platform),configured:oe.configured})),update:{currentVersion:re.currentVersion,latestVersion:re.latestVersion??null,updateAvailable:re.updateAvailable}}}var Qd=Promise.resolve();function Nh(j,K,te={}){let re=async()=>{let ce=[],{log:de,error:we}=console;console.log=(...xe)=>ce.push(xe.map(String).join(" ")),console.error=console.log;try{return{ok:await ir(j,[],{selectTargets:async()=>[K],output:new vh({write(Ce,Se,Ne){ce.push(String(Ce).replace(/\n$/,"")),Ne()}}),...te})===0,output:ce.join(`
5919
+ `)}}finally{console.log=de,console.error=we}},oe=Qd.then(re);return Qd=oe.then(()=>{return},()=>{return}),oe}async function Mh(j,K={}){let[te,re,oe]=await Promise.all([Hh(K.command),Uh(K.fetchRepo),Promise.resolve(gr(j,ne(j),K.logsDir).totalBlocked)]);return{starred:te,starCount:re,blockedTotal:oe}}async function Hh(j="gh",K=Ji){if(await zi(j,["auth","status"],K)!==0)return null;let te=await zi(j,["api",`/user/starred/${fo}`],K);if(te===0)return!0;if(te===null)return null;return!1}function zi(j,K,te){return new Promise((re)=>{let oe=eu(j,K,{stdio:"ignore",windowsHide:!0}),ce=!1,de,we=(xe)=>{if(ce)return;if(ce=!0,de)clearTimeout(de);re(xe)};oe.once("error",()=>we(null)),oe.once("close",we),de=setTimeout(()=>{oe.kill(),we(null)},te)})}async function Uh(j=fetch){try{let K=await j(`https://api.github.com/repos/${fo}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(Ji)});if(!K.ok)return null;let te=await K.json();return typeof te.stargazers_count==="number"?te.stargazers_count:null}catch{return null}}function Gh(j){if(j[0]!=="help")return!1;let K=j[1];if(!K)fi(),process.exit(0);if(tr(K))process.exit(0);console.error(`Unknown command: ${K}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var Bh={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),tr("hook",console.error),process.exit(1)},install:async(j)=>{process.exit(await ir("install",j))},update:async(j)=>{process.exit(await Ei(j))},uninstall:async(j)=>{process.exit(await ir("uninstall",j))},rule:async(j)=>{process.exit(await Ud(l(),j))},policy:async(j)=>{process.exit(await nd(l(),j))},status:async(j)=>{if(Kt(At({label:"status"},j).errors))process.exit(1);Bd(l())},statusline:async(j)=>{let K=At({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},j);if(K.errors.length===0&&K.flags.claudeCode){await Gi(l());return}if(Kt(K.errors),!K.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");tr("statusline",console.error),process.exit(1)},doctor:async(j)=>{let K=ii(j);if(!K)process.exit(1);let te=await Rl(l(),{json:K.json,skipUpdateCheck:K.skipUpdateCheck});process.exit(te)},logs:async(j)=>{process.exit(await ts(l(),j))},gui:async(j)=>{process.exit(await tu(j))},explain:async(j)=>{process.exit(await jl(l(),j))}};async function qh(j){let K=At({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},j);if(Gh(j))return;let te=j[0],re=te?mr(te):void 0;if(K.help&&re&&re.name!=="rule")tr(re.name),process.exit(0);if(!te||K.help&&!re)fi(),process.exit(0);if(K.flags.version)Ml(),process.exit(0);if(re){await Bh[re.name](j.slice(1));return}if(te==="--statusline"){await Gi(l());return}console.error(te.startsWith("-")?`Unknown option: ${te}`:`Unknown command: ${te}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{qh as runCli};