cc-safety-net 2.5.1 → 2.6.0

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,49 @@
1
- import{a,s,_e,We,k,tt,Be,c,o,ze,R,T,Ce,rt,f,qe,l,r,v,i,ie,n,g,pe,j,it,st,u,fe,me,at,D,Y,se,S,ct,U,b,Ee,G,d,Z,Ke,Je,N,w,P,ge,he,Ae,lt,m,e,Ie,ke,Ye,Ze,ae,Re,ce,Oe,X,H,De,ye,W,Xe,B,Q,ee,le,Qe,et,C,z,Ne,Fe,Me,E,$e,Te,je,h,t,te,be,y,x,A,ut,Ue,Ge,p,V}from"./chunks/index-8cqwk53d.js";import{re,q,He,F,M}from"./chunks/index-3rm5n91g.js";var wu=["-h","--help"];function gn(_,I){let O=Object.entries(_.booleans??{}),L=Object.entries(_.values??{}),J=Object.entries(_.lists??{}),K=Object.fromEntries(O.map(([Se])=>[Se,!1])),ne={},oe=Object.fromEntries(J.map(([Se])=>[Se,[]])),de=[],ue=[],ve=!1,xe=-1;for(let[Se,Pe]of I.entries()){if(Se<=xe)continue;if(Pe==="--"){de.push(...I.slice(Se+1));break}if(wu.includes(Pe)){ve=!0;continue}let we=O.find(([,Ve])=>Ve.includes(Pe));if(we){K[we[0]]=!0;continue}let Le=L.find(([,Ve])=>Ve.includes(Pe));if(Le){let Ve=I[Se+1];if(Ve===void 0||Ve.startsWith("-")){ue.push(`${Pe} requires a value`);continue}ne[Le[0]]=Ve,xe=Se+1;continue}let en=J.find(([,Ve])=>Ve.includes(Pe));if(en){let Ve=I.slice(Se+1),on=Ve.findIndex((an)=>an.startsWith("-")),sn=Ve.slice(0,on===-1?Ve.length:on);if(sn.length===0){ue.push(`${Pe} requires at least one value`);continue}oe[en[0]]=[...oe[en[0]]??[],...sn],xe=Se+sn.length;continue}if(Pe.startsWith("-")){ue.push(`Unknown option for ${_.label}: ${Pe}`);continue}if(_.positionals==="tail"){de.push(...I.slice(Se));break}de.push(Pe)}if(_.positionals!=="list"&&_.positionals!=="tail")ue.push(...de.map((Se)=>`Unexpected argument for ${_.label}: ${Se}`));return{flags:K,values:ne,lists:oe,positionals:de,help:ve,errors:ue}}function On(_){for(let I of _)console.error(I);return _.length>0}import{readdirSync as Eu,statSync as ns,unlinkSync as Au}from"node:fs";import{basename as ts,dirname as _u,isAbsolute as Iu,join as Tu,relative as $u,resolve as Ou,sep as Du}from"node:path";var Xi=(_)=>{let I=Date.now()-new Date(_).getTime();if(!Number.isFinite(I))return"";let O=Math.floor(I/60000),L=Math.floor(O/60),J=Math.floor(L/24);if(J>0)return`${J}d ago`;if(L>0)return`${L}h ago`;if(O>0)return`${O}m ago`;return"just now"},co=(_)=>{let I=(_??"").trim().split(/\s+/).filter((J)=>J&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(J)),O=I[0]?.split("/").pop();if(!O)return null;let L=I[1];return L&&/^[a-z][a-z0-9-]*$/.test(L)?`${O} ${L}`:O};function Qi(_){let I=(J)=>`${J.sessionId}
2
- ${co(J.segment||J.command)}`,O=_.filter((J)=>J.decision!=="allow"),L=O.filter((J)=>J.sessionId).reduce((J,K)=>J.set(I(K),(J.get(I(K))??0)+1),new Map);return new Set(O.filter((J)=>J.failureStage||(L.get(I(J))??0)>=2))}import{existsSync as ku,readdirSync as xu,readFileSync as Su}from"node:fs";import{join as Cu}from"node:path";function zn(_,I){try{return xu(_,{withFileTypes:!0,encoding:"utf8"}).flatMap((O)=>{let L=Cu(_,O.name);if(O.isDirectory())return zn(L,I);if(O.name.endsWith(".jsonl"))return[L];return[]})}catch{if(I&&ku(_))I.count++;return[]}}var Ru=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function Pu(_){if(!_||typeof _!=="object"||Array.isArray(_))return!1;let I=_;if(typeof I.ts!=="string"||typeof I.command!=="string")return!1;return Ru.every((O)=>I[O]===void 0||typeof I[O]==="string")}function ht(_,I){try{return Su(_,"utf-8").split(`
3
- `).filter(Boolean).flatMap((O)=>{try{let L=JSON.parse(O);if(!Pu(L)){if(I)I.count++;return[]}return[L]}catch{if(I)I.count++;return[]}})}catch{if(I)I.count++;return[]}}function hn(_){return Array.from(_,(I)=>{let O=I.charCodeAt(0);if(O<=31||O>=127&&O<=159)return`\\x${O.toString(16).padStart(2,"0")}`;return I}).join("")}function Lu(_,I){let O=re(_),L=gn({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"]}},I);if(On(L.errors))return null;if(L.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(L.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let J=L.values.limit===void 0?20:es(L.values.limit);if(J===null)return console.error("--limit must be a positive number"),null;let K=L.values.since===void 0?Math.min(30,O):es(L.values.since);if(K===null||K>O)return console.error(`--since must be a positive number of days no greater than ${O}`),null;let ne={limit:J,limitExplicit:L.values.limit!==void 0,since:K,sinceExplicit:L.values.since!==void 0,all:L.flags.all,json:L.flags.json,suspect:L.flags.suspect,pruneLegacy:L.flags.pruneLegacy,dryRun:L.flags.dryRun,id:L.values.id,agent:L.values.agent,rule:L.values.rule,session:L.values.session,project:L.values.project===void 0?void 0:Ou(L.values.project)};if(ne.id&&(ne.agent!==void 0||ne.rule!==void 0||ne.session!==void 0||ne.project!==void 0||ne.suspect||ne.sinceExplicit||ne.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(ne.pruneLegacy&&(ne.id!==void 0||ne.agent!==void 0||ne.rule!==void 0||ne.session!==void 0||ne.project!==void 0||ne.suspect||ne.all||ne.sinceExplicit||ne.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(ne.dryRun&&!ne.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return ne}async function rs(_,I,O={}){let L=Lu(_,I);if(!L)return 1;let J=O.logsDir??F(_);if(L.pruneLegacy)return Nu(J,L.json,L.dryRun);if(!J)return console.log(L.json?"[]":L.id?`No retained audit log entry found for id ${hn(L.id)}.`:"No audit log entries found."),0;q(_,J);let K={count:0},ne=zn(J,K).flatMap((xe)=>ht(xe,K).map((Se)=>({entry:Se,file:xe})));if(K.count>0)console.error(`warning: ${K.count} audit log ${K.count===1?"source":"sources"} could not be read; these results are incomplete`);if(L.id)return Mu(ne,L,O.timeZone);let oe=Date.now()-L.since*24*60*60*1000,de=ne.filter((xe)=>Uu(xe,L,J,oe)),ue=L.suspect?Qi(de.map((xe)=>xe.entry)):null,ve=(ue?de.filter((xe)=>ue.has(xe.entry)):de).sort((xe,Se)=>Date.parse(Se.entry.ts)-Date.parse(xe.entry.ts)).slice(0,L.limit);if(L.json)return console.log(JSON.stringify(ve.map((xe)=>xe.entry),null,2)),0;if(ve.length===0)return console.log("No audit log entries found."),0;for(let xe of ve)console.log(qu(xe.entry,O.timeZone));return 0}function Nu(_,I,O){let L=_?Fu(_).map((oe)=>Tu(_,oe)):[];if(O)return ju(L,I);let J=[],K=0,ne=0;for(let oe of L){let de=ns(oe,{throwIfNoEntry:!1})?.size??0,ue=Hu(oe);if(ue){J.push(`${ts(oe)}: ${ue}`);continue}K++,ne+=de}if(I)return console.log(JSON.stringify({removedFiles:K,removedBytes:ne,failedFiles:J.length})),J.length===0?0:1;console.log(K===0&&J.length===0?"No legacy audit log files found.":`Removed ${K} legacy audit log ${K===1?"file":"files"} (${os(ne)}).`);for(let oe of J)console.error(`Could not remove ${hn(oe)}`);if(console.log("Nested v2 audit logs were not changed."),K>0)console.log("This deletion cannot be undone.");return J.length===0?0:1}function ju(_,I){let O=_.reduce((L,J)=>L+(ns(J,{throwIfNoEntry:!1})?.size??0),0);if(I)return console.log(JSON.stringify({dryRun:!0,files:_.length,bytes:O})),0;if(console.log(_.length===0?"No legacy audit log files found.":`Would remove ${_.length} legacy audit log ${_.length===1?"file":"files"} (${os(O)}).`),console.log("Nested v2 audit logs are not included."),_.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Fu(_){try{return Eu(_,{withFileTypes:!0}).filter((I)=>I.isFile()&&I.name.endsWith(".jsonl")).map((I)=>I.name)}catch{return[]}}function Hu(_){try{return Au(_),null}catch(I){return I instanceof Error?I.message:String(I)}}function os(_){let I=["B","KiB","MiB","GiB"],O=Math.min(Math.floor(Math.log2(Math.max(_,1))/10),I.length-1);return`${Math.round(_/1024**O*10)/10} ${I[O]}`}function Mu(_,I,O){let L=_.filter((K)=>K.entry.id===I.id);if(L.length>1)return console.error(`Multiple audit log entries found for id ${hn(I.id??"")}.`),1;if(I.json)return console.log(JSON.stringify(L.map((K)=>K.entry),null,2)),0;let J=L[0];if(!J)return console.log(`No retained audit log entry found for id ${hn(I.id??"")}.`),0;return console.log(Vu(J.entry,O)),0}function Uu(_,I,O,L){if(!I.all&&_.entry.decision==="allow")return!1;if(Date.parse(_.entry.ts)<L)return!1;if(I.agent!==void 0&&_.entry.agent!==I.agent)return!1;if(I.rule!==void 0&&_.entry.ruleId!==I.rule)return!1;if(I.session!==void 0&&!Gu(_,O,I.session))return!1;if(I.project!==void 0&&!Bu(_.entry.cwd,I.project))return!1;return!0}function Gu(_,I,O){if(_.entry.sessionId===O)return!0;return _u(_.file)===I&&ts(_.file,".jsonl")===O}function Bu(_,I){if(!_)return!1;let O=$u(I,_);return O!==".."&&!O.startsWith(`..${Du}`)&&!Iu(O)}function qu(_,I){let O=hn(_.id??"-"),L=hn(_.decision??"deny"),J=_.cwd?` [${hn(_.cwd)}]`:"",K=_.segment||_.command,ne=K===_.command?"":"↳ ",oe=K.length>50?`${K.slice(0,50)}…`:K;return`${O.padEnd(16)} ${hn(is(_.ts,I))} ${L.padEnd(5)} ${hn(_.agent??"-").padEnd(15)} ${hn(_.ruleId??"-").padEnd(20)} ${ne}${hn(oe)}${J}`}function Vu(_,I){let O=(J)=>hn(J===void 0||J===null||J===""?"-":J),L=_.shape?`${_.agent??"-"} (shape: ${_.shape})`:_.agent??"-";return[`id: ${O(_.id)}`,`ts: ${O(is(_.ts,I))}`,`decision: ${O(_.decision)}`,`agent: ${O(L)}`,`level: ${O(_.level)}`,`tool: ${O(_.toolName)}`,`rule: ${O(_.ruleId)}`,`intent: ${O(_.intent)}`,`stage: ${O(_.failureStage)}`,`error: ${O(_.errorCode)}`,`session: ${O(_.sessionId)}`,`cwd: ${O(_.cwd)}`,`version: ${O(_.v)}`,`truncated: ${O(_.truncated===!0?"yes":void 0)}`,`reason: ${O(_.reason)}`,`command: ${O(_.command)}`,`segment: ${O(_.segment)}`].join(`
4
- `)}function is(_,I){let O=new Date(_);if(Number.isNaN(O.getTime()))return _;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:I}).format(O)}function es(_){let I=Number(_);return Number.isFinite(I)&&I>0?I:null}var ss={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 as={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 ls={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 uo=["npx","--offline","--no-install","@deepseek-ai/dsh","--version"],ir=[{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:8,runtime:{order:6,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:8,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:7,runtime:{order:5,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:7,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",doctorOrder:9,runtime:{order:7,flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{order:9,flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:10,runtime:{order:8,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:10,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:11,runtime:{order:9,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:11,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:12,install:{order:12,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:13,install:{order:13,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:14,install:{order:14,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:"deepseek-harness",displayName:"DeepSeek Harness",doctorOrder:6,install:{order:6,flag:"--deepseek-harness",artifactKind:"package",probeCommand:uo}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],sr=ir.slice().sort((_,I)=>_.doctorOrder-I.doctorOrder).map((_)=>_.id),It=ir.filter((_)=>("runtime"in _)).slice().sort((_,I)=>_.runtime.order-I.runtime.order).map((_)=>({id:_.id,displayName:"displayName"in _.runtime?_.runtime.displayName:_.displayName,flags:_.runtime.flags,legacyFlags:"legacyFlags"in _.runtime?_.runtime.legacyFlags:[],description:_.runtime.description,legacyTopLevelFlags:_.runtime.legacyTopLevelFlags})),En=ir.slice().sort((_,I)=>_.install.order-I.install.order).map((_)=>({id:_.id,..._.install})).map(({order:_,...I})=>I),zu=Object.fromEntries(ir.map((_)=>[_.id,_.displayName]));function fn(_){return zu[_]}var Ju=It.map((_)=>({flags:_.flags.join(", "),description:_.description})),Wu=It.flatMap((_)=>_.flags.map((I)=>`cc-safety-net hook ${I}`)),cs={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Ju,{flags:"-h, --help",description:"Show this help"}],examples:Wu};var ds={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...En.map((_)=>({flags:_.flag,description:`Install ${fn(_.id)} ${_.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...En.map((_)=>`cc-safety-net install ${_.flag}`)]},us={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...En.map((_)=>({flags:_.flag,description:`Uninstall ${fn(_.id)} ${_.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...En.map((_)=>`cc-safety-net uninstall ${_.flag}`)]},ps={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 fs={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 ar={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 po=[{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"}],fo=["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"],yt={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"},...po.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",...fo,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var ms={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 gs={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 lr=[ms,ss,fs,as,yt,ar,ds,ps,us,cs,ls,gs];function Ku(_){return _.aliases??[]}function cr(_){let I=_.toLowerCase();return lr.find((O)=>O.name.toLowerCase()===I||Ku(O).some((L)=>L.toLowerCase()===I))}import{basename as Yu}from"node:path";function dr(_,I=7,O=F(_)){let L=Date.now()-I*24*60*60*1000,J=[],K=new Set,ne=0,oe,de,ue,ve;if(O)q(_,O);let xe={count:0},Se=O?zn(O,xe):[];for(let we of Se)for(let Le of ht(we,xe)){if(Le.decision==="allow")continue;let en=new Date(Le.ts).getTime();if(en>=L){if(ne++,K.add(Le.sessionId??Yu(we,".jsonl")),de===void 0||en<=de)oe=Le.ts,de=en;if(ve===void 0||en>ve)ue=Le.ts,ve=en;Zu(J,Le,en)}}let Pe=J.map((we)=>({timestamp:we.ts,command:we.command,reason:we.reason,relativeTime:Xi(new Date(we.ts))}));return{totalBlocked:ne,sessionCount:K.size,recentEntries:Pe,oldestEntry:oe,newestEntry:ue,unreadable:xe.count}}function Zu(_,I,O){let L=_.findIndex((J)=>O>new Date(J.ts).getTime());if(L===-1){if(_.length<3)_.push(I);return}if(_.splice(L,0,I),_.length>3)_.pop()}import{dirname as cp}from"node:path";import{dirname as Xu,join as Qu,resolve as ep}from"node:path";var np="config.json";function bn(_,I,O,L){g(tp(_),`${JSON.stringify(I,null,2)}
5
- `,O,L)}function tp(_){return typeof _==="string"?ie(_):_}function go(_){return{errors:ae(op(_),": "," "),ruleNames:new Set(Oe(_).map((I)=>I.toLowerCase()))}}var rp="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",hs="must match pattern (letters, numbers, hyphens, underscores)";function op(_){if(!ys(_))return[e([],"Config must be an object")];return[..._.version===1?[]:[e(["version"],"must be 1")],...ip(_.rules)]}function ip(_){if(_===void 0)return[];if(!Array.isArray(_))return[e(["rules"],"must be an array")];return[..._.flatMap((I,O)=>ys(I)?sp(I,["rules",O]):[e(["rules",O],"must be an object")]),...Ie(_)]}function sp(_,I){return[...mo(_.name,[...I,"name"],"required string",u,rp),...mo(_.command,[...I,"command"],"required string",w,hs),..._.subcommand===void 0?[]:mo(_.subcommand,[...I,"subcommand"],"must be a string if provided",w,hs),...ap(_.block_args,[...I,"block_args"]),...lp(_.reason,[...I,"reason"]),..._.intent===void 0||Re(_.intent)?[]:[e([...I,"intent"],ke)]]}function mo(_,I,O,L,J){if(typeof _!=="string")return[e(I,O)];return L.test(_)?[]:[e(I,J)]}function ap(_,I){if(!Array.isArray(_))return[e(I,"required array")];if(_.length===0)return[e(I,"must have at least one element")];return _.flatMap((O,L)=>{if(typeof O!=="string")return[e([...I,L],"must be a string")];return O===""?[e([...I,L],"must not be empty")]:[]})}function lp(_,I){if(typeof _!=="string")return[e(I,"required string")];if(_==="")return[e(I,"must not be empty")];return _.length>P?[e(I,`must be at most ${P} characters`)]:[]}function ys(_){return!!_&&typeof _==="object"&&!Array.isArray(_)}function ho(_){let I=vs(_);if(!I.ok)return I.result;return go(I.parsed)}function vs(_){let I=[],O=new Set;try{let L=typeof _==="string"?ie(_):_,J=n(L);if(J===null)return I.push(`File not found: ${L.path}`),{ok:!1,result:{errors:I,ruleNames:O}};if(!J.trim())return I.push("Config file is empty"),{ok:!1,result:{errors:I,ruleNames:O}};return{ok:!0,parsed:JSON.parse(J)}}catch(L){if(L instanceof r)return I.push(L.message),{ok:!1,result:{errors:I,ruleNames:O}};let J=L instanceof Error?L.message:String(L);return I.push(L instanceof SyntaxError?"Invalid JSON":J),{ok:!1,result:{errors:I,ruleNames:O}}}}function bs(_){return ep(_,".safety-net.json")}function Mn(_){let I=vs(_);if(!I.ok)return I.result;let O=Ye(I.parsed);return{errors:O.errors,ruleNames:O.sources}}function ur(_,I={}){return Qu(Xu(Ee(_,I)),np)}function ws(_,I,O){let L;try{if(n(I)===null)return{path:_,exists:!1,valid:!1,ruleCount:0};L=Mn(I),L.errors.push(...H(_,O))}catch(J){if(!(J instanceof r))throw J;L={errors:[J.message],ruleNames:new Set}}return{path:_,exists:!0,valid:L.errors.length===0,ruleCount:L.ruleNames.size,...L.errors.length>0?{errors:L.errors}:{}}}function dp(_,I){return{source:I,name:_.name,command:_.command,subcommand:_.subcommand,blockArgs:[..._.block_args],reason:_.reason}}function ks(_,I){let O=G(_),L=U(I),J=cp(O),K=X(_,{cwd:I,userConfigPath:O,projectConfigPath:L,userConfigDir:J}),ne=Z(_,{cwd:I,userConfigPath:O,projectConfigPath:L,userConfigDir:J}),oe=new Map(K.rulebooks.flatMap((de)=>de.rules.map((ue)=>[ue,de.source])));return{userConfig:ws(O,ne.userConfigTarget,ne.userScope),projectConfig:ws(L,ne.projectConfigTarget,ne.projectScope),effectiveRules:K.rules.map((de)=>dp(de,oe.get(de.name)??"project"))}}var up=[{flag:o.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:o.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:o.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:o.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:o.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:o.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:o.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:o.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function xs(_){return[...up.map((I)=>({name:I.flag.name,value:Ce(I.flag,_.env),isSet:rt(I.flag,_.env),legacyName:I.flag.legacyName,legacyValue:I.flag.legacyName?_.env.get(I.flag.legacyName):void 0,legacyIsSet:I.flag.legacyName?_.env.get(I.flag.legacyName)!==void 0:void 0,description:I.description,defaultBehavior:I.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:_.env.get("CC_SAFETY_NET_HOME"),isSet:_.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var Ss={error:0,warning:1,info:2},pp=["policy","config","audit"];function fp(_){return _.map((I)=>{if(I==="ownership")return"is not owned by the current user";if(I==="permissions")return"has unsafe permissions";if(I==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var mp=[{derive:(_)=>_.hooks.length>0&&_.hooks.every((I)=>!I.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:(_)=>_.hooks.filter((I)=>I.inspectionStatus==="failed").map((I)=>{let O=fn(I.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${O} inspection failed`,detail:`Doctor could not verify the ${O} integration configuration.`,fixHint:`Correct the reported ${O} configuration error, then run \`cc-safety-net doctor\` again.`,integration:I.platform}})},{derive:(_)=>_.userConfig.exists&&!_.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:_.userConfig.path}]:[]},{derive:(_)=>_.projectConfig.exists&&!_.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:_.projectConfig.path}]:[]},{derive:(_)=>_.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${_.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:(_)=>_.v2Leftovers&&_.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: ${_.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(_)=>{let I=_.environment.find((O)=>O.name==="CC_SAFETY_NET_AUDIT_SCOPE");return ze(I?.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."}]:[]}},...pp.map((_)=>({derive:(I)=>I.posture.directories.filter((O)=>O.kind===_&&O.status==="unsafe").map((O)=>({checkId:`posture.${_}-directory-unsafe`,severity:"error",title:`${_[0]?.toUpperCase()}${_.slice(1)} directory is unsafe`,detail:`The ${_} directory ${fp(O.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...O.path?{path:O.path}:{}}))})),{derive:(_)=>{let I=[..._.effectiveSafety.weakenedRuleOverrides].sort();return I.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: ${I.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${I.join(", ")}.`}]:[]}}];function Cs(_){return mp.flatMap((I,O)=>I.derive(_).map((L,J)=>({finding:L,catalogOrder:O,occurrence:J}))).sort((I,O)=>Ss[I.finding.severity]-Ss[O.finding.severity]||I.catalogOrder-O.catalogOrder||I.occurrence-O.occurrence).map((I)=>I.finding)}function Dn(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var gp=(_)=>Dn()?`\x1B[32m${_}\x1B[0m`:_,hp=(_)=>Dn()?`\x1B[33m${_}\x1B[0m`:_,yp=(_)=>Dn()?`\x1B[34m${_}\x1B[0m`:_,vp=(_)=>Dn()?`\x1B[36m${_}\x1B[0m`:_,bp=(_)=>Dn()?`\x1B[31m${_}\x1B[0m`:_,wp=(_)=>Dn()?`\x1B[2m${_}\x1B[0m`:_,kp=(_)=>Dn()?`\x1B[1m${_}\x1B[0m`:_,nn={green:gp,yellow:hp,blue:yp,cyan:vp,red:bp,dim:wp,bold:kp},xp="\x1B[0m",Sp=[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 Cp(_){let I=_;return()=>(I=(I*1664525+1013904223)%4294967296,I/4294967296)}function Rp(_){let I=[...Sp],O=Cp(_);for(let L=I.length-1;L>0;L--){let J=Math.floor(O()*(L+1)),K=I[L];I[L]=I[J],I[J]=K}return I}function Pp(_,I=0){if(!Dn())return"";let O=Rp(I);return`\x1B[38;5;${O[_%O.length]}m`}function Rs(_,I,O=0){if(!Dn())return`"${_}"`;return`${Pp(I,O)}"${_}"${xp}`}function pr(_){return _==="default"?"built-in default":`${_} policy`}var Ep=new RegExp("\x1B\\[[0-9;]*m","g"),yo=(_)=>_.replace(Ep,"").length;function Jn(_){let I=(_.headers??_.rows[0]??[]).map((ne,oe)=>{let de=Math.max(..._.rows.map((ue)=>yo(ue[oe]??"")));return Math.max(yo(ne),de)}),O=(ne,oe)=>ne+" ".repeat(Math.max(0,oe-yo(ne))),L=(ne,oe)=>oe[0]+I.map((de)=>ne.repeat(de+2)).join(oe[1])+oe[2],J=(ne)=>`│ ${ne.map((oe,de)=>O(oe,I[de]??0)).join(" │ ")} │`,K=_.headers?[` ${J(_.headers)}`,` ${L("─",["├","┼","┤"])}`]:[];return[` ${L("─",["┌","┬","┐"])}`,...K,..._.rows.map((ne)=>` ${J(ne)}`),` ${L("─",["└","┴","┘"])}`].join(`
6
- `)}function Ps(_){let I=[];I.push("Hook Integration"),I.push(Ap(_));let O=[],L=[];for(let J of _){let K=fn(J.platform);if(J.errors&&J.errors.length>0)for(let ne of J.errors)if(J.configured)O.push({platform:K,message:ne});else L.push({platform:K,message:ne})}for(let J of O)I.push(` Warning (${J.platform}): ${J.message}`);for(let J of L)I.push(nn.red(` Error (${J.platform}): ${J.message}`));return I.join(`
7
- `)}function Ap(_){let I=["Platform","Discovery","Configuration","Inspection"],O=_.map((L)=>{let J=fn(L.platform);if(L.inspectionStatus==="not-inspected"){let de=nn.dim("Not inspected");return[J,de,de,de]}let K=L.detected?nn.green("Detected"):L.inspectionStatus==="failed"?nn.red("Unknown"):nn.dim("Not detected"),ne=L.configured?nn.green("Configured"):L.detected?nn.yellow("Not configured"):L.inspectionStatus==="failed"?nn.red("Unknown"):nn.dim("Not applicable"),oe=L.inspectionStatus==="verified"?nn.green("Verified"):L.inspectionStatus==="failed"?nn.red("Failed"):nn.dim("Not applicable");return[J,K,ne,oe]});return Jn({headers:I,rows:O})}function Es(_){let O=["Guard Engine Verification",` Synthetic self-test: ${_.failed>0?nn.red(`${_.passed}/${_.total} FAIL`):nn.green(`${_.passed}/${_.total} passed`)}`],L=_.results.filter((J)=>!J.passed);if(L.length>0){O.push(""),O.push(nn.red(" Failures:"));for(let J of L)O.push(nn.red(` • ${J.description}`)),O.push(nn.red(` expected ${J.expected}, got ${J.actual}`))}return O.join(`
8
- `)}function _p(_){if(_.length===0)return" (no custom rules)";let I=["Source","Name","Command","Block Args"],O=_.map((L)=>[L.source,L.name,L.subcommand?`${L.command} ${L.subcommand}`:L.command,L.blockArgs.join(", ")]);return Jn({headers:I,rows:O})}function As(_){let I=[];if(I.push("Configuration"),I.push(Ip(_.userConfig,_.projectConfig)),I.push(""),_.effectiveRules.length>0)I.push(` Effective rules (${_.effectiveRules.length} total):`),I.push(_p(_.effectiveRules));else I.push(" Effective rules: (none - using built-in rules only)");return I.join(`
9
- `)}function Ip(_,I){let O=["Scope","Status"],L=(K)=>{if(!K.exists)return nn.dim("N/A");if(!K.valid)return nn.red(`Invalid (${K.errors?.[0]??"unknown error"})`);return nn.green("Configured")},J=[["User",L(_)],["Project",L(I)]];return Jn({headers:O,rows:J})}function _s(_){let I=[];return I.push("Environment"),I.push(Tp(_)),I.join(`
10
- `)}function Is(_){let I=_.effectiveSafety.policyScopes,O=["Effective Safety",` Selected preset: ${_.effectiveSafety.selectedPreset}${I?` (${pr(I.levelScope)})`:""}`,` Effective: ${_.effectiveSafety.level}`],L=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[J,K]of L){let ne=_.effectiveSafety.capabilities[J],oe=ne.enabled?nn.green("ON"):nn.dim("OFF"),de=ne.sources.length>0?` (${ne.sources.join(", ")})`:"";O.push(` ${K}: ${oe} via ${ne.source}${de}`)}if(I&&I.weakenings.length>0){O.push(" Project policy deltas:");for(let J of I.weakenings)O.push(` ${J}`)}O.push(` Stored rule customizations: ${_.effectiveSafety.ruleCounts.stored}`),O.push(` Effective rule customizations: ${_.effectiveSafety.ruleCounts.effective}`);for(let[J,K]of Object.entries(_.effectiveSafety.ruleOverrides))O.push(` ${J}: ${K}`);return O.join(`
11
- `)}function Ts(_){let I=["Findings"];if(_.length===0)return I.push(" No findings from inspected doctor facts."),I.join(`
12
- `);for(let O of _){let L=`[${O.severity.toUpperCase()}] ${O.checkId}: ${hn(O.title)}`,J=O.severity==="error"?nn.red:O.severity==="warning"?nn.yellow:nn.blue;if(I.push(` ${J(L)}`),I.push(` ${hn(O.detail)}`),O.path)I.push(` Path: ${hn(O.path)}`);if(O.fixHint)I.push(` Fix: ${hn(O.fixHint)}`)}return I.join(`
13
- `)}function Tp(_){let I=["Variable","Status","Legacy"],O=_.map((L)=>{let J=L.isSet?nn.green("✓"):nn.dim("✗"),K=L.legacyName&&L.legacyIsSet?`${L.legacyName} ${nn.green("✓")}`:L.legacyName??"";return[L.name,J,K]});return Jn({headers:I,rows:O})}function $s(_){let I=[];if(_.totalBlocked===0)I.push("Recent Activity"),I.push(" No blocked commands in the last 7 days"),I.push(" Tip: This is normal for new installations");else I.push(`Recent Activity · last 7 days (${_.totalBlocked} blocked / ${_.sessionCount} sessions)`),I.push($p(_.recentEntries));if(_.unreadable>0)I.push(` Warning: ${_.unreadable} audit log ${_.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return I.join(`
14
- `)}function $p(_){let I=["Time","Command"],O=_.map((L)=>{let J=hn(L.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),K=J.length>40?`${J.slice(0,37)}...`:J;return[L.relativeTime,K]});return Jn({headers:I,rows:O})}function Os(_){let I=[];if(I.push("Update Check"),_.latestVersion===null&&!_.error)return I.push(fr([["Status",nn.dim("Skipped")],["Installed",_.currentVersion]])),I.join(`
15
- `);if(_.error)return I.push(fr([["Status",`${nn.yellow("⚠")} Error`],["Installed",_.currentVersion],["Error",nn.dim(_.error)]])),I.join(`
16
- `);if(_.updateAvailable)return I.push(fr([["Status",`${nn.yellow("⚠")} Update Available`],["Current",_.currentVersion],["Latest",nn.green(_.latestVersion??"")]])),I.push(""),I.push(" Run: bunx cc-safety-net@latest doctor"),I.push(" Or: npx cc-safety-net@latest doctor"),I.join(`
17
- `);return I.push(fr([["Status",`${nn.green("✓")} Up to date`],["Version",_.currentVersion]])),I.join(`
18
- `)}function fr(_){return Jn({rows:_})}function Ds(_){let I=[];return I.push("System Info"),I.push(Op(_)),I.join(`
19
- `)}function Op(_){let I=["Component","Version"],O=(K)=>{if(K===null)return nn.dim("not found");return K},J=[{label:"cc-safety-net",value:_.version},...sr.map((K)=>({label:fn(K),value:_.versions[K]??null})),{label:"Node.js",value:_.nodeVersion},{label:"npm",value:_.npmVersion},{label:"Bun",value:_.bunVersion},{label:"Platform",value:_.platform}].map((K)=>[K.label,O(K.value)]);return Jn({headers:I,rows:J})}function Ls(_){if(_.findings.length===0)return nn.green(`
20
- No findings from inspected doctor facts.`);let I={error:_.findings.filter((K)=>K.severity==="error").length,warning:_.findings.filter((K)=>K.severity==="warning").length,info:_.findings.filter((K)=>K.severity==="info").length},O=["error","warning","info"].filter((K)=>I[K]>0).map((K)=>`${I[K]} ${K}`),L=_.findings.length===1?"finding":"findings",J=`
21
- ${_.findings.length} ${L}: ${O.join(", ")}.`;if(I.error>0)return nn.red(J);if(I.warning>0)return nn.yellow(J);return nn.blue(J)}import{lstatSync as Dp}from"node:fs";import{dirname as vo}from"node:path";function bo(_,I){try{let O=Dp(I);if(O.isSymbolicLink())return{kind:_,path:I,status:"unsafe",issues:["symlink"]};if(!O.isDirectory())return{kind:_,path:I,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:_,path:I,status:"unknown",issues:[]};let L=[...O.uid!==process.getuid()?["ownership"]:[],...(O.mode&18)!==0?["permissions"]:[]];return{kind:_,path:I,status:L.length>0?"unsafe":"safe",issues:L}}catch(O){if(typeof O==="object"&&O!==null&&"code"in O&&O.code==="ENOENT")return{kind:_,path:I,status:"not-applicable",issues:[]};return{kind:_,path:I,status:"unknown",issues:[]}}}function Ns(_,I){let O=F(_);return{directories:[bo("policy",vo(vo(I))),bo("config",vo(I)),...O?[bo("audit",O)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as Lp}from"node:child_process";import{existsSync as js}from"node:fs";import{delimiter as Np,extname as jp,join as Fp}from"node:path";import{stripVTControlCharacters as Fs}from"node:util";var Ms="2.5.1",Hp=5000,Mp="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function un(){return Ms}function wo(_,I){let O=_[I];if(O)return O;let L=Object.keys(_).find((J)=>J.toLowerCase()===I.toLowerCase()&&!!_[J]);return L?_[L]:O}function Up(_){return(wo(_,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((I)=>I.length>0)}function Gp(_,I){let O=jp(_)?[_]:[...Up(I).map((L)=>`${_}${L}`),_];if(_.includes("/")||_.includes("\\"))return O.find((L)=>js(L))??_;return(wo(I,"PATH")??"").split(Np).flatMap((L)=>O.map((J)=>Fp(L,J))).find((L)=>js(L))??_}function Hs(_){if(!/[\s"&|<>^]/.test(_))return _;return`"${_.replace(/"/g,'""')}"`}function Wn(_,I){let[O,...L]=_,J=I[Mp]==="win32"?"win32":process.platform;if(!O||J!=="win32")return{cmd:O??"",args:L};let K=Gp(O,I);if(!/\.(?:bat|cmd)$/i.test(K))return{cmd:K,args:L};return{cmd:wo(I,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",Hs(K),...L.map(Hs)].join(" ")]}}var vt=async(_,I=Hp)=>{let O=await Bp(_,{timeoutMs:I});if(O.code!==0)return null;return Fs(O.stdout).trim()||Fs(O.stderr).trim()||null};function Bp(_,I){let[O,...L]=_;if(!O)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((J)=>{try{let K=Wn([O,...L],process.env),ne=Lp(K.cmd,K.args,{stdio:["ignore","pipe","pipe"]}),oe=!1,de="",ue="";ne.stdout.on("data",(Se)=>{de+=Se.toString()}),ne.stderr.on("data",(Se)=>{ue+=Se.toString()});let ve=(Se)=>{if(oe)return;oe=!0,clearTimeout(xe),J(Se)},xe=setTimeout(()=>{ne.kill(),ve({code:null,stdout:de,stderr:ue})},I.timeoutMs);ne.on("close",(Se)=>{ve({code:Se,stdout:de,stderr:ue})}),ne.on("error",()=>{ve({code:null,stdout:de,stderr:ue})})}catch{J({code:null,stdout:"",stderr:""})}})}function mr(_){if(!_)return null;let I=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(_);if(I)return I[1]??null;let O=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(_);if(O)return O[1]??null;return _.split(`
22
- `)[0]?.trim()||null}async function gr(_,I=vt,O=process.cwd()){let L=Promise.all(En.map(async(xe)=>[xe.id,mr(await I([...xe.probeCommand]))])),[J,K,ne,oe,de,ue,ve]=await Promise.all([L,L.then(async(xe)=>{let Se=xe.find(([Le])=>Le==="opencode")?.[1];if(!Se?.startsWith("2.")||!_(Se))return null;let Pe=["--param",`location[directory]=${O}`],we=["opencode","api","integration.list",...Pe];return await I(we,30000),I(["opencode","api","plugin.list",...Pe],30000)}),I(["codex","plugin","list"],30000),I(["amp","plugins","list"],30000),I(["node","--version"]),I(["npm","--version"]),I(["bun","--version"])]);return{version:Ms,versions:Object.fromEntries(J),codexPluginListOutput:ne,ampPluginListOutput:oe,openCodePluginListOutput:K,nodeVersion:mr(de),npmVersion:mr(ue),bunVersion:mr(ve),platform:`${process.platform} ${process.arch}`}}function ko(_,I){if(I==="dev")return!1;let O=_.split(".").map(Number),L=I.split(".").map(Number),[J=0,K=0,ne=0]=O,[oe=0,de=0,ue=0]=L;if(J!==oe)return J>oe;if(K!==de)return K>de;return ne>ue}async function Un(){let _=un(),I=new AbortController,O=setTimeout(()=>I.abort(),3000);try{let L=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:I.signal});if(!L.ok)return{currentVersion:_,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${L.status}`};let J=await L.json(),K=ko(J.version,_);return{currentVersion:_,latestVersion:J.version,updateAvailable:K}}catch(L){return{currentVersion:_,latestVersion:null,updateAvailable:!1,error:L instanceof Error?L.message:"Network error"}}finally{clearTimeout(O)}}import*as Ws from"node:readline";var qs=(_)=>`\x1B[${_}B`,qp=(_)=>`\x1B[${_}A`;var Us=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function Vp(_){return new Promise((I)=>setTimeout(I,_))}function zp(_,I,O){if(!O)return I(_);if(O.aborted)return Promise.resolve();return new Promise((L,J)=>{let K=()=>O.removeEventListener("abort",ne),ne=()=>{K(),L()};O.addEventListener("abort",ne,{once:!0}),I(_).then(()=>{K(),L()},(oe)=>{K(),J(oe)})})}function hr(_){return Math.max(0,Math.min(1,_))}function bt(_){return Math.max(0,Math.min(255,Math.round(_)))}function xo(_){return _<=0.0031308?12.92*_:1.055*_**0.4166666666666667-0.055}function Jp(_,I,O){let L=O*Math.PI/180,J=I*Math.cos(L),K=I*Math.sin(L),ne=(_+0.3963377774*J+0.2158037573*K)**3,oe=(_-0.1055613458*J-0.0638541728*K)**3,de=(_-0.0894841775*J-1.291485548*K)**3;return{blue:bt(xo(hr(-0.0041960863*ne-0.7034186147*oe+1.707614701*de))*255),green:bt(xo(hr(-1.2684380046*ne+2.6097574011*oe-0.3413193965*de))*255),red:bt(xo(hr(4.0767416621*ne-3.3077115913*oe+0.2309699292*de))*255)}}function So(_,I){let O=(I*_*180/Math.PI%360+360)%360;return Jp(0.72,0.15,O)}function Vs(_,I=0.1){let O=So(I,_);return`\x1B[38;2;${O.red};${O.green};${O.blue}m`}function Wp(_,I){return{blue:bt(_.blue+(255-_.blue)*I),green:bt(_.green+(255-_.green)*I),red:bt(_.red+(255-_.red)*I)}}function zs(_,I,O){let L=Math.imul(_+2654435769,2246822507)^Math.imul(I+3266489909,668265263)^Math.imul(O+374761393,2654435761),J=L^L>>>15,K=Math.imul(J,739982445),ne=K^K>>>12,oe=Math.imul(ne,695872825);return((oe^oe>>>15)>>>0)/4294967296}function Kp(_,I,O){let L=Math.floor(zs(_,I,O)*Us.length);return Us[L]??"░"}function Gs(_){let I=hr(_);return I*I*I*(I*(I*6-15)+10)}function Yp(_){if(_.length===0)return"";let I=[],O=!1,L="";for(let J of _){let K=`${J.red};${J.green};${J.blue}`;if(J.bold!==O)I.push(J.bold?"\x1B[1m":"\x1B[22m"),O=J.bold;if(K!==L)I.push(`\x1B[38;2;${K}m`),L=K;I.push(J.character)}return`${I.join("")}\x1B[22m\x1B[39m`}function Zp(_,I,O,L,J){return _.map((K,ne)=>({...So(O,L+I+ne/J),bold:!1,character:K}))}function Xp(_,I,O,L,J,K,ne,oe){let de=Math.max(1,L*0.75),ue=Math.min(1,O/de),ve=J*Gs(ue),xe=Math.max(0,(O-de)/Math.max(1,L-de)),Se=(1-Gs(O/L))*oe*2,Pe=0.35*Math.max(0,1-xe*2),we=ue>=1,Le=Math.min(_.length,Math.ceil(ve+2+1));return _.slice(0,Le).map((en,Ve)=>{let on=So(K,ne+I+Ve/oe+Se),sn=Ve+zs(I,Ve,7919)*2-1;if(sn>ve+2)return{...on,bold:!1,character:" "};let an=ve-sn,rn=0.8*Math.exp(-(an*an)/12.5),pn=Math.min(0.9,rn+Pe),xn=!we&&sn>ve-4;return{...Wp(on,pn),bold:pn>0.3,character:xn?Kp(I,Ve,O):en}})}function Bs(_){return`\x1B[?2026h${_.map((I,O)=>`\x1B8${O>0?qs(O):""}${Yp(I)}`).join("")}\x1B[?2026l`}async function Co(_,I={}){if(!_)return;let O=I.output??process.stdout,L=I.sleep??Vp,J=I.seed??0,K=_.split(`
23
- `).map((ve)=>Array.from(ve)),ne=Math.max(...K.map((ve)=>ve.length)),oe=12000*K.filter((ve)=>ve.length>0).length/40,de=ne>0?Math.max(1,Math.ceil(oe/16.666666666666668)):0,ue=de>0?oe/de:0;O.write(`\x1B[?25l${K.length>1?`${`
24
- `.repeat(K.length-1)}${qp(K.length-1)}`:""}\x1B7`);try{for(let ve=1;ve<=de;ve+=1){if(I.signal?.aborted)break;O.write(Bs(K.map((xe,Se)=>Xp(xe,Se,ve,de,ne,0.1,J,3)))),await zp(ue,L,I.signal)}}finally{if(O.write(Bs(K.map((ve,xe)=>Zp(ve,xe,0.1,J,3)))),O.write("\x1B8"),K.length>1)O.write(qs(K.length-1));O.write(`
25
- \x1B[0m\x1B[?25h`)}}var Js=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
- `);function Qp(_){return Boolean(_.isTTY)}async function Tt(_={}){let I=_.output??process.stdout;if(!Qp(I))return;let O=_.input??process.stdin,L={output:I,seed:_.seed??Math.random()*8192,sleep:_.sleep};if(!O.isTTY||typeof O.setRawMode!=="function"){await Co(Js,L);return}let J=new AbortController,K=O.readableFlowing===!0,ne=O.isRaw===!0,oe=!1,de=(ue,ve)=>{if(ve.ctrl&&ve.name==="c")oe=!0;if(oe||ve.name==="return"||ve.name==="enter")J.abort()};Ws.emitKeypressEvents(O),O.on("keypress",de),O.setRawMode(!0),O.resume();try{await Co(Js,{...L,signal:J.signal})}finally{if(O.off("keypress",de),O.setRawMode(ne),!K)O.pause()}if(!oe)return;if(_.onInterrupt){_.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as of}from"node:crypto";import{existsSync as Zs}from"node:fs";import{dirname as yr,join as Xs}from"node:path";import{dirname as Ks,join as ef,resolve as nf}from"node:path";var tf="rule.lock";function rf(_){return ef(Ks(_),tf)}function Ys(_={}){return nf(_.cwd??process.cwd(),".safety-net.json")}function wn(_,I){let O=I.global?I.userConfigPath??G(_,I):I.projectConfigPath??U(I.cwd??process.cwd()),L=I.global?Ke(_,I):Je(O,I.cwd??process.cwd()),J=rf(O);return{configDir:Ks(O),configPath:O,lockPath:J,filesystemScope:L,configTarget:i(L,O),lockTarget:i(L,J)}}var sf="`cc-safety-net rule sync` is deprecated: rulebooks are live files that need no synchronization. This run only migrates the lock and cache an earlier version left behind.",af="cache",lf="rulebooks";function Qs(_,I={}){let O=wn(_,I),L=i(O.filesystemScope,na(O.configDir)),J=n(O.lockTarget);if(console.log(sf),J===null&&!Zs(L.path))return console.log(`No v2 lock or cache leftovers found in ${yr(O.configDir)}; nothing to migrate.`),0;let K=ff(J),ne=m(O.configTarget);if(!ne.config&&(n(O.configTarget)!==null||K.size>0))return console.error(`Cannot migrate: the rules config in ${yr(O.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let oe=ne.config?.rules??[];for(let de of oe.flatMap((ue)=>cf(ue,K,O,L,I.global===!0)))console.log(de);return j(O.lockTarget),it(L),console.log(`Removed the v2 lock and cache under ${yr(O.configDir)}.`),0}function ea(_,I){return[...new Set([{cwd:I},{cwd:I,global:!0}].flatMap((O)=>{let L=wn(_,O);return[L.lockPath,na(L.configDir)]}))].filter((O)=>Zs(O))}function cf(_,I,O,L,J){if(!S(_))return[];let K=D(_).name,ne=i(O.filesystemScope,N(O.configDir,K)),oe=n(ne);if(oe!==null&&df(oe,K))return[];let de=I.get(_),ue=de?uf(de,K,L.path,O.filesystemScope):null;if(ue===null)return[`Could not migrate ${_} from the v2 cache. Run \`cc-safety-net rule update ${_}${J?" --global":""}\` to vendor it.`];if(g(ne,ue),oe!==null)return[`Restored ${_} from the v2 cache over an invalid file.`];return[`Vendored ${_} from the v2 cache.`]}function df(_,I){let O=ye(_);return!("problem"in O)&&O.rulebook.name===I}function uf(_,I,O,L){let J=Xs(O,lf,`${pf(_)}--${_.digest.replace("sha256:","").slice(0,12)}`,fe),K=n(i(L,J));if(K===null||hf(K)!==_.digest)return null;let ne=ye(K);if("problem"in ne||ne.rulebook.name!==I)return null;return K}function na(_){return Xs(yr(_),af)}function pf(_){return([_.owner,_.repo,_.display_ref,_.name].every((L)=>typeof L==="string"&&L!=="")?`${_.owner}/${_.repo}#${_.display_ref}/${_.name}`:_.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function ff(_){let I=_===null?null:gf(_),O=ta(I)&&Array.isArray(I.rulebooks)?I.rulebooks:[];return new Map(O.filter(mf).map((L)=>[L.spec,L]))}function mf(_){return ta(_)&&typeof _.spec==="string"&&typeof _.digest==="string"}function ta(_){return!!_&&typeof _==="object"}function gf(_){try{return JSON.parse(_)}catch{return null}}function hf(_){return`sha256:${of("sha256").update(_).digest("hex")}`}var ra="\r\x1B[2K",yf="\x1B[?25l",vf="\x1B[39m",bf="\x1B[?25h",wf=100,kf=0.55,xf=80,oa=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function Sf(_){return new Promise((I)=>setTimeout(I,_))}async function vr(_,I={}){let O=I.output??process.stdout;if(!O.isTTY)return _;let L=I.sleep??Sf,J=!1,K=_.then((oe)=>(J=!0,oe),(oe)=>{throw J=!0,oe});if(await Promise.race([K.then(()=>!0),L(wf).then(()=>!1)]))return K;O.write(yf);try{for(let oe=0;!J;oe+=1)O.write(`${ra}${Vs(oe*kf)}${oa[oe%oa.length]}${vf} ${I.loadingMessage??"Loading…"}`),await Promise.race([K,L(xf)]);return await K}finally{O.write(`${ra}${bf}`)}}async function $t(_,I,O,L={}){let J=I();if(_)await O();if(_&&J.ready)await vr(J.ready,L);return J.finish()}import{stripVTControlCharacters as Cf}from"node:util";var br="amp plugins list",Rf=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function ia(_){if(!_.ampPluginListOutput)return{platform:"amp",status:"n/a"};let I=Cf(_.ampPluginListOutput).split(`
27
- `).map((O)=>Rf.exec(O)?.[1]).find((O)=>O!==void 0);if(!I)return{platform:"amp",status:"n/a"};if(I!=="active")return{platform:"amp",status:"disabled",method:br,configPath:br,errors:[`Amp personal plugin cc-safety-net is ${I}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:br,configPath:br}}import{existsSync as If,readFileSync as Tf}from"node:fs";import{isAbsolute as Kk,join as _f}from"node:path";function Ot(_){return _f(_,".gemini","config","hooks.json")}var $f=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Of(_){if(!_||typeof _!=="object"||Array.isArray(_))return[];return Object.values(_).flatMap((I)=>{if(!I||typeof I!=="object"||Array.isArray(I))return[];let O=I,L=O.PreToolUse;if(!Array.isArray(L))return[];return L.flatMap((J)=>{if(!J||typeof J!=="object"||Array.isArray(J))return[];let K=J.hooks;if(!Array.isArray(K))return[];return K.flatMap((ne)=>{if(!ne||typeof ne!=="object"||Array.isArray(ne))return[];let oe=ne.command;if(typeof oe!=="string"||!$f.test(oe))return[];return[{command:oe,enabled:O.enabled!==!1}]})})})}function sa(_){let I=Ot(_.environment.home);if(!If(I))return{platform:"antigravity-cli",status:"n/a",configPath:I};let O;try{O=Of(JSON.parse(Tf(I,"utf-8")))}catch(L){return{platform:"antigravity-cli",status:"n/a",configPath:I,errors:[`Failed to parse Antigravity hooks config ${I}: ${L instanceof Error?L.message:String(L)}`]}}if(O.some((L)=>L.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:I};if(O.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:I};return{platform:"antigravity-cli",status:"n/a",configPath:I}}import{join as Po}from"node:path";import{existsSync as Df,lstatSync as Lf,readFileSync as Nf}from"node:fs";import{join as jf}from"node:path";function Rn(_,I=(O)=>O){if(!Df(_))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(I(Nf(_,"utf-8")))}}catch{return{kind:"unreadable"}}}function Ln(_,I){if(_==="~")return I;if(_.startsWith("~/")||_.startsWith("~\\"))return jf(I,_.slice(2));return _}function cn(_){try{return Lf(_)}catch{return}}function wr(_,I){let O=cn(I);if(!O)return{platform:_,status:"n/a",configPath:I};if(!O.isSymbolicLink()&&O.isDirectory())return;return{platform:_,status:"n/a",configPath:I,errors:[`${I} is a symlink or not a directory; move or remove it before installing`]}}function tn(_,I){return typeof _==="object"&&_!==null?_[I]:void 0}var Ro="cc-safety-net@cc-marketplace";function kr(_){return _.env.get("CLAUDE_CONFIG_DIR")||Po(_.home,".claude")}function aa(_){return Po(kr(_),"plugins","installed_plugins.json")}function la(_,I){let O=tn(tn(_,"plugins"),I);return Array.isArray(O)&&O.length>0}function xr(_,I){let O=Rn(aa(_));return O.kind==="ok"&&la(O.value,I)}function Eo(_){let I=aa(_),O=Rn(I);if(O.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(O.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!la(O.value,Ro))return{platform:"claude-code",status:"n/a"};let L=Po(kr(_),"settings.json"),J=Rn(L);if(J.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(J.kind==="ok"&&tn(tn(J.value,"enabledPlugins"),Ro)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:L,errors:[`${Ro} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:I}}function ca(_){return Eo(_.environment)}var da="Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it.";function ua(_){if(!_.codexPluginListOutput)return{platform:"codex",status:"n/a"};let I=_.codexPluginListOutput.split(`
28
- `).find((O)=>O.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!I)return{platform:"codex",status:"n/a"};if(!I.includes("installed,"))return{platform:"codex",status:"n/a"};if(!I.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",errors:["Codex runs only trusted hooks, and doctor cannot check trust. Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."]}}import{existsSync as Er,readdirSync as Ff,readFileSync as Hf}from"node:fs";import{join as vn}from"node:path";function Sn(_){let I="",O=0,L=!1,J=!1,K=-1;while(O<_.length){let ne=_[O],oe=_[O+1];if(J){I+=ne,J=!1,O++;continue}if(ne==='"'&&!L){L=!0,K=-1,I+=ne,O++;continue}if(ne==='"'&&L){L=!1,I+=ne,O++;continue}if(ne==="\\"&&L){J=!0,I+=ne,O++;continue}if(L){I+=ne,O++;continue}if(ne==="/"&&oe==="/"){while(O<_.length&&_[O]!==`
29
- `)O++;continue}if(ne==="/"&&oe==="*"){O+=2;while(O<_.length-1){if(_[O]==="*"&&_[O+1]==="/"){O+=2;break}O++}continue}if(ne===","){K=I.length,I+=ne,O++;continue}if(ne==="}"||ne==="]"){if(K!==-1){let de=I.slice(K+1);if(/^\s*$/.test(de))I=I.slice(0,K)+de}K=-1,I+=ne,O++;continue}if(!/\s/.test(ne))K=-1;I+=ne,O++}return I}function fa(_,I,O){let L=I+1,J=!1;while(L<_.length){if(J){J=!1,L++;continue}if(_[L]==="\\"){J=!0,L++;continue}if(_[L]==='"')return L+1;L++}throw Error(O)}function _o(_,I,O){let L=_[I],J=L==="["?"]":"}",K=0,ne=I;while(ne<_.length){let oe=O.skipComment?.(_,ne)??ne;if(oe!==ne){ne=oe;continue}if(_[ne]==='"'){ne=fa(_,ne,O.stringError);continue}if(_[ne]===L)K++;if(_[ne]===J){if(K--,K===0)return ne}ne++}throw Error(O.bracketError)}function ma(_,I){let O=_.lastIndexOf(`
30
- `,I)+1;return/^[ \t]*/.exec(_.slice(O))?.[0]??""}function Sr(_,I){let O=I.end+(/^\s*/.exec(_.slice(I.end))?.[0].length??0);if(_[O]===","){let ne=_[O+1]===`
31
- `?O+2:O+1;return`${_.slice(0,I.start)}${_.slice(ne)}`}let L=_.slice(0,I.start).search(/\s*$/)-1;if(_[L]!==",")return`${_.slice(0,I.start)}${_.slice(I.end)}`;let J=_.lastIndexOf(`
32
- `,L-1),K=J!==-1&&/^\s*$/.test(_.slice(J+1,L))?J:L;return`${_.slice(0,K)}${_.slice(I.end)}`}function Ao(_,I){if(_.startsWith("//",I)){let O=_.indexOf(`
33
- `,I+2);return O===-1?_.length:O+1}if(_.startsWith("/*",I)){let O=_.indexOf("*/",I+2);return O===-1?_.length:O+2}return I}function pa(_,I){let O=I;while(O<_.length){if(/\s/.test(_[O]??"")){O++;continue}let L=Ao(_,O);if(L===O)return O;O=L}return O}function ga(_,I,O){let L=0,J=0;while(J<_.length){let K=Ao(_,J);if(K!==J){J=K;continue}if(_[J]==='"'){let ne=fa(_,J,O.stringError);if(L===1&&JSON.parse(_.slice(J,ne))===I){let oe=pa(_,ne),de=pa(_,oe+1);if(_[oe]===":"&&_[de]==="[")return{start:de,end:_o(_,de,{skipComment:Ao,...O})}}J=ne;continue}if(_[J]==="{"||_[J]==="[")L++;if(_[J]==="}"||_[J]==="]")L--;J++}return}var _n="cc-safety-net@cc-marketplace",Cr=["cc-marketplace","cc-safety-net"],ha=["_direct","copilot-safety-net"],ya=["cc-marketplace","safety-net"],va="safety-net@cc-marketplace";function Rr(_,I){let O=I.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${O}([^a-z0-9-]|$)`,"m").test(_??"")}function ba(_){return Rr(_,"cc-safety-net@cc-marketplace")}function wa(_){return Rr(_,"cc-marketplace")}function ka(_){return Rr(_,"copilot-safety-net")}function xa(_){return Rr(_,"safety-net@cc-marketplace")}function Pr(_){if(!_?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(_)}function Ca(_,I){if(!_)return null;let O=_.match(/(\d+)\.(\d+)\.(\d+)/);if(!O)return null;let L=[Number(O[1]),Number(O[2]),Number(O[3])];for(let J=0;J<I.length;J++){let K=L[J]??0,ne=I[J]??0;if(K!==ne)return K>ne}return!0}function Mf(_){return Ca(_,[0,0,422])}function Uf(_){return Ca(_,[1,0,8])}function Lt(_){return _.env.get("COPILOT_HOME")||vn(_.home,".copilot")}function Io(_){return(_.hooks?.preToolUse??[]).some((O)=>{if(O.type!==void 0&&O.type!=="command")return!1;return Pr(O.command)||Pr(O.bash)||Pr(O.powershell)||Pr(O.exec&&[O.exec,...O.args??[]].join(" "))})}function Dt(_){return _===void 0||typeof _==="string"}function Gf(_){return _===void 0||Array.isArray(_)&&_.every((I)=>typeof I==="string")}function Bf(_){if(!_||typeof _!=="object"||Array.isArray(_))return!1;let I=_;if(I.disableAllHooks!==void 0&&typeof I.disableAllHooks!=="boolean")return!1;if(I.hooks===void 0)return!0;if(!I.hooks||typeof I.hooks!=="object"||Array.isArray(I.hooks))return!1;let O=I.hooks.preToolUse;if(O===void 0)return!0;return Array.isArray(O)&&O.every((L)=>L!==null&&typeof L==="object"&&!Array.isArray(L)&&Dt(L.type)&&Dt(L.command)&&Dt(L.bash)&&Dt(L.powershell)&&Dt(L.exec)&&Gf(L.args))}function To(_,I){try{let O=JSON.parse(Sn(Hf(_,"utf-8")));if(!Bf(O)){I?.push(`Invalid hook config ${_}: hooks.preToolUse must be an array of hook objects`);return}return O}catch(O){I?.push(`Failed to parse ${_}: ${O instanceof Error?O.message:String(O)}`);return}}function Ra(_,I){try{return Ff(_).filter((O)=>O.endsWith(".json")).sort((O,L)=>O.localeCompare(L))}catch(O){return I?.push(`Failed to read ${_}: ${O instanceof Error?O.message:String(O)}`),[]}}function qf(_,I){if(!Er(_))return[];let O=[];for(let L of Ra(_,I)){let J=vn(_,L),K=To(J,I);if(K&&Io(K))O.push(J)}return O}function wt(_,I){if(!Er(_))return;let O=To(_,I);if(!O)return;return{path:_,config:O}}function Sa(_,I,O,L){if(I){_.push(`GitHub Copilot CLI ${I} does not support ${O}; requires ${L}+`);return}_.push(`GitHub Copilot CLI version unavailable; skipping ${O} because it requires ${L}+`)}function Vf(_){for(let I of _){if(I?.config.disableAllHooks===!0)return I.path;if(I?.config.disableAllHooks===!1)return}return}function zf(_,I,O,L){let J=Lt(_),K=vn(I,".github","hooks"),ne=vn(J,"hooks"),oe=vn(I,".github","copilot"),de=vn(I,".claude"),ue=Uf(O),ve=ue===!0?L:void 0,xe=[wt(vn(oe,"settings.local.json"),ve),wt(vn(oe,"settings.json"),ve),wt(vn(de,"settings.local.json"),ve),wt(vn(de,"settings.json"),ve)],Se=[wt(vn(J,"settings.json"),ve),wt(vn(J,"config.json"),ve)];if(ue!==!1){let an=Vf([...xe,...Se]);if(an){if(ue===null)L.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${an} as active`);return{activeConfigPaths:[],repoInlineSources:xe,disabledBy:an}}}let Pe=qf(K,L),we=Mf(O),Le=we===!0?L:void 0,en=Er(ne)?Ra(ne,Le):[],Ve=[];for(let an of en){let rn=vn(ne,an),pn=To(rn,Le);if(pn&&Io(pn))Ve.push(rn)}if(we!==!0&&Ve.length>0)Sa(L,O,`user hook files in ${ne}`,"0.0.422"),Ve.length=0;let on=[];for(let an of[...xe,...Se]){if(!an)continue;if(!Io(an.config))continue;if(ue===!0){on.push(an);continue}Sa(L,O,"inline hook definitions in Copilot config files","1.0.8");break}let sn=(an)=>an.filter((rn)=>!!rn&&on.includes(rn)).map((rn)=>rn.path);return{activeConfigPaths:[...sn(xe),...Pe,...sn(Se),...Ve],repoInlineSources:xe}}function Pa(_){let I=[],O=zf(_.environment,_.cwd,_.copilotCliVersion,I);if(O.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:O.disabledBy,configPaths:[O.disabledBy],errors:I.length>0?I:void 0};let L=Lt(_.environment),J=vn(L,"installed-plugins",...Cr),K=Er(J),ne=vn(L,"settings.json"),oe=Rn(ne,Sn),de=(Pe)=>tn(tn(Pe,"enabledPlugins"),_n),ue=O.repoInlineSources.find((Pe)=>typeof de(Pe?.config)==="boolean"),ve=ue??(oe.kind==="ok"?{path:ne,config:oe.value}:void 0);if(K&&!ue&&oe.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};let xe=K&&ve!==void 0&&de(ve.config)===!1;if(xe&&O.activeConfigPaths.length===0)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:ve.path,errors:[`${_n} is installed but not enabled in Copilot CLI`]};let Se=K&&!xe;if(Se||O.activeConfigPaths.length>0){let Pe=O.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:Se?"plugin config":"hook config",configPath:Pe??(Se?J:void 0),configPaths:O.activeConfigPaths.length>0?O.activeConfigPaths:void 0,errors:I.length>0?I:void 0}}return{platform:"copilot-cli",status:"n/a",errors:I.length>0?I:void 0}}import{existsSync as tm,readFileSync as rm}from"node:fs";import{existsSync as Ea,mkdirSync as Kf,readFileSync as Yf}from"node:fs";import{dirname as Zf,join as Xf}from"node:path";import{renameSync as Jf,writeFileSync as Wf}from"node:fs";function mn(_,I){let O=`${_}.${process.pid}.tmp`;Wf(O,I),Jf(O,_)}var In=Object.fromEntries(It.map((_)=>[_.id,`npx -y cc-safety-net hook ${_.flags[1]}`]));var Nt=In.cursor,Aa=30;function _r(_){return Xf(_.home,".cursor","hooks.json")}function Kn(_){return typeof _==="object"&&_!==null&&!Array.isArray(_)}function $o(){return{command:Nt,timeout:Aa,failClosed:!0}}function Ar(_){return Kn(_)&&_.command===Nt}function Qf(_){return Object.keys(_).length===3&&_.command===Nt&&_.timeout===Aa&&_.failClosed===!0}function em(_){try{return JSON.parse(Yf(_,"utf-8"))}catch(I){if(I instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${_}: ${I.message}`);throw I}}function _a(_){let I=em(_);if(!Kn(I))throw Error(`Cursor hooks config ${_} must be a JSON object`);if(I.version!==1)throw Error(`Cursor hooks config ${_} must set "version": 1`);if(I.hooks!==void 0&&!Kn(I.hooks))throw Error(`Cursor hooks config ${_} "hooks" must be an object`);let O=Kn(I.hooks)?I.hooks.preToolUse:void 0;if(O!==void 0&&!Array.isArray(O))throw Error(`Cursor hooks config ${_} "hooks.preToolUse" must be an array`);return I}function Ia(_){let I=Kn(_.hooks)?_.hooks.preToolUse:void 0;return Array.isArray(I)?I:[]}function nm(_){if(!_.some(Ar))return[..._,$o()];return _.reduce((I,O)=>{if(!Ar(O))return I.result.push(O),I;if(!I.inserted)I.result.push($o()),I.inserted=!0;return I},{result:[],inserted:!1}).result}function Ta(_,I,O){let L=Kn(I.hooks)?I.hooks:{},J={...I,hooks:{...L,preToolUse:O}};mn(_,`${JSON.stringify(J,null,2)}
34
- `)}function $a(_){let I=_r(_);if(!Ea(I))return Kf(Zf(I),{recursive:!0}),mn(I,`${JSON.stringify({version:1,hooks:{preToolUse:[$o()]}},null,2)}
35
- `),{path:I,alreadyInstalled:!1};let O=_a(I),L=Ia(O),J=L.filter(Ar);if(Kn(O.hooks)&&Array.isArray(O.hooks.preToolUse)&&J.length===1&&J[0]!==void 0&&Qf(J[0]))return{path:I,alreadyInstalled:!0};return Ta(I,O,nm(L)),{path:I,alreadyInstalled:!1}}function Oa(_){let I=_r(_);if(!Ea(I))return{path:I,alreadyInstalled:!1};let O=_a(I),L=Ia(O),J=L.filter((K)=>!Ar(K));if(J.length===L.length)return{path:I,alreadyInstalled:!1};return Ta(I,O,J),{path:I,alreadyInstalled:!0}}function om(_){if(!_||typeof _!=="object"||Array.isArray(_))return[];let I=_.hooks;if(!I||typeof I!=="object"||Array.isArray(I))return[];let O=I.preToolUse;if(!Array.isArray(O))return[];return O.filter((L)=>!!L&&typeof L==="object"&&!Array.isArray(L)&&L.command===Nt)}function im(_){let I=[];if(_.length>1)I.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let O=_[0];if(O&&O.failClosed!==!0)I.push('Managed hook is missing "failClosed": true; reinstall to repair');if(O&&O.timeout!==30)I.push('Managed hook "timeout" is not 30; reinstall to repair');return I}function Da(_){let I=_r(_.environment);if(!tm(I))return{platform:"cursor",status:"n/a",configPath:I};let O;try{O=JSON.parse(rm(I,"utf-8"))}catch(K){return{platform:"cursor",status:"n/a",configPath:I,errors:[`Failed to parse Cursor hooks config ${I}: ${K instanceof Error?K.message:String(K)}`]}}let L=om(O);if(L.length===0)return{platform:"cursor",status:"n/a",configPath:I};let J=im(L);return{platform:"cursor",status:"configured",method:"hook config",configPath:I,errors:J.length>0?J:void 0}}import{readdirSync as sm}from"node:fs";import{join as Oo,resolve as am}from"node:path";var Do="cc-safety-net";function Lo(_){let I=_.env.get("DSH_HOME");return Oo(I?.trim()?am(Ln(I,_.home)):Oo(_.home,".dsh"),"profiles")}function La(_){let I=Lo(_),O=cn(I)?.isDirectory()?sm(I,{withFileTypes:!0}).filter((J)=>J.isDirectory()&&J.name!=="node_modules").map((J)=>{let K=Oo(I,J.name,"package.json");return{name:J.name,configPath:K,manifest:Rn(K)}}):[];return{installed:O.flatMap((J)=>{if(J.manifest.kind!=="ok")return[];let K=J.manifest.value;if(tn(tn(K,"dependencies"),Do)===void 0)return[];let ne=tn(tn(tn(K,"dsh"),"profile"),"bundles");return[{name:J.name,configPath:J.configPath,enabled:Array.isArray(ne)&&ne.includes(Do)}]}),unreadable:O.some((J)=>J.manifest.kind==="unreadable")}}function No(_){return La(_).installed}function Na(_){let I=La(_.environment),O=I.installed.filter((K)=>K.enabled),L=I.installed.filter((K)=>!K.enabled),J=L.map((K)=>`${Do} is installed in the ${K.name} profile but its bundle is disabled`);if(O.length>0)return{platform:"deepseek-harness",status:"configured",method:"dsh bundle",configPaths:O.map((K)=>K.configPath),...J.length>0?{errors:J}:{}};if(L.length>0)return{platform:"deepseek-harness",status:"disabled",method:"dsh bundle",configPaths:L.map((K)=>K.configPath),errors:J};return I.unreadable?{platform:"deepseek-harness",status:"not-inspected"}:{platform:"deepseek-harness",status:"n/a"}}import{existsSync as lm}from"node:fs";import{join as jo}from"node:path";var Fo="gemini-safety-net";function Ho(_){let I=jo(_.home,".gemini","extensions"),O=jo(I,Fo);if(!lm(O))return{platform:"gemini-cli",status:"n/a"};let L=jo(I,"extension-enablement.json"),J=Rn(L);if(J.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let K=J.kind==="ok"?tn(tn(J.value,Fo),"overrides"):void 0;if(Array.isArray(K)&&K.some((oe)=>typeof oe==="string"&&oe.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:L,errors:[`${Fo} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:O}}function ja(_){return Ho(_.environment)}import{existsSync as pm,readFileSync as fm}from"node:fs";import{existsSync as Ha,mkdirSync as cm,readFileSync as Ma,rmSync as dm}from"node:fs";import{dirname as um,join as Fa}from"node:path";var jt=In["grok-build"],$r=30;function Or(_){return Fa(_.env.get("GROK_HOME")??Fa(_.home,".grok"),"hooks","cc-safety-net.json")}function Yn(_){return typeof _==="object"&&_!==null&&!Array.isArray(_)}function Ir(){return{hooks:[{type:"command",command:jt,timeout:$r}]}}function Ua(_){return Yn(_)&&_.command===jt}function Ga(_){return _.flatMap((I)=>{if(!Yn(I)||!Array.isArray(I.hooks))return[I];let O=I.hooks.filter((L)=>!Ua(L));if(O.length===I.hooks.length)return[I];return O.length===0?[]:[{...I,hooks:O}]})}function Ba(_){try{let I=JSON.parse(_);return Yn(I)?I:null}catch{return null}}function qa(_){let I=Yn(_.hooks)?_.hooks.PreToolUse:void 0;return Array.isArray(I)?I:[]}function Tr(_,I,O){let L=Yn(I.hooks)?I.hooks:{};mn(_,`${JSON.stringify({...I,hooks:{...L,PreToolUse:O}},null,2)}
36
- `)}function Va(_){let I=Or(_);if(!Ha(I))return cm(um(I),{recursive:!0}),Tr(I,{},[Ir()]),{path:I,alreadyInstalled:!1};let O=Ba(Ma(I,"utf-8"));if(!O)return Tr(I,{},[Ir()]),{path:I,alreadyInstalled:!1};let L=qa(O),J=L.filter((K)=>Yn(K)&&Array.isArray(K.hooks)&&K.hooks.some(Ua));if(J.length===1&&JSON.stringify(J[0])===JSON.stringify(Ir()))return{path:I,alreadyInstalled:!0};return Tr(I,O,[...Ga(L),Ir()]),{path:I,alreadyInstalled:!1}}function za(_){let I=Or(_);if(!Ha(I))return{path:I,alreadyInstalled:!1};let O=Ba(Ma(I,"utf-8"));if(!O)return{path:I,alreadyInstalled:!1};let L=qa(O),J=Ga(L);if(JSON.stringify(J)===JSON.stringify(L))return{path:I,alreadyInstalled:!1};let K=Yn(O.hooks)?O.hooks:{};if(J.length===0&&Object.keys(O).length===1&&Object.keys(K).length===1)return dm(I),{path:I,alreadyInstalled:!0};return Tr(I,O,J),{path:I,alreadyInstalled:!0}}function Ft(_){return!!_&&typeof _==="object"&&!Array.isArray(_)}function mm(_){if(!Ft(_)||!Ft(_.hooks))return[];let I=_.hooks.PreToolUse;if(!Array.isArray(I))return[];return I.filter((O)=>Ft(O)&&Array.isArray(O.hooks)&&O.hooks.some((L)=>Ft(L)&&L.command===jt))}function gm(_){let O=(Array.isArray(_.hooks)?_.hooks.filter(Ft):[]).find((L)=>L.command===jt);return[..._.matcher===void 0||_.matcher===""||_.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...O?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...O?.timeout===$r?[]:[`Managed hook "timeout" is not ${$r}; reinstall to repair`]]}function Ja(_){let I=Or(_.environment);if(!pm(I))return{platform:"grok-build",status:"n/a",configPath:I};let O;try{O=JSON.parse(fm(I,"utf-8"))}catch(K){return{platform:"grok-build",status:"n/a",configPath:I,errors:[`Failed to parse Grok Build hooks config ${I}: ${K instanceof Error?K.message:String(K)}`]}}let L=mm(O)[0];if(!L)return{platform:"grok-build",status:"n/a",configPath:I};let J=gm(L);return{platform:"grok-build",status:"configured",method:"hook config",configPath:I,errors:J.length>0?J:void 0}}import{readFileSync as tl}from"node:fs";import{join as rl}from"node:path";var Pn="cc-safety-net",Mo="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",hm=30;function Wa(_){return`${Mo}
37
- # version: ${_}
38
- `}function ym(_){return`${Wa(_)}name: ${Pn}
39
- version: "${_}"
1
+ import{a,s,Pe,Be,R,nt,ze,c,n,Ve,T,x,pe,ot,f,Ke,u,o,v,i,se,r,g,me,H,st,at,d,ge,he,ct,N,Z,ae,S,lt,_,h,ke,W,l,L,X,Je,Ye,F,w,I,ye,be,Ae,ut,m,e,Oe,Re,Ze,Xe,ce,Te,le,De,Q,B,Ne,xe,z,Qe,V,ee,te,ue,et,tt,C,M,Le,Me,$e,E,je,_e,Ue,y,t,ne,ve,b,k,A,dt,Ge,He,p,q}from"./chunks/index-wwg1vy7s.js";import{oe,K,We,U,G}from"./chunks/index-a00fdxyv.js";var ep=["-h","--help"];function gn(P,O){let D=Object.entries(P.booleans??{}),j=Object.entries(P.values??{}),J=Object.entries(P.lists??{}),Y=Object.fromEntries(D.map(([Se])=>[Se,!1])),re={},ie=Object.fromEntries(J.map(([Se])=>[Se,[]])),de=[],fe=[],we=!1,Ce=-1;for(let[Se,Ie]of O.entries()){if(Se<=Ce)continue;if(Ie==="--"){de.push(...O.slice(Se+1));break}if(ep.includes(Ie)){we=!0;continue}let Ee=D.find(([,en])=>en.includes(Ie));if(Ee){Y[Ee[0]]=!0;continue}let qe=j.find(([,en])=>en.includes(Ie));if(qe){let en=O[Se+1];if(en===void 0||en.startsWith("-")){fe.push(`${Ie} requires a value`);continue}re[qe[0]]=en,Ce=Se+1;continue}let Fe=J.find(([,en])=>en.includes(Ie));if(Fe){let en=O.slice(Se+1),on=en.findIndex((an)=>an.startsWith("-")),sn=en.slice(0,on===-1?en.length:on);if(sn.length===0){fe.push(`${Ie} requires at least one value`);continue}ie[Fe[0]]=[...ie[Fe[0]]??[],...sn],Ce=Se+sn.length;continue}if(Ie.startsWith("-")){fe.push(`Unknown option for ${P.label}: ${Ie}`);continue}if(P.positionals==="tail"){de.push(...O.slice(Se));break}de.push(Ie)}if(P.positionals!=="list"&&P.positionals!=="tail")fe.push(...de.map((Se)=>`Unexpected argument for ${P.label}: ${Se}`));return{flags:Y,values:re,lists:ie,positionals:de,help:we,errors:fe}}function Dn(P){for(let O of P)console.error(O);return P.length>0}import{readdirSync as ap,statSync as vs,unlinkSync as lp}from"node:fs";import{basename as bs,dirname as cp,isAbsolute as dp,join as up,relative as pp,resolve as fp,sep as mp}from"node:path";var gs=(P)=>{let O=Date.now()-new Date(P).getTime();if(!Number.isFinite(O))return"";let D=Math.floor(O/60000),j=Math.floor(D/60),J=Math.floor(j/24);if(J>0)return`${J}d ago`;if(j>0)return`${j}h ago`;if(D>0)return`${D}m ago`;return"just now"},ko=(P)=>{let O=(P??"").trim().split(/\s+/).filter((J)=>J&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(J)),D=O[0]?.split("/").pop();if(!D)return null;let j=O[1];return j&&/^[a-z][a-z0-9-]*$/.test(j)?`${D} ${j}`:D};function hs(P){let O=(J)=>`${J.sessionId}
2
+ ${ko(J.segment||J.command)}`,D=P.filter((J)=>J.decision!=="allow"),j=D.filter((J)=>J.sessionId).reduce((J,Y)=>J.set(O(Y),(J.get(O(Y))??0)+1),new Map);return new Set(D.filter((J)=>J.failureStage||(j.get(O(J))??0)>=2))}import{existsSync as np,readdirSync as tp,readFileSync as rp}from"node:fs";import{join as op}from"node:path";function zn(P,O){try{return tp(P,{withFileTypes:!0,encoding:"utf8"}).flatMap((D)=>{let j=op(P,D.name);if(D.isDirectory())return zn(j,O);if(D.name.endsWith(".jsonl"))return[j];return[]})}catch{if(O&&np(P))O.count++;return[]}}var ip=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function sp(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let O=P;if(typeof O.ts!=="string"||typeof O.command!=="string")return!1;return ip.every((D)=>O[D]===void 0||typeof O[D]==="string")}function kt(P,O){try{return rp(P,"utf-8").split(`
3
+ `).filter(Boolean).flatMap((D)=>{try{let j=JSON.parse(D);if(!sp(j)){if(O)O.count++;return[]}return[j]}catch{if(O)O.count++;return[]}})}catch{if(O)O.count++;return[]}}function hn(P){return Array.from(P,(O)=>{let D=O.charCodeAt(0);if(D<=31||D>=127&&D<=159)return`\\x${D.toString(16).padStart(2,"0")}`;return O}).join("")}function gp(P,O){let D=oe(P),j=gn({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"]}},O);if(Dn(j.errors))return null;if(j.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(j.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let J=j.values.limit===void 0?20:ys(j.values.limit);if(J===null)return console.error("--limit must be a positive number"),null;let Y=j.values.since===void 0?Math.min(30,D):ys(j.values.since);if(Y===null||Y>D)return console.error(`--since must be a positive number of days no greater than ${D}`),null;let re={limit:J,limitExplicit:j.values.limit!==void 0,since:Y,sinceExplicit:j.values.since!==void 0,all:j.flags.all,json:j.flags.json,suspect:j.flags.suspect,pruneLegacy:j.flags.pruneLegacy,dryRun:j.flags.dryRun,id:j.values.id,agent:j.values.agent,rule:j.values.rule,session:j.values.session,project:j.values.project===void 0?void 0:fp(j.values.project)};if(re.id&&(re.agent!==void 0||re.rule!==void 0||re.session!==void 0||re.project!==void 0||re.suspect||re.sinceExplicit||re.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(re.pruneLegacy&&(re.id!==void 0||re.agent!==void 0||re.rule!==void 0||re.session!==void 0||re.project!==void 0||re.suspect||re.all||re.sinceExplicit||re.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(re.dryRun&&!re.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return re}async function ws(P,O,D={}){let j=gp(P,O);if(!j)return 1;let J=D.logsDir??U(P);if(j.pruneLegacy)return hp(J,j.json,j.dryRun);if(!J)return console.log(j.json?"[]":j.id?`No retained audit log entry found for id ${hn(j.id)}.`:"No audit log entries found."),0;K(P,J);let Y={count:0},re=zn(J,Y).flatMap((Ce)=>kt(Ce,Y).map((Se)=>({entry:Se,file:Ce})));if(Y.count>0)console.error(`warning: ${Y.count} audit log ${Y.count===1?"source":"sources"} could not be read; these results are incomplete`);if(j.id)return wp(re,j,D.timeZone);let ie=Date.now()-j.since*24*60*60*1000,de=re.filter((Ce)=>kp(Ce,j,J,ie)),fe=j.suspect?hs(de.map((Ce)=>Ce.entry)):null,we=(fe?de.filter((Ce)=>fe.has(Ce.entry)):de).sort((Ce,Se)=>Date.parse(Se.entry.ts)-Date.parse(Ce.entry.ts)).slice(0,j.limit);if(j.json)return console.log(JSON.stringify(we.map((Ce)=>Ce.entry),null,2)),0;if(we.length===0)return console.log("No audit log entries found."),0;for(let Ce of we)console.log(Sp(Ce.entry,D.timeZone));return 0}function hp(P,O,D){let j=P?vp(P).map((ie)=>up(P,ie)):[];if(D)return yp(j,O);let J=[],Y=0,re=0;for(let ie of j){let de=vs(ie,{throwIfNoEntry:!1})?.size??0,fe=bp(ie);if(fe){J.push(`${bs(ie)}: ${fe}`);continue}Y++,re+=de}if(O)return console.log(JSON.stringify({removedFiles:Y,removedBytes:re,failedFiles:J.length})),J.length===0?0:1;console.log(Y===0&&J.length===0?"No legacy audit log files found.":`Removed ${Y} legacy audit log ${Y===1?"file":"files"} (${ks(re)}).`);for(let ie of J)console.error(`Could not remove ${hn(ie)}`);if(console.log("Nested v2 audit logs were not changed."),Y>0)console.log("This deletion cannot be undone.");return J.length===0?0:1}function yp(P,O){let D=P.reduce((j,J)=>j+(vs(J,{throwIfNoEntry:!1})?.size??0),0);if(O)return console.log(JSON.stringify({dryRun:!0,files:P.length,bytes:D})),0;if(console.log(P.length===0?"No legacy audit log files found.":`Would remove ${P.length} legacy audit log ${P.length===1?"file":"files"} (${ks(D)}).`),console.log("Nested v2 audit logs are not included."),P.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function vp(P){try{return ap(P,{withFileTypes:!0}).filter((O)=>O.isFile()&&O.name.endsWith(".jsonl")).map((O)=>O.name)}catch{return[]}}function bp(P){try{return lp(P),null}catch(O){return O instanceof Error?O.message:String(O)}}function ks(P){let O=["B","KiB","MiB","GiB"],D=Math.min(Math.floor(Math.log2(Math.max(P,1))/10),O.length-1);return`${Math.round(P/1024**D*10)/10} ${O[D]}`}function wp(P,O,D){let j=P.filter((Y)=>Y.entry.id===O.id);if(j.length>1)return console.error(`Multiple audit log entries found for id ${hn(O.id??"")}.`),1;if(O.json)return console.log(JSON.stringify(j.map((Y)=>Y.entry),null,2)),0;let J=j[0];if(!J)return console.log(`No retained audit log entry found for id ${hn(O.id??"")}.`),0;return console.log(Rp(J.entry,D)),0}function kp(P,O,D,j){if(!O.all&&P.entry.decision==="allow")return!1;if(Date.parse(P.entry.ts)<j)return!1;if(O.agent!==void 0&&P.entry.agent!==O.agent)return!1;if(O.rule!==void 0&&P.entry.ruleId!==O.rule)return!1;if(O.session!==void 0&&!xp(P,D,O.session))return!1;if(O.project!==void 0&&!Cp(P.entry.cwd,O.project))return!1;return!0}function xp(P,O,D){if(P.entry.sessionId===D)return!0;return cp(P.file)===O&&bs(P.file,".jsonl")===D}function Cp(P,O){if(!P)return!1;let D=pp(O,P);return D!==".."&&!D.startsWith(`..${mp}`)&&!dp(D)}function Sp(P,O){let D=hn(P.id??"-"),j=hn(P.decision??"deny"),J=P.cwd?` [${hn(P.cwd)}]`:"",Y=P.segment||P.command,re=Y===P.command?"":"↳ ",ie=Y.length>50?`${Y.slice(0,50)}…`:Y;return`${D.padEnd(16)} ${hn(xs(P.ts,O))} ${j.padEnd(5)} ${hn(P.agent??"-").padEnd(15)} ${hn(P.ruleId??"-").padEnd(20)} ${re}${hn(ie)}${J}`}function Rp(P,O){let D=(J)=>hn(J===void 0||J===null||J===""?"-":J),j=P.shape?`${P.agent??"-"} (shape: ${P.shape})`:P.agent??"-";return[`id: ${D(P.id)}`,`ts: ${D(xs(P.ts,O))}`,`decision: ${D(P.decision)}`,`agent: ${D(j)}`,`level: ${D(P.level)}`,`tool: ${D(P.toolName)}`,`rule: ${D(P.ruleId)}`,`intent: ${D(P.intent)}`,`stage: ${D(P.failureStage)}`,`error: ${D(P.errorCode)}`,`session: ${D(P.sessionId)}`,`cwd: ${D(P.cwd)}`,`version: ${D(P.v)}`,`truncated: ${D(P.truncated===!0?"yes":void 0)}`,`reason: ${D(P.reason)}`,`command: ${D(P.command)}`,`segment: ${D(P.segment)}`].join(`
4
+ `)}function xs(P,O){let D=new Date(P);if(Number.isNaN(D.getTime()))return P;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:O}).format(D)}function ys(P){let O=Number(P);return Number.isFinite(O)&&O>0?O:null}var Cs={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 Ss={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 Rs={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 xo=["npx","--offline","--no-install","@deepseek-ai/dsh","--version"],pr=[{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:10,runtime:{order:8,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:10,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:9,runtime:{order:7,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:9,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",doctorOrder:11,runtime:{order:9,flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{order:11,flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:12,runtime:{order:10,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:12,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:13,runtime:{order:11,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:13,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:14,install:{order:14,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:15,install:{order:15,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:16,install:{order:16,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:"deepseek-harness",displayName:"DeepSeek Harness",doctorOrder:6,install:{order:6,flag:"--deepseek-harness",artifactKind:"package",probeCommand:xo}},{id:"devin",displayName:"Devin CLI",doctorOrder:7,runtime:{order:5,flags:["-dv","--devin"],description:"Run as Devin CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:7,flag:"--devin",artifactKind:"hook config",probeCommand:["devin","--version"]}},{id:"droid",displayName:"Factory Droid",doctorOrder:8,runtime:{order:6,flags:["-fd","--droid"],description:"Run as Factory Droid PreToolUse hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--droid",artifactKind:"hook config",probeCommand:["droid","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],fr=pr.slice().sort((P,O)=>P.doctorOrder-O.doctorOrder).map((P)=>P.id),Ht=pr.filter((P)=>("runtime"in P)).slice().sort((P,O)=>P.runtime.order-O.runtime.order).map((P)=>({id:P.id,displayName:"displayName"in P.runtime?P.runtime.displayName:P.displayName,flags:P.runtime.flags,legacyFlags:"legacyFlags"in P.runtime?P.runtime.legacyFlags:[],description:P.runtime.description,legacyTopLevelFlags:P.runtime.legacyTopLevelFlags})),En=pr.slice().sort((P,O)=>P.install.order-O.install.order).map((P)=>({id:P.id,...P.install})).map(({order:P,...O})=>O),Pp=Object.fromEntries(pr.map((P)=>[P.id,P.displayName]));function mn(P){return Pp[P]}var Ep=Ht.map((P)=>({flags:P.flags.join(", "),description:P.description})),Ap=Ht.flatMap((P)=>P.flags.map((O)=>`cc-safety-net hook ${O}`)),Ps={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Ep,{flags:"-h, --help",description:"Show this help"}],examples:Ap};var Es={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...En.map((P)=>({flags:P.flag,description:`Install ${mn(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...En.map((P)=>`cc-safety-net install ${P.flag}`)]},As={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...En.map((P)=>({flags:P.flag,description:`Uninstall ${mn(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...En.map((P)=>`cc-safety-net uninstall ${P.flag}`)]},Is={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 _s={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 mr={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 Co=[{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"}],So=["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"],xt={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"},...Co.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",...So,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var Ts={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 $s={name:"statusline",description:"Print status line with mode indicators for shell integration",usage:"statusline --claude-code",options:[{flags:"-cc, --claude-code",description:"Print status line for Claude Code"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net statusline -cc","cc-safety-net statusline --claude-code"]};var gr=[Ts,Cs,_s,Ss,xt,mr,Es,Is,As,Ps,Rs,$s];function Ip(P){return P.aliases??[]}function hr(P){let O=P.toLowerCase();return gr.find((D)=>D.name.toLowerCase()===O||Ip(D).some((j)=>j.toLowerCase()===O))}import{existsSync as ch}from"node:fs";import{basename as _p}from"node:path";function yr(P,O=7,D=U(P)){let j=Date.now()-O*24*60*60*1000,J=[],Y=new Set,re=0,ie,de,fe,we;if(D)K(P,D);let Ce={count:0},Se=D?zn(D,Ce):[];for(let Ee of Se)for(let qe of kt(Ee,Ce)){if(qe.decision==="allow")continue;let Fe=new Date(qe.ts).getTime();if(Fe>=j){if(re++,Y.add(qe.sessionId??_p(Ee,".jsonl")),de===void 0||Fe<=de)ie=qe.ts,de=Fe;if(we===void 0||Fe>we)fe=qe.ts,we=Fe;Tp(J,qe,Fe)}}let Ie=J.map((Ee)=>({timestamp:Ee.ts,command:Ee.command,reason:Ee.reason,relativeTime:gs(new Date(Ee.ts))}));return{totalBlocked:re,sessionCount:Y.size,recentEntries:Ie,oldestEntry:ie,newestEntry:fe,unreadable:Ce.count}}function Tp(P,O,D){let j=P.findIndex((J)=>D>new Date(J.ts).getTime());if(j===-1){if(P.length<3)P.push(O);return}if(P.splice(j,0,O),P.length>3)P.pop()}import{dirname as Bp}from"node:path";import{dirname as $p,join as Op,resolve as Dp}from"node:path";var Lp="config.json";function wn(P,O,D,j){g(Np(P),`${JSON.stringify(O,null,2)}
5
+ `,D,j)}function Np(P){return typeof P==="string"?se(P):P}function Po(P){return{errors:ce(Fp(P),": "," "),ruleNames:new Set(De(P).map((O)=>O.toLowerCase()))}}var jp="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",Os="must match pattern (letters, numbers, hyphens, underscores)";function Fp(P){if(!Ds(P))return[e([],"Config must be an object")];return[...P.version===1?[]:[e(["version"],"must be 1")],...Hp(P.rules)]}function Hp(P){if(P===void 0)return[];if(!Array.isArray(P))return[e(["rules"],"must be an array")];return[...P.flatMap((O,D)=>Ds(O)?Mp(O,["rules",D]):[e(["rules",D],"must be an object")]),...Oe(P)]}function Mp(P,O){return[...Ro(P.name,[...O,"name"],"required string",d,jp),...Ro(P.command,[...O,"command"],"required string",w,Os),...P.subcommand===void 0?[]:Ro(P.subcommand,[...O,"subcommand"],"must be a string if provided",w,Os),...Up(P.block_args,[...O,"block_args"]),...Gp(P.reason,[...O,"reason"]),...P.intent===void 0||Te(P.intent)?[]:[e([...O,"intent"],Re)]]}function Ro(P,O,D,j,J){if(typeof P!=="string")return[e(O,D)];return j.test(P)?[]:[e(O,J)]}function Up(P,O){if(!Array.isArray(P))return[e(O,"required array")];if(P.length===0)return[e(O,"must have at least one element")];return P.flatMap((D,j)=>{if(typeof D!=="string")return[e([...O,j],"must be a string")];return D===""?[e([...O,j],"must not be empty")]:[]})}function Gp(P,O){if(typeof P!=="string")return[e(O,"required string")];if(P==="")return[e(O,"must not be empty")];return P.length>I?[e(O,`must be at most ${I} characters`)]:[]}function Ds(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function Eo(P){let O=Ls(P);if(!O.ok)return O.result;return Po(O.parsed)}function Ls(P){let O=[],D=new Set;try{let j=typeof P==="string"?se(P):P,J=r(j);if(J===null)return O.push(`File not found: ${j.path}`),{ok:!1,result:{errors:O,ruleNames:D}};if(!J.trim())return O.push("Config file is empty"),{ok:!1,result:{errors:O,ruleNames:D}};return{ok:!0,parsed:JSON.parse(J)}}catch(j){if(j instanceof o)return O.push(j.message),{ok:!1,result:{errors:O,ruleNames:D}};let J=j instanceof Error?j.message:String(j);return O.push(j instanceof SyntaxError?"Invalid JSON":J),{ok:!1,result:{errors:O,ruleNames:D}}}}function vr(P){return Dp(P,".safety-net.json")}function Un(P){let O=Ls(P);if(!O.ok)return O.result;let D=Ze(O.parsed);return{errors:D.errors,ruleNames:D.sources}}function Ct(P,O={}){return Op($p(ke(P,O)),Lp)}function Ns(P,O,D){let j;try{if(r(O)===null)return{path:P,exists:!1,valid:!1,ruleCount:0};j=Un(O),j.errors.push(...B(P,D))}catch(J){if(!(J instanceof o))throw J;j={errors:[J.message],ruleNames:new Set}}return{path:P,exists:!0,valid:j.errors.length===0,ruleCount:j.ruleNames.size,...j.errors.length>0?{errors:j.errors}:{}}}function qp(P,O){return{source:O,name:P.name,command:P.command,subcommand:P.subcommand,blockArgs:[...P.block_args],reason:P.reason}}function js(P,O){let D=W(P),j=_(O),J=Bp(D),Y=Q(P,{cwd:O,userConfigPath:D,projectConfigPath:j,userConfigDir:J}),re=X(P,{cwd:O,userConfigPath:D,projectConfigPath:j,userConfigDir:J}),ie=new Map(Y.rulebooks.flatMap((de)=>de.rules.map((fe)=>[fe,de.source])));return{userConfig:Ns(D,re.userConfigTarget,re.userScope),projectConfig:Ns(j,re.projectConfigTarget,re.projectScope),effectiveRules:Y.rules.map((de)=>qp(de,ie.get(de.name)??"project"))}}var Vp=[{flag:n.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:n.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:n.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:n.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:n.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:n.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:n.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:n.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"},{flag:n.projectTightenOnly,description:"Ignore project policy settings that weaken the user policy",defaultBehavior:"off"}];function Fs(P){return[...Vp.map((O)=>({name:O.flag.name,value:pe(O.flag,P.env),isSet:ot(O.flag,P.env),legacyName:O.flag.legacyName,legacyValue:O.flag.legacyName?P.env.get(O.flag.legacyName):void 0,legacyIsSet:O.flag.legacyName?P.env.get(O.flag.legacyName)!==void 0:void 0,description:O.description,defaultBehavior:O.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:P.env.get("CC_SAFETY_NET_HOME"),isSet:P.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var Hs={error:0,warning:1,info:2},Jp=["policy","config","audit"];function zp(P){return P.map((O)=>{if(O==="ownership")return"is not owned by the current user";if(O==="permissions")return"has unsafe permissions";if(O==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Kp=[{derive:(P)=>P.hooks.length>0&&P.hooks.every((O)=>!O.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(P)=>P.hooks.filter((O)=>O.inspectionStatus==="failed").map((O)=>{let D=mn(O.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${D} inspection failed`,detail:`Doctor could not verify the ${D} integration configuration.`,fixHint:`Correct the reported ${D} configuration error, then run \`cc-safety-net doctor\` again.`,integration:O.platform}})},{derive:(P)=>P.userConfig.exists&&!P.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.userConfig.path}]:[]},{derive:(P)=>P.projectConfig.exists&&!P.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.projectConfig.path}]:[]},{derive:(P)=>P.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${P.configState.reason}`,fixHint:"Fix the file named in the reason, or run `cc-safety-net rule update` to vendor a remote source, then rerun doctor."}]:[]},{derive:(P)=>P.v2Leftovers&&P.v2Leftovers.length>0?[{checkId:"config.v2-leftovers",severity:"info",title:"Rulebook lock and cache leftovers detected",detail:`Files an earlier version left behind are no longer read: ${P.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(P)=>P.legacyConfigs&&P.legacyConfigs.length>0?[{checkId:"config.legacy-ignored",severity:"warning",title:"Legacy inline rule configs are ignored",detail:`CC Safety Net no longer loads these files, so their rules enforce nothing: ${P.legacyConfigs.join(", ")}.`,fixHint:"Run `cc-safety-net rule migrate` to convert them (add `--cleanup` to delete each file once it is converted), then rerun doctor."}]:[]},{derive:(P)=>{let O=P.environment.find((D)=>D.name==="CC_SAFETY_NET_AUDIT_SCOPE");return Ve(O?.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."}]:[]}},...Jp.map((P)=>({derive:(O)=>O.posture.directories.filter((D)=>D.kind===P&&D.status==="unsafe").map((D)=>({checkId:`posture.${P}-directory-unsafe`,severity:"error",title:`${P[0]?.toUpperCase()}${P.slice(1)} directory is unsafe`,detail:`The ${P} directory ${zp(D.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...D.path?{path:D.path}:{}}))})),{derive:(P)=>{let O=[...P.effectiveSafety.weakenedRuleOverrides].sort();return O.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: ${O.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${O.join(", ")}.`}]:[]}}];function Ms(P){return Kp.flatMap((O,D)=>O.derive(P).map((j,J)=>({finding:j,catalogOrder:D,occurrence:J}))).sort((O,D)=>Hs[O.finding.severity]-Hs[D.finding.severity]||O.catalogOrder-D.catalogOrder||O.occurrence-D.occurrence).map((O)=>O.finding)}function Ln(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var Wp=(P)=>Ln()?`\x1B[32m${P}\x1B[0m`:P,Yp=(P)=>Ln()?`\x1B[33m${P}\x1B[0m`:P,Zp=(P)=>Ln()?`\x1B[34m${P}\x1B[0m`:P,Xp=(P)=>Ln()?`\x1B[36m${P}\x1B[0m`:P,Qp=(P)=>Ln()?`\x1B[31m${P}\x1B[0m`:P,ef=(P)=>Ln()?`\x1B[2m${P}\x1B[0m`:P,nf=(P)=>Ln()?`\x1B[1m${P}\x1B[0m`:P,nn={green:Wp,yellow:Yp,blue:Zp,cyan:Xp,red:Qp,dim:ef,bold:nf},tf="\x1B[0m",rf=[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 of(P){let O=P;return()=>(O=(O*1664525+1013904223)%4294967296,O/4294967296)}function sf(P){let O=[...rf],D=of(P);for(let j=O.length-1;j>0;j--){let J=Math.floor(D()*(j+1)),Y=O[j];O[j]=O[J],O[J]=Y}return O}function af(P,O=0){if(!Ln())return"";let D=sf(O);return`\x1B[38;5;${D[P%D.length]}m`}function Us(P,O,D=0){if(!Ln())return`"${P}"`;return`${af(O,D)}"${P}"${tf}`}function br(P){return P==="default"?"built-in default":`${P} policy`}var lf=new RegExp("\x1B\\[[0-9;]*m","g"),Ao=(P)=>P.replace(lf,"").length;function Kn(P){let O=(P.headers??P.rows[0]??[]).map((re,ie)=>{let de=Math.max(...P.rows.map((fe)=>Ao(fe[ie]??"")));return Math.max(Ao(re),de)}),D=(re,ie)=>re+" ".repeat(Math.max(0,ie-Ao(re))),j=(re,ie)=>ie[0]+O.map((de)=>re.repeat(de+2)).join(ie[1])+ie[2],J=(re)=>`│ ${re.map((ie,de)=>D(ie,O[de]??0)).join(" │ ")} │`,Y=P.headers?[` ${J(P.headers)}`,` ${j("─",["├","┼","┤"])}`]:[];return[` ${j("─",["┌","┬","┐"])}`,...Y,...P.rows.map((re)=>` ${J(re)}`),` ${j("─",["└","┴","┘"])}`].join(`
6
+ `)}function Gs(P){let O=[];O.push("Hook Integration"),O.push(cf(P));let D=[],j=[];for(let J of P){let Y=mn(J.platform);if(J.errors&&J.errors.length>0)for(let re of J.errors)if(J.configured)D.push({platform:Y,message:re});else j.push({platform:Y,message:re})}for(let J of D)O.push(` Warning (${J.platform}): ${J.message}`);for(let J of j)O.push(nn.red(` Error (${J.platform}): ${J.message}`));return O.join(`
7
+ `)}function cf(P){let O=["Platform","Discovery","Configuration","Inspection"],D=P.map((j)=>{let J=mn(j.platform);if(j.inspectionStatus==="not-inspected"){let de=nn.dim("Not inspected");return[J,de,de,de]}let Y=j.detected?nn.green("Detected"):j.inspectionStatus==="failed"?nn.red("Unknown"):nn.dim("Not detected"),re=j.configured?nn.green("Configured"):j.detected?nn.yellow("Not configured"):j.inspectionStatus==="failed"?nn.red("Unknown"):nn.dim("Not applicable"),ie=j.inspectionStatus==="verified"?nn.green("Verified"):j.inspectionStatus==="failed"?nn.red("Failed"):nn.dim("Not applicable");return[J,Y,re,ie]});return Kn({headers:O,rows:D})}function Bs(P){let D=["Guard Engine Verification",` Synthetic self-test: ${P.failed>0?nn.red(`${P.passed}/${P.total} FAIL`):nn.green(`${P.passed}/${P.total} passed`)}`],j=P.results.filter((J)=>!J.passed);if(j.length>0){D.push(""),D.push(nn.red(" Failures:"));for(let J of j)D.push(nn.red(` • ${J.description}`)),D.push(nn.red(` expected ${J.expected}, got ${J.actual}`))}return D.join(`
8
+ `)}function df(P){if(P.length===0)return" (no custom rules)";let O=["Source","Name","Command","Block Args"],D=P.map((j)=>[j.source,j.name,j.subcommand?`${j.command} ${j.subcommand}`:j.command,j.blockArgs.join(", ")]);return Kn({headers:O,rows:D})}function qs(P){let O=[];if(O.push("Configuration"),O.push(uf(P.userConfig,P.projectConfig)),O.push(""),P.effectiveRules.length>0)O.push(` Effective rules (${P.effectiveRules.length} total):`),O.push(df(P.effectiveRules));else O.push(" Effective rules: (none - using built-in rules only)");return O.join(`
9
+ `)}function uf(P,O){let D=["Scope","Status"],j=(Y)=>{if(!Y.exists)return nn.dim("N/A");if(!Y.valid)return nn.red(`Invalid (${Y.errors?.[0]??"unknown error"})`);return nn.green("Configured")},J=[["User",j(P)],["Project",j(O)]];return Kn({headers:D,rows:J})}function Vs(P){let O=[];return O.push("Environment"),O.push(pf(P)),O.join(`
10
+ `)}function Js(P){let O=P.effectiveSafety.policyScopes,D=["Effective Safety",` Selected preset: ${P.effectiveSafety.selectedPreset}${O?` (${br(O.levelScope)})`:""}`,` Effective: ${P.effectiveSafety.level}`],j=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[J,Y]of j){let re=P.effectiveSafety.capabilities[J],ie=re.enabled?nn.green("ON"):nn.dim("OFF"),de=re.sources.length>0?` (${re.sources.join(", ")})`:"";D.push(` ${Y}: ${ie} via ${re.source}${de}`)}if(O&&O.weakenings.length>0){D.push(` Project policy deltas${O.weakeningsIgnored?" (ignored)":""}:`);for(let J of O.weakenings)D.push(` ${J}`)}D.push(` Stored rule customizations: ${P.effectiveSafety.ruleCounts.stored}`),D.push(` Effective rule customizations: ${P.effectiveSafety.ruleCounts.effective}`);for(let[J,Y]of Object.entries(P.effectiveSafety.ruleOverrides))D.push(` ${J}: ${Y}`);return D.join(`
11
+ `)}function zs(P){let O=["Findings"];if(P.length===0)return O.push(" No findings from inspected doctor facts."),O.join(`
12
+ `);for(let D of P){let j=`[${D.severity.toUpperCase()}] ${D.checkId}: ${hn(D.title)}`,J=D.severity==="error"?nn.red:D.severity==="warning"?nn.yellow:nn.blue;if(O.push(` ${J(j)}`),O.push(` ${hn(D.detail)}`),D.path)O.push(` Path: ${hn(D.path)}`);if(D.fixHint)O.push(` Fix: ${hn(D.fixHint)}`)}return O.join(`
13
+ `)}function pf(P){let O=["Variable","Status","Legacy"],D=P.map((j)=>{let J=j.isSet?nn.green("✓"):nn.dim("✗"),Y=j.legacyName&&j.legacyIsSet?`${j.legacyName} ${nn.green("✓")}`:j.legacyName??"";return[j.name,J,Y]});return Kn({headers:O,rows:D})}function Ks(P){let O=[];if(P.totalBlocked===0)O.push("Recent Activity"),O.push(" No blocked commands in the last 7 days"),O.push(" Tip: This is normal for new installations");else O.push(`Recent Activity · last 7 days (${P.totalBlocked} blocked / ${P.sessionCount} sessions)`),O.push(ff(P.recentEntries));if(P.unreadable>0)O.push(` Warning: ${P.unreadable} audit log ${P.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return O.join(`
14
+ `)}function ff(P){let O=["Time","Command"],D=P.map((j)=>{let J=hn(j.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),Y=J.length>40?`${J.slice(0,37)}...`:J;return[j.relativeTime,Y]});return Kn({headers:O,rows:D})}function Ws(P){let O=[];if(O.push("Update Check"),P.latestVersion===null&&!P.error)return O.push(wr([["Status",nn.dim("Skipped")],["Installed",P.currentVersion]])),O.join(`
15
+ `);if(P.error)return O.push(wr([["Status",`${nn.yellow("⚠")} Error`],["Installed",P.currentVersion],["Error",nn.dim(P.error)]])),O.join(`
16
+ `);if(P.updateAvailable)return O.push(wr([["Status",`${nn.yellow("⚠")} Update Available`],["Current",P.currentVersion],["Latest",nn.green(P.latestVersion??"")]])),O.push(""),O.push(" Run: bunx cc-safety-net@latest doctor"),O.push(" Or: npx cc-safety-net@latest doctor"),O.join(`
17
+ `);return O.push(wr([["Status",`${nn.green("✓")} Up to date`],["Version",P.currentVersion]])),O.join(`
18
+ `)}function wr(P){return Kn({rows:P})}function Ys(P){let O=[];return O.push("System Info"),O.push(mf(P)),O.join(`
19
+ `)}function mf(P){let O=["Component","Version"],D=(Y)=>{if(Y===null)return nn.dim("not found");return Y},J=[{label:"cc-safety-net",value:P.version},...fr.map((Y)=>({label:mn(Y),value:P.versions[Y]??null})),{label:"Node.js",value:P.nodeVersion},{label:"npm",value:P.npmVersion},{label:"Bun",value:P.bunVersion},{label:"Platform",value:P.platform}].map((Y)=>[Y.label,D(Y.value)]);return Kn({headers:O,rows:J})}function Zs(P){if(P.findings.length===0)return nn.green(`
20
+ No findings from inspected doctor facts.`);let O={error:P.findings.filter((Y)=>Y.severity==="error").length,warning:P.findings.filter((Y)=>Y.severity==="warning").length,info:P.findings.filter((Y)=>Y.severity==="info").length},D=["error","warning","info"].filter((Y)=>O[Y]>0).map((Y)=>`${O[Y]} ${Y}`),j=P.findings.length===1?"finding":"findings",J=`
21
+ ${P.findings.length} ${j}: ${D.join(", ")}.`;if(O.error>0)return nn.red(J);if(O.warning>0)return nn.yellow(J);return nn.blue(J)}import{lstatSync as gf}from"node:fs";import{dirname as Io}from"node:path";function _o(P,O){try{let D=gf(O);if(D.isSymbolicLink())return{kind:P,path:O,status:"unsafe",issues:["symlink"]};if(!D.isDirectory())return{kind:P,path:O,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:P,path:O,status:"unknown",issues:[]};let j=[...D.uid!==process.getuid()?["ownership"]:[],...(D.mode&18)!==0?["permissions"]:[]];return{kind:P,path:O,status:j.length>0?"unsafe":"safe",issues:j}}catch(D){if(typeof D==="object"&&D!==null&&"code"in D&&D.code==="ENOENT")return{kind:P,path:O,status:"not-applicable",issues:[]};return{kind:P,path:O,status:"unknown",issues:[]}}}function Xs(P,O){let D=U(P);return{directories:[_o("policy",Io(Io(O))),_o("config",Io(O)),...D?[_o("audit",D)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as hf}from"node:child_process";import{existsSync as Qs}from"node:fs";import{delimiter as yf,extname as vf,join as bf}from"node:path";import{stripVTControlCharacters as ea}from"node:util";var ta="2.6.0",wf=5000,kf="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function pn(){return ta}function To(P,O){let D=P[O];if(D)return D;let j=Object.keys(P).find((J)=>J.toLowerCase()===O.toLowerCase()&&!!P[J]);return j?P[j]:D}function xf(P){return(To(P,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((O)=>O.length>0)}function Cf(P,O){let D=vf(P)?[P]:[...xf(O).map((j)=>`${P}${j}`),P];if(P.includes("/")||P.includes("\\"))return D.find((j)=>Qs(j))??P;return(To(O,"PATH")??"").split(yf).flatMap((j)=>D.map((J)=>bf(j,J))).find((j)=>Qs(j))??P}function na(P){if(!/[\s"&|<>^]/.test(P))return P;return`"${P.replace(/"/g,'""')}"`}function Wn(P,O){let[D,...j]=P,J=O[kf]==="win32"?"win32":process.platform;if(!D||J!=="win32")return{cmd:D??"",args:j};let Y=Cf(D,O);if(!/\.(?:bat|cmd)$/i.test(Y))return{cmd:Y,args:j};return{cmd:To(O,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",na(Y),...j.map(na)].join(" ")]}}var St=async(P,O=wf)=>{let D=await Sf(P,{timeoutMs:O});if(D.code!==0)return null;return ea(D.stdout).trim()||ea(D.stderr).trim()||null};function Sf(P,O){let[D,...j]=P;if(!D)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((J)=>{try{let Y=Wn([D,...j],process.env),re=hf(Y.cmd,Y.args,{stdio:["ignore","pipe","pipe"]}),ie=!1,de="",fe="";re.stdout.on("data",(Se)=>{de+=Se.toString()}),re.stderr.on("data",(Se)=>{fe+=Se.toString()});let we=(Se)=>{if(ie)return;ie=!0,clearTimeout(Ce),J(Se)},Ce=setTimeout(()=>{re.kill(),we({code:null,stdout:de,stderr:fe})},O.timeoutMs);re.on("close",(Se)=>{we({code:Se,stdout:de,stderr:fe})}),re.on("error",()=>{we({code:null,stdout:de,stderr:fe})})}catch{J({code:null,stdout:"",stderr:""})}})}function kr(P){if(!P)return null;let O=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(P);if(O)return O[1]??null;let D=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(P);if(D)return D[1]??null;return P.split(`
22
+ `)[0]?.trim()||null}async function xr(P,O=St,D=process.cwd()){let j=Promise.all(En.map(async(Ce)=>[Ce.id,kr(await O([...Ce.probeCommand]))])),[J,Y,re,ie,de,fe,we]=await Promise.all([j,j.then(async(Ce)=>{let Se=Ce.find(([qe])=>qe==="opencode")?.[1];if(!Se?.startsWith("2.")||!P(Se))return null;let Ie=["--param",`location[directory]=${D}`],Ee=["opencode","api","integration.list",...Ie];return await O(Ee,30000),O(["opencode","api","plugin.list",...Ie],30000)}),O(["codex","plugin","list"],30000),O(["amp","plugins","list"],30000),O(["node","--version"]),O(["npm","--version"]),O(["bun","--version"])]);return{version:ta,versions:Object.fromEntries(J),codexPluginListOutput:re,ampPluginListOutput:ie,openCodePluginListOutput:Y,nodeVersion:kr(de),npmVersion:kr(fe),bunVersion:kr(we),platform:`${process.platform} ${process.arch}`}}function $o(P,O){if(O==="dev")return!1;let D=P.split(".").map(Number),j=O.split(".").map(Number),[J=0,Y=0,re=0]=D,[ie=0,de=0,fe=0]=j;if(J!==ie)return J>ie;if(Y!==de)return Y>de;return re>fe}async function Gn(){let P=pn(),O=new AbortController,D=setTimeout(()=>O.abort(),3000);try{let j=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:O.signal});if(!j.ok)return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${j.status}`};let J=await j.json(),Y=$o(J.version,P);return{currentVersion:P,latestVersion:J.version,updateAvailable:Y}}catch(j){return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:j instanceof Error?j.message:"Network error"}}finally{clearTimeout(D)}}import*as da from"node:readline";var sa=(P)=>`\x1B[${P}B`,Rf=(P)=>`\x1B[${P}A`;var ra=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function Pf(P){return new Promise((O)=>setTimeout(O,P))}function Ef(P,O,D){if(!D)return O(P);if(D.aborted)return Promise.resolve();return new Promise((j,J)=>{let Y=()=>D.removeEventListener("abort",re),re=()=>{Y(),j()};D.addEventListener("abort",re,{once:!0}),O(P).then(()=>{Y(),j()},(ie)=>{Y(),J(ie)})})}function Cr(P){return Math.max(0,Math.min(1,P))}function Rt(P){return Math.max(0,Math.min(255,Math.round(P)))}function Oo(P){return P<=0.0031308?12.92*P:1.055*P**0.4166666666666667-0.055}function Af(P,O,D){let j=D*Math.PI/180,J=O*Math.cos(j),Y=O*Math.sin(j),re=(P+0.3963377774*J+0.2158037573*Y)**3,ie=(P-0.1055613458*J-0.0638541728*Y)**3,de=(P-0.0894841775*J-1.291485548*Y)**3;return{blue:Rt(Oo(Cr(-0.0041960863*re-0.7034186147*ie+1.707614701*de))*255),green:Rt(Oo(Cr(-1.2684380046*re+2.6097574011*ie-0.3413193965*de))*255),red:Rt(Oo(Cr(4.0767416621*re-3.3077115913*ie+0.2309699292*de))*255)}}function Do(P,O){let D=(O*P*180/Math.PI%360+360)%360;return Af(0.72,0.15,D)}function aa(P,O=0.1){let D=Do(O,P);return`\x1B[38;2;${D.red};${D.green};${D.blue}m`}function If(P,O){return{blue:Rt(P.blue+(255-P.blue)*O),green:Rt(P.green+(255-P.green)*O),red:Rt(P.red+(255-P.red)*O)}}function la(P,O,D){let j=Math.imul(P+2654435769,2246822507)^Math.imul(O+3266489909,668265263)^Math.imul(D+374761393,2654435761),J=j^j>>>15,Y=Math.imul(J,739982445),re=Y^Y>>>12,ie=Math.imul(re,695872825);return((ie^ie>>>15)>>>0)/4294967296}function _f(P,O,D){let j=Math.floor(la(P,O,D)*ra.length);return ra[j]??"░"}function oa(P){let O=Cr(P);return O*O*O*(O*(O*6-15)+10)}function Tf(P){if(P.length===0)return"";let O=[],D=!1,j="";for(let J of P){let Y=`${J.red};${J.green};${J.blue}`;if(J.bold!==D)O.push(J.bold?"\x1B[1m":"\x1B[22m"),D=J.bold;if(Y!==j)O.push(`\x1B[38;2;${Y}m`),j=Y;O.push(J.character)}return`${O.join("")}\x1B[22m\x1B[39m`}function $f(P,O,D,j,J){return P.map((Y,re)=>({...Do(D,j+O+re/J),bold:!1,character:Y}))}function Of(P,O,D,j,J,Y,re,ie){let de=Math.max(1,j*0.75),fe=Math.min(1,D/de),we=J*oa(fe),Ce=Math.max(0,(D-de)/Math.max(1,j-de)),Se=(1-oa(D/j))*ie*2,Ie=0.35*Math.max(0,1-Ce*2),Ee=fe>=1,qe=Math.min(P.length,Math.ceil(we+2+1));return P.slice(0,qe).map((Fe,en)=>{let on=Do(Y,re+O+en/ie+Se),sn=en+la(O,en,7919)*2-1;if(sn>we+2)return{...on,bold:!1,character:" "};let an=we-sn,rn=0.8*Math.exp(-(an*an)/12.5),fn=Math.min(0.9,rn+Ie),On=!Ee&&sn>we-4;return{...If(on,fn),bold:fn>0.3,character:On?_f(O,en,D):Fe}})}function ia(P){return`\x1B[?2026h${P.map((O,D)=>`\x1B8${D>0?sa(D):""}${Tf(O)}`).join("")}\x1B[?2026l`}async function Lo(P,O={}){if(!P)return;let D=O.output??process.stdout,j=O.sleep??Pf,J=O.seed??0,Y=P.split(`
23
+ `).map((we)=>Array.from(we)),re=Math.max(...Y.map((we)=>we.length)),ie=12000*Y.filter((we)=>we.length>0).length/40,de=re>0?Math.max(1,Math.ceil(ie/16.666666666666668)):0,fe=de>0?ie/de:0;D.write(`\x1B[?25l${Y.length>1?`${`
24
+ `.repeat(Y.length-1)}${Rf(Y.length-1)}`:""}\x1B7`);try{for(let we=1;we<=de;we+=1){if(O.signal?.aborted)break;D.write(ia(Y.map((Ce,Se)=>Of(Ce,Se,we,de,re,0.1,J,3)))),await Ef(fe,j,O.signal)}}finally{if(D.write(ia(Y.map((we,Ce)=>$f(we,Ce,0.1,J,3)))),D.write("\x1B8"),Y.length>1)D.write(sa(Y.length-1));D.write(`
25
+ \x1B[0m\x1B[?25h`)}}var ca=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
+ `);function Df(P){return Boolean(P.isTTY)}async function Mt(P={}){let O=P.output??process.stdout;if(!Df(O))return;let D=P.input??process.stdin,j={output:O,seed:P.seed??Math.random()*8192,sleep:P.sleep};if(!D.isTTY||typeof D.setRawMode!=="function"){await Lo(ca,j);return}let J=new AbortController,Y=D.readableFlowing===!0,re=D.isRaw===!0,ie=!1,de=(fe,we)=>{if(we.ctrl&&we.name==="c")ie=!0;if(ie||we.name==="return"||we.name==="enter")J.abort()};da.emitKeypressEvents(D),D.on("keypress",de),D.setRawMode(!0),D.resume();try{await Lo(ca,{...j,signal:J.signal})}finally{if(D.off("keypress",de),D.setRawMode(re),!Y)D.pause()}if(!ie)return;if(P.onInterrupt){P.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as Hf}from"node:crypto";import{existsSync as fa}from"node:fs";import{dirname as Sr,join as ma}from"node:path";import{dirname as ua,join as Lf,resolve as Nf}from"node:path";var jf="rule.lock";function Ff(P){return Lf(ua(P),jf)}function pa(P={}){return Nf(P.cwd??process.cwd(),".safety-net.json")}function kn(P,O){let D=O.global?O.userConfigPath??W(P,O):O.projectConfigPath??_(O.cwd??process.cwd()),j=O.global?Je(P,O):Ye(D,O.cwd??process.cwd()),J=Ff(D);return{configDir:ua(D),configPath:D,lockPath:J,filesystemScope:j,configTarget:i(j,D),lockTarget:i(j,J)}}var Mf="`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.",Uf="cache",Gf="rulebooks";function ga(P,O={}){let D=kn(P,O),j=i(D.filesystemScope,ya(D.configDir)),J=r(D.lockTarget);if(console.log(Mf),J===null&&!fa(j.path))return console.log(`No v2 lock or cache leftovers found in ${Sr(D.configDir)}; nothing to migrate.`),0;let Y=zf(J),re=m(D.configTarget);if(!re.config&&(r(D.configTarget)!==null||Y.size>0))return console.error(`Cannot migrate: the rules config in ${Sr(D.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let ie=re.config?.rules??[];for(let de of ie.flatMap((fe)=>Bf(fe,Y,D,j,O.global===!0)))console.log(de);return H(D.lockTarget),st(j),console.log(`Removed the v2 lock and cache under ${Sr(D.configDir)}.`),0}function ha(P,O){return[...new Set([{cwd:O},{cwd:O,global:!0}].flatMap((D)=>{let j=kn(P,D);return[j.lockPath,ya(j.configDir)]}))].filter((D)=>fa(D))}function Bf(P,O,D,j,J){if(!S(P))return[];let Y=N(P).name,re=i(D.filesystemScope,F(D.configDir,Y)),ie=r(re);if(ie!==null&&qf(ie,Y))return[];let de=O.get(P),fe=de?Vf(de,Y,j.path,D.filesystemScope):null;if(fe===null)return[`Could not migrate ${P} from the v2 cache. Run \`cc-safety-net rule update ${P}${J?" --global":""}\` to vendor it.`];if(g(re,fe),ie!==null)return[`Restored ${P} from the v2 cache over an invalid file.`];return[`Vendored ${P} from the v2 cache.`]}function qf(P,O){let D=xe(P);return!("problem"in D)&&D.rulebook.name===O}function Vf(P,O,D,j){let J=ma(D,Gf,`${Jf(P)}--${P.digest.replace("sha256:","").slice(0,12)}`,ge),Y=r(i(j,J));if(Y===null||Yf(Y)!==P.digest)return null;let re=xe(Y);if("problem"in re||re.rulebook.name!==O)return null;return Y}function ya(P){return ma(Sr(P),Uf)}function Jf(P){return([P.owner,P.repo,P.display_ref,P.name].every((j)=>typeof j==="string"&&j!=="")?`${P.owner}/${P.repo}#${P.display_ref}/${P.name}`:P.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function zf(P){let O=P===null?null:Wf(P),D=va(O)&&Array.isArray(O.rulebooks)?O.rulebooks:[];return new Map(D.filter(Kf).map((j)=>[j.spec,j]))}function Kf(P){return va(P)&&typeof P.spec==="string"&&typeof P.digest==="string"}function va(P){return!!P&&typeof P==="object"}function Wf(P){try{return JSON.parse(P)}catch{return null}}function Yf(P){return`sha256:${Hf("sha256").update(P).digest("hex")}`}var ba="\r\x1B[2K",Zf="\x1B[?25l",Xf="\x1B[39m",Qf="\x1B[?25h",em=100,nm=0.55,tm=80,wa=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function rm(P){return new Promise((O)=>setTimeout(O,P))}async function Rr(P,O={}){let D=O.output??process.stdout;if(!D.isTTY)return P;let j=O.sleep??rm,J=!1,Y=P.then((ie)=>(J=!0,ie),(ie)=>{throw J=!0,ie});if(await Promise.race([Y.then(()=>!0),j(em).then(()=>!1)]))return Y;D.write(Zf);try{for(let ie=0;!J;ie+=1)D.write(`${ba}${aa(ie*nm)}${wa[ie%wa.length]}${Xf} ${O.loadingMessage??"Loading…"}`),await Promise.race([Y,j(tm)]);return await Y}finally{D.write(`${ba}${Qf}`)}}async function Ut(P,O,D,j={}){let J=O();if(P)await D();if(P&&J.ready)await Rr(J.ready,j);return J.finish()}import{stripVTControlCharacters as om}from"node:util";var Pr="amp plugins list",im=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function ka(P){if(!P.ampPluginListOutput)return{platform:"amp",status:"n/a"};let O=om(P.ampPluginListOutput).split(`
27
+ `).map((D)=>im.exec(D)?.[1]).find((D)=>D!==void 0);if(!O)return{platform:"amp",status:"n/a"};if(O!=="active")return{platform:"amp",status:"disabled",method:Pr,configPath:Pr,errors:[`Amp personal plugin cc-safety-net is ${O}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:Pr,configPath:Pr}}import{existsSync as dm,readFileSync as um}from"node:fs";import{isAbsolute as qx,join as cm}from"node:path";function Gt(P){return cm(P,".gemini","config","hooks.json")}var pm=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function fm(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];return Object.values(P).flatMap((O)=>{if(!O||typeof O!=="object"||Array.isArray(O))return[];let D=O,j=D.PreToolUse;if(!Array.isArray(j))return[];return j.flatMap((J)=>{if(!J||typeof J!=="object"||Array.isArray(J))return[];let Y=J.hooks;if(!Array.isArray(Y))return[];return Y.flatMap((re)=>{if(!re||typeof re!=="object"||Array.isArray(re))return[];let ie=re.command;if(typeof ie!=="string"||!pm.test(ie))return[];return[{command:ie,enabled:D.enabled!==!1}]})})})}function xa(P){let O=Gt(P.environment.home);if(!dm(O))return{platform:"antigravity-cli",status:"n/a",configPath:O};let D;try{D=fm(JSON.parse(um(O,"utf-8")))}catch(j){return{platform:"antigravity-cli",status:"n/a",configPath:O,errors:[`Failed to parse Antigravity hooks config ${O}: ${j instanceof Error?j.message:String(j)}`]}}if(D.some((j)=>j.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:O};if(D.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:O};return{platform:"antigravity-cli",status:"n/a",configPath:O}}import{join as jo}from"node:path";import{existsSync as mm,lstatSync as gm,readFileSync as hm}from"node:fs";import{join as ym}from"node:path";function Rn(P,O=(D)=>D){if(!mm(P))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(O(hm(P,"utf-8")))}}catch{return{kind:"unreadable"}}}function Nn(P,O){if(P==="~")return O;if(P.startsWith("~/")||P.startsWith("~\\"))return ym(O,P.slice(2));return P}function dn(P){try{return gm(P)}catch{return}}function Er(P,O){let D=dn(O);if(!D)return{platform:P,status:"n/a",configPath:O};if(!D.isSymbolicLink()&&D.isDirectory())return;return{platform:P,status:"n/a",configPath:O,errors:[`${O} is a symlink or not a directory; move or remove it before installing`]}}function tn(P,O){return typeof P==="object"&&P!==null?P[O]:void 0}var No="cc-safety-net@cc-marketplace";function Ar(P){return P.env.get("CLAUDE_CONFIG_DIR")||jo(P.home,".claude")}function Ca(P){return jo(Ar(P),"plugins","installed_plugins.json")}function Sa(P,O){let D=tn(tn(P,"plugins"),O);return Array.isArray(D)&&D.length>0}function Ir(P,O){let D=Rn(Ca(P));return D.kind==="ok"&&Sa(D.value,O)}function Fo(P){let O=Ca(P),D=Rn(O);if(D.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(D.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!Sa(D.value,No))return{platform:"claude-code",status:"n/a"};let j=jo(Ar(P),"settings.json"),J=Rn(j);if(J.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(J.kind==="ok"&&tn(tn(J.value,"enabledPlugins"),No)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:j,errors:[`${No} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:O}}function Ra(P){return Fo(P.environment)}var Pa="Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it.";function Ea(P){if(!P.codexPluginListOutput)return{platform:"codex",status:"n/a"};let O=P.codexPluginListOutput.split(`
28
+ `).find((D)=>D.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!O)return{platform:"codex",status:"n/a"};if(!O.includes("installed,"))return{platform:"codex",status:"n/a"};if(!O.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",errors:["Codex runs only trusted hooks, and doctor cannot check trust. Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."]}}import{existsSync as Or,readdirSync as vm,readFileSync as bm}from"node:fs";import{join as bn}from"node:path";function vn(P){let O="",D=0,j=!1,J=!1,Y=-1;while(D<P.length){let re=P[D],ie=P[D+1];if(J){O+=re,J=!1,D++;continue}if(re==='"'&&!j){j=!0,Y=-1,O+=re,D++;continue}if(re==='"'&&j){j=!1,O+=re,D++;continue}if(re==="\\"&&j){J=!0,O+=re,D++;continue}if(j){O+=re,D++;continue}if(re==="/"&&ie==="/"){while(D<P.length&&P[D]!==`
29
+ `)D++;continue}if(re==="/"&&ie==="*"){D+=2;while(D<P.length-1){if(P[D]==="*"&&P[D+1]==="/"){D+=2;break}D++}continue}if(re===","){Y=O.length,O+=re,D++;continue}if(re==="}"||re==="]"){if(Y!==-1){let de=O.slice(Y+1);if(/^\s*$/.test(de))O=O.slice(0,Y)+de}Y=-1,O+=re,D++;continue}if(!/\s/.test(re))Y=-1;O+=re,D++}return O}function Ia(P,O,D){let j=O+1,J=!1;while(j<P.length){if(J){J=!1,j++;continue}if(P[j]==="\\"){J=!0,j++;continue}if(P[j]==='"')return j+1;j++}throw Error(D)}function Mo(P,O,D){let j=P[O],J=j==="["?"]":"}",Y=0,re=O;while(re<P.length){let ie=D.skipComment?.(P,re)??re;if(ie!==re){re=ie;continue}if(P[re]==='"'){re=Ia(P,re,D.stringError);continue}if(P[re]===j)Y++;if(P[re]===J){if(Y--,Y===0)return re}re++}throw Error(D.bracketError)}function _a(P,O){let D=P.lastIndexOf(`
30
+ `,O)+1;return/^[ \t]*/.exec(P.slice(D))?.[0]??""}function Ta(P,O){let D=O.end+(/^\s*/.exec(P.slice(O.end))?.[0].length??0);if(P[D]===","){let re=P[D+1]===`
31
+ `?D+2:D+1;return`${P.slice(0,O.start)}${P.slice(re)}`}let j=P.slice(0,O.start).search(/\s*$/)-1;if(P[j]!==",")return`${P.slice(0,O.start)}${P.slice(O.end)}`;let J=P.lastIndexOf(`
32
+ `,j-1),Y=J!==-1&&/^\s*$/.test(P.slice(J+1,j))?J:j;return`${P.slice(0,Y)}${P.slice(O.end)}`}function Ho(P,O){if(P.startsWith("//",O)){let D=P.indexOf(`
33
+ `,O+2);return D===-1?P.length:D+1}if(P.startsWith("/*",O)){let D=P.indexOf("*/",O+2);return D===-1?P.length:D+2}return O}function Aa(P,O){let D=O;while(D<P.length){if(/\s/.test(P[D]??"")){D++;continue}let j=Ho(P,D);if(j===D)return D;D=j}return D}function $a(P,O,D){let j=0,J=0;while(J<P.length){let Y=Ho(P,J);if(Y!==J){J=Y;continue}if(P[J]==='"'){let re=Ia(P,J,D.stringError);if(j===1&&JSON.parse(P.slice(J,re))===O){let ie=Aa(P,re),de=Aa(P,ie+1);if(P[ie]===":"&&P[de]==="[")return{start:de,end:Mo(P,de,{skipComment:Ho,...D})}}J=re;continue}if(P[J]==="{"||P[J]==="[")j++;if(P[J]==="}"||P[J]==="]")j--;J++}return}var In="cc-safety-net@cc-marketplace",_r=["cc-marketplace","cc-safety-net"],Oa=["_direct","copilot-safety-net"],Da=["cc-marketplace","safety-net"],La="safety-net@cc-marketplace";function Tr(P,O){let D=O.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${D}([^a-z0-9-]|$)`,"m").test(P??"")}function Na(P){return Tr(P,"cc-safety-net@cc-marketplace")}function ja(P){return Tr(P,"cc-marketplace")}function Fa(P){return Tr(P,"copilot-safety-net")}function Ha(P){return Tr(P,"safety-net@cc-marketplace")}function $r(P){if(!P?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(P)}function Ua(P,O){if(!P)return null;let D=P.match(/(\d+)\.(\d+)\.(\d+)/);if(!D)return null;let j=[Number(D[1]),Number(D[2]),Number(D[3])];for(let J=0;J<O.length;J++){let Y=j[J]??0,re=O[J]??0;if(Y!==re)return Y>re}return!0}function wm(P){return Ua(P,[0,0,422])}function km(P){return Ua(P,[1,0,8])}function qt(P){return P.env.get("COPILOT_HOME")||bn(P.home,".copilot")}function Uo(P){return(P.hooks?.preToolUse??[]).some((D)=>{if(D.type!==void 0&&D.type!=="command")return!1;return $r(D.command)||$r(D.bash)||$r(D.powershell)||$r(D.exec&&[D.exec,...D.args??[]].join(" "))})}function Bt(P){return P===void 0||typeof P==="string"}function xm(P){return P===void 0||Array.isArray(P)&&P.every((O)=>typeof O==="string")}function Cm(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let O=P;if(O.disableAllHooks!==void 0&&typeof O.disableAllHooks!=="boolean")return!1;if(O.hooks===void 0)return!0;if(!O.hooks||typeof O.hooks!=="object"||Array.isArray(O.hooks))return!1;let D=O.hooks.preToolUse;if(D===void 0)return!0;return Array.isArray(D)&&D.every((j)=>j!==null&&typeof j==="object"&&!Array.isArray(j)&&Bt(j.type)&&Bt(j.command)&&Bt(j.bash)&&Bt(j.powershell)&&Bt(j.exec)&&xm(j.args))}function Go(P,O){try{let D=JSON.parse(vn(bm(P,"utf-8")));if(!Cm(D)){O?.push(`Invalid hook config ${P}: hooks.preToolUse must be an array of hook objects`);return}return D}catch(D){O?.push(`Failed to parse ${P}: ${D instanceof Error?D.message:String(D)}`);return}}function Ga(P,O){try{return vm(P).filter((D)=>D.endsWith(".json")).sort((D,j)=>D.localeCompare(j))}catch(D){return O?.push(`Failed to read ${P}: ${D instanceof Error?D.message:String(D)}`),[]}}function Sm(P,O){if(!Or(P))return[];let D=[];for(let j of Ga(P,O)){let J=bn(P,j),Y=Go(J,O);if(Y&&Uo(Y))D.push(J)}return D}function Pt(P,O){if(!Or(P))return;let D=Go(P,O);if(!D)return;return{path:P,config:D}}function Ma(P,O,D,j){if(O){P.push(`GitHub Copilot CLI ${O} does not support ${D}; requires ${j}+`);return}P.push(`GitHub Copilot CLI version unavailable; skipping ${D} because it requires ${j}+`)}function Rm(P){for(let O of P){if(O?.config.disableAllHooks===!0)return O.path;if(O?.config.disableAllHooks===!1)return}return}function Pm(P,O,D,j){let J=qt(P),Y=bn(O,".github","hooks"),re=bn(J,"hooks"),ie=bn(O,".github","copilot"),de=bn(O,".claude"),fe=km(D),we=fe===!0?j:void 0,Ce=[Pt(bn(ie,"settings.local.json"),we),Pt(bn(ie,"settings.json"),we),Pt(bn(de,"settings.local.json"),we),Pt(bn(de,"settings.json"),we)],Se=[Pt(bn(J,"settings.json"),we),Pt(bn(J,"config.json"),we)];if(fe!==!1){let an=Rm([...Ce,...Se]);if(an){if(fe===null)j.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${an} as active`);return{activeConfigPaths:[],repoInlineSources:Ce,disabledBy:an}}}let Ie=Sm(Y,j),Ee=wm(D),qe=Ee===!0?j:void 0,Fe=Or(re)?Ga(re,qe):[],en=[];for(let an of Fe){let rn=bn(re,an),fn=Go(rn,qe);if(fn&&Uo(fn))en.push(rn)}if(Ee!==!0&&en.length>0)Ma(j,D,`user hook files in ${re}`,"0.0.422"),en.length=0;let on=[];for(let an of[...Ce,...Se]){if(!an)continue;if(!Uo(an.config))continue;if(fe===!0){on.push(an);continue}Ma(j,D,"inline hook definitions in Copilot config files","1.0.8");break}let sn=(an)=>an.filter((rn)=>!!rn&&on.includes(rn)).map((rn)=>rn.path);return{activeConfigPaths:[...sn(Ce),...Ie,...sn(Se),...en],repoInlineSources:Ce}}function Ba(P){let O=[],D=Pm(P.environment,P.cwd,P.copilotCliVersion,O);if(D.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:D.disabledBy,configPaths:[D.disabledBy],errors:O.length>0?O:void 0};let j=qt(P.environment),J=bn(j,"installed-plugins",..._r),Y=Or(J),re=bn(j,"settings.json"),ie=Rn(re,vn),de=(Ie)=>tn(tn(Ie,"enabledPlugins"),In),fe=D.repoInlineSources.find((Ie)=>typeof de(Ie?.config)==="boolean"),we=fe??(ie.kind==="ok"?{path:re,config:ie.value}:void 0);if(Y&&!fe&&ie.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};let Ce=Y&&we!==void 0&&de(we.config)===!1;if(Ce&&D.activeConfigPaths.length===0)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:we.path,errors:[`${In} is installed but not enabled in Copilot CLI`]};let Se=Y&&!Ce;if(Se||D.activeConfigPaths.length>0){let Ie=D.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:Se?"plugin config":"hook config",configPath:Ie??(Se?J:void 0),configPaths:D.activeConfigPaths.length>0?D.activeConfigPaths:void 0,errors:O.length>0?O:void 0}}return{platform:"copilot-cli",status:"n/a",errors:O.length>0?O:void 0}}import{existsSync as Fm,readFileSync as Hm}from"node:fs";import{existsSync as qa,mkdirSync as Tm,readFileSync as $m}from"node:fs";import{dirname as Om,join as Dm}from"node:path";import{existsSync as Em,renameSync as Am,statSync as Im,writeFileSync as _m}from"node:fs";function cn(P,O){let D=`${P}.${process.pid}.tmp`;_m(D,O,Em(P)?{mode:Im(P).mode&511}:{}),Am(D,P)}var xn=Object.fromEntries(Ht.map((P)=>[P.id,`npx -y cc-safety-net hook ${P.flags[1]}`]));var Vt=xn.cursor,Va=30;function Lr(P){return Dm(P.home,".cursor","hooks.json")}function Yn(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Bo(){return{command:Vt,timeout:Va,failClosed:!0}}function Dr(P){return Yn(P)&&P.command===Vt}function Lm(P){return Object.keys(P).length===3&&P.command===Vt&&P.timeout===Va&&P.failClosed===!0}function Nm(P){try{return JSON.parse($m(P,"utf-8"))}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${P}: ${O.message}`);throw O}}function Ja(P){let O=Nm(P);if(!Yn(O))throw Error(`Cursor hooks config ${P} must be a JSON object`);if(O.version!==1)throw Error(`Cursor hooks config ${P} must set "version": 1`);if(O.hooks!==void 0&&!Yn(O.hooks))throw Error(`Cursor hooks config ${P} "hooks" must be an object`);let D=Yn(O.hooks)?O.hooks.preToolUse:void 0;if(D!==void 0&&!Array.isArray(D))throw Error(`Cursor hooks config ${P} "hooks.preToolUse" must be an array`);return O}function za(P){let O=Yn(P.hooks)?P.hooks.preToolUse:void 0;return Array.isArray(O)?O:[]}function jm(P){if(!P.some(Dr))return[...P,Bo()];return P.reduce((O,D)=>{if(!Dr(D))return O.result.push(D),O;if(!O.inserted)O.result.push(Bo()),O.inserted=!0;return O},{result:[],inserted:!1}).result}function Ka(P,O,D){let j=Yn(O.hooks)?O.hooks:{},J={...O,hooks:{...j,preToolUse:D}};cn(P,`${JSON.stringify(J,null,2)}
34
+ `)}function Wa(P){let O=Lr(P);if(!qa(O))return Tm(Om(O),{recursive:!0}),cn(O,`${JSON.stringify({version:1,hooks:{preToolUse:[Bo()]}},null,2)}
35
+ `),{path:O,alreadyInstalled:!1};let D=Ja(O),j=za(D),J=j.filter(Dr);if(Yn(D.hooks)&&Array.isArray(D.hooks.preToolUse)&&J.length===1&&J[0]!==void 0&&Lm(J[0]))return{path:O,alreadyInstalled:!0};return Ka(O,D,jm(j)),{path:O,alreadyInstalled:!1}}function Ya(P){let O=Lr(P);if(!qa(O))return{path:O,alreadyInstalled:!1};let D=Ja(O),j=za(D),J=j.filter((Y)=>!Dr(Y));if(J.length===j.length)return{path:O,alreadyInstalled:!1};return Ka(O,D,J),{path:O,alreadyInstalled:!0}}function Mm(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];let O=P.hooks;if(!O||typeof O!=="object"||Array.isArray(O))return[];let D=O.preToolUse;if(!Array.isArray(D))return[];return D.filter((j)=>!!j&&typeof j==="object"&&!Array.isArray(j)&&j.command===Vt)}function Um(P){let O=[];if(P.length>1)O.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let D=P[0];if(D&&D.failClosed!==!0)O.push('Managed hook is missing "failClosed": true; reinstall to repair');if(D&&D.timeout!==30)O.push('Managed hook "timeout" is not 30; reinstall to repair');return O}function Za(P){let O=Lr(P.environment);if(!Fm(O))return{platform:"cursor",status:"n/a",configPath:O};let D;try{D=JSON.parse(Hm(O,"utf-8"))}catch(Y){return{platform:"cursor",status:"n/a",configPath:O,errors:[`Failed to parse Cursor hooks config ${O}: ${Y instanceof Error?Y.message:String(Y)}`]}}let j=Mm(D);if(j.length===0)return{platform:"cursor",status:"n/a",configPath:O};let J=Um(j);return{platform:"cursor",status:"configured",method:"hook config",configPath:O,errors:J.length>0?J:void 0}}import{readdirSync as Gm}from"node:fs";import{join as qo,resolve as Bm}from"node:path";var Vo="cc-safety-net";function Jo(P){let O=P.env.get("DSH_HOME");return qo(O?.trim()?Bm(Nn(O,P.home)):qo(P.home,".dsh"),"profiles")}function Xa(P){let O=Jo(P),D=dn(O)?.isDirectory()?Gm(O,{withFileTypes:!0}).filter((J)=>J.isDirectory()&&J.name!=="node_modules").map((J)=>{let Y=qo(O,J.name,"package.json");return{name:J.name,configPath:Y,manifest:Rn(Y)}}):[];return{installed:D.flatMap((J)=>{if(J.manifest.kind!=="ok")return[];let Y=J.manifest.value;if(tn(tn(Y,"dependencies"),Vo)===void 0)return[];let re=tn(tn(tn(Y,"dsh"),"profile"),"bundles");return[{name:J.name,configPath:J.configPath,enabled:Array.isArray(re)&&re.includes(Vo)}]}),unreadable:D.some((J)=>J.manifest.kind==="unreadable")}}function zo(P){return Xa(P).installed}function Qa(P){let O=Xa(P.environment),D=O.installed.filter((Y)=>Y.enabled),j=O.installed.filter((Y)=>!Y.enabled),J=j.map((Y)=>`${Vo} is installed in the ${Y.name} profile but its bundle is disabled`);if(D.length>0)return{platform:"deepseek-harness",status:"configured",method:"dsh bundle",configPaths:D.map((Y)=>Y.configPath),...J.length>0?{errors:J}:{}};if(j.length>0)return{platform:"deepseek-harness",status:"disabled",method:"dsh bundle",configPaths:j.map((Y)=>Y.configPath),errors:J};return O.unreadable?{platform:"deepseek-harness",status:"not-inspected"}:{platform:"deepseek-harness",status:"n/a"}}import{existsSync as Wm}from"node:fs";import{existsSync as tl,mkdirSync as qm,readFileSync as Vm}from"node:fs";import{dirname as Jm,join as Yo}from"node:path";function Ko(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Wo(P,O){return Ko(P)&&P.command===O}function el(P,O){return Ko(P)&&Array.isArray(P.hooks)&&P.hooks.some((D)=>Wo(D,O))}function Zn(P,O){return{hooks:[{type:"command",command:P,timeout:O}]}}function jn(P,O){return P.flatMap((D)=>{if(!Ko(D)||!Array.isArray(D.hooks))return[D];let j=D.hooks.filter((J)=>!Wo(J,O));if(j.length===D.hooks.length)return[D];return j.length===0?[]:[{...D,hooks:j}]})}function Et(P,O,D){let j=P.filter((J)=>el(J,O));return j.length===1&&JSON.stringify(j[0])===JSON.stringify(Zn(O,D))}function At(P,O){return P.find((D)=>el(D,O))}function It(P,O,D){let j=Array.isArray(P.hooks)?P.hooks.find((J)=>Wo(J,O)):void 0;return[...P.matcher===void 0||P.matcher===""||P.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...j?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...j?.timeout===D?[]:[`Managed hook "timeout" is not ${D}; reinstall to repair`]]}var Xn=xn.devin,Nr=30,zm={config:{},hooks:{},preToolUse:[]};function jr(P,O=process.platform){let D=O==="win32"?P.env.get("APPDATA")||Yo(P.home,"AppData","Roaming"):P.env.get("XDG_CONFIG_HOME")||Yo(P.home,".config");return Yo(D,"devin","config.json")}function nl(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Km(P){try{return{ok:!0,value:JSON.parse(vn(Vm(P,"utf-8")))}}catch(O){return{ok:!1,message:O instanceof Error?O.message:String(O)}}}function Zo(P){let O=Km(P);if(!O.ok)return`Failed to parse Devin CLI config ${P}: ${O.message}`;let D=O.value;if(!nl(D))return`Devin CLI config ${P} must be a JSON object`;let j=D.hooks===void 0?{}:D.hooks;if(!nl(j))return`Devin CLI config ${P} "hooks" must be an object`;let J=j.PreToolUse===void 0?[]:j.PreToolUse;if(!Array.isArray(J))return`Devin CLI config ${P} "hooks.PreToolUse" must be an array`;return{config:D,hooks:j,preToolUse:J}}function rl(P){let O=Zo(P);if(typeof O==="string")throw Error(O);return O}function ol(P,O,D){let j={...O.config,hooks:{...O.hooks,PreToolUse:D}};cn(P,`${JSON.stringify(j,null,2)}
36
+ `)}function il(P){let O=jr(P),D=tl(O)?rl(O):zm;if(Et(D.preToolUse,Xn,Nr))return{path:O,alreadyInstalled:!0};return qm(Jm(O),{recursive:!0}),ol(O,D,[...jn(D.preToolUse,Xn),Zn(Xn,Nr)]),{path:O,alreadyInstalled:!1}}function sl(P){let O=jr(P);if(!tl(O))return{path:O,alreadyInstalled:!1};let D=rl(O),j=jn(D.preToolUse,Xn);if(JSON.stringify(j)===JSON.stringify(D.preToolUse))return{path:O,alreadyInstalled:!1};return ol(O,D,j),{path:O,alreadyInstalled:!0}}function al(P){let O=jr(P.environment);if(!Wm(O))return{platform:"devin",status:"n/a",configPath:O};let D=Zo(O);if(typeof D==="string")return{platform:"devin",status:"n/a",configPath:O,errors:[D]};let j=At(D.preToolUse,Xn);if(!j)return{platform:"devin",status:"n/a",configPath:O};let J=It(j,Xn,Nr);return{platform:"devin",status:"configured",method:"hook config",configPath:O,errors:J.length>0?J:void 0}}import{existsSync as ng,readFileSync as tg}from"node:fs";import{existsSync as Fr,mkdirSync as Ym,readFileSync as Zm,rmSync as Xm}from"node:fs";import{dirname as Qm,join as ll}from"node:path";var Qn=xn.droid,Hr=30;function Mr(P){return ll(P.home,".factory","hooks.json")}function cl(P){return ll(P.home,".factory","settings.json")}function Xo(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function dl(P){try{return JSON.parse(Zm(P,"utf-8"))}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Factory Droid hooks config ${P}: ${O.message}`);throw O}}function ul(P){let O=dl(P);if(!Xo(O))throw Error(`Factory Droid hooks config ${P} must be a JSON object`);if(O.PreToolUse===void 0||Array.isArray(O.PreToolUse))return O;throw Error(`Factory Droid hooks config ${P} "PreToolUse" must be an array`)}function eg(P){if(!Fr(P))return{};let O=dl(P);return Xo(O)&&Xo(O.hooks)?O.hooks:{}}function pl(P){return Array.isArray(P.PreToolUse)?P.PreToolUse:[]}function fl(P,O,D){cn(P,`${JSON.stringify({...O,PreToolUse:D},null,2)}
37
+ `)}function ml(P){let O=Mr(P),D=Fr(O),j=D?ul(O):eg(cl(P)),J=pl(j);if(D&&Et(J,Qn,Hr))return{path:O,alreadyInstalled:!0};return Ym(Qm(O),{recursive:!0}),fl(O,j,[...jn(J,Qn),Zn(Qn,Hr)]),{path:O,alreadyInstalled:!1}}function gl(P){let O=Mr(P);if(!Fr(O))return{path:O,alreadyInstalled:!1};let D=ul(O),j=pl(D),J=jn(j,Qn);if(JSON.stringify(J)===JSON.stringify(j))return{path:O,alreadyInstalled:!1};let Y=Fr(cl(P));if(J.length===0&&Object.keys(D).length===1&&!Y)return Xm(O),{path:O,alreadyInstalled:!0};return fl(O,D,J),{path:O,alreadyInstalled:!0}}function hl(P){let O=Mr(P.environment);if(!ng(O))return{platform:"droid",status:"n/a",configPath:O};let D;try{D=JSON.parse(tg(O,"utf-8"))}catch(re){return{platform:"droid",status:"n/a",configPath:O,errors:[`Failed to parse Factory Droid hooks config ${O}: ${re instanceof Error?re.message:String(re)}`]}}let j=typeof D==="object"&&D!==null&&"PreToolUse"in D?D.PreToolUse:void 0,J=At(Array.isArray(j)?j:[],Qn);if(!J)return{platform:"droid",status:"n/a",configPath:O};let Y=[...J.commandRegex===void 0||J.commandRegex===""?[]:['Managed hook has a "commandRegex" that narrows coverage; reinstall to repair'],...It(J,Qn,Hr)];return{platform:"droid",status:"configured",method:"hook config",configPath:O,errors:Y.length>0?Y:void 0}}import{existsSync as rg}from"node:fs";import{join as Qo}from"node:path";var ei="gemini-safety-net";function ni(P){let O=Qo(P.home,".gemini","extensions"),D=Qo(O,ei);if(!rg(D))return{platform:"gemini-cli",status:"n/a"};let j=Qo(O,"extension-enablement.json"),J=Rn(j);if(J.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let Y=J.kind==="ok"?tn(tn(J.value,ei),"overrides"):void 0;if(Array.isArray(Y)&&Y.some((ie)=>typeof ie==="string"&&ie.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:j,errors:[`${ei} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:D}}function yl(P){return ni(P.environment)}import{existsSync as ag,readFileSync as lg}from"node:fs";import{existsSync as bl,mkdirSync as og,readFileSync as wl,rmSync as ig}from"node:fs";import{dirname as sg,join as vl}from"node:path";var rt=xn["grok-build"],Gr=30,ti=Zn(rt,Gr);function Br(P){return vl(P.env.get("GROK_HOME")??vl(P.home,".grok"),"hooks","cc-safety-net.json")}function qr(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function kl(P){try{let O=JSON.parse(P);return qr(O)?O:null}catch{return null}}function xl(P){let O=qr(P.hooks)?P.hooks.PreToolUse:void 0;return Array.isArray(O)?O:[]}function Ur(P,O,D){let j=qr(O.hooks)?O.hooks:{};cn(P,`${JSON.stringify({...O,hooks:{...j,PreToolUse:D}},null,2)}
38
+ `)}function Cl(P){let O=Br(P);if(!bl(O))return og(sg(O),{recursive:!0}),Ur(O,{},[ti]),{path:O,alreadyInstalled:!1};let D=kl(wl(O,"utf-8"));if(!D)return Ur(O,{},[ti]),{path:O,alreadyInstalled:!1};let j=xl(D);if(Et(j,rt,Gr))return{path:O,alreadyInstalled:!0};return Ur(O,D,[...jn(j,rt),ti]),{path:O,alreadyInstalled:!1}}function Sl(P){let O=Br(P);if(!bl(O))return{path:O,alreadyInstalled:!1};let D=kl(wl(O,"utf-8"));if(!D)return{path:O,alreadyInstalled:!1};let j=xl(D),J=jn(j,rt);if(JSON.stringify(J)===JSON.stringify(j))return{path:O,alreadyInstalled:!1};let Y=qr(D.hooks)?D.hooks:{};if(J.length===0&&Object.keys(D).length===1&&Object.keys(Y).length===1)return ig(O),{path:O,alreadyInstalled:!0};return Ur(O,D,J),{path:O,alreadyInstalled:!0}}function Rl(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function Pl(P){let O=Br(P.environment);if(!ag(O))return{platform:"grok-build",status:"n/a",configPath:O};let D;try{D=JSON.parse(lg(O,"utf-8"))}catch(re){return{platform:"grok-build",status:"n/a",configPath:O,errors:[`Failed to parse Grok Build hooks config ${O}: ${re instanceof Error?re.message:String(re)}`]}}let j=Rl(D)&&Rl(D.hooks)?D.hooks.PreToolUse:void 0,J=At(Array.isArray(j)?j:[],rt);if(!J)return{platform:"grok-build",status:"n/a",configPath:O};let Y=It(J,rt,Gr);return{platform:"grok-build",status:"configured",method:"hook config",configPath:O,errors:Y.length>0?Y:void 0}}import{readFileSync as Ll}from"node:fs";import{join as Nl}from"node:path";var Pn="cc-safety-net",ri="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",cg=30;function El(P){return`${ri}
39
+ # version: ${P}
40
+ `}function dg(P){return`${El(P)}name: ${Pn}
41
+ version: "${P}"
40
42
  description: "Block destructive commands and secret-file access before Hermes runs a tool."
41
43
  author: "cc-safety-net"
42
44
  provides_hooks:
43
45
  - pre_tool_call
44
- `}function vm(_){return`${Wa(_)}"""CC Safety Net guard for Hermes Agent.
46
+ `}function ug(P){return`${El(P)}"""CC Safety Net guard for Hermes Agent.
45
47
 
46
48
  Registers pre_tool_call and forwards the tool call to the packaged CC Safety Net
47
49
  adapter (cc-safety-net hook --hermes-agent) over JSON stdin. The adapter prints nothing
@@ -57,8 +59,8 @@ import subprocess
57
59
 
58
60
  HOOK_EVENT = "pre_tool_call"
59
61
  SUPPORTED_TOOLS = ("patch", "read_file", "terminal", "write_file")
60
- ANALYZER = [${In["hermes-agent"].split(" ").map((I)=>`"${I}"`).join(", ")}]
61
- TIMEOUT_SECONDS = ${hm}
62
+ ANALYZER = [${xn["hermes-agent"].split(" ").map((O)=>`"${O}"`).join(", ")}]
63
+ TIMEOUT_SECONDS = ${cg}
62
64
 
63
65
 
64
66
  def _block(detail):
@@ -211,85 +213,85 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
211
213
 
212
214
  def register(ctx):
213
215
  ctx.register_hook("pre_tool_call", _pre_tool_call)
214
- `}function Ht(_){return[{name:"__init__.py",content:vm(_)},{name:"plugin.yaml",content:ym(_)}]}import{mkdirSync as bm,readdirSync as wm,readFileSync as Ka,rmSync as Uo}from"node:fs";import{basename as km,dirname as xm,join as Nn}from"node:path";var Sm="__pycache__",Cm=/^[a-z0-9][a-z0-9_-]{0,63}$/;function Rm(_){try{return Ka(_,"utf-8").trim()}catch{return}}function Go(_){let I=_.env.get("HERMES_HOME")?.trim();if(I&&km(xm(I))==="profiles")return I;let O=I||Nn(_.home,".hermes"),L=Nn(O,"active_profile"),J=Rm(L),K=J?.toLowerCase();if(!K||K==="default")return O;if(!Cm.test(K))throw Error(`Invalid Hermes profile name "${J}" in ${L}; run \`hermes profile use <name>\` with a valid profile.`);return Nn(O,"profiles",K)}function Bo(_){return Nn(Go(_),"plugins",Pn)}function qo(_){return _.startsWith(Mo)}function Vo(_,I){let O=Bo(_),L=cn(O);if(L&&(L.isSymbolicLink()||!L.isDirectory()))throw Error(`Refusing to ${I} ${O}: not a regular directory. Move or remove it and rerun ${I==="install"?"install":"uninstall"} --hermes-agent.`);return O}function Ya(_,I){let O=cn(_);if(!O)return;if(O.isSymbolicLink()||!O.isFile())throw Error(`Refusing to ${I} ${_}: not a regular file. Move or remove it.`);let L=Ka(_,"utf-8");if(!qo(L))throw Error(`Refusing to ${I} unmanaged file at ${_}. Move or remove it.`);return L}function Za(_){let I=Vo(_,"install"),O=Ht(un());if(O.map((J)=>Ya(Nn(I,J.name),"overwrite")).every((J,K)=>J===O[K]?.content))return{path:I,alreadyInstalled:!0};return bm(I,{recursive:!0}),O.forEach((J)=>{mn(Nn(I,J.name),J.content)}),{path:I,alreadyInstalled:!1}}function zo(_){let I=Vo(_,"remove");if(!cn(I))return[];return Ht(un()).filter((O)=>Ya(Nn(I,O.name),"remove")!==void 0)}function Xa(_){let I=Vo(_,"remove");if(!cn(I))return{path:I,alreadyInstalled:!1};let O=zo(_);if(O.forEach((L)=>{Uo(Nn(I,L.name))}),Uo(Nn(I,Sm),{recursive:!0,force:!0}),wm(I).length===0)Uo(I,{recursive:!0});return{path:I,alreadyInstalled:O.length>0}}var Mt="hermes-agent",Qa=/^([^\s#][^:]*):/,Pm=/^\s+([A-Za-z_][\w-]*):/,el=/^\s+-\s*(.*)$/;function Em(_){return _.trim().replace(/^(["'])(.*)\1$/,"$2")}function Am(_){let I=_.split(/\r?\n/),O=I.findIndex((K)=>Qa.exec(K)?.[1]?.trim()==="plugins");if(O===-1)return[];let L=I.slice(O+1),J=L.findIndex((K)=>Qa.test(K));return J===-1?L:L.slice(0,J)}function nl(_,I){let O=Am(_),L=O.findIndex((ne)=>Pm.exec(ne)?.[1]===I);if(L===-1)return[];let J=O.slice(L+1),K=J.findIndex((ne)=>!el.test(ne));return(K===-1?J:J.slice(0,K)).map((ne)=>Em(el.exec(ne)?.[1]??""))}function _m(_){try{return tl(rl(Go(_),"config.yaml"),"utf-8")}catch{return}}function Jo(_){let I=_m(_)??"";return nl(I,"enabled").includes(Pn)&&!nl(I,"disabled").includes(Pn)}function ol(_){return/^# version:\s*(.+)$/m.exec(_)?.[1]?.trim()}function Im(_,I){let O=cn(_);if(!O)return{error:`${I.name} is missing from ${_}; run install --hermes-agent`};if(O.isSymbolicLink()||!O.isFile())return{error:`${_} is a symlink or not a regular file; move or remove it`};try{let L=tl(_,"utf-8");if(!qo(L))return{error:`Unmanaged ${I.name} occupies ${_}; move or remove it`};if(ol(L)===un()&&L!==I.content)return{error:`Modified ${I.name} occupies ${_}; run install --hermes-agent to restore it`};return{content:L}}catch(L){return{error:`Failed to read ${_}: ${L instanceof Error?L.message:String(L)}`}}}function Tm(_){try{return{path:Bo(_)}}catch(I){return{error:I instanceof Error?I.message:String(I)}}}function il(_){let I=Tm(_.environment);if("error"in I)return{platform:Mt,status:"n/a",errors:[I.error]};let O=I.path,L=wr(Mt,O);if(L)return L;let J=Ht(un()).map((de)=>Im(rl(O,de.name),de)),K=J.flatMap((de)=>("error"in de)?[de.error]:[]);if(K.length>0)return{platform:Mt,status:"n/a",configPath:O,errors:K};let ne=J.some((de)=>("content"in de)&&ol(de.content)!==un()),oe=ne?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!Jo(_.environment))return{platform:Mt,status:"disabled",method:"plugin directory",configPath:O,errors:[`${Pn} is not enabled in Hermes; run \`hermes plugins enable ${Pn}\``,...oe]};return{platform:Mt,status:"configured",method:"plugin directory",configPath:O,errors:ne?oe:void 0}}import{existsSync as $m,readFileSync as Om}from"node:fs";import{join as sl}from"node:path";var Dm=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function Lm(_){return sl(_.env.get("KIMI_CODE_HOME")||sl(_.home,".kimi-code"),"config.toml")}function Ut(_){let I=Lm(_.environment);if(!$m(I))return{platform:"kimi-code",status:"n/a",configPath:I};try{if(!Dm.test(Om(I,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:I}}catch(O){return{platform:"kimi-code",status:"n/a",configPath:I,errors:[`Failed to read ${I}: ${O instanceof Error?O.message:String(O)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:I}}import{readFileSync as hl}from"node:fs";import{join as Bt}from"node:path";var dn="cc-safety-net",Cn="index.js",kt="openclaw.plugin.json",xt="package.json";var Dr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as Fm,lstatSync as Hm,readdirSync as Mm,readFileSync as Um}from"node:fs";import{dirname as ll,join as Gn}from"node:path";import{fileURLToPath as Gm}from"node:url";import{spawn as Nm}from"node:child_process";function jm(_){return _.join(" ")}function Wo(_,I,O){return[`Failed to run ${jm(_)}${I===null?"":` (exit ${I})`}.`,O.trim()].filter(Boolean).join(`
215
- `)}function Ko(_){let I={stdout:"",stderr:""};return _.stdout.setEncoding("utf-8"),_.stderr.setEncoding("utf-8"),_.stdout.on("data",(O)=>{I.stdout+=O}),_.stderr.on("data",(O)=>{I.stderr+=O}),I}function yn(_,I){return new Promise((O,L)=>{let J=Wn([..._],process.env),K=Nm(J.cmd,J.args,{stdio:["ignore","pipe","pipe"]}),ne=Ko(K),oe=()=>[ne.stdout,ne.stderr].filter(Boolean).join(`
216
- `),de=I?.timeoutMs??120000,ue=setTimeout(()=>{K.kill(),L(Error(Wo(_,null,`Timed out after ${de}ms.
217
- ${oe()}`.trim())))},de);K.on("error",(ve)=>{clearTimeout(ue),L(Error(Wo(_,null,`${ve.message}
218
- ${oe()}`.trim())))}),K.on("close",(ve)=>{if(clearTimeout(ue),ve!==0){L(Error(Wo(_,ve,oe())));return}O(I?.stdoutOnly?ne.stdout:oe())})})}async function Yo(_){for(let I of _)await yn(I)}async function al(_){for(let I of _)try{await yn(I)}catch(O){console.warn(O instanceof Error?O.message:String(O))}}var Zo=Gn("openclaw",dn),Zn=`run \`openclaw plugins enable ${dn}\``,Bm="config reload superseded by a newer runtime config source",qm=[Cn,kt,xt];function cl(_){let I=_.env.get("OPENCLAW_HOME")?.trim();return I?Ln(I,_.home):_.home}function dl(_){let I=cl(_),O=_.env.get("OPENCLAW_STATE_DIR")?.trim();if(O)return Ln(O,I);let L=_.env.get("OPENCLAW_CONFIG_PATH")?.trim();return L?ll(Ln(L,I)):Gn(I,".openclaw")}function ul(_){let I=_.env.get("OPENCLAW_CONFIG_PATH")?.trim();return I?Ln(I,cl(_)):Gn(dl(_),"openclaw.json")}function Gt(_){return Gn(dl(_),"extensions",dn)}function Vm(_){let I=Mm(_);if(I.length===0)return!0;if(I.some((J)=>!qm.includes(J)))return!1;let O=Gn(_,Cn),L=cn(O);return L!==void 0&&!L.isSymbolicLink()&&L.isFile()&&Um(O,"utf-8").startsWith(Dr)}function Xo(_){let I=Gt(_),O=cn(I);if(!O)return;if(!O.isSymbolicLink()&&O.isDirectory()&&Vm(I))return;throw Error(`Refusing to modify ${I}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function pl(){let _=ll(Gm(import.meta.url));return[Gn(_,Zo),Gn(_,"..",Zo),Gn(_,"..","..","..","dist",Zo)]}function Qo(_=pl()){return _.find((I)=>Fm(I)&&Hm(I).isDirectory())}function zm(_=pl()){let I=Qo(_);if(!I)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return I}function fl(_=zm()){return[["openclaw","plugins","install",_,"--force","--accept-capabilities"]]}function Jm(_){let I=(()=>{try{return JSON.parse(_)}catch{return}})(),O=tn(tn(I,"plugin"),"status");return typeof O==="string"?O:void 0}async function Wm(){await yn(["openclaw","plugins","enable",dn]).catch((_)=>{if(!(_ instanceof Error&&_.message.includes(Bm)))throw _})}async function ml(_){let I=async()=>Jm(await yn(["openclaw","plugins","inspect",dn,"--runtime","--json"],{stdoutOnly:!0})),O=await I(),L=O==="disabled"&&_;if(L)await Wm();let J=L?await I():O;if(J==="loaded")return;throw Error(`${J===void 0?`The ${dn} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:J==="disabled"?`OpenClaw reports the ${dn} plugin with status "disabled"; ${Zn}.`:`OpenClaw reports the ${dn} plugin with status "${J}".`} Run \`openclaw plugins inspect ${dn} --runtime\` for details.`)}var Lr="openclaw";function St(_,I){let O=Bt(_,I),L=cn(O);if(!L)return{error:`${I} is missing from ${O}; run install --openclaw`};if(L.isSymbolicLink()||!L.isFile())return{error:`${O} is a symlink or not a regular file; move or remove it`};try{return{content:hl(O,"utf-8")}}catch(J){return{error:`Failed to read ${O}: ${J instanceof Error?J.message:String(J)}`}}}function yl(_){try{return JSON.parse(Sn(_))}catch{return}}function Km(_){let I=St(_,kt);if("error"in I)return I.error;if(tn(yl(I.content),"id")===dn)return;return`${Bt(_,kt)} is not a valid ${dn} manifest; run install --openclaw`}function Ym(_){let I=St(_,xt);if("error"in I)return I.error;let O=tn(tn(yl(I.content),"openclaw"),"extensions");if(Array.isArray(O)&&O.includes(`./${Cn}`))return;return`${Bt(_,xt)} does not point OpenClaw at ${Cn}; run install --openclaw`}function gl(_){return Array.isArray(_)?_.filter((I)=>typeof I==="string"):[]}function Zm(_){let I=ul(_);if(!cn(I))return`${dn} is not enabled; ${Zn}`;let O=(()=>{try{return JSON.parse(Sn(hl(I,"utf-8")))}catch{return}})();if(O===void 0)return`Failed to read ${I}; fix it, then ${Zn}`;let L=tn(O,"plugins");if(tn(L,"enabled")===!1)return`plugins.enabled is false in ${I}; no OpenClaw plugin loads`;let J=tn(tn(tn(L,"entries"),dn),"enabled");if(gl(tn(L,"deny")).includes(dn)||J===!1)return`${dn} is disabled in ${I}; ${Zn}`;let K=gl(tn(L,"allow"));if(K.length>0&&!K.includes(dn))return`plugins.allow in ${I} does not list ${dn}; add it, then ${Zn}`;if(K.includes(dn)||J===!0)return;return`${dn} is not enabled; ${Zn}`}function vl(_){return/^\/\/ version:\s*(.+)$/m.exec(_)?.[1]?.trim()}function Xm(_,I,O){if(O===void 0)return[];let L=St(O,Cn);if(!(("content"in L)&&vl(L.content)===I))return[];return[Cn,kt,xt].flatMap((K)=>{let ne=St(_,K),oe=St(O,K);if("error"in ne||"error"in oe||ne.content===oe.content)return[];return[`Modified ${K} occupies ${Bt(_,K)}; run install --openclaw to restore it`]})}function bl(_){let I=Gt(_.environment),O=wr(Lr,I);if(O)return O;let L=St(I,Cn),K=["error"in L?L.error:L.content.startsWith(Dr)?void 0:`Unmanaged ${Cn} occupies ${Bt(I,Cn)}; move or remove it`,Km(I),Ym(I)].filter((ve)=>ve!==void 0),ne="content"in L?vl(L.content):void 0,oe=K.length>0?K:Xm(I,ne,Qo());if(oe.length>0)return{platform:Lr,status:"n/a",configPath:I,errors:oe};let de=ne===un()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],ue=Zm(_.environment);if(ue)return{platform:Lr,status:"disabled",method:"plugin directory",configPath:I,errors:[ue,...de]};return{platform:Lr,status:"configured",method:"plugin directory",configPath:I,errors:de.length>0?de:void 0}}import{existsSync as ag,readFileSync as lg}from"node:fs";import{basename as cg}from"node:path";import{existsSync as Nr,readFileSync as ei,rmSync as Qm}from"node:fs";import{join as Tn}from"node:path";import{pathToFileURL as eg}from"node:url";var qt="cc-safety-net",Xn=`${qt}@latest`,ni=["opencode.json","opencode.jsonc"],ng=60,tg=250,wl="CCSafetyNetPlugin",rg={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function kl(_){return Tn(_.env.get("XDG_CONFIG_HOME")||Tn(_.home,".config"),"opencode")}function ti(_){return _.env.get("OPENCODE_CONFIG_DIR")||kl(_)}function ri(_){return ni.map((I)=>Tn(ti(_),I))}function oi(_){return[...new Set([ti(_),kl(_)])].flatMap((I)=>ni.map((O)=>Tn(I,O)))}function xl(_){return Tn(_.env.get("XDG_CACHE_HOME")||Tn(_.home,".cache"),"opencode","packages",Xn)}function Sl(_){Qm(xl(_),{recursive:!0,force:!0})}async function Cl(_){let I=(await yn(["opencode","--version"],{stdoutOnly:!0})).trim(),O=/^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(I),L=Number(O?.[1]),J=Number(O?.[2]),K=Number(O?.[3]);if(!O||L!==1&&L!==2||L===1&&(J<18||J===18&&K<29)||L===2&&J===0&&K<6)throw Error(`OpenCode 1.18.29+ or 2.0.6+ is required; found ${I||"an unknown version"}.`);if(L===2){for(let ne of ri(_)){if(!Nr(ne))continue;let oe=si(ei(ne,"utf-8"),ne);if(["plugin","plugins"].some((ue)=>{let ve=tn(oe,ue);return Array.isArray(ve)&&ve.some((xe)=>jr(xe)&&(typeof xe==="string"?xe:tn(xe,"package"))!==Xn)}))throw Error(`Change the cc-safety-net package spec in ${ne} to ${Xn}, preserving its options, then retry. Adding another spec would create a duplicate plugin ID.`)}return{commands:[],afterInstall:async()=>{if((await yn(["opencode","plugin","add",Xn],{stdoutOnly:!0})).includes("is already configured in"))await yn(["opencode","plugin","update",Xn]);let oe=await El();if(!/^cc-safety-net\s+\S+\s+cc-safety-net@latest\s*$/m.test(oe))throw Error("OpenCode did not load cc-safety-net from cc-safety-net@latest. Run `opencode plugin list` for details.");let de=["--param",`location[directory]=${process.cwd()}`];await yn(["opencode","api","integration.list",...de]);let ue=await yn(["opencode","api","plugin.list",...de],{stdoutOnly:!0}),ve=ii(ue);if(ve)throw Error(ve);if(!Rl(ue).some(Pl))throw Error("OpenCode lists no active cc-safety-net for this directory. Run `opencode api plugin.list` for details.")}}}return Sl(_),{commands:[["opencode","plugin","-g","-f",Xn]],afterInstall:()=>ig(_)}}function Rl(_){return og(_).filter((I)=>tn(I,"id")===qt||jr(tn(tn(I,"source"),"target"))).map((I)=>tn(I,"state"))}function Pl(_){return tn(_,"status")==="active"}function ii(_){let I=Rl(_);if(I.some(Pl))return;let O=I.find((L)=>tn(L,"status")==="failed");if(!O)return;return`OpenCode reports cc-safety-net failed: ${String(tn(O,"error")).split(`
219
- `)[0]}`}function og(_){if(!_)return[];try{let I=tn(JSON.parse(_),"data");return Array.isArray(I)?I:[]}catch{return[]}}async function El(_=1){let I=await yn(["opencode","plugin","list"],{stdoutOnly:!0});if(/^cc-safety-net\s|\scc-safety-net@latest\s*$/m.test(I)||_===ng)return I;return await new Promise((O)=>setTimeout(O,tg)),El(_+1)}async function ig(_){let I=Tn(xl(_),"node_modules",qt),O=Tn(I,"package.json");if(!Nr(O))throw Error(`The OpenCode plugin cache at ${I} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${Xn}\` for details.`);let L=tn(JSON.parse(ei(O,"utf-8")),"main");if(typeof L!=="string")throw Error(`The cached OpenCode plugin at ${I} declares no "main" entry.`);let J=Tn(I,L);if(typeof(await import(eg(J).href))[wl]==="function")return;throw Error(`The cached OpenCode plugin at ${J} does not export a callable ${wl}, so OpenCode would load nothing and fail open.`)}function si(_,I){try{return JSON.parse(Sn(_))}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${I}: ${O.message}`);throw O}}function jr(_){let I=typeof _==="string"?_:tn(_,"package");return typeof I==="string"&&(I===qt||I.startsWith(`${qt}@`))}function ai(_){return["plugin","plugins"].some((I)=>{let O=tn(_,I);return Array.isArray(O)&&O.some(jr)})}function sg(_,I){let L=["plugin","plugins"].flatMap((J)=>{let K=ga(_,J,rg);if(!K)return[];let ne=[],oe=0,de=K.start+1,ue=_.slice(K.start+1,K.end).matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|[^"\s{}[\],/]+|[{}[\],]/g);for(let ve of ue){if(ve[0].startsWith("//")||ve[0].startsWith("/*"))continue;let xe=K.start+1+ve.index;if(oe===0)de=xe;if(ve[0]==="{"||ve[0]==="[")oe++;if(ve[0]==="}"||ve[0]==="]")oe--;if(oe!==0||ve[0]===",")continue;let Se=xe+ve[0].length;if(jr(JSON.parse(Sn(_.slice(de,Se)))))ne.push({start:de,end:Se})}return ne}).sort((J,K)=>J.start-K.start).reverse().reduce((J,K)=>{let ne=/^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*,/.exec(J.slice(K.end));if(ne?.[0].includes("/")){let oe=K.end+ne[0].length-1;return J.slice(0,K.start)+J.slice(K.end,oe)+J.slice(oe+1)}return Sr(J,K)},_);return si(L,I),L}function Al(_){Sl(_);let I=oi(_),O=I.find((K)=>Nr(K)),L=[],J=[];for(let K of I){if(!Nr(K))continue;try{let ne=ei(K,"utf-8");if(!ai(si(ne,K)))continue;mn(K,sg(ne,K)),J.push(K)}catch(ne){L.push(ne instanceof Error?ne.message:String(ne))}}if(L.length>0)throw Error(L.join(`
220
- `));return{path:J[0]??O??Tn(ti(_),ni[0]),alreadyInstalled:J.length>0}}function Ct(_){let I=[];for(let O of _.openCodeVersion?.startsWith("2.")?ri(_.environment):oi(_.environment))if(ag(O))try{let L=lg(O,"utf-8"),J=Sn(L),K=JSON.parse(J);if(ai(K)){let ne=ii(_.openCodePluginListOutput);if(ne)return{platform:"opencode",status:"disabled",method:"opencode api plugin.list",configPath:O,errors:[...I,ne]};return{platform:"opencode",status:"configured",method:"plugin array",configPath:O,errors:I.length>0?I:void 0}}}catch(L){I.push(`Failed to parse ${cg(O)}: ${L instanceof Error?L.message:String(L)}`)}return{platform:"opencode",status:"n/a",errors:I.length>0?I:void 0}}import{join as _l}from"node:path";function li(_){let I=_.env.get("PI_CODING_AGENT_DIR");return _l(I?Ln(I,_.home):_l(_.home,".pi","agent"),"settings.json")}function ci(_){if(typeof _!=="string")return!1;return _==="npm:cc-safety-net"||_.startsWith("npm:cc-safety-net@")}function Il(_){let I=li(_.environment),O=Rn(I);if(O.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(O.kind==="missing")return{platform:"pi",status:"n/a"};let L=tn(O.value,"packages");if(!Array.isArray(L))return{platform:"pi",status:"n/a"};let J=L.find((oe)=>ci(typeof oe==="string"?oe:tn(oe,"source")));if(J===void 0)return{platform:"pi",status:"n/a"};let K=tn(J,"extensions");if(Array.isArray(K)&&K.some((oe)=>typeof oe==="string"&&oe.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:I,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:I}}var dg={amp:ia,"antigravity-cli":sa,"claude-code":ca,codex:ua,"copilot-cli":Pa,cursor:Da,"deepseek-harness":Na,"gemini-cli":ja,"grok-build":Ja,"hermes-agent":il,"kimi-code":Ut,openclaw:bl,opencode:Ct,pi:Il};function Rt(_,I,O){let L={...O,cwd:I,environment:_};return sr.map((J)=>ug(dg[J](L)))}function ug(_){if(_.status==="not-inspected")return{platform:_.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:_.platform,detected:_.status!=="n/a",configured:_.status==="configured",inspectionStatus:_.status!=="n/a"?"verified":_.errors&&_.errors.length>0?"failed":"not-applicable",method:_.method,configPath:_.configPath,configPaths:_.configPaths,errors:_.errors}}import{join as pg}from"node:path";var fg=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}]),mg=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([])})})}),gg={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 Tl(_){let I=pg(_.tmpdir,"cc-safety-net-self-test"),O=fg.map((L)=>{let J=M(_,l("self-test",{command:L.command},{kind:"command",shell:"auto"},{configCwd:I,executionCwd:I},L.command),{guard:{dependencies:{loadPolicySnapshot:()=>mg,getModes:()=>gg,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),K=L.expectBlocked?"blocked":"allowed",ne=J.decision.kind==="deny"?"blocked":"allowed";return{command:L.command,description:L.description,expected:K,actual:ne,passed:K===ne,reason:J.decision.kind==="deny"?J.decision.reason:void 0,ruleId:J.decision.kind==="deny"?J.decision.ruleId:void 0}});return{passed:O.filter((L)=>L.passed).length,failed:O.filter((L)=>!L.passed).length,total:O.length,results:O}}function di(_){let I=gn({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},_);if(On(I.errors))return null;return{json:I.flags.json,skipUpdateCheck:I.flags.skipUpdateCheck}}async function $l(_,I={}){let O=await $t(!I.json,()=>{let L=hg(_,I);return{ready:L,finish:()=>L}},()=>Tt(),{loadingMessage:"Checking system status…"});if(I.json)console.log(JSON.stringify(O,null,2));else yg(O);return O.engineSelfTest.failed>0||O.findings.some((L)=>L.severity==="error")?1:0}async function hg(_,I){let O=I.cwd??process.cwd(),L=await gr((Le)=>Ct({environment:_,cwd:O,openCodeVersion:Le}).status!=="n/a",void 0,O),J=Rt(_,O,{ampPluginListOutput:L.ampPluginListOutput,codexPluginListOutput:L.codexPluginListOutput,copilotCliVersion:L.versions["copilot-cli"],openCodeVersion:L.versions.opencode,openCodePluginListOutput:L.openCodePluginListOutput}),K=ks(_,O),ne=xs(_),oe=E(_,{cwd:O}),de=oe.policy,ue=R(de,_.env),ve=B(de,ue.capabilities),xe=dr(_,7),Se=ea(_,O),Pe=I.skipUpdateCheck?{currentVersion:un(),latestVersion:null,updateAvailable:!1}:await Un(),we={hooks:J,engineSelfTest:Tl(_),userConfig:K.userConfig,projectConfig:K.projectConfig,configState:$e(oe),effectiveRules:K.effectiveRules,environment:ne,effectiveSafety:{selectedPreset:de.safety.level??"standard",level:ue.effectiveLevel,capabilities:ue.capabilities,ruleOverrides:de.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(ve).filter(([,Le])=>Le.source==="rule_override"&&Le.override==="off"&&Le.inheritedEnabled&&Le.changesInherited).map(([Le])=>Le),ruleCounts:{stored:Object.keys(de.destructiveCommandRuleOverrides).length,effective:Object.values(ve).filter((Le)=>Le.changesInherited).length},...oe.policyScopes?{policyScopes:oe.policyScopes}:{}},...Se.length>0?{v2Leftovers:Se}:{},posture:Ns(_,K.userConfig.path),activity:xe,update:Pe,system:L};return{...we,findings:Cs(we)}}function yg(_){console.log(),console.log(Ps(_.hooks)),console.log(),console.log(Es(_.engineSelfTest)),console.log(),console.log(As(_)),console.log(),console.log(_s(_.environment)),console.log(),console.log(Is(_)),console.log(),console.log(Ts(_.findings)),console.log(),console.log($s(_.activity)),console.log(),console.log(Ds(_.system)),console.log(),console.log(Os(_.update)),console.log(Ls(_))}import{existsSync as vg}from"node:fs";var bg=/^[A-Za-z0-9_@%+=:,./-]+$/,Ol="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function ui(_){let I=gn({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},_);if(On(I.errors))return console.error(Ol),console.error("Pass -- before a command that starts with dashes."),null;if(I.values.cwd!==void 0&&!vg(I.values.cwd))return console.error(`Error: --cwd path does not exist: ${I.values.cwd}`),null;let O=I.positionals.length===1?I.positionals[0]:I.positionals.map((L)=>bg.test(L)?L:`'${L.replaceAll("'","'\\''")}'`).join(" ");if(!O)return console.error("Error: No command provided"),console.error(Ol),null;return{json:I.flags.json,cwd:I.values.cwd,command:O}}function Dl(_){if(_)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 Ll(_,I){let L=I-18;return[`${_.dtl}${_.dh.repeat(I)}${_.dtr}`,`${_.dv} Command Analysis${" ".repeat(L)}${_.dv}`,`${_.dbl}${_.dh.repeat(I)}${_.dbr}`]}function pi(_){return JSON.stringify(_)}function Nl(_,I=0){return`[${_.map((L,J)=>Rs(L,J,I)).join(",")}]`}function Vt(_,I,O=70){let L=_.split(" "),J=[],K="";for(let ne of L)if(K&&K.length+ne.length+1>O)J.push(K),K=ne;else K=K?`${K} ${ne}`:ne;if(K)J.push(K);return J.map((ne,oe)=>oe===0?ne:`${I}${ne}`)}function jl(_,I,O){let L=[];switch(_.type){case"parse":return null;case"env-strip":return L.push(""),L.push(`STEP ${I} ${O.h} Strip environment variables`),L.push(` Removed: ${_.envVars.map((J)=>`${J}=<redacted>`).join(", ")}`),L.push(` Tokens: ${pi(_.output)}`),{lines:L,incrementStep:!0};case"leading-tokens-stripped":return L.push(""),L.push(`STEP ${I} ${O.h} Strip wrappers`),L.push(` Removed: ${_.removed.join(", ")}`),L.push(` Tokens: ${pi(_.output)}`),{lines:L,incrementStep:!0};case"shell-wrapper":return L.push(""),L.push(`STEP ${I} ${O.h} Detect shell wrapper`),L.push(` Wrapper: ${_.wrapper} -c`),L.push(` Inner: ${_.innerCommand}`),{lines:L,incrementStep:!0};case"interpreter":{if(L.push(""),L.push(`STEP ${I} ${O.h} Detect interpreter`),L.push(` Interpreter: ${_.interpreter}`),L.push(` Code: ${_.codeArg}`),_.paranoidBlocked)L.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:L,incrementStep:!0}}case"busybox":return L.push(""),L.push(`STEP ${I} ${O.h} Busybox wrapper`),L.push(` Subcommand: ${_.subcommand}`),{lines:L,incrementStep:!0};case"transparent-wrapper":return L.push(""),L.push(`STEP ${I} ${O.h} Transparent wrapper`),L.push(` Wrapper: ${_.wrapper}`),L.push(` Tokens: ${pi(_.output)}`),{lines:L,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(L.push(""),L.push(`STEP ${I} ${O.h} Match rules`),L.push(` Rule: ${_.rule}()`),_.matched)L.push(" Result: MATCHED");else L.push(" Result: No match");return{lines:L,incrementStep:!0}}case"worktree-relaxation":return L.push(""),L.push(`STEP ${I} ${O.h} Worktree relaxation`),L.push(` Mode: ${o.worktree.name}`),L.push(` Git cwd: ${_.gitCwd}`),L.push(" Result: Allowed local discard in linked worktree"),{lines:L,incrementStep:!0};case"temp-root-relaxation":return L.push(""),L.push(`STEP ${I} ${O.h} Temp-root relaxation`),L.push(` Git cwd: ${_.gitCwd}`),L.push(" Result: Allowed git discard in a temp-root repository"),{lines:L,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(_.embeddedCommandFound)return L.push(""),L.push(`STEP ${I} ${O.h} Fallback scan`),L.push(` Found: ${_.embeddedCommandFound}`),{lines:L,incrementStep:!0};return null}case"custom-rules-check":{if(_.rulesChecked){if(L.push(""),L.push(`STEP ${I} ${O.h} Custom rules`),_.matched)L.push(" Result: MATCHED");else L.push(" Result: No match");return{lines:L,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(_.matched)return L.push(""),L.push(`STEP ${I} ${O.h} Dangerous text check`),L.push(` Token: ${_.token}`),L.push(" Result: MATCHED"),{lines:L,incrementStep:!0};return null}case"strict-unparseable":return L.push(""),L.push(`STEP ${I} ${O.h} Strict mode check`),L.push(` Command: ${_.rawCommand}`),L.push(" Result: ✗ UNPARSEABLE"),{lines:L,incrementStep:!0};case"segment-skipped":return null;case"error":return L.push(""),L.push(`ERROR: ${_.message}`),{lines:L,incrementStep:!1};default:return _}}function fi(_,I){let O=Dl(I?.asciiOnly??!1),L=58,J=[],K=1;J.push(...Ll(O,58)),J.push("");let ne=_.trace.steps.find((we)=>we.type==="error");if(ne&&ne.type==="error"){J.push("ERROR"),J.push(` ${ne.message}`),J.push(""),J.push("RESULT"),J.push(` Status: ${_.result==="blocked"?nn.red("BLOCKED"):nn.green("ALLOWED")}`),J.push(""),J.push("CONFIG");let we=_.configSource??"none";return J.push(` Path: ${we}`),J.join(`
221
- `)}let oe=_.trace.steps.find((we)=>we.type==="parse");if(oe&&oe.type==="parse"){J.push("INPUT"),J.push(` ${oe.input}`),J.push(""),J.push(`STEP ${K} ${O.h} Split shell commands`),K++;for(let we=0;we<oe.segments.length;we++){let Le=oe.segments[we];if(Le){let en=Math.random();J.push(` Segment ${we+1}: ${Nl(Le,en)}`)}}}let de=_.trace.segments,ue=de.length>1;for(let we of de){if(ue){J.push("");let on="";if(oe&&oe.type==="parse"){let lo=oe.segments[we.index];if(lo)on=lo.join(" ")}let sn=54,an=on,rn=` Segment ${we.index+1}: `,pn=" ";if(on){if(rn.length+on.length+pn.length>sn){let bu=sn-rn.length-pn.length;an=`${on.substring(0,bu-1)}…`}}let xn=on?`${rn}${an}${pn}`:` Segment ${we.index+1} `,yu=on?`${rn}${nn.cyan(an)}${pn}`:xn,Yi=58-xn.length,Zi=Math.floor(Yi/2),vu=Yi-Zi;J.push(`${O.sh.repeat(Zi)}${yu}${O.sh.repeat(vu)}`)}if(we.steps.find((on)=>on.type==="segment-skipped")){J.push(""),J.push(" (skipped — prior segment blocked)");continue}let en=!1,Ve=!1;for(let on of we.steps){let sn=jl(on,K,O);if(sn){if(Ve=!0,on.type==="recurse"){J.push("");let an=" RECURSING ",rn=58-an.length-4;J.push(` ${O.tl}${O.h}${an}${O.h.repeat(rn)}`),J.push(` ${O.v}`),en=!0;continue}for(let an of sn.lines)if(en)J.push(` ${O.v} ${an}`);else J.push(an);if(sn.incrementStep)K++}}if(en)J.push(` ${O.v}`),J.push(` ${O.bl}${O.h.repeat(56)}`);if(!Ve)J.push(""),J.push(` ${nn.green("✓")} Allowed (no matching rules)`)}if(J.push(""),J.push("RESULT"),_.result==="blocked"){if(J.push(` Status: ${nn.red("BLOCKED")}`),_.customRule){if(J.push(` Rule: ${_.customRule.id}`),_.customRule.rulebook)J.push(` Rulebook: ${_.customRule.rulebook.name} ${_.customRule.rulebook.version}`);if(_.customRule.source)J.push(` Source: ${_.customRule.source}`);if(_.customRule.override)J.push(` Override: reason ${_.customRule.override.reason}`)}if(_.reason){let we=Vt(_.reason," ");J.push(` Reason: ${we[0]}`);for(let Le=1;Le<we.length;Le++)J.push(we[Le]??"")}}else J.push(` Status: ${nn.green("ALLOWED")}`);J.push(""),J.push("CONFIG");let ve=_.configSource??"none",xe=_.configValid?"":" (invalid)";J.push(` Path: ${ve}${xe}`);let Se=_.safetyPresetScope;J.push(` Safety preset: ${_.selectedPreset??"standard"}${Se?` (${pr(Se)})`:""}`),J.push(` Effective capabilities: ${_.effectiveLevel}`);let Pe=Object.entries(_.destructiveCommandRuleOverrides??{});if(J.push(` Rule customizations: ${Pe.length}`),_.ruleActivation)J.push(` Rule activation: ${_.ruleActivation.id} — ${_.ruleActivation.enabled?"on":"off"} via ${_.ruleActivation.source}`);return J.join(`
222
- `)}function mi(_){return JSON.stringify(_,null,2)}import{resolve as Cg}from"node:path";var wg=["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 Fl(_){let I=0,O={allocateSegment(){return I++},getNextSegmentIndex(){return I},recordGlobal(L){_.record({kind:"step",scope:"global",step:L})},recordSegment(L,J=O.currentSegmentIndex){if(J===void 0)return;_.record({kind:"step",scope:"segment",segmentIndex:J,step:L})}};return O}function Hl(_={}){let I=[],O=_.maxEvents??512,L={maxTextLength:_.maxTextLength??2048,maxListLength:_.maxListLength??128,maxObjectProperties:_.maxObjectProperties??_.maxListLength??128,maxDepth:_.maxDepth??16},J,K=new Set;return{record(ne){if(J)return;if(!ne||I.length>=O)return;try{I.push(yi(kg(ne,L,K)))}catch{}},finish(){if(J)return J;return J=yi({events:Object.freeze(I)}),J}}}function kg(_,I,O){if(_.kind!=="step")throw TypeError("invalid trace event");let{scope:L,step:J}=_;Fr(J,O,I);let K=gi(J,I,O);if(L==="global")return{kind:"step",scope:"global",step:K};if(L!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:_.segmentIndex,step:K}}function Fr(_,I,O,L=0,J=new WeakSet){if(typeof _==="string"){let oe=_.slice(0,O.maxTextLength);if(!Be(oe))return;for(let de of tt(oe))for(let ue of de.match(/[^\s"'()$]+/g)??[])I.add(Ml(ue));return}if(!_||typeof _!=="object"||L>=O.maxDepth||J.has(_))return;if(J.add(_),Array.isArray(_)){let oe=Math.min(_.length,O.maxListLength);for(let de=0;de<oe;de++)Fr(_[de],I,O,L+1,J);return}let K=0,ne=new Set;for(let oe in _){if(!Object.hasOwn(_,oe))continue;if(K>=O.maxObjectProperties)break;K++,Fr(oe,I,O);let de=hi(oe,O,I);if(ne.has(de))continue;ne.add(de),Fr(_[oe],I,O,L+1,J)}}function gi(_,I,O,L=0,J=new WeakSet){if(typeof _==="string")return hi(_,I,O);if(!_||typeof _!=="object")return _;if(L>=I.maxDepth)return;if(J.has(_))return;if(J.add(_),Array.isArray(_)){let oe=[],de=Math.min(_.length,I.maxListLength);for(let ue=0;ue<de;ue++)oe.push(gi(_[ue],I,O,L+1,J));return oe}let K={},ne=0;for(let oe in _){if(!Object.hasOwn(_,oe))continue;if(ne>=I.maxObjectProperties)break;ne++;let de=hi(oe,I,O);if(Object.hasOwn(K,de))continue;Object.defineProperty(K,de,{value:gi(_[oe],I,O,L+1,J),enumerable:!0,configurable:!0,writable:!0})}return K}function hi(_,I,O){let L=_.slice(0,I.maxTextLength),J=Be(L)?We(L):L,K=O.size>0?Sg(J,O):J;return(xg(K)?_e(K):K).slice(0,I.maxTextLength)}function xg(_){return _.includes("PRIVATE KEY")||_.includes("://")||_.includes("eyJ")||_.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(_)||_.length>=14&&wg.some((I)=>_.includes(I))||_.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(_)}function Sg(_,I){return _.replace(/[^\s"'()$]+/g,(O)=>I.has(Ml(O))?"<redacted>":O)}function Ml(_){let I=2166136261,O=2166136261;for(let L=0;L<_.length;L++)I=Math.imul(I^_.charCodeAt(L),16777619),O=Math.imul(O^_.charCodeAt(_.length-L-1),16777619);return`${I>>>0}:${O>>>0}:${_.length}`}function yi(_){if(_&&typeof _==="object"&&!Object.isFrozen(_)){for(let I of Object.values(_))yi(I);Object.freeze(_)}return _}function zt(_,I={},O){let L=Cg(I.cwd??process.cwd()),J=I.policySnapshot??E(O,{cwd:L,userConfigDir:I.userConfigDir}),K=R(J.policy,O.env),ne=je({policySnapshot:J,effectiveCapabilities:K.capabilities,strict:K.strict,paranoidRm:K.paranoidRm,paranoidInterpreters:K.paranoidInterpreters,worktreeMode:K.worktreeMode}),oe={effectiveLevel:ne.effectiveLevel,selectedPreset:J.policy.safety.level??"standard",...J.policyScopes?{safetyPresetScope:J.policyScopes.levelScope}:{},effectiveCapabilities:ne.effectiveCapabilities,destructiveCommandRuleOverrides:J.policy.destructiveCommandRuleOverrides},{configSource:de,configValid:ue}=Pg(O,{cwd:L,userConfigDir:I.userConfigDir});if(!_||!_.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:de,configValid:ue,...oe};let ve=h(_,"auto");if(ve.status==="limited")throw new y;let xe=ve.dialect==="powershell"?h(_,"posix"):ve,Se=ut(xe),Pe=Hl(),we=Fl(Pe);we.recordGlobal({type:"parse",input:_,segments:Se.map((xn)=>[...xn])});let Le=l("Bash",{command:_},{kind:"command",shell:"auto"},{configCwd:L,executionCwd:L},_),en=V(Le,{environment:O,trace:we,dependencies:{loadPolicySnapshot:()=>J}}),Ve=en.decision.kind==="deny"?en.decision:null;if(Ve&&(en.stage==="policy-protection"||en.stage==="secret-protection")){let xn=Rg(Ve);return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:xn.rule,matched:!0,reason:Ve.reason}]}]},result:"blocked",reason:k(Ve.reason),segment:k(Ul(Ve,_)),...xn.ruleId?{ruleId:k(xn.ruleId)}:{},configSource:de,configValid:ue,...oe}}let on=we.getNextSegmentIndex();if(Ve&&on>0&&on<Se.length)we.recordSegment({type:"segment-skipped",index:on,reason:"prior-segment-blocked"},on);let sn=Pe.finish(),an=Ve?.ruleId??Eg(Le,J,K,O),rn=W.find((xn)=>xn.id===an&&xn.activationCapability),pn=rn?ne.policy.effectiveDestructiveCommandRules[rn.id]:void 0;return{trace:_g(sn),result:Ve?"blocked":"allowed",reason:Ve?k(Ve.reason):void 0,segment:Ve?k(Ul(Ve,_)):void 0,ruleId:Ve?.ruleId?k(Ve.ruleId):void 0,customRule:Ag(Ig(Ve?.ruleId,J)),configSource:de,configValid:ue,...oe,...rn&&pn?{ruleActivation:{id:rn.id,...pn}}:{}}}function Ul(_,I){return _.evidence?.segment??I}function Rg(_){if(_.reason===Ge)return{ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};if(_.reason===Ue)return{ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};if(_.reason===x)return{ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};return{ruleId:_.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"}}function Pg(_,I){let O=U(I.cwd),L=G(_,I),J=Z(_,{cwd:I.cwd,userConfigDir:I.userConfigDir});try{if(n(J.projectConfigTarget)!==null){if(Mn(J.projectConfigTarget).errors.length===0)return{configSource:O,configValid:!0};return{configSource:O,configValid:!1}}}catch(K){if(K instanceof r)return{configSource:O,configValid:!1};throw K}try{if(n(J.userConfigTarget)!==null){let K=Mn(J.userConfigTarget);return{configSource:L,configValid:K.errors.length===0}}return{configSource:null,configValid:!0}}catch(K){if(K instanceof r)return{configSource:L,configValid:!1};throw K}}function Eg(_,I,O,L){let J=I.policy,K=Te({...J,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...J.destructiveCommandRuleOverrides,...Object.fromEntries(W.flatMap((oe)=>oe.activationCapability?[[oe.id,"on"]]:[]))}},I.state==="degraded"?{diagnostics:I.diagnostics,reason:I.reason}:void 0),ne=V(_,{environment:L,dependencies:{loadPolicySnapshot:()=>K,getModes:()=>({...O,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return ne.decision.kind==="deny"?ne.decision.ruleId:void 0}function Ag(_){if(!_)return;return{id:k(_.id),..._.rulebook?{rulebook:{name:k(_.rulebook.name),version:k(_.rulebook.version)}}:{},..._.source?{source:k(_.source)}:{},..._.override?{override:{type:"reason",reason:k(_.override.reason)}}:{}}}function _g(_){let I=_.events.flatMap((L)=>L.kind==="step"&&L.scope==="global"?[L.step]:[]),O=new Map;for(let L of _.events){if(L.kind!=="step"||L.scope!=="segment")continue;let J=O.get(L.segmentIndex)??{index:L.segmentIndex,steps:[]};J.steps.push(L.step),O.set(L.segmentIndex,J)}return{steps:I,segments:[...O.values()]}}function Ig(_,I){let O=_?.replace(/^custom\./,"");if(!O||!I.policy.rules.some((L)=>L.name===O))return;return I.ruleMetadata[O]??Object.freeze({id:O})}function Gl(_){return new Promise((I)=>{process.stdout.write(`${_}
223
- `,()=>I())})}async function Bl(_,I){let O=ui(I);if(!O)return 1;try{let L=zt(O.command,{cwd:O.cwd},_),J=!!process.env.NO_COLOR||!process.stdout.isTTY;return await Gl(O.json?mi(L):fi(L,{asciiOnly:J})),0}catch(L){let J=Tg(L instanceof p?L.cause:L);if(J===void 0)throw L;if(O.json)return await Gl(JSON.stringify({error:J})),1;return console.error(J),1}}function Tg(_){if(_ instanceof y)return _.message;if(_ instanceof f)return _.message;if(_ instanceof s&&a[_.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var ql="2.5.1",An=" ",Qn="cc-safety-net";function Vl(_){return _.argument?`${_.flags} ${_.argument}`:_.flags}function $g(_){return Math.max(..._.map((I)=>Vl(I).length))}function Og(_){return Math.max(..._.map((I)=>I.usage.length))}function Dg(_){return Math.max(..._.map((I)=>`${Qn} ${I.usage}`.length))}function Lg(_,I){let O=`${Qn} ${_.usage}`;return`${An}${O.padEnd(I+2)}${_.description}`}function jn(_,I){return`${An}${_.padEnd(Math.max(40,_.length+2))}${I}`}function Pt(_,I=console.log){let O=[];if(O.push(`${Qn} ${_.name}`),O.push(""),O.push(`${An}${_.description}`),O.push(""),O.push("USAGE:"),O.push(`${An}${Qn} ${_.usage}`),O.push(""),_.subcommands&&_.subcommands.length>0){O.push("SUBCOMMANDS:");let L=Og(_.subcommands);for(let J of _.subcommands)O.push(`${An}${J.usage.padEnd(L+2)}${J.description}`);O.push("")}if(_.options.length>0){O.push("OPTIONS:");let L=$g(_.options);for(let J of _.options){let K=Vl(J),ne=J.default?`${J.description} (default: ${J.default})`:J.description;O.push(`${An}${K.padEnd(L+2)}${ne}`)}O.push("")}if(_.examples&&_.examples.length>0){O.push("EXAMPLES:");for(let L of _.examples)O.push(`${An}${L}`)}I(O.join(`
224
- `))}function vi(){let _=Dg(lr),I=[];I.push(`${Qn} v${ql}`),I.push(""),I.push("Blocks destructive commands and secret access."),I.push(""),I.push("COMMANDS:");for(let O of lr)I.push(Lg(O,_));I.push(""),I.push("GLOBAL OPTIONS:"),I.push(`${An}-h, --help Show help (use with command for command-specific help)`),I.push(`${An}-V, --version Show version`),I.push(""),I.push("HELP:"),I.push(`${An}${Qn} help <command> Show help for a specific command`),I.push(`${An}${Qn} <command> --help Show help for a specific command`),I.push(""),I.push("ENVIRONMENT VARIABLES:"),I.push(jn(`${o.level.name}=standard|strict|paranoid`,"Set session safety level")),I.push(jn(`${o.worktree.name}=1`,"Allow local git discards in linked worktrees")),I.push(jn(`${o.debug.name}=1`,"Print diagnostic messages to stderr")),I.push(jn(`${o.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),I.push(jn("CC_SAFETY_NET_HOME","Override rule config home directory")),I.push(""),I.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),I.push(jn(`${o.strict.name}=1`,"Force safety.overrides.fail_closed on")),I.push(jn(`${o.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),I.push(jn(`${o.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),I.push(jn(`${o.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),I.push(""),I.push("Documentation: https://ccsafetynet.com/docs"),console.log(I.join(`
225
- `))}function zl(){console.log(ql)}function Jt(_,I=console.log){let O=cr(_);if(!O)return!1;if(O.name.toLowerCase()!==_.toLowerCase())return!1;return Pt(O,I),!0}import{existsSync as zr,readFileSync as Xc}from"node:fs";import{join as Vr}from"node:path";import*as Bn from"node:readline";function Ng(_){return _==="install"?"Install":"Uninstall"}function jg(_){return _==="install"?"Installing":"Uninstalling"}function Fg(_){return _==="install"?"into":"from"}function Kl(_){return _?.available===!0}function Hg(_,I){let O=new Set(I);return _.filter((L)=>O.has(L.target)).map((L)=>L.target)}function Jl(_,I,O){if(_.every((L)=>!L.available))return I;return Array.from({length:_.length},(L,J)=>J+1).map((L)=>(I+L*O+_.length)%_.length).find((L)=>Kl(_[L]))}function Mg(_,I,O){if(O.ctrl&&O.name==="c")return"interrupt";if(O.name==="escape"||I==="q")return"abort";if(_==="install"&&(I==="u"||I==="U"))return"update";if(O.name==="up"||I==="k")return"up";if(O.name==="down"||I==="j")return"down";if(O.name==="space"||I===" ")return"toggle";if(O.name==="return"||O.name==="enter")return"confirm";return null}function Ug(_){return{cursor:_.findIndex((I)=>I.available),selected:[]}}function Gg(_,I,O){if(O==="confirm"||O==="update"||O==="abort"||O==="interrupt")return{state:_,done:O};if(O==="up")return{state:{..._,cursor:Jl(I,_.cursor,-1)}};if(O==="down")return{state:{..._,cursor:Jl(I,_.cursor,1)}};let L=I[_.cursor];if(!Kl(L))return{state:_};let J=_.selected.includes(L.target)?_.selected.filter((K)=>K!==L.target):Hg(I,[..._.selected,L.target]);return{state:{..._,selected:J}}}var Yl="◉",Zl="◯",Xl=">",Ql=" ";function Bg(_,I,O,L={}){let J=L.color!==!1,K=J?nn.dim:(de)=>de,ne=J?nn.green:(de)=>de,oe=J?nn.bold:(de)=>de;return["",`${Ng(_)} CC Safety Net ${Fg(_)}:`,"",...I.map((de,ue)=>{let ve=O.selected.includes(de.target),xe=ue===O.cursor,Se=ve?Yl:Zl,Pe=xe?Xl:Ql,we=de.available?"":` (${de.unavailableReason??"not installed"})`,Le=`${Se} ${de.label}${we}`,en=!de.available?K(Le):ve?ne(Le):xe?oe(Le):Le;return`${Pe} ${en}`}),"",_==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":I.some((de)=>de.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${_}. q/Esc: close`].join(`
226
- `)}var Wl=["global-hook","plugin"];function qg(_,I,O={}){let L=O.color!==!1?nn.bold:(K)=>K;return["","Install the Kimi Code integration as:","",...[`Global hook — ${I?"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((K,ne)=>{let oe=ne===_,de=`${oe?Yl:Zl} ${K}`;return`${oe?Xl:Ql} ${oe?L(de):de}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
227
- `)}function ec(_){let{input:I,output:O}=_;Bn.emitKeypressEvents(I);let L=I.isRaw===!0;I.setRawMode(!0),I.resume();let J=0,K=()=>{if(J===0)return;Bn.moveCursor(O,0,-J),Bn.cursorTo(O,0),Bn.clearScreenDown(O)},ne=()=>{K();let oe=_.render();O.write(`${oe}
228
- `),J=oe.split(`
229
- `).length};return new Promise((oe)=>{let de=(ve)=>{I.off("keypress",ue),I.setRawMode(L),I.pause(),K(),oe(ve)};function ue(ve,xe){_.onKey(ve,xe,{finish:de,draw:ne})}I.on("keypress",ue),ne()})}function nc(_={}){let I=0;return ec({input:_.input??process.stdin,output:_.output??process.stdout,render:()=>qg(I,_.globalHookInstalled===!0),onKey:(O,L,J)=>{if(L.ctrl&&L.name==="c"){J.finish(null),(_.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(L.name==="escape"||O==="q")return J.finish(null);if(L.name==="return"||L.name==="enter")return J.finish(Wl[I]);if(L.name==="up"||L.name==="down"||O==="k"||O==="j")I=(I+1)%Wl.length,J.draw()}})}function bi(_=process.stdin,I=process.stdout){return Boolean(_.isTTY&&I.isTTY&&typeof _.setRawMode==="function")}function tc(_,I,O={}){let L=O.output??process.stdout,J=Ug(I);return ec({input:O.input??process.stdin,output:L,render:()=>Bg(_,I,J),onKey:(K,ne,oe)=>{let de=Mg(_,K,ne);if(!de)return;let ue=Gg(J,I,de);if(J=ue.state,ue.done==="interrupt"){oe.finish(null),(O.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(ue.done==="abort")return oe.finish(null);if(ue.done==="update")return oe.finish("update");if(ue.done==="confirm"){if(J.selected.length===0){L.write("\x07"),oe.draw();return}oe.finish([...J.selected]),L.write(`${jg(_)} selected integrations...
230
- `);return}oe.draw()}})}import{existsSync as rc,lstatSync as zg,mkdirSync as Jg,mkdtempSync as Wg,readdirSync as Kg,readFileSync as At,rmSync as Mr}from"node:fs";import{basename as Yg,dirname as Zg,join as kn}from"node:path";import{fileURLToPath as Xg}from"node:url";var wi="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",nt="cc-safety-net",ot="cc-safety-net/index.ts";import{spawn as Vg}from"node:child_process";var ki=(_,I)=>{let O=Wn([..._],process.env);return new Promise((L)=>{let J=Vg(O.cmd,O.args,{cwd:I,stdio:["ignore","pipe","pipe"]}),K=Ko(J),ne=!1,oe=setTimeout(()=>{ne=!0,J.kill()},120000);J.on("error",(de)=>{clearTimeout(oe),L({status:null,errorCode:de.code,stdout:K.stdout,stderr:[de.message,K.stderr].filter(Boolean).join(`
231
- `)})}),J.on("close",(de)=>{clearTimeout(oe),L({status:ne?null:de,errorCode:ne?"ETIMEDOUT":void 0,stdout:K.stdout,stderr:K.stderr})})})};var Et="cc-safety-net.ts",xi=kn("amp",ot);function Qg(_){return kn(_.home,".config","amp","plugins","cc-safety-net.ts")}function eh(){let _=Zg(Xg(import.meta.url)),I=kn(_,xi),O=kn(_,"..",xi),L=kn(_,"..","..","..","dist",xi);return[I,O,L]}function nh(_=eh()){let I=_.find((O)=>rc(O)&&zg(O).isFile());if(!I)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return I}function oc(_){try{return JSON.parse(_)}catch{return}}function Ur(_){return _.subarray(0,Buffer.byteLength(wi)).toString("utf-8")===wi}async function Wt(_,I,O){let L=await _(I,O);if(L.status===0)return L;throw Error([`Failed to run ${I.join(" ")}${L.status===null?"":` (exit ${L.status})`}.`,[L.stdout,L.stderr].filter(Boolean).join(`
216
+ `}function Jt(P){return[{name:"__init__.py",content:ug(P)},{name:"plugin.yaml",content:dg(P)}]}import{mkdirSync as pg,readdirSync as fg,readFileSync as Al,rmSync as oi}from"node:fs";import{basename as mg,dirname as gg,join as Fn}from"node:path";var hg="__pycache__",yg=/^[a-z0-9][a-z0-9_-]{0,63}$/;function vg(P){try{return Al(P,"utf-8").trim()}catch{return}}function ii(P){let O=P.env.get("HERMES_HOME")?.trim();if(O&&mg(gg(O))==="profiles")return O;let D=O||Fn(P.home,".hermes"),j=Fn(D,"active_profile"),J=vg(j),Y=J?.toLowerCase();if(!Y||Y==="default")return D;if(!yg.test(Y))throw Error(`Invalid Hermes profile name "${J}" in ${j}; run \`hermes profile use <name>\` with a valid profile.`);return Fn(D,"profiles",Y)}function si(P){return Fn(ii(P),"plugins",Pn)}function ai(P){return P.startsWith(ri)}function li(P,O){let D=si(P),j=dn(D);if(j&&(j.isSymbolicLink()||!j.isDirectory()))throw Error(`Refusing to ${O} ${D}: not a regular directory. Move or remove it and rerun ${O==="install"?"install":"uninstall"} --hermes-agent.`);return D}function Il(P,O){let D=dn(P);if(!D)return;if(D.isSymbolicLink()||!D.isFile())throw Error(`Refusing to ${O} ${P}: not a regular file. Move or remove it.`);let j=Al(P,"utf-8");if(!ai(j))throw Error(`Refusing to ${O} unmanaged file at ${P}. Move or remove it.`);return j}function _l(P){let O=li(P,"install"),D=Jt(pn());if(D.map((J)=>Il(Fn(O,J.name),"overwrite")).every((J,Y)=>J===D[Y]?.content))return{path:O,alreadyInstalled:!0};return pg(O,{recursive:!0}),D.forEach((J)=>{cn(Fn(O,J.name),J.content)}),{path:O,alreadyInstalled:!1}}function ci(P){let O=li(P,"remove");if(!dn(O))return[];return Jt(pn()).filter((D)=>Il(Fn(O,D.name),"remove")!==void 0)}function Tl(P){let O=li(P,"remove");if(!dn(O))return{path:O,alreadyInstalled:!1};let D=ci(P);if(D.forEach((j)=>{oi(Fn(O,j.name))}),oi(Fn(O,hg),{recursive:!0,force:!0}),fg(O).length===0)oi(O,{recursive:!0});return{path:O,alreadyInstalled:D.length>0}}var zt="hermes-agent",$l=/^([^\s#][^:]*):/,bg=/^\s+([A-Za-z_][\w-]*):/,Ol=/^\s+-\s*(.*)$/;function wg(P){return P.trim().replace(/^(["'])(.*)\1$/,"$2")}function kg(P){let O=P.split(/\r?\n/),D=O.findIndex((Y)=>$l.exec(Y)?.[1]?.trim()==="plugins");if(D===-1)return[];let j=O.slice(D+1),J=j.findIndex((Y)=>$l.test(Y));return J===-1?j:j.slice(0,J)}function Dl(P,O){let D=kg(P),j=D.findIndex((re)=>bg.exec(re)?.[1]===O);if(j===-1)return[];let J=D.slice(j+1),Y=J.findIndex((re)=>!Ol.test(re));return(Y===-1?J:J.slice(0,Y)).map((re)=>wg(Ol.exec(re)?.[1]??""))}function xg(P){try{return Ll(Nl(ii(P),"config.yaml"),"utf-8")}catch{return}}function di(P){let O=xg(P)??"";return Dl(O,"enabled").includes(Pn)&&!Dl(O,"disabled").includes(Pn)}function jl(P){return/^# version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function Cg(P,O){let D=dn(P);if(!D)return{error:`${O.name} is missing from ${P}; run install --hermes-agent`};if(D.isSymbolicLink()||!D.isFile())return{error:`${P} is a symlink or not a regular file; move or remove it`};try{let j=Ll(P,"utf-8");if(!ai(j))return{error:`Unmanaged ${O.name} occupies ${P}; move or remove it`};if(jl(j)===pn()&&j!==O.content)return{error:`Modified ${O.name} occupies ${P}; run install --hermes-agent to restore it`};return{content:j}}catch(j){return{error:`Failed to read ${P}: ${j instanceof Error?j.message:String(j)}`}}}function Sg(P){try{return{path:si(P)}}catch(O){return{error:O instanceof Error?O.message:String(O)}}}function Fl(P){let O=Sg(P.environment);if("error"in O)return{platform:zt,status:"n/a",errors:[O.error]};let D=O.path,j=Er(zt,D);if(j)return j;let J=Jt(pn()).map((de)=>Cg(Nl(D,de.name),de)),Y=J.flatMap((de)=>("error"in de)?[de.error]:[]);if(Y.length>0)return{platform:zt,status:"n/a",configPath:D,errors:Y};let re=J.some((de)=>("content"in de)&&jl(de.content)!==pn()),ie=re?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!di(P.environment))return{platform:zt,status:"disabled",method:"plugin directory",configPath:D,errors:[`${Pn} is not enabled in Hermes; run \`hermes plugins enable ${Pn}\``,...ie]};return{platform:zt,status:"configured",method:"plugin directory",configPath:D,errors:re?ie:void 0}}import{existsSync as Rg,readFileSync as Pg}from"node:fs";import{join as Hl}from"node:path";var Eg=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function Ag(P){return Hl(P.env.get("KIMI_CODE_HOME")||Hl(P.home,".kimi-code"),"config.toml")}function Kt(P){let O=Ag(P.environment);if(!Rg(O))return{platform:"kimi-code",status:"n/a",configPath:O};try{if(!Eg.test(Pg(O,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:O}}catch(D){return{platform:"kimi-code",status:"n/a",configPath:O,errors:[`Failed to read ${O}: ${D instanceof Error?D.message:String(D)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:O}}import{readFileSync as Wl}from"node:fs";import{join as Yt}from"node:path";var un="cc-safety-net",Sn="index.js",_t="openclaw.plugin.json",Tt="package.json";var Vr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as Tg,lstatSync as $g,readdirSync as Og,readFileSync as Dg}from"node:fs";import{dirname as Ul,join as Bn}from"node:path";import{fileURLToPath as Lg}from"node:url";import{spawn as Ig}from"node:child_process";function _g(P){return P.join(" ")}function ui(P,O,D){return[`Failed to run ${_g(P)}${O===null?"":` (exit ${O})`}.`,D.trim()].filter(Boolean).join(`
217
+ `)}function pi(P){let O={stdout:"",stderr:""};return P.stdout.setEncoding("utf-8"),P.stderr.setEncoding("utf-8"),P.stdout.on("data",(D)=>{O.stdout+=D}),P.stderr.on("data",(D)=>{O.stderr+=D}),O}function yn(P,O){return new Promise((D,j)=>{let J=Wn([...P],process.env),Y=Ig(J.cmd,J.args,{stdio:["ignore","pipe","pipe"]}),re=pi(Y),ie=()=>[re.stdout,re.stderr].filter(Boolean).join(`
218
+ `),de=O?.timeoutMs??120000,fe=setTimeout(()=>{Y.kill(),j(Error(ui(P,null,`Timed out after ${de}ms.
219
+ ${ie()}`.trim())))},de);Y.on("error",(we)=>{clearTimeout(fe),j(Error(ui(P,null,`${we.message}
220
+ ${ie()}`.trim())))}),Y.on("close",(we)=>{if(clearTimeout(fe),we!==0){j(Error(ui(P,we,ie())));return}D(O?.stdoutOnly?re.stdout:ie())})})}async function fi(P){for(let O of P)await yn(O)}async function Ml(P){for(let O of P)try{await yn(O)}catch(D){console.warn(D instanceof Error?D.message:String(D))}}var mi=Bn("openclaw",un),it=`run \`openclaw plugins enable ${un}\``,Ng="config reload superseded by a newer runtime config source",jg=[Sn,_t,Tt];function Gl(P){let O=P.env.get("OPENCLAW_HOME")?.trim();return O?Nn(O,P.home):P.home}function Bl(P){let O=Gl(P),D=P.env.get("OPENCLAW_STATE_DIR")?.trim();if(D)return Nn(D,O);let j=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return j?Ul(Nn(j,O)):Bn(O,".openclaw")}function ql(P){let O=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return O?Nn(O,Gl(P)):Bn(Bl(P),"openclaw.json")}function Wt(P){return Bn(Bl(P),"extensions",un)}function Fg(P){let O=Og(P);if(O.length===0)return!0;if(O.some((J)=>!jg.includes(J)))return!1;let D=Bn(P,Sn),j=dn(D);return j!==void 0&&!j.isSymbolicLink()&&j.isFile()&&Dg(D,"utf-8").startsWith(Vr)}function gi(P){let O=Wt(P),D=dn(O);if(!D)return;if(!D.isSymbolicLink()&&D.isDirectory()&&Fg(O))return;throw Error(`Refusing to modify ${O}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function Vl(){let P=Ul(Lg(import.meta.url));return[Bn(P,mi),Bn(P,"..",mi),Bn(P,"..","..","..","dist",mi)]}function hi(P=Vl()){return P.find((O)=>Tg(O)&&$g(O).isDirectory())}function Hg(P=Vl()){let O=hi(P);if(!O)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return O}function Jl(P=Hg()){return[["openclaw","plugins","install",P,"--force","--accept-capabilities"]]}function Mg(P){let O=(()=>{try{return JSON.parse(P)}catch{return}})(),D=tn(tn(O,"plugin"),"status");return typeof D==="string"?D:void 0}async function Ug(){await yn(["openclaw","plugins","enable",un]).catch((P)=>{if(!(P instanceof Error&&P.message.includes(Ng)))throw P})}async function zl(P){let O=async()=>Mg(await yn(["openclaw","plugins","inspect",un,"--runtime","--json"],{stdoutOnly:!0})),D=await O(),j=D==="disabled"&&P;if(j)await Ug();let J=j?await O():D;if(J==="loaded")return;throw Error(`${J===void 0?`The ${un} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:J==="disabled"?`OpenClaw reports the ${un} plugin with status "disabled"; ${it}.`:`OpenClaw reports the ${un} plugin with status "${J}".`} Run \`openclaw plugins inspect ${un} --runtime\` for details.`)}var Jr="openclaw";function $t(P,O){let D=Yt(P,O),j=dn(D);if(!j)return{error:`${O} is missing from ${D}; run install --openclaw`};if(j.isSymbolicLink()||!j.isFile())return{error:`${D} is a symlink or not a regular file; move or remove it`};try{return{content:Wl(D,"utf-8")}}catch(J){return{error:`Failed to read ${D}: ${J instanceof Error?J.message:String(J)}`}}}function Yl(P){try{return JSON.parse(vn(P))}catch{return}}function Gg(P){let O=$t(P,_t);if("error"in O)return O.error;if(tn(Yl(O.content),"id")===un)return;return`${Yt(P,_t)} is not a valid ${un} manifest; run install --openclaw`}function Bg(P){let O=$t(P,Tt);if("error"in O)return O.error;let D=tn(tn(Yl(O.content),"openclaw"),"extensions");if(Array.isArray(D)&&D.includes(`./${Sn}`))return;return`${Yt(P,Tt)} does not point OpenClaw at ${Sn}; run install --openclaw`}function Kl(P){return Array.isArray(P)?P.filter((O)=>typeof O==="string"):[]}function qg(P){let O=ql(P);if(!dn(O))return`${un} is not enabled; ${it}`;let D=(()=>{try{return JSON.parse(vn(Wl(O,"utf-8")))}catch{return}})();if(D===void 0)return`Failed to read ${O}; fix it, then ${it}`;let j=tn(D,"plugins");if(tn(j,"enabled")===!1)return`plugins.enabled is false in ${O}; no OpenClaw plugin loads`;let J=tn(tn(tn(j,"entries"),un),"enabled");if(Kl(tn(j,"deny")).includes(un)||J===!1)return`${un} is disabled in ${O}; ${it}`;let Y=Kl(tn(j,"allow"));if(Y.length>0&&!Y.includes(un))return`plugins.allow in ${O} does not list ${un}; add it, then ${it}`;if(Y.includes(un)||J===!0)return;return`${un} is not enabled; ${it}`}function Zl(P){return/^\/\/ version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function Vg(P,O,D){if(D===void 0)return[];let j=$t(D,Sn);if(!(("content"in j)&&Zl(j.content)===O))return[];return[Sn,_t,Tt].flatMap((Y)=>{let re=$t(P,Y),ie=$t(D,Y);if("error"in re||"error"in ie||re.content===ie.content)return[];return[`Modified ${Y} occupies ${Yt(P,Y)}; run install --openclaw to restore it`]})}function Xl(P){let O=Wt(P.environment),D=Er(Jr,O);if(D)return D;let j=$t(O,Sn),Y=["error"in j?j.error:j.content.startsWith(Vr)?void 0:`Unmanaged ${Sn} occupies ${Yt(O,Sn)}; move or remove it`,Gg(O),Bg(O)].filter((we)=>we!==void 0),re="content"in j?Zl(j.content):void 0,ie=Y.length>0?Y:Vg(O,re,hi());if(ie.length>0)return{platform:Jr,status:"n/a",configPath:O,errors:ie};let de=re===pn()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],fe=qg(P.environment);if(fe)return{platform:Jr,status:"disabled",method:"plugin directory",configPath:O,errors:[fe,...de]};return{platform:Jr,status:"configured",method:"plugin directory",configPath:O,errors:de.length>0?de:void 0}}import{existsSync as eh,readFileSync as nh}from"node:fs";import{basename as th}from"node:path";import{existsSync as zr,readFileSync as yi,rmSync as Jg}from"node:fs";import{join as _n}from"node:path";import{pathToFileURL as zg}from"node:url";var Zt="cc-safety-net",pt=`${Zt}@latest`,vi=["opencode.json","opencode.jsonc"],Kg=60,Wg=250,Ql="CCSafetyNetPlugin",Yg={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function ec(P){return _n(P.env.get("XDG_CONFIG_HOME")||_n(P.home,".config"),"opencode")}function bi(P){return P.env.get("OPENCODE_CONFIG_DIR")||ec(P)}function wi(P){return vi.map((O)=>_n(bi(P),O))}function ki(P){return[...new Set([bi(P),ec(P)])].flatMap((O)=>vi.map((D)=>_n(O,D)))}function nc(P){return _n(P.env.get("XDG_CACHE_HOME")||_n(P.home,".cache"),"opencode","packages",pt)}function tc(P){Jg(nc(P),{recursive:!0,force:!0})}async function rc(P){let O=(await yn(["opencode","--version"],{stdoutOnly:!0})).trim(),D=/^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(O),j=Number(D?.[1]),J=Number(D?.[2]),Y=Number(D?.[3]);if(!D||j!==1&&j!==2||j===1&&(J<18||J===18&&Y<29)||j===2&&J===0&&Y<6)throw Error(`OpenCode 1.18.29+ or 2.0.6+ is required; found ${O||"an unknown version"}.`);if(j===2){for(let re of wi(P)){if(!zr(re))continue;let ie=Ci(yi(re,"utf-8"),re);if(["plugin","plugins"].some((fe)=>{let we=tn(ie,fe);return Array.isArray(we)&&we.some((Ce)=>Kr(Ce)&&(typeof Ce==="string"?Ce:tn(Ce,"package"))!==pt)}))throw Error(`Change the cc-safety-net package spec in ${re} to ${pt}, preserving its options, then retry. Adding another spec would create a duplicate plugin ID.`)}return{commands:[],afterInstall:async()=>{if((await yn(["opencode","plugin","add",pt],{stdoutOnly:!0})).includes("is already configured in"))await yn(["opencode","plugin","update",pt]);let ie=await sc();if(!/^cc-safety-net\s+\S+\s+cc-safety-net@latest\s*$/m.test(ie))throw Error("OpenCode did not load cc-safety-net from cc-safety-net@latest. Run `opencode plugin list` for details.");let de=["--param",`location[directory]=${process.cwd()}`];await yn(["opencode","api","integration.list",...de]);let fe=await yn(["opencode","api","plugin.list",...de],{stdoutOnly:!0}),we=xi(fe);if(we)throw Error(we);if(!oc(fe).some(ic))throw Error("OpenCode lists no active cc-safety-net for this directory. Run `opencode api plugin.list` for details.")}}}return tc(P),{commands:[["opencode","plugin","-g","-f",pt]],afterInstall:()=>Xg(P)}}function oc(P){return Zg(P).filter((O)=>tn(O,"id")===Zt||Kr(tn(tn(O,"source"),"target"))).map((O)=>tn(O,"state"))}function ic(P){return tn(P,"status")==="active"}function xi(P){let O=oc(P);if(O.some(ic))return;let D=O.find((j)=>tn(j,"status")==="failed");if(!D)return;return`OpenCode reports cc-safety-net failed: ${String(tn(D,"error")).split(`
221
+ `)[0]}`}function Zg(P){if(!P)return[];try{let O=tn(JSON.parse(P),"data");return Array.isArray(O)?O:[]}catch{return[]}}async function sc(P=1){let O=await yn(["opencode","plugin","list"],{stdoutOnly:!0});if(/^cc-safety-net\s|\scc-safety-net@latest\s*$/m.test(O)||P===Kg)return O;return await new Promise((D)=>setTimeout(D,Wg)),sc(P+1)}async function Xg(P){let O=_n(nc(P),"node_modules",Zt),D=_n(O,"package.json");if(!zr(D))throw Error(`The OpenCode plugin cache at ${O} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${pt}\` for details.`);let j=tn(JSON.parse(yi(D,"utf-8")),"main");if(typeof j!=="string")throw Error(`The cached OpenCode plugin at ${O} declares no "main" entry.`);let J=_n(O,j);if(typeof(await import(zg(J).href))[Ql]==="function")return;throw Error(`The cached OpenCode plugin at ${J} does not export a callable ${Ql}, so OpenCode would load nothing and fail open.`)}function Ci(P,O){try{return JSON.parse(vn(P))}catch(D){if(D instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${O}: ${D.message}`);throw D}}function Kr(P){let O=typeof P==="string"?P:tn(P,"package");return typeof O==="string"&&(O===Zt||O.startsWith(`${Zt}@`))}function Si(P){return["plugin","plugins"].some((O)=>{let D=tn(P,O);return Array.isArray(D)&&D.some(Kr)})}function Qg(P,O){let j=["plugin","plugins"].flatMap((J)=>{let Y=$a(P,J,Yg);if(!Y)return[];let re=[],ie=0,de=Y.start+1,fe=P.slice(Y.start+1,Y.end).matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|[^"\s{}[\],/]+|[{}[\],]/g);for(let we of fe){if(we[0].startsWith("//")||we[0].startsWith("/*"))continue;let Ce=Y.start+1+we.index;if(ie===0)de=Ce;if(we[0]==="{"||we[0]==="[")ie++;if(we[0]==="}"||we[0]==="]")ie--;if(ie!==0||we[0]===",")continue;let Se=Ce+we[0].length;if(Kr(JSON.parse(vn(P.slice(de,Se)))))re.push({start:de,end:Se})}return re}).sort((J,Y)=>J.start-Y.start).reverse().reduce((J,Y)=>{let re=/^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*,/.exec(J.slice(Y.end));if(re?.[0].includes("/")){let ie=Y.end+re[0].length-1;return J.slice(0,Y.start)+J.slice(Y.end,ie)+J.slice(ie+1)}return Ta(J,Y)},P);return Ci(j,O),j}function ac(P){tc(P);let O=ki(P),D=O.find((Y)=>zr(Y)),j=[],J=[];for(let Y of O){if(!zr(Y))continue;try{let re=yi(Y,"utf-8");if(!Si(Ci(re,Y)))continue;cn(Y,Qg(re,Y)),J.push(Y)}catch(re){j.push(re instanceof Error?re.message:String(re))}}if(j.length>0)throw Error(j.join(`
222
+ `));return{path:J[0]??D??_n(bi(P),vi[0]),alreadyInstalled:J.length>0}}function Ot(P){let O=[];for(let D of P.openCodeVersion?.startsWith("2.")?wi(P.environment):ki(P.environment))if(eh(D))try{let j=nh(D,"utf-8"),J=vn(j),Y=JSON.parse(J);if(Si(Y)){let re=xi(P.openCodePluginListOutput);if(re)return{platform:"opencode",status:"disabled",method:"opencode api plugin.list",configPath:D,errors:[...O,re]};return{platform:"opencode",status:"configured",method:"plugin array",configPath:D,errors:O.length>0?O:void 0}}}catch(j){O.push(`Failed to parse ${th(D)}: ${j instanceof Error?j.message:String(j)}`)}return{platform:"opencode",status:"n/a",errors:O.length>0?O:void 0}}import{join as lc}from"node:path";function Ri(P){let O=P.env.get("PI_CODING_AGENT_DIR");return lc(O?Nn(O,P.home):lc(P.home,".pi","agent"),"settings.json")}function Pi(P){if(typeof P!=="string")return!1;return P==="npm:cc-safety-net"||P.startsWith("npm:cc-safety-net@")}function cc(P){let O=Ri(P.environment),D=Rn(O);if(D.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(D.kind==="missing")return{platform:"pi",status:"n/a"};let j=tn(D.value,"packages");if(!Array.isArray(j))return{platform:"pi",status:"n/a"};let J=j.find((ie)=>Pi(typeof ie==="string"?ie:tn(ie,"source")));if(J===void 0)return{platform:"pi",status:"n/a"};let Y=tn(J,"extensions");if(Array.isArray(Y)&&Y.some((ie)=>typeof ie==="string"&&ie.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:O,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:O}}var rh={amp:ka,"antigravity-cli":xa,"claude-code":Ra,codex:Ea,"copilot-cli":Ba,cursor:Za,"deepseek-harness":Qa,devin:al,droid:hl,"gemini-cli":yl,"grok-build":Pl,"hermes-agent":Fl,"kimi-code":Kt,openclaw:Xl,opencode:Ot,pi:cc};function Dt(P,O,D){let j={...D,cwd:O,environment:P};return fr.map((J)=>oh(rh[J](j)))}function oh(P){if(P.status==="not-inspected")return{platform:P.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:P.platform,detected:P.status!=="n/a",configured:P.status==="configured",inspectionStatus:P.status!=="n/a"?"verified":P.errors&&P.errors.length>0?"failed":"not-applicable",method:P.method,configPath:P.configPath,configPaths:P.configPaths,errors:P.errors}}import{join as ih}from"node:path";var sh=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}]),ah=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([])})})}),lh={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 dc(P){let O=ih(P.tmpdir,"cc-safety-net-self-test"),D=sh.map((j)=>{let J=G(P,u("self-test",{command:j.command},{kind:"command",shell:"auto"},{configCwd:O,executionCwd:O},j.command),{guard:{dependencies:{loadPolicySnapshot:()=>ah,getModes:()=>lh,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),Y=j.expectBlocked?"blocked":"allowed",re=J.decision.kind==="deny"?"blocked":"allowed";return{command:j.command,description:j.description,expected:Y,actual:re,passed:Y===re,reason:J.decision.kind==="deny"?J.decision.reason:void 0,ruleId:J.decision.kind==="deny"?J.decision.ruleId:void 0}});return{passed:D.filter((j)=>j.passed).length,failed:D.filter((j)=>!j.passed).length,total:D.length,results:D}}function Ei(P){let O=gn({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},P);if(Dn(O.errors))return null;return{json:O.flags.json,skipUpdateCheck:O.flags.skipUpdateCheck}}async function uc(P,O={}){let D=await Ut(!O.json,()=>{let j=dh(P,O);return{ready:j,finish:()=>j}},()=>Mt(),{loadingMessage:"Checking system status…"});if(O.json)console.log(JSON.stringify(D,null,2));else uh(D);return D.engineSelfTest.failed>0||D.findings.some((j)=>j.severity==="error")?1:0}async function dh(P,O){let D=O.cwd??process.cwd(),j=await xr((Fe)=>Ot({environment:P,cwd:D,openCodeVersion:Fe}).status!=="n/a",void 0,D),J=Dt(P,D,{ampPluginListOutput:j.ampPluginListOutput,codexPluginListOutput:j.codexPluginListOutput,copilotCliVersion:j.versions["copilot-cli"],openCodeVersion:j.versions.opencode,openCodePluginListOutput:j.openCodePluginListOutput}),Y=js(P,D),re=Fs(P),ie=E(P,{cwd:D}),de=ie.policy,fe=T(de,P.env),we=V(de,fe.capabilities),Ce=yr(P,7),Se=ha(P,D),Ie=[vr(D),Ct(P)].filter((Fe)=>ch(Fe)),Ee=O.skipUpdateCheck?{currentVersion:pn(),latestVersion:null,updateAvailable:!1}:await Gn(),qe={hooks:J,engineSelfTest:dc(P),userConfig:Y.userConfig,projectConfig:Y.projectConfig,configState:je(ie),effectiveRules:Y.effectiveRules,environment:re,effectiveSafety:{selectedPreset:de.safety.level??"standard",level:fe.effectiveLevel,capabilities:fe.capabilities,ruleOverrides:de.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(we).filter(([,Fe])=>Fe.source==="rule_override"&&Fe.override==="off"&&Fe.inheritedEnabled&&Fe.changesInherited).map(([Fe])=>Fe),ruleCounts:{stored:Object.keys(de.destructiveCommandRuleOverrides).length,effective:Object.values(we).filter((Fe)=>Fe.changesInherited).length},...ie.policyScopes?{policyScopes:ie.policyScopes}:{}},...Se.length>0?{v2Leftovers:Se}:{},...Ie.length>0?{legacyConfigs:Ie}:{},posture:Xs(P,Y.userConfig.path),activity:Ce,update:Ee,system:j};return{...qe,findings:Ms(qe)}}function uh(P){console.log(),console.log(Gs(P.hooks)),console.log(),console.log(Bs(P.engineSelfTest)),console.log(),console.log(qs(P)),console.log(),console.log(Vs(P.environment)),console.log(),console.log(Js(P)),console.log(),console.log(zs(P.findings)),console.log(),console.log(Ks(P.activity)),console.log(),console.log(Ys(P.system)),console.log(),console.log(Ws(P.update)),console.log(Zs(P))}import{existsSync as ph}from"node:fs";var fh=/^[A-Za-z0-9_@%+=:,./-]+$/,pc="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Ai(P){let O=gn({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},P);if(Dn(O.errors))return console.error(pc),console.error("Pass -- before a command that starts with dashes."),null;if(O.values.cwd!==void 0&&!ph(O.values.cwd))return console.error(`Error: --cwd path does not exist: ${O.values.cwd}`),null;let D=O.positionals.length===1?O.positionals[0]:O.positionals.map((j)=>fh.test(j)?j:`'${j.replaceAll("'","'\\''")}'`).join(" ");if(!D)return console.error("Error: No command provided"),console.error(pc),null;return{json:O.flags.json,cwd:O.values.cwd,command:D}}function fc(P){if(P)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function mc(P,O){let j=O-18;return[`${P.dtl}${P.dh.repeat(O)}${P.dtr}`,`${P.dv} Command Analysis${" ".repeat(j)}${P.dv}`,`${P.dbl}${P.dh.repeat(O)}${P.dbr}`]}function Ii(P){return JSON.stringify(P)}function gc(P,O=0){return`[${P.map((j,J)=>Us(j,J,O)).join(",")}]`}function Xt(P,O,D=70){let j=P.split(" "),J=[],Y="";for(let re of j)if(Y&&Y.length+re.length+1>D)J.push(Y),Y=re;else Y=Y?`${Y} ${re}`:re;if(Y)J.push(Y);return J.map((re,ie)=>ie===0?re:`${O}${re}`)}function hc(P,O,D){let j=[];switch(P.type){case"parse":return null;case"env-strip":return j.push(""),j.push(`STEP ${O} ${D.h} Strip environment variables`),j.push(` Removed: ${P.envVars.map((J)=>`${J}=<redacted>`).join(", ")}`),j.push(` Tokens: ${Ii(P.output)}`),{lines:j,incrementStep:!0};case"leading-tokens-stripped":return j.push(""),j.push(`STEP ${O} ${D.h} Strip wrappers`),j.push(` Removed: ${P.removed.join(", ")}`),j.push(` Tokens: ${Ii(P.output)}`),{lines:j,incrementStep:!0};case"shell-wrapper":return j.push(""),j.push(`STEP ${O} ${D.h} Detect shell wrapper`),j.push(` Wrapper: ${P.wrapper} -c`),j.push(` Inner: ${P.innerCommand}`),{lines:j,incrementStep:!0};case"interpreter":{if(j.push(""),j.push(`STEP ${O} ${D.h} Detect interpreter`),j.push(` Interpreter: ${P.interpreter}`),j.push(` Code: ${P.codeArg}`),P.paranoidBlocked)j.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:j,incrementStep:!0}}case"busybox":return j.push(""),j.push(`STEP ${O} ${D.h} Busybox wrapper`),j.push(` Subcommand: ${P.subcommand}`),{lines:j,incrementStep:!0};case"transparent-wrapper":return j.push(""),j.push(`STEP ${O} ${D.h} Transparent wrapper`),j.push(` Wrapper: ${P.wrapper}`),j.push(` Tokens: ${Ii(P.output)}`),{lines:j,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(j.push(""),j.push(`STEP ${O} ${D.h} Match rules`),j.push(` Rule: ${P.rule}()`),P.matched)j.push(" Result: MATCHED");else j.push(" Result: No match");return{lines:j,incrementStep:!0}}case"worktree-relaxation":return j.push(""),j.push(`STEP ${O} ${D.h} Worktree relaxation`),j.push(` Mode: ${n.worktree.name}`),j.push(` Git cwd: ${P.gitCwd}`),j.push(" Result: Allowed local discard in linked worktree"),{lines:j,incrementStep:!0};case"temp-root-relaxation":return j.push(""),j.push(`STEP ${O} ${D.h} Temp-root relaxation`),j.push(` Git cwd: ${P.gitCwd}`),j.push(" Result: Allowed git discard in a temp-root repository"),{lines:j,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(P.embeddedCommandFound)return j.push(""),j.push(`STEP ${O} ${D.h} Fallback scan`),j.push(` Found: ${P.embeddedCommandFound}`),{lines:j,incrementStep:!0};return null}case"custom-rules-check":{if(P.rulesChecked){if(j.push(""),j.push(`STEP ${O} ${D.h} Custom rules`),P.matched)j.push(" Result: MATCHED");else j.push(" Result: No match");return{lines:j,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(P.matched)return j.push(""),j.push(`STEP ${O} ${D.h} Dangerous text check`),j.push(` Token: ${P.token}`),j.push(" Result: MATCHED"),{lines:j,incrementStep:!0};return null}case"strict-unparseable":return j.push(""),j.push(`STEP ${O} ${D.h} Strict mode check`),j.push(` Command: ${P.rawCommand}`),j.push(" Result: ✗ UNPARSEABLE"),{lines:j,incrementStep:!0};case"segment-skipped":return null;case"error":return j.push(""),j.push(`ERROR: ${P.message}`),{lines:j,incrementStep:!1};default:return P}}function _i(P,O){let D=fc(O?.asciiOnly??!1),j=58,J=[],Y=1;J.push(...mc(D,58)),J.push("");let re=P.trace.steps.find((Ee)=>Ee.type==="error");if(re&&re.type==="error"){J.push("ERROR"),J.push(` ${re.message}`),J.push(""),J.push("RESULT"),J.push(` Status: ${P.result==="blocked"?nn.red("BLOCKED"):nn.green("ALLOWED")}`),J.push(""),J.push("CONFIG");let Ee=P.configSource??"none";return J.push(` Path: ${Ee}`),J.join(`
223
+ `)}let ie=P.trace.steps.find((Ee)=>Ee.type==="parse");if(ie&&ie.type==="parse"){J.push("INPUT"),J.push(` ${ie.input}`),J.push(""),J.push(`STEP ${Y} ${D.h} Split shell commands`),Y++;for(let Ee=0;Ee<ie.segments.length;Ee++){let qe=ie.segments[Ee];if(qe){let Fe=Math.random();J.push(` Segment ${Ee+1}: ${gc(qe,Fe)}`)}}}let de=P.trace.segments,fe=de.length>1;for(let Ee of de){if(fe){J.push("");let on="";if(ie&&ie.type==="parse"){let wo=ie.segments[Ee.index];if(wo)on=wo.join(" ")}let sn=54,an=on,rn=` Segment ${Ee.index+1}: `,fn=" ";if(on){if(rn.length+on.length+fn.length>sn){let Qu=sn-rn.length-fn.length;an=`${on.substring(0,Qu-1)}…`}}let On=on?`${rn}${an}${fn}`:` Segment ${Ee.index+1} `,Zu=on?`${rn}${nn.cyan(an)}${fn}`:On,fs=58-On.length,ms=Math.floor(fs/2),Xu=fs-ms;J.push(`${D.sh.repeat(ms)}${Zu}${D.sh.repeat(Xu)}`)}if(Ee.steps.find((on)=>on.type==="segment-skipped")){J.push(""),J.push(" (skipped — prior segment blocked)");continue}let Fe=!1,en=!1;for(let on of Ee.steps){let sn=hc(on,Y,D);if(sn){if(en=!0,on.type==="recurse"){J.push("");let an=" RECURSING ",rn=58-an.length-4;J.push(` ${D.tl}${D.h}${an}${D.h.repeat(rn)}`),J.push(` ${D.v}`),Fe=!0;continue}for(let an of sn.lines)if(Fe)J.push(` ${D.v} ${an}`);else J.push(an);if(sn.incrementStep)Y++}}if(Fe)J.push(` ${D.v}`),J.push(` ${D.bl}${D.h.repeat(56)}`);if(!en)J.push(""),J.push(` ${nn.green("✓")} Allowed (no matching rules)`)}if(J.push(""),J.push("RESULT"),P.result==="blocked"){if(J.push(` Status: ${nn.red("BLOCKED")}`),P.customRule){if(J.push(` Rule: ${P.customRule.id}`),P.customRule.rulebook)J.push(` Rulebook: ${P.customRule.rulebook.name} ${P.customRule.rulebook.version}`);if(P.customRule.source)J.push(` Source: ${P.customRule.source}`);if(P.customRule.override)J.push(` Override: reason ${P.customRule.override.reason}`)}if(P.reason){let Ee=Xt(P.reason," ");J.push(` Reason: ${Ee[0]}`);for(let qe=1;qe<Ee.length;qe++)J.push(Ee[qe]??"")}}else J.push(` Status: ${nn.green("ALLOWED")}`);J.push(""),J.push("CONFIG");let we=P.configSource??"none",Ce=P.configValid?"":" (invalid)";J.push(` Path: ${we}${Ce}`);let Se=P.safetyPresetScope;J.push(` Safety preset: ${P.selectedPreset??"standard"}${Se?` (${br(Se)})`:""}`),J.push(` Effective capabilities: ${P.effectiveLevel}`);let Ie=Object.entries(P.destructiveCommandRuleOverrides??{});if(J.push(` Rule customizations: ${Ie.length}`),P.ruleActivation)J.push(` Rule activation: ${P.ruleActivation.id} — ${P.ruleActivation.enabled?"on":"off"} via ${P.ruleActivation.source}`);return J.join(`
224
+ `)}function Ti(P){return JSON.stringify(P,null,2)}import{resolve as vh}from"node:path";var mh=["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 yc(P){let O=0,D={allocateSegment(){return O++},getNextSegmentIndex(){return O},recordGlobal(j){P.record({kind:"step",scope:"global",step:j})},recordSegment(j,J=D.currentSegmentIndex){if(J===void 0)return;P.record({kind:"step",scope:"segment",segmentIndex:J,step:j})}};return D}function vc(P={}){let O=[],D=P.maxEvents??512,j={maxTextLength:P.maxTextLength??2048,maxListLength:P.maxListLength??128,maxObjectProperties:P.maxObjectProperties??P.maxListLength??128,maxDepth:P.maxDepth??16},J,Y=new Set;return{record(re){if(J)return;if(!re||O.length>=D)return;try{O.push(Di(gh(re,j,Y)))}catch{}},finish(){if(J)return J;return J=Di({events:Object.freeze(O)}),J}}}function gh(P,O,D){if(P.kind!=="step")throw TypeError("invalid trace event");let{scope:j,step:J}=P;Wr(J,D,O);let Y=$i(J,O,D);if(j==="global")return{kind:"step",scope:"global",step:Y};if(j!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:P.segmentIndex,step:Y}}function Wr(P,O,D,j=0,J=new WeakSet){if(typeof P==="string"){let ie=P.slice(0,D.maxTextLength);if(!ze(ie))return;for(let de of nt(ie))for(let fe of de.match(/[^\s"'()$]+/g)??[])O.add(bc(fe));return}if(!P||typeof P!=="object"||j>=D.maxDepth||J.has(P))return;if(J.add(P),Array.isArray(P)){let ie=Math.min(P.length,D.maxListLength);for(let de=0;de<ie;de++)Wr(P[de],O,D,j+1,J);return}let Y=0,re=new Set;for(let ie in P){if(!Object.hasOwn(P,ie))continue;if(Y>=D.maxObjectProperties)break;Y++,Wr(ie,O,D);let de=Oi(ie,D,O);if(re.has(de))continue;re.add(de),Wr(P[ie],O,D,j+1,J)}}function $i(P,O,D,j=0,J=new WeakSet){if(typeof P==="string")return Oi(P,O,D);if(!P||typeof P!=="object")return P;if(j>=O.maxDepth)return;if(J.has(P))return;if(J.add(P),Array.isArray(P)){let ie=[],de=Math.min(P.length,O.maxListLength);for(let fe=0;fe<de;fe++)ie.push($i(P[fe],O,D,j+1,J));return ie}let Y={},re=0;for(let ie in P){if(!Object.hasOwn(P,ie))continue;if(re>=O.maxObjectProperties)break;re++;let de=Oi(ie,O,D);if(Object.hasOwn(Y,de))continue;Object.defineProperty(Y,de,{value:$i(P[ie],O,D,j+1,J),enumerable:!0,configurable:!0,writable:!0})}return Y}function Oi(P,O,D){let j=P.slice(0,O.maxTextLength),J=ze(j)?Be(j):j,Y=D.size>0?yh(J,D):J;return(hh(Y)?Pe(Y):Y).slice(0,O.maxTextLength)}function hh(P){return P.includes("PRIVATE KEY")||P.includes("://")||P.includes("eyJ")||P.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(P)||P.length>=14&&mh.some((O)=>P.includes(O))||P.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(P)}function yh(P,O){return P.replace(/[^\s"'()$]+/g,(D)=>O.has(bc(D))?"<redacted>":D)}function bc(P){let O=2166136261,D=2166136261;for(let j=0;j<P.length;j++)O=Math.imul(O^P.charCodeAt(j),16777619),D=Math.imul(D^P.charCodeAt(P.length-j-1),16777619);return`${O>>>0}:${D>>>0}:${P.length}`}function Di(P){if(P&&typeof P==="object"&&!Object.isFrozen(P)){for(let O of Object.values(P))Di(O);Object.freeze(P)}return P}function Qt(P,O={},D){let j=vh(O.cwd??process.cwd()),J=O.policySnapshot??E(D,{cwd:j,userConfigDir:O.userConfigDir}),Y=T(J.policy,D.env),re=Ue({policySnapshot:J,effectiveCapabilities:Y.capabilities,strict:Y.strict,paranoidRm:Y.paranoidRm,paranoidInterpreters:Y.paranoidInterpreters,worktreeMode:Y.worktreeMode}),ie={effectiveLevel:re.effectiveLevel,selectedPreset:J.policy.safety.level??"standard",...J.policyScopes?{safetyPresetScope:J.policyScopes.levelScope}:{},effectiveCapabilities:re.effectiveCapabilities,destructiveCommandRuleOverrides:J.policy.destructiveCommandRuleOverrides},{configSource:de,configValid:fe}=wh(D,{cwd:j,userConfigDir:O.userConfigDir});if(!P||!P.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:de,configValid:fe,...ie};let we=y(P,"auto");if(we.status==="limited")throw new b;let Ce=we.dialect==="powershell"?y(P,"posix"):we,Se=dt(Ce),Ie=vc(),Ee=yc(Ie);Ee.recordGlobal({type:"parse",input:P,segments:Se.map((On)=>[...On])});let qe=u("Bash",{command:P},{kind:"command",shell:"auto"},{configCwd:j,executionCwd:j},P),Fe=q(qe,{environment:D,trace:Ee,dependencies:{loadPolicySnapshot:()=>J}}),en=Fe.decision.kind==="deny"?Fe.decision:null;if(en&&(Fe.stage==="policy-protection"||Fe.stage==="secret-protection"))return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:bh(en),matched:!0,reason:en.reason}]}]},result:"blocked",reason:R(en.reason),segment:R(wc(en,P)),ruleId:R(en.ruleId),configSource:de,configValid:fe,...ie};let on=Ee.getNextSegmentIndex();if(en&&on>0&&on<Se.length)Ee.recordSegment({type:"segment-skipped",index:on,reason:"prior-segment-blocked"},on);let sn=Ie.finish(),an=en?.ruleId??kh(qe,J,Y,D),rn=z.find((On)=>On.id===an&&On.activationCapability),fn=rn?re.policy.effectiveDestructiveCommandRules[rn.id]:void 0;return{trace:Ch(sn),result:en?"blocked":"allowed",reason:en?R(en.reason):void 0,segment:en?R(wc(en,P)):void 0,ruleId:en?R(en.ruleId):void 0,customRule:xh(Sh(en?.ruleId,J)),configSource:de,configValid:fe,...ie,...rn&&fn?{ruleActivation:{id:rn.id,...fn}}:{}}}function wc(P,O){return P.evidence?.segment??O}function bh(P){if(P.reason===He)return"policy-protection:findPolicyConfigMutationTargetInSemanticFacts";if(P.reason===Ge)return"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts";if(P.reason===k)return"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts";return"secret-protection:findSensitiveTargetInSemanticFacts"}function wh(P,O){let D=_(O.cwd),j=W(P,O),J=X(P,{cwd:O.cwd,userConfigDir:O.userConfigDir});try{if(r(J.projectConfigTarget)!==null){if(Un(J.projectConfigTarget).errors.length===0)return{configSource:D,configValid:!0};return{configSource:D,configValid:!1}}}catch(Y){if(Y instanceof o)return{configSource:D,configValid:!1};throw Y}try{if(r(J.userConfigTarget)!==null){let Y=Un(J.userConfigTarget);return{configSource:j,configValid:Y.errors.length===0}}return{configSource:null,configValid:!0}}catch(Y){if(Y instanceof o)return{configSource:j,configValid:!1};throw Y}}function kh(P,O,D,j){let J=O.policy,Y=_e({...J,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...J.destructiveCommandRuleOverrides,...Object.fromEntries(z.flatMap((ie)=>ie.activationCapability?[[ie.id,"on"]]:[]))}},O.state==="degraded"?{diagnostics:O.diagnostics,reason:O.reason}:void 0),re=q(P,{environment:j,dependencies:{loadPolicySnapshot:()=>Y,getModes:()=>({...D,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return re.decision.kind==="deny"?re.decision.ruleId:void 0}function xh(P){if(!P)return;return{id:R(P.id),...P.rulebook?{rulebook:{name:R(P.rulebook.name),version:R(P.rulebook.version)}}:{},...P.source?{source:R(P.source)}:{},...P.override?{override:{type:"reason",reason:R(P.override.reason)}}:{}}}function Ch(P){let O=P.events.flatMap((j)=>j.kind==="step"&&j.scope==="global"?[j.step]:[]),D=new Map;for(let j of P.events){if(j.kind!=="step"||j.scope!=="segment")continue;let J=D.get(j.segmentIndex)??{index:j.segmentIndex,steps:[]};J.steps.push(j.step),D.set(j.segmentIndex,J)}return{steps:O,segments:[...D.values()]}}function Sh(P,O){let D=P?.replace(/^custom\./,"");if(!D||!O.policy.rules.some((j)=>j.name===D))return;return O.ruleMetadata[D]??Object.freeze({id:D})}function kc(P){return new Promise((O)=>{process.stdout.write(`${P}
225
+ `,()=>O())})}async function xc(P,O){let D=Ai(O);if(!D)return 1;try{let j=Qt(D.command,{cwd:D.cwd},P),J=!!process.env.NO_COLOR||!process.stdout.isTTY;return await kc(D.json?Ti(j):_i(j,{asciiOnly:J})),0}catch(j){let J=Rh(j instanceof p?j.cause:j);if(J===void 0)throw j;if(D.json)return await kc(JSON.stringify({error:J})),1;return console.error(J),1}}function Rh(P){if(P instanceof b)return P.message;if(P instanceof f)return P.message;if(P instanceof s&&a[P.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var Cc="2.6.0",An=" ",ft="cc-safety-net";function Sc(P){return P.argument?`${P.flags} ${P.argument}`:P.flags}function Ph(P){return Math.max(...P.map((O)=>Sc(O).length))}function Eh(P){return Math.max(...P.map((O)=>O.usage.length))}function Ah(P){return Math.max(...P.map((O)=>`${ft} ${O.usage}`.length))}function Ih(P,O){let D=`${ft} ${P.usage}`;return`${An}${D.padEnd(O+2)}${P.description}`}function Tn(P,O){return`${An}${P.padEnd(Math.max(40,P.length+2))}${O}`}function Lt(P,O=console.log){let D=[];if(D.push(`${ft} ${P.name}`),D.push(""),D.push(`${An}${P.description}`),D.push(""),D.push("USAGE:"),D.push(`${An}${ft} ${P.usage}`),D.push(""),P.subcommands&&P.subcommands.length>0){D.push("SUBCOMMANDS:");let j=Eh(P.subcommands);for(let J of P.subcommands)D.push(`${An}${J.usage.padEnd(j+2)}${J.description}`);D.push("")}if(P.options.length>0){D.push("OPTIONS:");let j=Ph(P.options);for(let J of P.options){let Y=Sc(J),re=J.default?`${J.description} (default: ${J.default})`:J.description;D.push(`${An}${Y.padEnd(j+2)}${re}`)}D.push("")}if(P.examples&&P.examples.length>0){D.push("EXAMPLES:");for(let j of P.examples)D.push(`${An}${j}`)}O(D.join(`
226
+ `))}function Li(){let P=Ah(gr),O=[];O.push(`${ft} v${Cc}`),O.push(""),O.push("Blocks destructive commands and secret access."),O.push(""),O.push("COMMANDS:");for(let D of gr)O.push(Ih(D,P));O.push(""),O.push("GLOBAL OPTIONS:"),O.push(`${An}-h, --help Show help (use with command for command-specific help)`),O.push(`${An}-V, --version Show version`),O.push(""),O.push("HELP:"),O.push(`${An}${ft} help <command> Show help for a specific command`),O.push(`${An}${ft} <command> --help Show help for a specific command`),O.push(""),O.push("ENVIRONMENT VARIABLES:"),O.push(Tn(`${n.level.name}=standard|strict|paranoid`,"Set session safety level")),O.push(Tn(`${n.worktree.name}=1`,"Allow local git discards in linked worktrees")),O.push(Tn(`${n.debug.name}=1`,"Print diagnostic messages to stderr")),O.push(Tn(`${n.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),O.push(Tn(`${n.projectTightenOnly.name}=1`,"Ignore project policy settings that weaken the user policy")),O.push(Tn("CC_SAFETY_NET_HOME","Override rule config home directory")),O.push(""),O.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),O.push(Tn(`${n.strict.name}=1`,"Force safety.overrides.fail_closed on")),O.push(Tn(`${n.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),O.push(Tn(`${n.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),O.push(Tn(`${n.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),O.push(""),O.push("Documentation: https://ccsafetynet.com/docs"),console.log(O.join(`
227
+ `))}function Rc(){console.log(Cc)}function er(P,O=console.log){let D=hr(P);if(!D)return!1;if(D.name.toLowerCase()!==P.toLowerCase())return!1;return Lt(D,O),!0}import{existsSync as ro,readFileSync as Td}from"node:fs";import{join as to}from"node:path";import*as qn from"node:readline";function _h(P){return P==="install"?"Install":"Uninstall"}function Th(P){return P==="install"?"Installing":"Uninstalling"}function $h(P){return P==="install"?"into":"from"}function Ac(P){return P?.available===!0}function Oh(P,O){let D=new Set(O);return P.filter((j)=>D.has(j.target)).map((j)=>j.target)}function Pc(P,O,D){if(P.every((j)=>!j.available))return O;return Array.from({length:P.length},(j,J)=>J+1).map((j)=>(O+j*D+P.length)%P.length).find((j)=>Ac(P[j]))}function Dh(P,O,D){if(D.ctrl&&D.name==="c")return"interrupt";if(D.name==="escape"||O==="q")return"abort";if(P==="install"&&(O==="u"||O==="U"))return"update";if(D.name==="up"||O==="k")return"up";if(D.name==="down"||O==="j")return"down";if(D.name==="space"||O===" ")return"toggle";if(D.name==="return"||D.name==="enter")return"confirm";return null}function Lh(P){return{cursor:P.findIndex((O)=>O.available),selected:[]}}function Nh(P,O,D){if(D==="confirm"||D==="update"||D==="abort"||D==="interrupt")return{state:P,done:D};if(D==="up")return{state:{...P,cursor:Pc(O,P.cursor,-1)}};if(D==="down")return{state:{...P,cursor:Pc(O,P.cursor,1)}};let j=O[P.cursor];if(!Ac(j))return{state:P};let J=P.selected.includes(j.target)?P.selected.filter((Y)=>Y!==j.target):Oh(O,[...P.selected,j.target]);return{state:{...P,selected:J}}}var Ic="◉",_c="◯",Tc=">",$c=" ";function jh(P,O,D){return["",`${_h(P)} CC Safety Net ${$h(P)}:`,"",...O.map((j,J)=>{let Y=D.selected.includes(j.target),re=J===D.cursor,ie=Y?Ic:_c,de=re?Tc:$c,fe=j.available?"":` (${j.unavailableReason??"not installed"})`,we=`${ie} ${j.label}${fe}`,Ce=!j.available?nn.dim(we):Y?nn.green(we):re?nn.bold(we):we;return`${de} ${Ce}`}),"",P==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":O.some((j)=>j.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${P}. q/Esc: close`].join(`
228
+ `)}var Ec=["global-hook","plugin"];function Fh(P,O,D={}){let j=D.color!==!1?nn.bold:(Y)=>Y;return["","Install the Kimi Code integration as:","",...[`Global hook — ${O?"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((Y,re)=>{let ie=re===P,de=`${ie?Ic:_c} ${Y}`;return`${ie?Tc:$c} ${ie?j(de):de}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
229
+ `)}function Oc(P){let{input:O,output:D}=P;qn.emitKeypressEvents(O);let j=O.isRaw===!0;O.setRawMode(!0),O.resume();let J=0,Y=()=>{if(J===0)return;qn.moveCursor(D,0,-J),qn.cursorTo(D,0),qn.clearScreenDown(D)},re=()=>{Y();let ie=P.render();D.write(`${ie}
230
+ `),J=ie.split(`
231
+ `).length};return new Promise((ie)=>{let de=(we)=>{O.off("keypress",fe),O.setRawMode(j),O.pause(),Y(),ie(we)};function fe(we,Ce){P.onKey(we,Ce,{finish:de,draw:re})}O.on("keypress",fe),re()})}function Dc(P={}){let O=0;return Oc({input:P.input??process.stdin,output:P.output??process.stdout,render:()=>Fh(O,P.globalHookInstalled===!0),onKey:(D,j,J)=>{if(j.ctrl&&j.name==="c"){J.finish(null),(P.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(j.name==="escape"||D==="q")return J.finish(null);if(j.name==="return"||j.name==="enter")return J.finish(Ec[O]);if(j.name==="up"||j.name==="down"||D==="k"||D==="j")O=(O+1)%Ec.length,J.draw()}})}function Ni(P=process.stdin,O=process.stdout){return Boolean(P.isTTY&&O.isTTY&&typeof P.setRawMode==="function")}function Lc(P,O,D={}){let j=D.output??process.stdout,J=Lh(O);return Oc({input:D.input??process.stdin,output:j,render:()=>jh(P,O,J),onKey:(Y,re,ie)=>{let de=Dh(P,Y,re);if(!de)return;let fe=Nh(J,O,de);if(J=fe.state,fe.done==="interrupt"){ie.finish(null),(D.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(fe.done==="abort")return ie.finish(null);if(fe.done==="update")return ie.finish("update");if(fe.done==="confirm"){if(J.selected.length===0){j.write("\x07"),ie.draw();return}ie.finish([...J.selected]),j.write(`${Th(P)} selected integrations...
232
+ `);return}ie.draw()}})}import{existsSync as Nc,lstatSync as Mh,mkdirSync as Uh,mkdtempSync as Gh,readdirSync as Bh,readFileSync as jt,rmSync as Zr}from"node:fs";import{basename as qh,dirname as Vh,join as Cn}from"node:path";import{fileURLToPath as Jh}from"node:url";var ji="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",mt="cc-safety-net",gt="cc-safety-net/index.ts";import{spawn as Hh}from"node:child_process";var Fi=(P,O)=>{let D=Wn([...P],process.env);return new Promise((j)=>{let J=Hh(D.cmd,D.args,{cwd:O,stdio:["ignore","pipe","pipe"]}),Y=pi(J),re=!1,ie=setTimeout(()=>{re=!0,J.kill()},120000);J.on("error",(de)=>{clearTimeout(ie),j({status:null,errorCode:de.code,stdout:Y.stdout,stderr:[de.message,Y.stderr].filter(Boolean).join(`
233
+ `)})}),J.on("close",(de)=>{clearTimeout(ie),j({status:re?null:de,errorCode:re?"ETIMEDOUT":void 0,stdout:Y.stdout,stderr:Y.stderr})})})};var Nt="cc-safety-net.ts",Hi=Cn("amp",gt);function zh(P){return Cn(P.home,".config","amp","plugins","cc-safety-net.ts")}function Kh(){let P=Vh(Jh(import.meta.url)),O=Cn(P,Hi),D=Cn(P,"..",Hi),j=Cn(P,"..","..","..","dist",Hi);return[O,D,j]}function Wh(P=Kh()){let O=P.find((D)=>Nc(D)&&Mh(D).isFile());if(!O)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return O}function jc(P){try{return JSON.parse(P)}catch{return}}function Xr(P){return P.subarray(0,Buffer.byteLength(ji)).toString("utf-8")===ji}async function nr(P,O,D){let j=await P(O,D);if(j.status===0)return j;throw Error([`Failed to run ${O.join(" ")}${j.status===null?"":` (exit ${j.status})`}.`,[j.stdout,j.stderr].filter(Boolean).join(`
232
234
  `).trim()].filter(Boolean).join(`
233
- `))}async function ic(_){let I=await _(["amp","plugins","repositories","--json"]);if(I.status===null)throw Error(`${I.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 (${I.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
234
- ${I.stderr}`.trim());if(I.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${I.status}). Sign in with "amp login" and rerun install --amp.
235
- ${[I.stdout,I.stderr].filter(Boolean).join(`
236
- `)}`.trim());let O=oc(I.stdout),L=(Array.isArray(O)?O:[]).filter((J)=>tn(J,"scope")==="user"&&tn(J,"exists")===!0&&tn(J,"viewerCanWrite")===!0).map((J)=>tn(J,"cloneRef")).find((J)=>typeof J==="string"&&J.length>0);if(!L)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 L}async function sc(_,I,O){let L=Wg(kn(I.tmpdir,"cc-safety-net-amp-"));try{return await Wt(_,["amp","clone","user-plugins",L]),await O(L)}finally{Mr(L,{recursive:!0,force:!0})}}function Si(_){return`rerun ${_==="overwrite"?"install":"uninstall"} --amp`}function ac(_,I,O){let L=kn(_,I),J=cn(L);if(!J)return;if(J.isSymbolicLink()||!J.isFile())throw Error(`Refusing to ${O} ${I} in your Amp personal plugins repository: not a regular file. Remove it there and ${Si(O)}.`);let K=At(L);if(Ur(K))return K;throw Error(`Refusing to ${O} unmanaged file ${I} in your Amp personal plugins repository. Remove it there and ${Si(O)}.`)}function lc(_,I){let O=kn(_,nt),L=cn(O);if(!L)return;if(L.isSymbolicLink()||!L.isDirectory())throw Error(`Refusing to ${I} ${nt} in your Amp personal plugins repository: not a regular directory. Remove it there and ${Si(I)}.`);return ac(_,ot,I)}function th(_){let I=kn(_,Et),O=cn(I);if(!O||O.isSymbolicLink()||!O.isFile())return;let L=At(I);return Ur(L)?L:void 0}async function cc(_,I,O,L){if(await Wt(_,O,I),(await Wt(_,["git","status","--porcelain"],I)).stdout.trim()==="")return!1;return await Wt(_,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",L],I),await Wt(_,["git","push","origin","HEAD"],I),!0}function Hr(_,I){rh(_,I),oh(_,I)}function dc(_,I){if(I==="keep")return;throw Error(`Local Amp plugin ${_} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function rh(_,I){let O=Qg(_),L=cn(O);if(!L)return;if(!L.isSymbolicLink()&&L.isFile()&&Ur(At(O))){Mr(O);return}dc(O,I)}function oh(_,I){let O=kn(_.home,".config","amp","plugins",nt),L=cn(O);if(!L)return;if(!L.isSymbolicLink()&&L.isDirectory()&&ih(O)){Mr(O,{recursive:!0});return}dc(O,I)}function ih(_){let I=Yg(ot);if(Kg(_).join("\x00")!==I)return!1;let O=kn(_,I),L=cn(O);return!!L&&!L.isSymbolicLink()&&L.isFile()&&Ur(At(O))}function sh(_){let I=d(_);if(!rc(I))return"";let O=oc(At(I,"utf-8"));if(!O||typeof O!=="object"||Array.isArray(O))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(C(O,_.home))};
237
- `}async function uc(_,I=nh(),O=ki){let L=Buffer.concat([At(I),Buffer.from(sh(_),"utf-8")]),J=await ic(O);return sc(O,_,async(K)=>{let ne=`${J}/${nt}`,oe=lc(K,"overwrite"),de=ac(K,Et,"overwrite");if(oe?.equals(L)&&!de)return Hr(_,"fail"),{path:ne,alreadyInstalled:!0};if(Jg(kn(K,nt),{recursive:!0}),mn(kn(K,ot),L),de)Mr(kn(K,Et));let ue=await cc(O,K,["git","add","--",ot,...de?[Et]:[]],`chore: update cc-safety-net plugin to v${un()}`);return Hr(_,"fail"),{path:ne,alreadyInstalled:!ue}})}async function pc(_,I=ki){let O=await ic(I);return sc(I,_,async(L)=>{let J=lc(L,"remove"),K=th(L),ne=`${O}/${K&&!J?Et:nt}`;if(!J&&!K)return Hr(_,"keep"),{path:ne,alreadyInstalled:!1};return await cc(I,L,["git","rm","--",...J?[ot]:[],...K?[Et]:[]],`chore: remove cc-safety-net plugin v${un()}`),Hr(_,"keep"),{path:ne,alreadyInstalled:!0}})}import{existsSync as fc,mkdirSync as ah,readFileSync as lh}from"node:fs";import{dirname as ch}from"node:path";var Ci=In["antigravity-cli"],dt="cc-safety-net";function pt(_){return Boolean(_)&&typeof _==="object"&&!Array.isArray(_)}function Br(){return{PreToolUse:[{hooks:[{type:"command",command:Ci,timeout:30}]}]}}function mc(_){try{let I=JSON.parse(lh(_,"utf-8"));if(!I||typeof I!=="object"||Array.isArray(I))throw Error("Antigravity hooks config must be a JSON object");return I}catch(I){if(I instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${_}: ${I.message}`);throw I}}function gc(_){let I=_[dt];if(I===void 0){let L=Br();return _[dt]=L,{definition:L,preToolUse:L.PreToolUse??[]}}if(!pt(I))throw Error(`Antigravity hooks config entry "${dt}" must be an object`);let O=Array.isArray(I.PreToolUse)?I.PreToolUse:[];return I.PreToolUse=O,{definition:I,preToolUse:O}}function hc(_){if(!Array.isArray(_.PreToolUse))return!1;return _.PreToolUse.some((I)=>pt(I)&&Array.isArray(I.hooks)&&I.hooks.some((O)=>pt(O)&&O.command===Ci))}function dh(_){return Object.values(_).some((I)=>pt(I)&&I.enabled!==!1&&hc(I))}function uh(_){if(_[dt]===void 0)return!1;let I=gc(_);if(I.definition.enabled!==!1||!hc(I.definition))return!1;return I.definition.enabled=!0,!0}function ph(_){if(_[dt]===void 0){_[dt]=Br();return}let I=gc(_);I.definition.enabled=!0,I.preToolUse.push(Br().PreToolUse?.[0]??{hooks:[]})}function fh(_){let I=!1;for(let O of Object.values(_)){if(!pt(O)||!Array.isArray(O.PreToolUse))continue;O.PreToolUse=O.PreToolUse.flatMap((L)=>{if(!pt(L)||!Array.isArray(L.hooks))return[L];let J=L.hooks.filter((K)=>!pt(K)||K.command!==Ci);if(J.length!==L.hooks.length)I=!0;return J.length===0?[]:[{...L,hooks:J}]})}return I}function Gr(_,I){mn(_,`${JSON.stringify(I,null,2)}
238
- `)}function yc(_){let I=Ot(_.home);if(ah(ch(I),{recursive:!0}),!fc(I))return Gr(I,{[dt]:Br()}),{path:I,alreadyInstalled:!1};let O=mc(I);if(dh(O))return{path:I,alreadyInstalled:!0};if(uh(O))return Gr(I,O),{path:I,alreadyInstalled:!1};return ph(O),Gr(I,O),{path:I,alreadyInstalled:!1}}function vc(_){let I=Ot(_.home);if(!fc(I))return{path:I,alreadyInstalled:!1};let O=mc(I);if(!fh(O))return{path:I,alreadyInstalled:!1};return Gr(I,O),{path:I,alreadyInstalled:!0}}import{existsSync as Ei,readlinkSync as hh}from"node:fs";import{join as qn}from"node:path";import{spawn as mh}from"node:child_process";var $n=En.map((_)=>({target:_.id,flag:_.flag,label:fn(_.id),probeCommand:_.probeCommand}));function Ri(_){let I=new Set(_);return $n.map((O)=>O.target).filter((O)=>I.has(O))}async function bc(_,I){for(let O of _)await I(O)}var gh=5000;function Kt(_,I=gh){return new Promise((O)=>{let L=Wn([..._],process.env),J=mh(L.cmd,L.args,{env:process.env,stdio:"ignore"}),K=!1,ne=(de)=>{if(K)return;K=!0,clearTimeout(oe),O(de)},oe=setTimeout(()=>{J.kill(),ne(!1)},I);J.on("error",()=>ne(!1)),J.on("close",(de)=>ne(de===0))})}function wc(_=Kt,I={}){let O=new Set(I.configuredTargets??[]);return Promise.all($n.map(async(L)=>({target:L.target,flag:L.flag,label:L.label,...xc(I.action,await _(L.probeCommand),O.has(L.target))})))}function kc(_,I){let O=new Set(I.configuredTargets??[]);return _.map((L)=>({...L,...xc(I.action,L.available,O.has(L.target))}))}function xc(_,I,O){if(_==="uninstall")return O?{available:!0}:{available:!1,unavailableReason:"not installed"};if(_==="install"&&O)return{available:!1,unavailableReason:"already installed"};if(!I)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}var Vn="cc-safety-net",Pc=["npx","-y","@deepseek-ai/dsh"],Sc="DeepSeek Harness",Cc=["@deepseek-ai","dsh-desktop"],Ec="Quit DeepSeek Harness Desktop, then run this command again: Desktop plugins can only change while it is closed.",Pi=(_)=>`DeepSeek Harness Desktop is not in its default location, so ${_} ${Vn} from its Plugins page.`,Ac=(_,I)=>Ei(qn(Lo(_),I,"package.json"));function Ai(_,I){let O=I.platform??process.platform,L=Ac(_,"desktop"),J=O==="darwin"?[qn(_.home,"Applications"),I.systemApplications??"/Applications"].map((K)=>qn(K,`${Sc}.app`,"Contents","Resources","runtime","cli","bin","dsh")):O==="win32"?[qn(_.env.get("LOCALAPPDATA")||qn(_.home,"AppData","Local"),"Programs",Sc,"resources","runtime","cli","bin","dsh.cmd")]:[];return{profile:L,cli:L?J.find((K)=>Ei(K)):void 0}}function _c(_,I=process.platform){if(I==="win32")return Ei(qn(_.env.get("APPDATA")||qn(_.home,"AppData","Roaming"),...Cc,"lockfile"));let O=yh(qn(_.home,"Library","Application Support",...Cc,"SingletonLock")),L=Number(/-(\d+)$/.exec(O??"")?.[1]);return Number.isInteger(L)&&L>0&&vh(L)}function yh(_){try{return hh(_)}catch{return}}function vh(_){try{return process.kill(_,0),!0}catch(I){return I.code==="EPERM"}}async function Ic(_,I={}){let O=Ai(_,I);if(O.cli&&_c(_,I.platform))throw Error(Ec);let L=!O.cli||Ac(_,"web")||await(I.probe??Kt)(uo),J=[...O.cli?[{profile:"desktop",label:"Desktop",dsh:[O.cli]}]:[],...L?[{profile:"web",label:"web",dsh:Pc}]:[]];return{commands:J.map((K)=>[...K.dsh,"plugin","--profile",K.profile,"add",`${Vn}@${un()}`]),afterInstall:async()=>{let K=new Set(No(_).filter((oe)=>oe.enabled).map((oe)=>oe.name)),ne=J.filter((oe)=>!K.has(oe.profile));if(ne.length>0)throw Error(`DeepSeek Harness installed ${Vn} in the ${Rc(ne)} but did not enable it. Enable it from the Plugins page.`)},message:[`Added ${Vn} to the DeepSeek Harness ${Rc(J)}.`,...O.profile&&!O.cli?[Pi("add")]:[]].join(`
239
- `)}}function Rc(_){return`${_.map((I)=>I.label).join(" and ")} profile${_.length>1?"s":""}`}function Tc(_,I={}){let O=new Set(No(_).map((K)=>K.name));if(!O.has("desktop")&&!O.has("web"))throw Error(`${Vn} is not installed in the DeepSeek Harness web or Desktop profile`);let L=O.has("desktop")?Ai(_,I).cli:void 0,J=O.has("desktop")&&!L;if(J&&!O.has("web"))throw Error(Pi("remove"));if(L&&_c(_,I.platform))throw Error(Ec);return{commands:[...L?[[L,"plugin","--profile","desktop","remove",Vn]]:[],...O.has("web")?[[...Pc,"plugin","--profile","web","remove",Vn]]:[]],...J?{afterUninstall:()=>{throw Error(`Removed ${Vn} from the DeepSeek Harness web profile, but ${Pi("remove")}`)}}:{}}}function $c(_,I,O={}){let L=Ai(I,O).cli!==void 0;return _.map((J)=>J.target==="deepseek-harness"&&L?{...J,available:!0,unavailableReason:void 0}:J)}import{existsSync as bh,readdirSync as wh,rmSync as kh}from"node:fs";import{join as xh}from"node:path";function Oc(_,I=process.platform,O){if(!bh(_))return;let L=I==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);wh(_).filter((J)=>J!==O&&L.test(J)).forEach((J)=>{kh(xh(_,J),{recursive:!0,force:!0})})}import{existsSync as Dc,readdirSync as Sh,rmSync as Ch}from"node:fs";import{join as _t}from"node:path";function qr(_,I=process.platform){let O=_t(_.env.get("npm_config_cache")||(I==="win32"?_t(_.env.get("LOCALAPPDATA")||_t(_.home,"AppData","Local"),"npm-cache"):_t(_.home,".npm")),"_npx");if(!Dc(O))return;Sh(O).filter((L)=>Dc(_t(O,L,"node_modules","cc-safety-net"))).forEach((L)=>{Ch(_t(O,L),{recursive:!0,force:!0})})}import{existsSync as Mc,mkdirSync as Ph,readFileSync as Uc}from"node:fs";import{dirname as Eh,join as Hc}from"node:path";function Rh(_,I){if(_[I]!=="#")return I;let O=_.indexOf(`
240
- `,I+1);return O===-1?_.length:O+1}function _i(_,I,O){let L=new RegExp(`^(\\s*)${I}\\s*=\\s*\\[`),J=0;for(let K of _.split(`
241
- `)){if(/^\s*\[/.test(K))return;let ne=L.exec(K);if(ne){let oe=J+ne[0].lastIndexOf("[");return{start:oe,end:_o(_,oe,{skipComment:Rh,...O})}}J+=K.length+1}return}function Lc(_,I,O){let L=_.slice(0,I.end).trimEnd(),J=ma(_,I.end),K=J===""?" ":`${J} `,ne=!L.endsWith("[")&&!L.endsWith(",");return`${L}${ne?",":""}
242
- ${K}${O}${_.slice(I.end)}`}function Nc(_,I,O){let L=_.indexOf(O,I.start);if(L===-1||L>I.end)return _;return Sr(_,{start:L,end:L+O.length})}function jc(_,I){let O=new RegExp(`^\\s*${I}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),L=_.split(`
243
- `),J=L.findIndex((oe)=>/^\s*\[/.test(oe)),K=J===-1?L:L.slice(0,J),ne=J===-1?[]:L.slice(J);return[...K.filter((oe)=>!O.test(oe)),...ne].join(`
244
- `)}function Fc(_,I,O){let L=new RegExp(`^\\s*\\[\\[${I}]]\\s*$`,"m");return _.split(/(?=^\s*\[)/m).filter((J)=>!L.test(J)||!J.includes(O)).join("").trimEnd()}var Yt=In["kimi-code"],Ii=`[[hooks]]
235
+ `))}async function Fc(P){let O=await P(["amp","plugins","repositories","--json"]);if(O.status===null)throw Error(`${O.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 (${O.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
236
+ ${O.stderr}`.trim());if(O.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${O.status}). Sign in with "amp login" and rerun install --amp.
237
+ ${[O.stdout,O.stderr].filter(Boolean).join(`
238
+ `)}`.trim());let D=jc(O.stdout),j=(Array.isArray(D)?D:[]).filter((J)=>tn(J,"scope")==="user"&&tn(J,"exists")===!0&&tn(J,"viewerCanWrite")===!0).map((J)=>tn(J,"cloneRef")).find((J)=>typeof J==="string"&&J.length>0);if(!j)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 j}async function Hc(P,O,D){let j=Gh(Cn(O.tmpdir,"cc-safety-net-amp-"));try{return await nr(P,["amp","clone","user-plugins",j]),await D(j)}finally{Zr(j,{recursive:!0,force:!0})}}function Mi(P){return`rerun ${P==="overwrite"?"install":"uninstall"} --amp`}function Mc(P,O,D){let j=Cn(P,O),J=dn(j);if(!J)return;if(J.isSymbolicLink()||!J.isFile())throw Error(`Refusing to ${D} ${O} in your Amp personal plugins repository: not a regular file. Remove it there and ${Mi(D)}.`);let Y=jt(j);if(Xr(Y))return Y;throw Error(`Refusing to ${D} unmanaged file ${O} in your Amp personal plugins repository. Remove it there and ${Mi(D)}.`)}function Uc(P,O){let D=Cn(P,mt),j=dn(D);if(!j)return;if(j.isSymbolicLink()||!j.isDirectory())throw Error(`Refusing to ${O} ${mt} in your Amp personal plugins repository: not a regular directory. Remove it there and ${Mi(O)}.`);return Mc(P,gt,O)}function Yh(P){let O=Cn(P,Nt),D=dn(O);if(!D||D.isSymbolicLink()||!D.isFile())return;let j=jt(O);return Xr(j)?j:void 0}async function Gc(P,O,D,j){if(await nr(P,D,O),(await nr(P,["git","status","--porcelain"],O)).stdout.trim()==="")return!1;return await nr(P,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",j],O),await nr(P,["git","push","origin","HEAD"],O),!0}function Yr(P,O){Zh(P,O),Xh(P,O)}function Bc(P,O){if(O==="keep")return;throw Error(`Local Amp plugin ${P} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function Zh(P,O){let D=zh(P),j=dn(D);if(!j)return;if(!j.isSymbolicLink()&&j.isFile()&&Xr(jt(D))){Zr(D);return}Bc(D,O)}function Xh(P,O){let D=Cn(P.home,".config","amp","plugins",mt),j=dn(D);if(!j)return;if(!j.isSymbolicLink()&&j.isDirectory()&&Qh(D)){Zr(D,{recursive:!0});return}Bc(D,O)}function Qh(P){let O=qh(gt);if(Bh(P).join("\x00")!==O)return!1;let D=Cn(P,O),j=dn(D);return!!j&&!j.isSymbolicLink()&&j.isFile()&&Xr(jt(D))}function ey(P){let O=l(P);if(!Nc(O))return"";let D=jc(jt(O,"utf-8"));if(!D||typeof D!=="object"||Array.isArray(D))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(C(D,P.home))};
239
+ `}async function qc(P,O=Wh(),D=Fi){let j=Buffer.concat([jt(O),Buffer.from(ey(P),"utf-8")]),J=await Fc(D);return Hc(D,P,async(Y)=>{let re=`${J}/${mt}`,ie=Uc(Y,"overwrite"),de=Mc(Y,Nt,"overwrite");if(ie?.equals(j)&&!de)return Yr(P,"fail"),{path:re,alreadyInstalled:!0};if(Uh(Cn(Y,mt),{recursive:!0}),cn(Cn(Y,gt),j),de)Zr(Cn(Y,Nt));let fe=await Gc(D,Y,["git","add","--",gt,...de?[Nt]:[]],`chore: update cc-safety-net plugin to v${pn()}`);return Yr(P,"fail"),{path:re,alreadyInstalled:!fe}})}async function Vc(P,O=Fi){let D=await Fc(O);return Hc(O,P,async(j)=>{let J=Uc(j,"remove"),Y=Yh(j),re=`${D}/${Y&&!J?Nt:mt}`;if(!J&&!Y)return Yr(P,"keep"),{path:re,alreadyInstalled:!1};return await Gc(O,j,["git","rm","--",...J?[gt]:[],...Y?[Nt]:[]],`chore: remove cc-safety-net plugin v${pn()}`),Yr(P,"keep"),{path:re,alreadyInstalled:!0}})}import{existsSync as Jc,mkdirSync as ny,readFileSync as ty}from"node:fs";import{dirname as ry}from"node:path";var Ui=xn["antigravity-cli"],ht="cc-safety-net";function yt(P){return Boolean(P)&&typeof P==="object"&&!Array.isArray(P)}function eo(){return{PreToolUse:[{hooks:[{type:"command",command:Ui,timeout:30}]}]}}function zc(P){try{let O=JSON.parse(ty(P,"utf-8"));if(!O||typeof O!=="object"||Array.isArray(O))throw Error("Antigravity hooks config must be a JSON object");return O}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${P}: ${O.message}`);throw O}}function Kc(P){let O=P[ht];if(O===void 0){let j=eo();return P[ht]=j,{definition:j,preToolUse:j.PreToolUse??[]}}if(!yt(O))throw Error(`Antigravity hooks config entry "${ht}" must be an object`);let D=Array.isArray(O.PreToolUse)?O.PreToolUse:[];return O.PreToolUse=D,{definition:O,preToolUse:D}}function Wc(P){if(!Array.isArray(P.PreToolUse))return!1;return P.PreToolUse.some((O)=>yt(O)&&Array.isArray(O.hooks)&&O.hooks.some((D)=>yt(D)&&D.command===Ui))}function oy(P){return Object.values(P).some((O)=>yt(O)&&O.enabled!==!1&&Wc(O))}function iy(P){if(P[ht]===void 0)return!1;let O=Kc(P);if(O.definition.enabled!==!1||!Wc(O.definition))return!1;return O.definition.enabled=!0,!0}function sy(P){if(P[ht]===void 0){P[ht]=eo();return}let O=Kc(P);O.definition.enabled=!0,O.preToolUse.push(eo().PreToolUse?.[0]??{hooks:[]})}function ay(P){let O=!1;for(let D of Object.values(P)){if(!yt(D)||!Array.isArray(D.PreToolUse))continue;D.PreToolUse=D.PreToolUse.flatMap((j)=>{if(!yt(j)||!Array.isArray(j.hooks))return[j];let J=j.hooks.filter((Y)=>!yt(Y)||Y.command!==Ui);if(J.length!==j.hooks.length)O=!0;return J.length===0?[]:[{...j,hooks:J}]})}return O}function Qr(P,O){cn(P,`${JSON.stringify(O,null,2)}
240
+ `)}function Yc(P){let O=Gt(P.home);if(ny(ry(O),{recursive:!0}),!Jc(O))return Qr(O,{[ht]:eo()}),{path:O,alreadyInstalled:!1};let D=zc(O);if(oy(D))return{path:O,alreadyInstalled:!0};if(iy(D))return Qr(O,D),{path:O,alreadyInstalled:!1};return sy(D),Qr(O,D),{path:O,alreadyInstalled:!1}}function Zc(P){let O=Gt(P.home);if(!Jc(O))return{path:O,alreadyInstalled:!1};let D=zc(O);if(!ay(D))return{path:O,alreadyInstalled:!1};return Qr(O,D),{path:O,alreadyInstalled:!0}}import{existsSync as qi,readlinkSync as dy}from"node:fs";import{join as Vn}from"node:path";import{spawn as ly}from"node:child_process";var $n=En.map((P)=>({target:P.id,flag:P.flag,label:mn(P.id),probeCommand:P.probeCommand}));function Gi(P){let O=new Set(P);return $n.map((D)=>D.target).filter((D)=>O.has(D))}async function Xc(P,O){for(let D of P)await O(D)}var cy=5000;function tr(P,O=cy){return new Promise((D)=>{let j=Wn([...P],process.env),J=ly(j.cmd,j.args,{env:process.env,stdio:"ignore"}),Y=!1,re=(de)=>{if(Y)return;Y=!0,clearTimeout(ie),D(de)},ie=setTimeout(()=>{J.kill(),re(!1)},O);J.on("error",()=>re(!1)),J.on("close",(de)=>re(de===0))})}function Qc(P=tr,O={}){let D=new Set(O.configuredTargets??[]);return Promise.all($n.map(async(j)=>({target:j.target,flag:j.flag,label:j.label,...nd(O.action,await P(j.probeCommand),D.has(j.target))})))}function ed(P,O){let D=new Set(O.configuredTargets??[]);return P.map((j)=>({...j,...nd(O.action,j.available,D.has(j.target))}))}function nd(P,O,D){if(P==="uninstall")return D?{available:!0}:{available:!1,unavailableReason:"not installed"};if(P==="install"&&D)return{available:!1,unavailableReason:"already installed"};if(!O)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}var Jn="cc-safety-net",id=["npx","-y","@deepseek-ai/dsh"],td="DeepSeek Harness",rd=["@deepseek-ai","dsh-desktop"],sd="Quit DeepSeek Harness Desktop, then run this command again: Desktop plugins can only change while it is closed.",Bi=(P)=>`DeepSeek Harness Desktop is not in its default location, so ${P} ${Jn} from its Plugins page.`,ad=(P,O)=>qi(Vn(Jo(P),O,"package.json"));function Vi(P,O){let D=O.platform??process.platform,j=ad(P,"desktop"),J=D==="darwin"?[Vn(P.home,"Applications"),O.systemApplications??"/Applications"].map((Y)=>Vn(Y,`${td}.app`,"Contents","Resources","runtime","cli","bin","dsh")):D==="win32"?[Vn(P.env.get("LOCALAPPDATA")||Vn(P.home,"AppData","Local"),"Programs",td,"resources","runtime","cli","bin","dsh.cmd")]:[];return{profile:j,cli:j?J.find((Y)=>qi(Y)):void 0}}function ld(P,O=process.platform){if(O==="win32")return qi(Vn(P.env.get("APPDATA")||Vn(P.home,"AppData","Roaming"),...rd,"lockfile"));let D=uy(Vn(P.home,"Library","Application Support",...rd,"SingletonLock")),j=Number(/-(\d+)$/.exec(D??"")?.[1]);return Number.isInteger(j)&&j>0&&py(j)}function uy(P){try{return dy(P)}catch{return}}function py(P){try{return process.kill(P,0),!0}catch(O){return O.code==="EPERM"}}async function cd(P,O={}){let D=Vi(P,O);if(D.cli&&ld(P,O.platform))throw Error(sd);let j=!D.cli||ad(P,"web")||await(O.probe??tr)(xo),J=[...D.cli?[{profile:"desktop",label:"Desktop",dsh:[D.cli]}]:[],...j?[{profile:"web",label:"web",dsh:id}]:[]];return{commands:J.map((Y)=>[...Y.dsh,"plugin","--profile",Y.profile,"add",`${Jn}@${pn()}`]),afterInstall:async()=>{let Y=new Set(zo(P).filter((ie)=>ie.enabled).map((ie)=>ie.name)),re=J.filter((ie)=>!Y.has(ie.profile));if(re.length>0)throw Error(`DeepSeek Harness installed ${Jn} in the ${od(re)} but did not enable it. Enable it from the Plugins page.`)},message:[`Added ${Jn} to the DeepSeek Harness ${od(J)}.`,...D.profile&&!D.cli?[Bi("add")]:[]].join(`
241
+ `)}}function od(P){return`${P.map((O)=>O.label).join(" and ")} profile${P.length>1?"s":""}`}function dd(P,O={}){let D=new Set(zo(P).map((Y)=>Y.name));if(!D.has("desktop")&&!D.has("web"))throw Error(`${Jn} is not installed in the DeepSeek Harness web or Desktop profile`);let j=D.has("desktop")?Vi(P,O).cli:void 0,J=D.has("desktop")&&!j;if(J&&!D.has("web"))throw Error(Bi("remove"));if(j&&ld(P,O.platform))throw Error(sd);return{commands:[...j?[[j,"plugin","--profile","desktop","remove",Jn]]:[],...D.has("web")?[[...id,"plugin","--profile","web","remove",Jn]]:[]],...J?{afterUninstall:()=>{throw Error(`Removed ${Jn} from the DeepSeek Harness web profile, but ${Bi("remove")}`)}}:{}}}function ud(P,O,D={}){let j=Vi(O,D).cli!==void 0;return P.map((J)=>J.target==="deepseek-harness"&&j?{...J,available:!0,unavailableReason:void 0}:J)}import{existsSync as fy,readdirSync as my,rmSync as gy}from"node:fs";import{join as hy}from"node:path";function pd(P,O=process.platform,D){if(!fy(P))return;let j=O==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);my(P).filter((J)=>J!==D&&j.test(J)).forEach((J)=>{gy(hy(P,J),{recursive:!0,force:!0})})}import{existsSync as fd,readdirSync as yy,rmSync as vy}from"node:fs";import{join as Ft}from"node:path";function no(P,O=process.platform){let D=Ft(P.env.get("npm_config_cache")||(O==="win32"?Ft(P.env.get("LOCALAPPDATA")||Ft(P.home,"AppData","Local"),"npm-cache"):Ft(P.home,".npm")),"_npx");if(!fd(D))return;yy(D).filter((j)=>fd(Ft(D,j,"node_modules","cc-safety-net"))).forEach((j)=>{vy(Ft(D,j),{recursive:!0,force:!0})})}import{existsSync as bd,mkdirSync as wy,readFileSync as wd}from"node:fs";import{dirname as ky,join as vd}from"node:path";function by(P,O){if(P[O]!=="#")return O;let D=P.indexOf(`
242
+ `,O+1);return D===-1?P.length:D+1}function Ji(P,O,D){let j=new RegExp(`^(\\s*)${O}\\s*=\\s*\\[`),J=0;for(let Y of P.split(`
243
+ `)){if(/^\s*\[/.test(Y))return;let re=j.exec(Y);if(re){let ie=J+re[0].lastIndexOf("[");return{start:ie,end:Mo(P,ie,{skipComment:by,...D})}}J+=Y.length+1}return}function md(P,O,D){let j=P.slice(0,O.end).trimEnd(),J=_a(P,O.end),Y=J===""?" ":`${J} `,re=!j.endsWith("[")&&!j.endsWith(",");return`${j}${re?",":""}
244
+ ${Y}${D}${P.slice(O.end)}`}function gd(P,O,D){let j=P.indexOf(D,O.start);if(j===-1||j>O.end)return P;return`${P.slice(0,j)}${P.slice(j+D.length).replace(/^\s*,/,"")}`}function hd(P,O){let D=new RegExp(`^\\s*${O}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),j=P.split(`
245
+ `),J=j.findIndex((ie)=>/^\s*\[/.test(ie)),Y=J===-1?j:j.slice(0,J),re=J===-1?[]:j.slice(J);return[...Y.filter((ie)=>!D.test(ie)),...re].join(`
246
+ `)}function yd(P,O,D){let j=new RegExp(`^\\s*\\[\\[${O}]]\\s*$`,"m");return P.split(/(?=^\s*\[)/m).filter((J)=>!j.test(J)||!J.includes(D)).join("").trimEnd()}var rr=xn["kimi-code"],zi=`[[hooks]]
245
247
  event = "PreToolUse"
246
- command = "${Yt}"`,Gc=`{ event = "PreToolUse", command = "${Yt}" }`,Bc={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function qc(_){return Hc(_.env.get("KIMI_CODE_HOME")??Hc(_.home,".kimi-code"),"config.toml")}function Ah(_){let I=_i(_,"hooks",Bc);if(I&&_.slice(I.start+1,I.end).trim())return Lc(_,I,Gc);let O=jc(_,"hooks").trimEnd();if(O==="")return`${Ii}
247
- `;return`${O}
248
-
249
- ${Ii}
250
- `}function Vc(_){let I=qc(_);if(Ph(Eh(I),{recursive:!0}),!Mc(I))return mn(I,`${Ii}
251
- `),{path:I,alreadyInstalled:!1};let O=Uc(I,"utf-8");if(O.includes(Yt))return{path:I,alreadyInstalled:!0};return mn(I,Ah(O)),{path:I,alreadyInstalled:!1}}function zc(_){let I=qc(_);if(!Mc(I))return{path:I,alreadyInstalled:!1};let O=Uc(I,"utf-8");if(!O.includes(Yt))return{path:I,alreadyInstalled:!1};let L=_i(O,"hooks",Bc),J=L?Nc(O,L,Gc):`${Fc(O,"hooks",Yt)}
252
- `;return mn(I,J),{path:I,alreadyInstalled:!0}}var Ti="safety-net@cc-marketplace",Jc=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),Wc=new Set(["antigravity-cli","cursor","grok-build","hermes-agent","kimi-code"]);function $i(_){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(_??"")}function Qc(_){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(_??"")}function _h(_){return/^Marketplace `cc-marketplace`\s*$/m.test(_??"")}var ed={"claude-code":{installCommands:(_)=>{let I=xr(_,"cc-safety-net@cc-marketplace");return{commands:[...I?[["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"]],...Eo(_).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:xr(_,Ti)?[["claude","plugin","uninstall",Ti]]:[],update:I}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(_,I)=>{let O=I??await yn(["codex","plugin","list"]),L=Qc(O);return{commands:[L||_h(O)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:$i(O)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:L}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:da},"copilot-cli":{installCommands:async()=>{let _=await yn(["copilot","plugin","list"]),I=[...ka(_)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...xa(_)?[["copilot","plugin","uninstall",va]]:[]];if(ba(_))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",_n]],cleanupCommands:I,update:!0};return{commands:[wa(await yn(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",_n]],cleanupCommands:I}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(_)=>{let I=Ho(_);if(I.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(I.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:(_)=>{let I=!zr(Vr(Gt(_),Cn));return{commands:fl(),afterInstall:()=>ml(I)}},uninstallCommands:[["openclaw","plugins","uninstall",dn,"--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(`
253
- `)},opencode:{installCommands:Cl},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]},"deepseek-harness":{installCommands:(_)=>Ic(_),uninstallCommands:(_)=>Tc(_)}};function nd(_,I=(O)=>O){try{let O=JSON.parse(I(Xc(_,"utf-8")));if(!O||typeof O!=="object"||Array.isArray(O))throw Error(`Settings file ${_} must be a JSON object`);return O}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse ${_}: ${O.message}`);throw O}}function Ih(_){let I=Vr(Lt(_),"settings.json");if(!zr(I))return;let O=nd(I,Sn),L=O.enabledPlugins;if(!L||typeof L!=="object"||Array.isArray(L))return;if(L[_n]!==!1)return;let J=Xc(I,"utf-8"),K=J.replace(new RegExp(`("${_n}"\\s*:\\s*)false`),"$1true");return L[_n]=!0,mn(I,K!==J?K:`${JSON.stringify(O,null,2)}
254
- `),`Enabled ${_n} plugin in ${I}`}function Th(_){let I=li(_);if(!zr(I))return;let O=nd(I);if(!Array.isArray(O.packages))return;let L=O.packages.find((J)=>!!J&&typeof J==="object"&&!Array.isArray(J)&&ci(J.source)&&("extensions"in J));if(!L)return;return delete L.extensions,mn(I,`${JSON.stringify(O,null,2)}
255
- `),`Enabled npm:cc-safety-net extensions in ${I}`}function Kc(_,I){let O=gn({label:I,booleans:Object.fromEntries($n.map((K)=>[K.target,[K.flag]]))},_),L=O.errors[0];if(L)throw Error(L);let J=$n.filter((K)=>O.flags[K.target]).map((K)=>K.target);if(J.length!==1)throw Error(`Choose exactly one ${I} target: ${$n.map((K)=>K.flag).join(", ")}`);return J[0]}async function td(_,I=vt){let[O,L,J]=await Promise.all([I(["amp","plugins","list"],30000),I(["codex","plugin","list"],30000),I(["copilot","--binary-version"])]);return{codexPluginListOutput:L,hooks:Rt(_,process.cwd(),{ampPluginListOutput:O,codexPluginListOutput:L,copilotCliVersion:J})}}async function $h(_,I,O=vt){let L=await td(_,O);return L.hooks.filter((J)=>I==="install"?J.configured:J.detected||J.inspectionStatus==="not-inspected").filter((J)=>J.platform!=="codex"||!$i(L.codexPluginListOutput)||Qc(L.codexPluginListOutput)).map((J)=>J.platform)}function Oh(_,I,O,L){if(O.length>0)return{finish:async()=>[Kc(O,I)]};if(!L.selectTargets&&!bi(L.input,L.output))return{finish:async()=>[Kc(O,I)]};let J=L.detectConfiguredTargets??(()=>$h(_,I,L.fetchVersion)),K=Promise.all([wc(L.probeTargets).then((ne)=>$c(ne,_)),J()]);return{ready:K,finish:async()=>{let[ne,oe]=await K,de=kc(ne,{action:I,configuredTargets:oe}),ue=L.selectTargets?await L.selectTargets(I,Zc(I,de)):await tc(I,Zc(I,de),{input:L.input,output:L.output});if(ue==="update")return ue;if(!ue||ue.length===0)return null;return Ri(ue)}}}async function Dh(_,I,O=!1,L){let J=ed[_];J.beforeInstall?.(I);let K=typeof J.installCommands==="function"?await J.installCommands(I,L):{commands:J.installCommands};return await Yo(K.commands),await al(K.cleanupCommands??[]),await K.afterInstall?.(),[`${K.update||O?"Updated":"Installed"} ${fn(_)} integration`,K.message??J.postInstallMessage].filter(Boolean).join(`
256
- `)}async function Lh(_,I){let O=ed[_];if(!O.uninstallCommands)throw Error(`${fn(_)} uninstall is not supported`);let L=typeof O.uninstallCommands==="function"?O.uninstallCommands(I):{commands:O.uninstallCommands};return await Yo(L.commands),L.afterUninstall?.(),`Uninstalled ${fn(_)} integration`}function Nh(_){let I=Al(_);return I.alreadyInstalled?`Uninstalled OpenCode plugin from ${I.path}`:`OpenCode plugin not installed in ${I.path}`}var rd={"antigravity-cli":{install:yc,uninstall:vc},cursor:{install:$a,uninstall:Oa},"grok-build":{install:Va,uninstall:za},"kimi-code":{install:Vc,uninstall:zc}};function jh(_,I,O,L=!1){if(_==="install"&&!L)qr(O);let J=rd[I][_](O),K=fn(I),ne=_!=="install"?"Uninstalled":L?"Updated":"Installed";return _==="install"&&J.alreadyInstalled?L?`${K} hook up to date in ${J.path}`:`${K} hook already installed in ${J.path}`:_==="uninstall"&&!J.alreadyInstalled?`${K} hook not installed in ${J.path}`:`${ne} ${K} hook ${_==="install"?"in":"from"} ${J.path}`}var od={amp:{install:uc,uninstall:pc,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:Xa,afterInstall:async(_)=>{let I=Jo(_);return await yn(["hermes","plugins","enable",Pn,"--no-allow-tool-override"]),!I},beforeUninstall:async(_)=>{zo(_);try{await yn(["hermes","plugins","disable",Pn])}catch(I){console.warn(`${I instanceof Error?I.message:String(I)}
257
- Removing the plugin files anyway; ${Pn} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function Fh(_,I,O,L=!1){let J=od[I];if(_==="uninstall")await J.beforeUninstall?.(O);let K=_==="install"?await J.install(O):await J.uninstall(O),ne=_==="install"&&await J.afterInstall?.(O),oe=fn(I),de=!ne&&(_==="install"&&K.alreadyInstalled||_==="uninstall"&&!K.alreadyInstalled);return[de?_==="install"?`${oe} plugin ${L?"up to date":"already installed"} at ${K.path}`:`${oe} plugin not installed at ${K.path}`:`${_!=="install"?"Uninstalled":L?"Updated":"Installed"} ${oe} plugin ${_==="install"?"at":"from"} ${K.path}`,de?void 0:J.restartNote].filter(Boolean).join(`
258
- `)}var Hh={"copilot-cli":{afterInstall:Ih},"hermes-agent":{beforeInstall:(_,I)=>{if(!I)qr(_)}},openclaw:{beforeUninstall:Xo},pi:{afterInstall:Th}};function Mh(_){return _ in rd}function Uh(_){return _ in od}var Yc=["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(`
259
- `);function Gh(_){if(Ut({environment:_,cwd:process.cwd()}).status!=="configured")return Yc;return[Yc,"",nn.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(`
248
+ command = "${rr}"`,kd=`{ event = "PreToolUse", command = "${rr}" }`,xd={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function Cd(P){return vd(P.env.get("KIMI_CODE_HOME")??vd(P.home,".kimi-code"),"config.toml")}function xy(P){let O=Ji(P,"hooks",xd);if(O&&P.slice(O.start+1,O.end).trim())return md(P,O,kd);let D=hd(P,"hooks").trimEnd();if(D==="")return`${zi}
249
+ `;return`${D}
250
+
251
+ ${zi}
252
+ `}function Sd(P){let O=Cd(P);if(wy(ky(O),{recursive:!0}),!bd(O))return cn(O,`${zi}
253
+ `),{path:O,alreadyInstalled:!1};let D=wd(O,"utf-8");if(D.includes(rr))return{path:O,alreadyInstalled:!0};return cn(O,xy(D)),{path:O,alreadyInstalled:!1}}function Rd(P){let O=Cd(P);if(!bd(O))return{path:O,alreadyInstalled:!1};let D=wd(O,"utf-8");if(!D.includes(rr))return{path:O,alreadyInstalled:!1};let j=Ji(D,"hooks",xd),J=j?gd(D,j,kd):`${yd(D,"hooks",rr)}
254
+ `;return cn(O,J),{path:O,alreadyInstalled:!0}}var Ki="safety-net@cc-marketplace",Pd=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),Ed=new Set(["antigravity-cli","cursor","devin","droid","grok-build","hermes-agent","kimi-code"]);function Wi(P){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(P??"")}function $d(P){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(P??"")}function Cy(P){return/^Marketplace `cc-marketplace`\s*$/m.test(P??"")}var Od={"claude-code":{installCommands:(P)=>{let O=Ir(P,"cc-safety-net@cc-marketplace");return{commands:[...O?[["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"]],...Fo(P).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Ir(P,Ki)?[["claude","plugin","uninstall",Ki]]:[],update:O}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(P,O)=>{let D=O??await yn(["codex","plugin","list"]),j=$d(D);return{commands:[j||Cy(D)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:Wi(D)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:j}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:Pa},"copilot-cli":{installCommands:async()=>{let P=await yn(["copilot","plugin","list"]),O=[...Fa(P)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...Ha(P)?[["copilot","plugin","uninstall",La]]:[]];if(Na(P))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",In]],cleanupCommands:O,update:!0};return{commands:[ja(await yn(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",In]],cleanupCommands:O}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(P)=>{let O=ni(P);if(O.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(O.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:gi,installCommands:(P)=>{let O=!ro(to(Wt(P),Sn));return{commands:Jl(),afterInstall:()=>zl(O)}},uninstallCommands:[["openclaw","plugins","uninstall",un,"--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(`
255
+ `)},opencode:{installCommands:rc},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]},"deepseek-harness":{installCommands:(P)=>cd(P),uninstallCommands:(P)=>dd(P)}};function Dd(P,O=(D)=>D){try{let D=JSON.parse(O(Td(P,"utf-8")));if(!D||typeof D!=="object"||Array.isArray(D))throw Error(`Settings file ${P} must be a JSON object`);return D}catch(D){if(D instanceof SyntaxError)throw Error(`Failed to parse ${P}: ${D.message}`);throw D}}function Sy(P){let O=to(qt(P),"settings.json");if(!ro(O))return;let D=Dd(O,vn),j=D.enabledPlugins;if(!j||typeof j!=="object"||Array.isArray(j))return;if(j[In]!==!1)return;let J=Td(O,"utf-8"),Y=J.replace(new RegExp(`("${In}"\\s*:\\s*)false`),"$1true");return j[In]=!0,cn(O,Y!==J?Y:`${JSON.stringify(D,null,2)}
256
+ `),`Enabled ${In} plugin in ${O}`}function Ry(P){let O=Ri(P);if(!ro(O))return;let D=Dd(O);if(!Array.isArray(D.packages))return;let j=D.packages.find((J)=>!!J&&typeof J==="object"&&!Array.isArray(J)&&Pi(J.source)&&("extensions"in J));if(!j)return;return delete j.extensions,cn(O,`${JSON.stringify(D,null,2)}
257
+ `),`Enabled npm:cc-safety-net extensions in ${O}`}function Ad(P,O){let D=gn({label:O,booleans:Object.fromEntries($n.map((Y)=>[Y.target,[Y.flag]]))},P),j=D.errors[0];if(j)throw Error(j);let J=$n.filter((Y)=>D.flags[Y.target]).map((Y)=>Y.target);if(J.length!==1)throw Error(`Choose exactly one ${O} target: ${$n.map((Y)=>Y.flag).join(", ")}`);return J[0]}async function Ld(P,O=St){let[D,j,J]=await Promise.all([O(["amp","plugins","list"],30000),O(["codex","plugin","list"],30000),O(["copilot","--binary-version"])]);return{codexPluginListOutput:j,hooks:Dt(P,process.cwd(),{ampPluginListOutput:D,codexPluginListOutput:j,copilotCliVersion:J})}}async function Py(P,O,D=St){let j=await Ld(P,D);return j.hooks.filter((J)=>O==="install"?J.configured:J.detected||J.inspectionStatus==="not-inspected").filter((J)=>J.platform!=="codex"||!Wi(j.codexPluginListOutput)||$d(j.codexPluginListOutput)).map((J)=>J.platform)}function Ey(P,O,D,j){if(D.length>0)return{finish:async()=>[Ad(D,O)]};if(!j.selectTargets&&!Ni(j.input,j.output))return{finish:async()=>[Ad(D,O)]};let J=j.detectConfiguredTargets??(()=>Py(P,O,j.fetchVersion)),Y=Promise.all([Qc(j.probeTargets).then((re)=>ud(re,P)),J()]);return{ready:Y,finish:async()=>{let[re,ie]=await Y,de=ed(re,{action:O,configuredTargets:ie}),fe=j.selectTargets?await j.selectTargets(O,_d(O,de)):await Lc(O,_d(O,de),{input:j.input,output:j.output});if(fe==="update")return fe;if(!fe||fe.length===0)return null;return Gi(fe)}}}async function Ay(P,O,D=!1,j){let J=Od[P];J.beforeInstall?.(O);let Y=typeof J.installCommands==="function"?await J.installCommands(O,j):{commands:J.installCommands};return await fi(Y.commands),await Ml(Y.cleanupCommands??[]),await Y.afterInstall?.(),[`${Y.update||D?"Updated":"Installed"} ${mn(P)} integration`,Y.message??J.postInstallMessage].filter(Boolean).join(`
258
+ `)}async function Iy(P,O){let D=Od[P];if(!D.uninstallCommands)throw Error(`${mn(P)} uninstall is not supported`);let j=typeof D.uninstallCommands==="function"?D.uninstallCommands(O):{commands:D.uninstallCommands};return await fi(j.commands),j.afterUninstall?.(),`Uninstalled ${mn(P)} integration`}function _y(P){let O=ac(P);return O.alreadyInstalled?`Uninstalled OpenCode plugin from ${O.path}`:`OpenCode plugin not installed in ${O.path}`}var Nd={"antigravity-cli":{install:Yc,uninstall:Zc},cursor:{install:Wa,uninstall:Ya},devin:{install:il,uninstall:sl},droid:{install:ml,uninstall:gl},"grok-build":{install:Cl,uninstall:Sl},"kimi-code":{install:Sd,uninstall:Rd}};function Ty(P,O,D,j=!1){if(P==="install"&&!j)no(D);let J=Nd[O][P](D),Y=mn(O),re=P!=="install"?"Uninstalled":j?"Updated":"Installed";return P==="install"&&J.alreadyInstalled?j?`${Y} hook up to date in ${J.path}`:`${Y} hook already installed in ${J.path}`:P==="uninstall"&&!J.alreadyInstalled?`${Y} hook not installed in ${J.path}`:`${re} ${Y} hook ${P==="install"?"in":"from"} ${J.path}`}var jd={amp:{install:qc,uninstall:Vc,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:_l,uninstall:Tl,afterInstall:async(P)=>{let O=di(P);return await yn(["hermes","plugins","enable",Pn,"--no-allow-tool-override"]),!O},beforeUninstall:async(P)=>{ci(P);try{await yn(["hermes","plugins","disable",Pn])}catch(O){console.warn(`${O instanceof Error?O.message:String(O)}
259
+ Removing the plugin files anyway; ${Pn} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function $y(P,O,D,j=!1){let J=jd[O];if(P==="uninstall")await J.beforeUninstall?.(D);let Y=P==="install"?await J.install(D):await J.uninstall(D),re=P==="install"&&await J.afterInstall?.(D),ie=mn(O),de=!re&&(P==="install"&&Y.alreadyInstalled||P==="uninstall"&&!Y.alreadyInstalled);return[de?P==="install"?`${ie} plugin ${j?"up to date":"already installed"} at ${Y.path}`:`${ie} plugin not installed at ${Y.path}`:`${P!=="install"?"Uninstalled":j?"Updated":"Installed"} ${ie} plugin ${P==="install"?"at":"from"} ${Y.path}`,de?void 0:J.restartNote].filter(Boolean).join(`
260
+ `)}var Oy={"copilot-cli":{afterInstall:Sy},"hermes-agent":{beforeInstall:(P,O)=>{if(!O)no(P)}},openclaw:{beforeUninstall:gi},pi:{afterInstall:Ry}};function Dy(P){return P in Nd}function Ly(P){return P in jd}var Id=["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(`
261
+ `);function Ny(P){if(Kt({environment:P,cwd:process.cwd()}).status!=="configured")return Id;return[Id,"",nn.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(`
260
262
  `))].join(`
261
- `)}function Zc(_,I){return I.map((O)=>_==="install"&&O.target==="kimi-code"&&O.unavailableReason==="already installed"?{...O,available:!0,unavailableReason:void 0,label:`${O.label} (global hook installed)`}:O)}function Bh(_,I){if(_.selectKimiInstallMethod)return _.selectKimiInstallMethod();if(!bi(_.input,_.output))return Promise.resolve("global-hook");return nc({input:_.input,output:_.output,globalHookInstalled:Ut({environment:I,cwd:process.cwd()}).status==="configured"})}async function id(_,I,O,L=!1,J){let K=Hh[I];if(_==="install")K?.beforeInstall?.(O,L);if(_==="uninstall")K?.beforeUninstall?.(O);if(Mh(I))return jh(_,I,O,L);if(Uh(I))return Fh(_,I,O,L);if(_==="uninstall")return I==="opencode"?Nh(O):Lh(I,O);return[await Dh(I,O,L,J),await K?.afterInstall?.(O)].filter(Boolean).join(`
262
- `)}function qh(_){let I=gn({label:"update"},_).errors[0];if(I)throw Error(I)}async function Vh(_,I=vt){let O=await td(_,I),L=Vr(Lt(_),"installed-plugins");return{targets:Ri([...O.hooks.filter((K)=>K.platform!=="copilot-cli"&&K.detected).map((K)=>K.platform),...[Cr,ya,ha].flatMap((K)=>zr(Vr(L,...K))?["copilot-cli"]:[]),...xr(_,Ti)?["claude-code"]:[],...$i(O.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:O.codexPluginListOutput}}async function zh(_){let I=c(),O=_.output??process.stdout,L=(_.scriptPath??process.argv[1]??"").split(/[\\/]/),J=L.find((Pe)=>/^bunx-\d+-/.test(Pe)),K=J!==void 0||L.includes("_npx")?null:(_.checkLatestVersion??Un)(),ne=async()=>{let Pe=K&&await K;if(Pe?.updateAvailable)O.write(`
263
- Update available: cc-safety-net ${Pe.currentVersion} → ${Pe.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
264
- `)},oe=Vh(I,_.fetchVersion??vt).then(async(Pe)=>{let we=new Set(Pe.targets);return{targets:Pe.targets,codexPluginListOutput:Pe.codexPluginListOutput,available:new Map(await Promise.all($n.filter((Le)=>we.has(Le.target)&&Jc.has(Le.target)).map(async(Le)=>[Le.target,await Kt(Le.probeCommand)])))}}),de=await $t(_.showBanner??!0,()=>({ready:oe,finish:()=>oe}),()=>Tt({input:_.input??process.stdin,output:O}),{loadingMessage:"Checking installed integrations…",output:O}),ue=await Promise.resolve().then(()=>(Oc(I.tmpdir,process.platform,J),null)).catch((Pe)=>Zt(Pe));if(de.targets.length===0){if(O.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),ue!==null)console.error(ue);return await ne(),ue===null?0:1}let ve=de.targets.some((Pe)=>Wc.has(Pe))?await Promise.resolve().then(()=>(qr(I),null)).catch((Pe)=>Zt(Pe)):null,xe=await vr(Promise.all(de.targets.map((Pe)=>{if(Jc.has(Pe)&&!de.available.get(Pe))return Promise.resolve({message:`${fn(Pe)} not found; skipped`,failed:!1});if(ve!==null&&Wc.has(Pe))return Promise.resolve({message:ve,failed:!0});return id("install",Pe,I,!0,de.codexPluginListOutput).then((we)=>({message:we,failed:!1}),(we)=>({message:Zt(we),failed:!0}))})),{loadingMessage:`Updating ${de.targets.length} integration${de.targets.length===1?"":"s"}…`,output:O}),Se=ue===null?xe:[...xe,{message:ue,failed:!0}];return Se.forEach((Pe)=>Pe.failed?console.error(Pe.message):O.write(`${Pe.message}
265
- `)),await ne(),Se.some((Pe)=>Pe.failed)?1:0}function Oi(_,I={}){return Promise.resolve().then(()=>qh(_)).then(()=>zh(I)).catch((O)=>(console.error(Zt(O)),1))}async function Xt(_,I,O={}){try{let L=c(),J=await $t(!0,()=>Oh(L,_,I,O),()=>Tt({input:O.input??process.stdin,output:O.output??process.stdout}),{loadingMessage:_==="install"?"Checking available integrations…":"Checking installed integrations…",output:O.output??process.stdout});if(!J)return(O.output??process.stdout).write(`Cancelled: nothing was ${_}ed.
266
- `),0;if(J==="update")return(O.runUpdate??(()=>Oi([],{fetchVersion:O.fetchVersion,input:O.input,output:O.output,showBanner:!1})))();let K=O.output??process.stdout;return await bc(J,async(ne)=>{if(ne==="kimi-code"&&_==="install"){let de=await Bh(O,L);if(de===null){K.write(`Cancelled: Kimi Code integration was not installed.
267
- `);return}if(de==="plugin"){K.write(`${Gh(L)}
268
- `);return}}let oe=await vr(id(_,ne,L),{loadingMessage:`${_==="install"?"Installing":"Uninstalling"} ${fn(ne)} integration…`,output:K});K.write(`${oe}
269
- `)}),0}catch(L){return console.error(Zt(L)),1}}function Zt(_){let I=_ instanceof Error?_.message:String(_),O=typeof _==="object"&&_!==null&&"code"in _?_.code:null;if(O==="EACCES"||O==="EPERM")return`${I}
270
- Check file permissions for the target config file and parent directory.`;if(O==="ENOENT")return`${I}
271
- Check that the target config path and parent directory exist.`;if(O==="ENOTDIR")return`${I}
272
- Check that every parent path component is a directory.`;return I}import{mkdirSync as Xh}from"node:fs";import{dirname as Qh}from"node:path";import{createInterface as ey}from"node:readline";import{existsSync as ad,readFileSync as Jh}from"node:fs";function ft(_,I){let O=et(_,I);return{policy:O.policy,errors:ae(Ze(O.issues,Qe,(L)=>L.kind==="custom")," "," ")}}function Qt(_,I){return ft(_,I).errors}function sd(_,I){return{"safety.level":_.safety.level,...Di("safety.overrides",_.safety.overrides),"workflow.worktree_mode":String(_.workflow.worktree_mode),"destructive_command_protection.enabled":String(_.destructive_command_protection.enabled),...Di("destructive_command_protection.overrides",_.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Li(_.destructive_command_protection.allow_paths),"secret_protection.enabled":String(_.secret_protection.enabled),...Di("secret_protection.overrides",_.secret_protection.overrides),"secret_protection.deny_paths":Li(_.secret_protection.deny_paths),"secret_protection.allow_paths":Li(_.secret_protection.allow_paths),...I?{"audit.retention_days":String(_.audit.retention_days)}:{}}}function Jr(_,I,O){let L=sd(_,O),J=sd(I,O);return[...new Set([...Object.keys(L),...Object.keys(J)])].flatMap((K)=>L[K]===J[K]?[]:[{field:K,before:L[K],after:J[K]}])}function er(_,I){let O=d(_,I);if(!ad(O))return{baseline:C(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,_.home),diagnostics:[]};let L=mt(O),J=ft(L.value,_.home);return{baseline:J.policy,diagnostics:L.errors.length>0?L.errors:J.errors}}function mt(_){if(!ad(_))return{errors:[`${_}: file not found`]};try{return{value:JSON.parse(Jh(_,"utf-8")),errors:[]}}catch(I){let O=I instanceof Error?I.message:String(I);return{errors:[`${_}: ${I instanceof SyntaxError?`Invalid JSON: ${O}`:O}`]}}}function Wr(_,I){let O=Wh(_)?_:{};return{version:I.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((L)=>O[L]!==void 0).map((L)=>[L,O[L]]))}}function Di(_,I){return Object.fromEntries(Object.entries(I).flatMap(([O,L])=>L===void 0?[]:[[`${_}.${O}`,String(L)]]))}function Li(_){return _.length===0?"(none)":_.join(", ")}function Wh(_){return!!_&&typeof _==="object"&&!Array.isArray(_)}import{chmodSync as Kh,existsSync as ld,mkdirSync as Yh,readFileSync as cd}from"node:fs";import{dirname as Zh}from"node:path";function dd(_,I={}){let O=d(_,I);if(!ld(O))return{path:O,exists:!1,raw:"",policy:z(),errors:[]};let L=cd(O,"utf-8");if(!L.trim())return{path:O,exists:!0,raw:L,policy:z(),errors:["Config file is empty"]};try{let J=ft(JSON.parse(L),_.home);return{path:O,exists:!0,raw:L,policy:J.policy,errors:J.errors}}catch(J){return{path:O,exists:!0,raw:L,policy:z(),errors:[`Invalid JSON: ${J instanceof Error?J.message:String(J)}`]}}}function Fn(_,I,O={}){let L=d(_,O),J=ft(I,_.home);if(J.errors.length>0)return{path:L,policy:z(),errors:J.errors};let K=J.policy;return Yh(Zh(L),{recursive:!0,mode:448}),g(ie(L),`${JSON.stringify(K,null,2)}
273
- `,384),Kh(L,384),{path:L,policy:K,errors:[]}}function ud(_,I){let O=ft(I,_.home);if(O.errors.length>0)return{errors:O.errors};return{preview:Ne(O.policy,_.env),errors:[]}}function pd(_,I={}){let O=d(_,I);if(!ld(O))return Fn(_,ee,I);let L=cd(O,"utf-8");if(!L.trim())return Fn(_,ee,I);try{return Fn(_,C(JSON.parse(L),_.home),I)}catch{return Fn(_,ee,I)}}var fd=new Set(["check","apply"]),md="(unset)";async function hd(_,I,O={}){let L=gn({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},I),J=L.positionals[0],K=[...L.errors,...J&&!fd.has(J)?[`Unknown policy subcommand: ${J}`]:[],...J&&fd.has(J)&&!L.positionals[1]?[`policy ${J} requires a file`]:[],...L.positionals.slice(2).map((we)=>`Unexpected policy argument: ${we}`)];if(K.length>0){for(let we of K)console.error(we);return 1}let ne=L.positionals[1];if(!J||!ne)return Pt(ar,console.error),1;let oe=L.flags.global?d(_):b(O.cwd??process.cwd()),de=mt(ne),ue=[...de.errors,...Qt(de.value,_.home).map((we)=>`${ne}: ${we}`),...!L.flags.global&&ry(de.value)&&de.value.audit!==void 0?[`${ne}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(ue.length>0){for(let we of ue)console.error(we);return 1}let ve=C(de.value,_.home);if(console.log(`Scope: ${L.flags.global?"user":"project"} (${oe})`),console.log(`Proposal: ${ne}`),L.flags.global)gd(C(mt(oe).value,_.home),ve,!0);if(!L.flags.global){let we=er(_).baseline;console.log("Effective policy (user + project merged):"),gd(Q(we,le(mt(oe).value,_.home).policy).policy,Q(we,le(de.value,_.home).policy).policy,!1)}if(J==="check")return 0;let xe=O.input??process.stdin,Se=O.output??process.stdout;if(!xe.isTTY||!Se.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${ne}${L.flags.global?" --global":""}`),1;if(!await ny(`Apply this policy to ${oe}? [y/N] `,xe,Se))return console.log("Cancelled; nothing was written."),0;return ty(_,oe,de.value,ve,L.flags.global),console.log(`Policy applied: ${oe}`),0}function ny(_,I,O){let L=ey({input:I,output:O,terminal:!1});return new Promise((J)=>{L.once("close",()=>J(!1)),L.question(_,(K)=>{J(/^y(es)?$/i.test(K.trim())),L.close()})})}function ty(_,I,O,L,J){if(J){Fn(_,L);return}Xh(Qh(I),{recursive:!0}),bn(I,Wr(O,L))}function gd(_,I,O){let L=Jr(_,I,O);if(L.length===0){console.log("No changes.");return}console.log(`Changes (${L.length}):`);for(let J of L)console.log(` ${J.field}: ${J.before??md} -> ${J.after??md}`)}function ry(_){return!!_&&typeof _==="object"&&!Array.isArray(_)}import{join as hv}from"node:path";var yd="# 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- `exec`, `nice`, `nohup`, `setsid`, `stdbuf`, `time`, and `timeout` are built-in transparent wrappers and need no configuration. Configure only other 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 Kr(_,I){if(!_.ok){xd(_);return}wd(_,I)}function bd(_,I,O){if(_.ok)console.log(O);if(!_.add){Kr(_,`Added rulebook source: ${I}`);return}if(!_.ok){xd(_);return}if(_.add.added.length>0)console.log(`Added ${_.add.added.length} ${_.add.added.length===1?"rulebook":"rulebooks"} from ${_.add.source} at ${_.add.ref}:`),_.add.added.forEach((L)=>{console.log(` - ${L}`)});if(_.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${_.add.source} at ${_.add.ref}: ${_.add.alreadyConfigured.join(", ")}`);if(_.add.commits.length>0)console.log(`Vendored at ${_.add.commits.map((L)=>L.slice(0,7)).join(", ")}.`);wd(_,"Rule config updated.")}function wd(_,I){for(let O of _.changes??[])console.log(O);console.log(I),console.log(""),oy(_.entries)}function oy(_){if(_.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${_.length}):`);for(let I of _)console.log(` - ${I.name} ${I.version} (${iy(I.ruleCount)})`),console.log(` Source: ${I.spec}`)}function iy(_){return`${_} ${_===1?"rule":"rules"}`}function kd(_){gt("Active sources",_.rulebooks,(I)=>[`[${I.source}] ${I.name} ${I.version}`,` Source: ${I.spec}`]),gt("Active rules",_.rules,(I)=>[`[${ay(_,I.name)}] ${I.name}`,...sy(I),` Reason: ${I.reason}`]),gt("Disabled rules",vd(_,"off"),(I)=>[I.key]),gt("Reason overrides",vd(_,"reason"),(I)=>[I.key,` Reason: ${I.value.reason}`]),gt("Transparent wrappers",_.transparent_wrappers,(I)=>[I]),gt("Issues",_.errors,(I)=>[I]),gt("Warnings",_.warnings,(I)=>[I])}function gt(_,I,O){if(I.length===0){console.log(`${_}: (none)`);return}console.log(`${_} (${I.length}):`);for(let L of I){let[J,...K]=O(L);console.log(` - ${J}`);for(let ne of K)console.log(` ${ne}`)}}function sy(_){if(!_.match)return[` Command: ${_.subcommand?`${_.command} ${_.subcommand}`:_.command}`,` Block args: ${_.block_args.join(", ")}`];return[` Command: ${[_.command,..._.match.command_path].join(" ")}`,..._.match.any_args?[` Any args: ${_.match.any_args.join(", ")}`]:[],..._.match.exclude_args?[` Exclude args: ${_.match.exclude_args.join(", ")}`]:[]]}function ay(_,I){return _.rulebooks.find((O)=>O.rules.includes(I))?.source??"project"}function vd(_,I){return Object.entries({..._.userConfig?.overrides,..._.projectConfig?.overrides}).filter((O)=>{if(I==="off")return O[1]==="off";return!!O[1]&&typeof O[1]==="object"}).map(([O,L])=>({key:O,value:L}))}function xd(_){for(let I of _.errors)console.error(I)}import{dirname as Vd,join as ro}from"node:path";import{join as Mi,resolve as by}from"node:path";function Ni(_){let I=m(_);if(I.errors.length>0)return{ok:!1,result:{ok:!1,errors:I.errors,entries:[]}};return{ok:!0,config:I.config??lt}}function Sd(_){bn(_,{version:1,rules:[],overrides:{},transparent_wrappers:[]})}function Cd(_){bn(_,{rulebook_version:1,name:"example-rules",version:"1.0.0",description:"Project-specific CC Safety Net rules.",author:"project",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as Qr}from"node:path";var ly="custom.";function Yr(_){if(_.rulebook_version!==2)return[];let I=_.rules.map((O)=>({name:O.name,command:O.command,block_args:[],match:O.match,reason:O.reason,intent:O.intent}));return(_.tests??[]).flatMap((O,L)=>{let J=ji(h(O.command));if(J.length===0)return[`tests[${L}]: could not parse fixture command: ${O.command}`];let K=J.reduce((ne,oe)=>ne??A(oe,I)?.id.slice(ly.length),void 0);if(O.expect==="blocked"){if(K===O.rule)return[];let ne=K?`"${K}" matched first`:"no rule matched";return[`tests[${L}]: expected "${O.rule}" to block "${O.command}" but ${ne}`]}return K?[`tests[${L}]: expected "${O.command}" to be allowed but "${K}" matched`]:[]})}function ji(_){return _.nodes.flatMap((I)=>{if(I.kind==="group"||I.kind==="function")return ji(I.body);if(I.kind!=="command")return[];let O=be(te(I.dialect,I.words)).words.map(t);return[...O.length>0?[O]:[],...I.nested.flatMap((L)=>ji(L))]})}var Zr=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function Xr(_={}){return{requests:0,responseBytes:0,maxRequests:_.maxRequests??Zr.maxRequests,maxResponseBytes:_.maxResponseBytes??Zr.maxResponseBytes}}function Hn(_){return{controller:new AbortController,budget:Xr(),resolveUrl:_}}function Rd(_){return _ instanceof Error&&_.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function Pd(_){if(_.requests>=_.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");_.requests++}function Ed(_,I){if(I>_.maxResponseBytes-_.responseBytes)throw _.responseBytes+=I,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");_.responseBytes+=I}var Id=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function Ad(_,I,O=v(Qr(Qr(I)),"rules policy"),L=Hn()){if(S(_))return py(_,L);return uy(_,I,O)}async function Td(_,I,O,L,J,K){if(!S(_))return Ad(_,I,O,L);let ne=J?null:cy(_,I,O);if(ne)return ne;if(!J&&!K)throw Error(`${_} is not vendored; run rule update ${_} to vendor it`);return Ad(_,I,O,L)}function cy(_,I,O=v(Qr(Qr(I)),"rules policy")){let L=D(_),J=N(I,L.name),K=n(i(O,J));if(K===null)return null;let ne=ce(Fi(K,`Invalid rulebook ${J}.`));if(ne.name!==L.name)throw Error(`rulebook name "${ne.name}" in ${J} must match "${L.name}"`);return{spec:_,rulebook:ne,content:K}}async function $d(_,I={}){if(!Y(_))throw Error(`Invalid GitHub repository source: ${_}`);let[O,L]=_.split("/");if(!O||!L)throw Error(`Invalid GitHub repository source: ${_}`);if(I.ref!==void 0&&!se(I.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${I.ref}`);let J=I.operation??Hn(),K=I.ref??await dy(O,L,_,J),ne=await Dd(O,L,K,_,J),oe=await eo(`https://api.github.com/repos/${O}/${L}/git/trees/${ne}?recursive=1`,"tree",J),de=oe.response;if(!de.ok)throw Error(`Failed to inspect ${_}: GitHub tree returned ${de.status}`);let ue=JSON.parse(oe.content);if(!Array.isArray(ue?.tree))throw Error(`Failed to inspect ${_}: unexpected GitHub tree response`);let ve=ue.tree,xe=[...new Set(ve.flatMap((Se)=>{if(!Se||typeof Se!=="object")return[];let Pe=Se;if(Pe.type!=="blob"||typeof Pe.path!=="string")return[];let we=Pe.path.match(at);return we?.[1]?[we[1]]:[]}))].sort();if(xe.length===0)throw Error(`No rulebooks found in ${_} under ${me}/`);return{source:_,owner:O,repo:L,ref:K,commit:ne,names:xe}}async function dy(_,I,O,L){let J=await eo(`https://api.github.com/repos/${_}/${I}`,"metadata",L),K=J.response;if(!K.ok)throw Error(`Failed to inspect ${O}: GitHub returned ${K.status}`);let oe=JSON.parse(J.content)?.default_branch;if(typeof oe!=="string"||oe==="")throw Error(`Failed to inspect ${O}: missing default branch`);if(!se(oe))throw Error(`GitHub returned an invalid default branch: ${oe}`);return oe}function uy(_,I,O){ct(_);let L=N(I,_),J=n(i(O,L));if(J===null)throw Error(`Rulebook source not found: ${_}`);let K=Od(Fi(J,"Invalid local rulebook source."));if(K.name!==_)throw Error(`rulebook name "${K.name}" must match local source "${_}"`);return{spec:_,rulebook:K,content:J}}async function py(_,I){let O=D(_),L=await Dd(O.owner,O.repo,O.ref,_,I),J=await eo(`https://raw.githubusercontent.com/${O.owner}/${O.repo}/${L}/${O.path}`,"raw",I),K=J.response;if(!K.ok)throw Error(`Failed to fetch ${_}: GitHub raw returned ${K.status}`);let ne=J.content,oe=Od(Fi(ne,"Invalid GitHub rulebook response."));if(oe.name!==O.name)throw Error(`rulebook name "${oe.name}" must match GitHub source "${O.name}"`);return{spec:_,rulebook:oe,content:ne}}function Od(_){let I=ce(_),O=Yr(I);if(O.length>0)throw Error(O.join("; "));return I}function Fi(_,I){try{return JSON.parse(_)}catch{throw Error(I)}}async function Dd(_,I,O,L,J){let K=await eo(`https://api.github.com/repos/${_}/${I}/commits/${encodeURIComponent(O)}`,"commit",J),ne=K.response;if(!ne.ok)throw Error(`Failed to resolve ${L}: GitHub returned ${ne.status}`);let oe=JSON.parse(K.content);if(typeof oe?.sha!=="string"||oe.sha==="")throw Error(`Failed to resolve commit for ${L}`);return oe.sha}async function fy(_,I,O={}){if(O.signal?.aborted)throw O.signal.reason;let L=O.budget??Xr(),J=new AbortController,K=()=>J.abort(O.signal?.reason);O.signal?.addEventListener("abort",K,{once:!0});let ne=!1,oe=setTimeout(()=>{if(J.signal.aborted)return;ne=!0,J.abort()},O.timeoutMs??Id.timeoutMs);try{if(O.signal?.aborted)throw O.signal.reason;Pd(L);let de=await fetch(_,{signal:J.signal,redirect:"error"});if(!de.ok)return Ld(de),{response:de,content:""};return{response:de,content:await my(de,I,L,()=>J.abort())}}catch(de){if(ne)throw Error("GitHub request timed out",{cause:de});if(O.signal?.aborted)throw O.signal.reason;throw de}finally{clearTimeout(oe),O.signal?.removeEventListener("abort",K)}}function eo(_,I,O){return fy(O.resolveUrl?.(_)??_,I,{budget:O.budget,signal:O.controller.signal})}async function my(_,I,O=Xr(),L){let J=Id[`${I}Bytes`],K=Number(_.headers.get("content-length"));if(Number.isFinite(K)&&K>J)throw Ld(_),Error(`GitHub ${I} response exceeds ${J} bytes`);if(!_.body)return"";let ne=_.body.getReader(),oe=[],de=0;while(!0){let ue=await ne.read();if(ue.done)break;try{Ed(O,ue.value.byteLength)}catch(ve){throw L?.(),_d(ne),ve}if(de+=ue.value.byteLength,de>J)throw L?.(),_d(ne),Error(`GitHub ${I} response exceeds ${J} bytes`);oe.push(Buffer.from(ue.value))}return Buffer.concat(oe,de).toString("utf-8")}function Ld(_){if(!_.body)return;Nd(()=>_.body?.cancel())}function _d(_){Nd(()=>_.cancel())}function Nd(_){try{Promise.resolve(_()).catch(()=>{})}catch{}}var gy=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function jd(_,I){let O=Md(_.rules,I);if(O.length>0)return{ok:!0,specs:O};return Hd(_.rules,I)}function Fd(_,I){let O=Md(_,I);if(O.length>0)return{ok:!0,specs:O};let L=yy(_,I);if(L.length>0)return{ok:!0,specs:L};let J=vy(_,I);if(!J.ok)return J;if(J.specs.length>0)return{ok:!0,specs:J.specs};return Hd(_,I)}function Hd(_,I){let O=_.filter((L)=>Hi(L)?.name===I);if(O.length===1)return{ok:!0,specs:O};return hy(I,O)}function hy(_,I){return{ok:!1,result:{ok:!1,errors:I.length===0?[`No configured rulebook matches ${_}`]:[`Ambiguous rulebook match ${_}: ${I.join(", ")}`],entries:[]}}}function Md(_,I){return _.filter((O)=>O===I)}function yy(_,I){let O=I.match(gy),L=O?.[1],J=O?.[2],K=O?.[3];if(!L||!J||!K||!se(K))return[];return Ud(_,(ne)=>ne.owner===L&&ne.repo===J&&ne.ref===K)}function vy(_,I){if(!Y(I))return{ok:!0,specs:[]};let[O,L]=I.split("/"),J=Ud(_,(ne)=>ne.owner===O&&ne.repo===L);if(new Set(J.map((ne)=>Hi(ne)?.ref).filter((ne)=>!!ne)).size<2)return{ok:!0,specs:J};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${I}. Use an explicit ref:`,` cc-safety-net rule remove ${I}#<ref>`],entries:[]}}}function Hi(_){try{return D(_)}catch{return null}}function Ud(_,I){return _.filter((O)=>{let L=Hi(O);return L?I(L):!1})}async function to(_,I={}){let O=Ui(I);return wy(_,O,await no(_,O,Hn()))}function wy(_,I,O){if(!O.ok)return O;let L=wn(_,I),J=[...new Set(H(L.configPath,L.filesystemScope))];if(J.length===0)return O;return{ok:!1,errors:J,entries:O.entries}}async function no(_,I,O,L={},J=new Set,K=new Set){try{let ne=wn(_,I),oe=Ni(ne.configTarget);if(!oe.ok)return oe.result;let de=oe.config,ue=I.only?jd(de,I.only):{ok:!0,specs:de.rules};if(!ue.ok)return ue.result;let ve=new Set([...I.refresh?ue.specs:[],...J]),xe=(rn)=>Td(rn,ne.configDir,ne.filesystemScope,O,ve.has(rn),!I.refresh||ve.has(rn)),Se=await Ty(de.rules,I.refresh?(rn)=>xe(rn).then((pn)=>({ok:!0,item:pn})).catch((pn)=>{if(Rd(pn))throw pn;return{ok:!1,spec:rn,message:pn instanceof Error?pn.message:String(pn)}}):async(rn)=>({ok:!0,item:await xe(rn)}),O),Pe=Se.filter((rn)=>!rn.ok),we=Se.filter((rn)=>rn.ok).map((rn)=>rn.item),Le=we.flatMap((rn)=>ky(rn,de.rules)),en=we.flatMap((rn)=>xy(rn,K,ne)),Ve=new Set([...Le,...en].map((rn)=>rn.spec)),on=[...Pe,...Le,...en],sn=[],an=Cy(sn,()=>we.flatMap((rn)=>Ve.has(rn.spec)||on.length>0&&K.has(rn.spec)?[]:Sy(rn,ne,L,sn)));return{ok:on.length===0,errors:on.map((rn)=>`Failed to update ${rn.spec}: ${rn.message}`),entries:we.map(Py),changes:an}}catch(ne){return tr(ne)}}function ky(_,I){if(!S(_.spec))return[];let O=De(_.spec),L=I.filter((J)=>J!==_.spec&&De(J).toLowerCase()===O.toLowerCase());if(L.length===0)return[];return[{ok:!1,spec:_.spec,message:`rulebook name "${O}" is also claimed by ${L.join(", ")}; rename one of them`}]}function xy(_,I,O){if(!I.has(_.spec)||!S(_.spec))return[];let L=N(O.configDir,_.rulebook.name),J=n(i(O.filesystemScope,L));if(J===null||J===_.content)return[];return[{ok:!1,spec:_.spec,message:`${L} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Sy(_,I,O,L){if(!S(_.spec))return[];let J=N(I.configDir,_.rulebook.name),K=i(I.filesystemScope,J),ne=n(K);if(ne===_.content)return[];return L?.push({target:K,previous:ne}),g(K,_.content,void 0,O._testAfterPolicyRename),Ry(_,ne)}function Cy(_,I){try{return I()}catch(O){for(let L of[..._].reverse()){if(L.previous===null){j(L.target);continue}g(L.target,L.previous)}throw O}}function Ry(_,I){if(I===null)return[`Vendored ${_.spec} (${_.rulebook.version})`];let O=ye(I),L="problem"in O?null:O.rulebook,J=new Map(L?.rules.map((ne)=>[ne.name,JSON.stringify(ne)])??[]),K=new Set(_.rulebook.rules.map((ne)=>ne.name));return[`Updated ${_.spec} (${L?.version??"unreadable"} -> ${_.rulebook.version})`,...[...K].filter((ne)=>!J.has(ne)).map((ne)=>` + ${ne}`),...[...J.keys()].filter((ne)=>!K.has(ne)).map((ne)=>` - ${ne}`),..._.rulebook.rules.filter((ne)=>{let oe=J.get(ne.name);return oe!==void 0&&oe!==JSON.stringify(ne)}).map((ne)=>` ~ ${ne.name}`)]}function Py(_){return{spec:_.spec,name:_.rulebook.name,version:_.rulebook.version,ruleCount:_.rulebook.rules.length}}async function Gd(_,I,O={}){return Ey(_,I,Oy(O),Hn())}async function Ey(_,I,O,L,J={}){let K=null,ne=!1;try{let oe=wn(_,O),de=n(oe.configTarget);K={target:oe.configTarget,content:de};let ue=Ni(oe.configTarget);if(!ue.ok)return ue.result;let ve=ue.config,xe=Y(I);Ay(I,O,xe);let Se=xe?await $d(I,{ref:O.ref,operation:L}):null,Pe=Se?_y(Se,O.rulebooks):[],we=Se?Pe.map((sn)=>Iy(ve.rules,Se,sn)??`${I}#${Se.ref}/${sn}`):[I],Le=we.filter((sn)=>!ve.rules.includes(sn)),en=[...ve.rules,...Le];if(en.length>ge)return $y();if(en.length!==ve.rules.length)ne=!0,bn(oe.configTarget,{version:1,rules:en,overrides:ve.overrides??{},transparent_wrappers:ve.transparent_wrappers??[]},void 0,J._testAfterPolicyRename);let Ve=await no(_,O,L,J,new Set(Le),new Set(Le));if(!Ve.ok)nr(oe.configTarget,de);if(!Ve.ok||!Se)return Ve;let on=Pe.filter((sn,an)=>Le.includes(we[an]??""));return{...Ve,add:{source:I,ref:Se.ref,selected:Pe,added:on,alreadyConfigured:Pe.filter((sn)=>!on.includes(sn)),commits:Le.length>0?[Se.commit]:[]}}}catch(oe){if(ne&&K)try{nr(K.target,K.content)}catch(de){return tr(de)}return tr(oe)}}function Ay(_,I,O){if(!O&&I.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!O&&I.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${_}`);if(I.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let L=I.rulebooks?.filter((J)=>!u.test(J))??[];if(L.length>0)throw Error(`Invalid rulebook names: ${L.join(", ")}`)}function _y(_,I){let O=I?[...new Set(I)]:_.names,L=O.filter((J)=>!_.names.includes(J));if(L.length>0)throw Error(`Rulebooks not found in ${_.source} at ${_.ref}: ${L.join(", ")}
274
- Available rulebooks: ${_.names.join(", ")}`);return O}function Iy(_,I,O){let L=`${I.source}#${I.ref}/${O}`;if(_.includes(L))return L;let J=`${I.source}#${I.commit}/${O}`;return _.find((K)=>K===J)}async function Ty(_,I,O=Hn()){if(_.length>ge)throw Error(he);let L=[],J=0,K,ne=Array.from({length:Math.min(_.length,Zr.concurrency)},async()=>{while(!K){let oe=J;if(oe>=_.length)return;J++;try{L[oe]=await I(_[oe],oe,O.controller.signal)}catch(de){if(!K)K={value:de},J=_.length,O.controller.abort(de);return}}});if(await Promise.all(ne),K)throw K.value;return L}function $y(){return{ok:!1,errors:[he],entries:[]}}function Ui(_){return{cwd:_.cwd,userConfigDir:_.userConfigDir,userConfigPath:_.userConfigPath,projectConfigPath:_.projectConfigPath,global:_.global,only:_.only,refresh:_.refresh}}function Oy(_){return{...Ui(_),ref:_.ref,rulebooks:_.rulebooks}}function Dy(_){return{...Ui(_),deleteSource:_.deleteSource}}async function Bd(_,I,O={}){try{return await Ly(_,I,Dy(O),{})}catch(L){return tr(L)}}async function Ly(_,I,O,L){let J=wn(_,O),K=m(J.configTarget);if(K.errors.length>0)return{ok:!1,errors:K.errors,entries:[]};if(!K.config)return{ok:!1,errors:[`No config found at ${J.configPath}`],entries:[]};let ne=Fd(K.config.rules,I);if(!ne.ok)return ne.result;let oe=O.deleteSource?Ny(J.configDir,ne.specs,J.filesystemScope):{ok:!0,dirs:[]};if(!oe.ok)return oe.result;let de=n(J.configTarget);if(de===null)return tr(Error("Rules config is unavailable."));try{bn(J.configTarget,{version:1,rules:K.config.rules.filter((xe)=>!ne.specs.includes(xe)),overrides:K.config.overrides??{},transparent_wrappers:K.config.transparent_wrappers??[]},void 0,L._testAfterPolicyRename)}catch(xe){throw nr(J.configTarget,de),xe}let ue=await no(_,O,Hn(),L);if(!ue.ok)return nr(J.configTarget,de),ue;let ve=jy(oe.dirs,L,J.filesystemScope);if(!ve.ok){nr(J.configTarget,de);let xe=await no(_,O,Hn(),L);if(!xe.ok)return{ok:!1,errors:[...ve.result.errors,...xe.errors],entries:xe.entries};return ve.result}return ue}function Ny(_,I,O){let L=I.flatMap((oe)=>u.test(oe)?[]:["--delete-source can only delete local rulebook sources"]),J=I.map((oe)=>Mi(_,oe)),K=L.length>0?[]:J.flatMap((oe)=>qd(oe,O)),ne=[...L,...K];return ne.length>0?{ok:!1,result:{ok:!1,errors:ne,entries:[]}}:{ok:!0,dirs:J}}function qd(_,I){let O=by(_),L=i(I,O),J=pe(L);if(!J)return[`Local rulebook source directory not found: ${_}`];let K=J.find((ne)=>ne.name==="rulebook.json");if(!K)return[`Local rulebook source directory is missing rulebook.json: ${_}`];if(K.kind!=="file")throw new r(I.label);if(n(i(I,Mi(O,"rulebook.json"))),J.length>1)return[`Local rulebook source directory contains extra files: ${_}. delete manually if you really want to remove the directory.`];return[]}function jy(_,I,O){let L=_.flatMap((J)=>{try{if(!pe(i(O,J)))return[];let K=qd(J,O);if(K.length>0)return K;return Fy(J,I,O),[]}catch(K){return[`Failed to delete local rulebook source ${J}: ${K instanceof Error?K.message:String(K)}`]}});return L.length>0?{ok:!1,result:{ok:!1,errors:L,entries:[]}}:{ok:!0}}function Fy(_,I,O){if(I._testDeleteLocalSourceDir){I._testDeleteLocalSourceDir(_);return}j(i(O,Mi(_,fe))),st(i(O,_))}function nr(_,I){if(I===null){j(_);return}g(_,I)}function tr(_){return{ok:!1,errors:[_ instanceof Error?_.message:String(_)],entries:[]}}var Hy=".safety-net.json",My="~/.cc-safety-net/config.json";async function Wd(_,I){return[await zd(_,{legacyPath:Ys({cwd:I.cwd}),configPath:U(I.cwd),defaultRulebookName:"project-rules",migratedFrom:Hy,cleanup:I.cleanup,syncOptions:{cwd:I.cwd}}),await zd(_,{legacyPath:ur(_),configPath:G(_),defaultRulebookName:"user-rules",migratedFrom:My,cleanup:I.cleanup,syncOptions:{cwd:I.cwd,global:!0}})].every((L)=>L)?0:1}async function zd(_,I){let O=wn(_,I.syncOptions),L=i(O.filesystemScope,I.legacyPath),J=n(L);if(J===null)return console.log(`No legacy config found at ${I.legacyPath}`),!0;let K=Gy(J);if(!K.ok){for(let Pe of K.errors)console.error(Pe);return!1}let ne=m(O.configTarget);if(ne.errors.length>0){for(let Pe of ne.errors)console.error(Pe);return!1}let oe=ne.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},de=By(Vd(I.configPath),oe.rules,I.defaultRulebookName,I.migratedFrom,O.filesystemScope),ue=ro(Vd(I.configPath),de,"rulebook.json"),ve=i(O.filesystemScope,ue),xe=[Jd(O.configTarget),Jd(ve)],Se=await Uy(_,I,O.configTarget,ve,de,K.config.rules,oe.rules.includes(de)?oe.rules:[...oe.rules,de],oe.overrides??{},oe.transparent_wrappers??[]);if(!Se.ok){zy(xe);for(let Pe of Se.errors)console.error(Pe);return!1}if(!I.cleanup)return console.log(`Migrated legacy config at ${I.legacyPath}. Legacy file is no longer used.`),!0;if(!Vy(O.configTarget,ve,de,I.migratedFrom,K.config.rules))return console.error(`Migration cleanup verification failed for ${I.legacyPath}`),!1;return j(L),console.log(`Deleted legacy config at ${I.legacyPath}`),!0}async function Uy(_,I,O,L,J,K,ne,oe,de){try{return bn(O,{version:1,rules:ne,overrides:oe,transparent_wrappers:de}),bn(L,qy(J,I.migratedFrom,K)),await to(_,I.syncOptions)}catch(ue){return{ok:!1,errors:[ue instanceof Error?ue.message:String(ue)]}}}function Gy(_){try{let I=JSON.parse(_),O=go(I);if(O.errors.length>0)return{ok:!1,errors:O.errors};return{ok:!0,config:{version:1,rules:I.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function By(_,I,O,L,J){let K=I.find((ne)=>Jy(i(J,ro(_,ne,"rulebook.json")))===L);if(K)return K;if(n(i(J,ro(_,O,"rulebook.json")))===null)return O;for(let ne=2;;ne++){let oe=`${O}-${ne}`;if(n(i(J,ro(_,oe,"rulebook.json")))===null)return oe}}function qy(_,I,O){return{rulebook_version:1,name:_,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:I,allowed_commands:[...new Set(O.map((L)=>L.command))],rules:O,tests:O.map((L)=>({command:[L.command,L.subcommand,L.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:L.name}))}}function Vy(_,I,O,L,J){if(!m(_).config?.rules.includes(O))return!1;try{let ne=n(I);if(ne===null)return!1;let oe=JSON.parse(ne);return oe.migrated_from===L&&JSON.stringify(oe.rules)===JSON.stringify(J)}catch{return!1}}function Jd(_){return{target:_,content:n(_)}}function zy(_){for(let I of _){if(I.content===null){j(I.target);continue}g(I.target,I.content)}}function Jy(_){let I=n(_);if(I===null)return null;try{let O=JSON.parse(I);return typeof O.migrated_from==="string"?O.migrated_from:null}catch{return null}}import{mkdir as Wy,readFile as Ky,writeFile as Yy}from"node:fs/promises";import{dirname as Zy,join as Xy}from"node:path";var Qy=86400000,ev=604800000;async function Yd(_,I=Date.now()){if(_.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let O=He(_);if(!O)return null;let L=Xy(O,".cc-safety-net","update-check.json"),J=await nv(L,I);if(!J.lastCheck||I-J.lastCheck>Qy){let oe=await Un();if(J.lastCheck=I,oe.latestVersion)J.latestVersion=oe.latestVersion;if(!await Kd(L,J))return null;if(oe.error)return null}let K=J.latestVersion,ne=un();if(!K||!ko(K,ne))return null;if(J.notifiedVersion===K&&J.notifiedAt!==void 0&&I-J.notifiedAt<ev)return null;if(J.notifiedVersion=K,J.notifiedAt=I,!await Kd(L,J))return null;return`UPDATE_AVAILABLE: cc-safety-net v${K} is available (running v${ne}). 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 nv(_,I){let O=await Ky(_,"utf8").then((K)=>JSON.parse(K)).catch(()=>{return});if(!O||typeof O!=="object"||Array.isArray(O))return{};let L=O,J=(K)=>typeof K==="number"&&Number.isFinite(K)&&K<=I?K:void 0;return{lastCheck:J(L.lastCheck),latestVersion:typeof L.latestVersion==="string"?L.latestVersion:void 0,notifiedVersion:typeof L.notifiedVersion==="string"?L.notifiedVersion:void 0,notifiedAt:J(L.notifiedAt)}}async function Kd(_,I){return Wy(Zy(_),{recursive:!0,mode:448}).then(()=>Yy(_,JSON.stringify(I),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as tv,resolve as Gi}from"node:path";var Zd="CC Safety Net Config",rv="═".repeat(Zd.length),ov="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",iv=new Set(["rule.json","rule.lock","cache"]);function Xd(_,I={}){try{return sv(_,I)}catch(O){if(O instanceof r)return console.error(O.message),1;throw O}}function sv(_,I){let O=I.cwd??process.cwd(),L=Z(_,{cwd:O}),J=ur(_),K=bs(O),ne=Gi(O,me),oe=i(L.userScope,J),de=i(L.projectScope,K),ue=!1,ve=!1,xe=[],Se=[],Pe=av(i(L.projectScope,ne));if(cv(),n(L.userConfigTarget)!==null){let we=Mn(L.userConfigTarget);if(we.errors.push(...H(L.userConfigPath,L.userScope)),xe.push({scope:"User",path:L.userConfigPath,result:we,schema:"rules",target:L.userConfigTarget}),we.errors.length>0)ue=!0}if(n(oe)!==null)if(ve=!0,n(L.userConfigTarget)!==null)Se.push(oo("user","cleanup"));else{let we=ho(oe);if(xe.push({scope:"User",path:J,result:we,schema:"legacy",inactive:!0,target:oe}),Se.push(oo("user",we.errors.length>0?"fix-or-delete":"migrate")),we.errors.length>0)ue=!0}if(n(L.projectConfigTarget)!==null){let we=Mn(L.projectConfigTarget);if(we.errors.push(...H(L.projectConfigPath,L.projectScope)),xe.push({scope:"Project",path:Gi(L.projectConfigPath),result:we,schema:"rules",target:L.projectConfigTarget}),we.errors.length>0)ue=!0;if(n(de)!==null)ve=!0,Se.push(oo("project","cleanup"))}else if(n(de)!==null){ve=!0,ue=!0;let we=ho(de);xe.push({scope:"Project",path:Gi(K),result:we,schema:"legacy",inactive:!0,target:de}),Se.push(oo("project",we.errors.length>0?"fix-or-delete":"migrate"))}if(Pe?.result.errors.length)ue=!0;if(xe.length===0&&!Pe)return console.log(`
275
- No config files found. Using built-in rules only.`),0;for(let we of xe)if(we.inactive)uv(we.scope,we.path,we.result);else if(we.result.errors.length>0)pv(we.scope,we.path,we.result.errors);else{if(we.schema==="rules"&&gv(we.target))console.log(`
276
- Added $schema to ${we.scope.toLowerCase()} config.`);dv(we.scope,we.path,we.result,we.schema)}for(let we of Se)console.error(`
277
- ${nn.red(we)}`);if(Pe)if(Pe.result.errors.length>0)mv(Pe.path,Pe.result.errors);else fv(Pe.path,Pe.result);if(ue)return console.error(`
278
- Config validation failed.`),1;return console.log(ve?`
263
+ `)}function _d(P,O){return O.map((D)=>P==="install"&&D.target==="kimi-code"&&D.unavailableReason==="already installed"?{...D,available:!0,unavailableReason:void 0,label:`${D.label} (global hook installed)`}:D)}function jy(P,O){if(P.selectKimiInstallMethod)return P.selectKimiInstallMethod();if(!Ni(P.input,P.output))return Promise.resolve("global-hook");return Dc({input:P.input,output:P.output,globalHookInstalled:Kt({environment:O,cwd:process.cwd()}).status==="configured"})}async function Fd(P,O,D,j=!1,J){let Y=Oy[O];if(P==="install")Y?.beforeInstall?.(D,j);if(P==="uninstall")Y?.beforeUninstall?.(D);if(Dy(O))return Ty(P,O,D,j);if(Ly(O))return $y(P,O,D,j);if(P==="uninstall")return O==="opencode"?_y(D):Iy(O,D);return[await Ay(O,D,j,J),await Y?.afterInstall?.(D)].filter(Boolean).join(`
264
+ `)}function Fy(P){let O=gn({label:"update"},P).errors[0];if(O)throw Error(O)}async function Hy(P,O=St){let D=await Ld(P,O),j=to(qt(P),"installed-plugins");return{targets:Gi([...D.hooks.filter((Y)=>Y.platform!=="copilot-cli"&&Y.detected).map((Y)=>Y.platform),...[_r,Da,Oa].flatMap((Y)=>ro(to(j,...Y))?["copilot-cli"]:[]),...Ir(P,Ki)?["claude-code"]:[],...Wi(D.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:D.codexPluginListOutput}}async function My(P){let O=c(),D=P.output??process.stdout,j=(P.scriptPath??process.argv[1]??"").split(/[\\/]/),J=j.find((Ie)=>/^bunx-\d+-/.test(Ie)),Y=J!==void 0||j.includes("_npx")?null:(P.checkLatestVersion??Gn)(),re=async()=>{let Ie=Y&&await Y;if(Ie?.updateAvailable)D.write(`
265
+ Update available: cc-safety-net ${Ie.currentVersion} → ${Ie.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
266
+ `)},ie=Hy(O,P.fetchVersion??St).then(async(Ie)=>{let Ee=new Set(Ie.targets);return{targets:Ie.targets,codexPluginListOutput:Ie.codexPluginListOutput,available:new Map(await Promise.all($n.filter((qe)=>Ee.has(qe.target)&&Pd.has(qe.target)).map(async(qe)=>[qe.target,await tr(qe.probeCommand)])))}}),de=await Ut(P.showBanner??!0,()=>({ready:ie,finish:()=>ie}),()=>Mt({input:P.input??process.stdin,output:D}),{loadingMessage:"Checking installed integrations…",output:D}),fe=await Promise.resolve().then(()=>(pd(O.tmpdir,process.platform,J),null)).catch((Ie)=>or(Ie));if(de.targets.length===0){if(D.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),fe!==null)console.error(fe);return await re(),fe===null?0:1}let we=de.targets.some((Ie)=>Ed.has(Ie))?await Promise.resolve().then(()=>(no(O),null)).catch((Ie)=>or(Ie)):null,Ce=await Rr(Promise.all(de.targets.map((Ie)=>{if(Pd.has(Ie)&&!de.available.get(Ie))return Promise.resolve({message:`${mn(Ie)} not found; skipped`,failed:!1});if(we!==null&&Ed.has(Ie))return Promise.resolve({message:we,failed:!0});return Fd("install",Ie,O,!0,de.codexPluginListOutput).then((Ee)=>({message:Ee,failed:!1}),(Ee)=>({message:or(Ee),failed:!0}))})),{loadingMessage:`Updating ${de.targets.length} integration${de.targets.length===1?"":"s"}…`,output:D}),Se=fe===null?Ce:[...Ce,{message:fe,failed:!0}];return Se.forEach((Ie)=>Ie.failed?console.error(Ie.message):D.write(`${Ie.message}
267
+ `)),await re(),Se.some((Ie)=>Ie.failed)?1:0}function Yi(P,O={}){return Promise.resolve().then(()=>Fy(P)).then(()=>My(O)).catch((D)=>(console.error(or(D)),1))}async function ir(P,O,D={}){try{let j=c(),J=await Ut(!0,()=>Ey(j,P,O,D),()=>Mt({input:D.input??process.stdin,output:D.output??process.stdout}),{loadingMessage:P==="install"?"Checking available integrations…":"Checking installed integrations…",output:D.output??process.stdout});if(!J)return(D.output??process.stdout).write(`Cancelled: nothing was ${P}ed.
268
+ `),0;if(J==="update")return(D.runUpdate??(()=>Yi([],{fetchVersion:D.fetchVersion,input:D.input,output:D.output,showBanner:!1})))();let Y=D.output??process.stdout;return await Xc(J,async(re)=>{if(re==="kimi-code"&&P==="install"){let de=await jy(D,j);if(de===null){Y.write(`Cancelled: Kimi Code integration was not installed.
269
+ `);return}if(de==="plugin"){Y.write(`${Ny(j)}
270
+ `);return}}let ie=await Rr(Fd(P,re,j),{loadingMessage:`${P==="install"?"Installing":"Uninstalling"} ${mn(re)} integration…`,output:Y});Y.write(`${ie}
271
+ `)}),0}catch(j){return console.error(or(j)),1}}function or(P){let O=P instanceof Error?P.message:String(P),D=typeof P==="object"&&P!==null&&"code"in P?P.code:null;if(D==="EACCES"||D==="EPERM")return`${O}
272
+ Check file permissions for the target config file and parent directory.`;if(D==="ENOENT")return`${O}
273
+ Check that the target config path and parent directory exist.`;if(D==="ENOTDIR")return`${O}
274
+ Check that every parent path component is a directory.`;return O}import{mkdirSync as Jy}from"node:fs";import{dirname as zy}from"node:path";import{createInterface as Ky}from"node:readline";import{existsSync as Md,readFileSync as Uy}from"node:fs";function vt(P,O){let D=tt(P,O);return{policy:D.policy,errors:ce(Xe(D.issues,et,(j)=>j.kind==="custom")," "," ")}}function sr(P,O){return vt(P,O).errors}function Hd(P,O){return{"safety.level":P.safety.level,...Zi("safety.overrides",P.safety.overrides),"workflow.worktree_mode":String(P.workflow.worktree_mode),"destructive_command_protection.enabled":String(P.destructive_command_protection.enabled),...Zi("destructive_command_protection.overrides",P.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Xi(P.destructive_command_protection.allow_paths),"secret_protection.enabled":String(P.secret_protection.enabled),...Zi("secret_protection.overrides",P.secret_protection.overrides),"secret_protection.deny_paths":Xi(P.secret_protection.deny_paths),"secret_protection.allow_paths":Xi(P.secret_protection.allow_paths),...O?{"audit.retention_days":String(P.audit.retention_days)}:{}}}function oo(P,O,D){let j=Hd(P,D),J=Hd(O,D);return[...new Set([...Object.keys(j),...Object.keys(J)])].flatMap((Y)=>j[Y]===J[Y]?[]:[{field:Y,before:j[Y],after:J[Y]}])}function ar(P,O){let D=l(P,O);if(!Md(D))return{baseline:C(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,P.home),diagnostics:[]};let j=bt(D),J=vt(j.value,P.home);return{baseline:J.policy,diagnostics:j.errors.length>0?j.errors:J.errors}}function bt(P){if(!Md(P))return{errors:[`${P}: file not found`]};try{return{value:JSON.parse(Uy(P,"utf-8")),errors:[]}}catch(O){let D=O instanceof Error?O.message:String(O);return{errors:[`${P}: ${O instanceof SyntaxError?`Invalid JSON: ${D}`:D}`]}}}function io(P,O){let D=Gy(P)?P:{};return{version:O.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((j)=>D[j]!==void 0).map((j)=>[j,D[j]]))}}function Zi(P,O){return Object.fromEntries(Object.entries(O).flatMap(([D,j])=>j===void 0?[]:[[`${P}.${D}`,String(j)]]))}function Xi(P){return P.length===0?"(none)":P.join(", ")}function Gy(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{chmodSync as By,existsSync as Ud,mkdirSync as qy,readFileSync as Gd}from"node:fs";import{dirname as Vy}from"node:path";function Bd(P,O={}){let D=l(P,O);if(!Ud(D))return{path:D,exists:!1,raw:"",policy:M(),errors:[]};let j=Gd(D,"utf-8");if(!j.trim())return{path:D,exists:!0,raw:j,policy:M(),errors:["Config file is empty"]};try{let J=vt(JSON.parse(j),P.home);return{path:D,exists:!0,raw:j,policy:J.policy,errors:J.errors}}catch(J){return{path:D,exists:!0,raw:j,policy:M(),errors:[`Invalid JSON: ${J instanceof Error?J.message:String(J)}`]}}}function Hn(P,O,D={}){let j=l(P,D),J=vt(O,P.home);if(J.errors.length>0)return{path:j,policy:M(),errors:J.errors};let Y=J.policy;return qy(Vy(j),{recursive:!0,mode:448}),g(se(j),`${JSON.stringify(Y,null,2)}
275
+ `,384),By(j,384),{path:j,policy:Y,errors:[]}}function qd(P,O){let D=vt(O,P.home);if(D.errors.length>0)return{errors:D.errors};return{preview:Le(D.policy,P.env),errors:[]}}function Vd(P,O={}){let D=l(P,O);if(!Ud(D))return Hn(P,te,O);let j=Gd(D,"utf-8");if(!j.trim())return Hn(P,te,O);try{return Hn(P,C(JSON.parse(j),P.home),O)}catch{return Hn(P,te,O)}}var Jd=new Set(["check","apply"]),zd="(unset)";async function Wd(P,O,D={}){let j=gn({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},O),J=j.positionals[0],Y=[...j.errors,...J&&!Jd.has(J)?[`Unknown policy subcommand: ${J}`]:[],...J&&Jd.has(J)&&!j.positionals[1]?[`policy ${J} requires a file`]:[],...j.positionals.slice(2).map((qe)=>`Unexpected policy argument: ${qe}`)];if(Y.length>0){for(let qe of Y)console.error(qe);return 1}let re=j.positionals[1];if(!J||!re)return Lt(mr,console.error),1;let ie=D.cwd??process.cwd(),de=j.flags.global?l(P):h(ie);if(!j.flags.global&&L(P,{cwd:ie}))return console.error(`${de} is the user policy, not a project policy; use --global for the user scope, or run from a project directory`),1;let fe=bt(re),we=[...fe.errors,...sr(fe.value,P.home).map((qe)=>`${re}: ${qe}`),...!j.flags.global&&Zy(fe.value)&&fe.value.audit!==void 0?[`${re}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(we.length>0){for(let qe of we)console.error(qe);return 1}let Ce=C(fe.value,P.home);if(console.log(`Scope: ${j.flags.global?"user":"project"} (${de})`),console.log(`Proposal: ${re}`),j.flags.global)Kd(C(bt(de).value,P.home),Ce,!0);if(!j.flags.global){let qe=ar(P).baseline;console.log("Effective policy (user + project merged):"),Kd(ee(qe,ue(bt(de).value,P.home).policy).policy,ee(qe,ue(fe.value,P.home).policy).policy,!1)}if(J==="check")return 0;let Se=D.input??process.stdin,Ie=D.output??process.stdout;if(!Se.isTTY||!Ie.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${re}${j.flags.global?" --global":""}`),1;if(!await Wy(`Apply this policy to ${de}? [y/N] `,Se,Ie))return console.log("Cancelled; nothing was written."),0;return Yy(P,de,fe.value,Ce,j.flags.global),console.log(`Policy applied: ${de}`),0}function Wy(P,O,D){let j=Ky({input:O,output:D,terminal:!1});return new Promise((J)=>{j.once("close",()=>J(!1)),j.question(P,(Y)=>{J(/^y(es)?$/i.test(Y.trim())),j.close()})})}function Yy(P,O,D,j,J){if(J){Hn(P,j);return}Jy(zy(O),{recursive:!0}),wn(O,io(D,j))}function Kd(P,O,D){let j=oo(P,O,D);if(j.length===0){console.log("No changes.");return}console.log(`Changes (${j.length}):`);for(let J of j)console.log(` ${J.field}: ${J.before??zd} -> ${J.after??zd}`)}function Zy(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{join as db}from"node:path";var Yd="# 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- `caffeinate`, `exec`, `nice`, `nohup`, `setsid`, `stdbuf`, `time`, and `timeout` are built-in transparent wrappers and need no configuration. Configure only other 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 so(P,O){if(!P.ok){nu(P);return}Qd(P,O)}function Xd(P,O,D){if(P.ok)console.log(D);if(!P.add){so(P,`Added rulebook source: ${O}`);return}if(!P.ok){nu(P);return}if(P.add.added.length>0)console.log(`Added ${P.add.added.length} ${P.add.added.length===1?"rulebook":"rulebooks"} from ${P.add.source} at ${P.add.ref}:`),P.add.added.forEach((j)=>{console.log(` - ${j}`)});if(P.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${P.add.source} at ${P.add.ref}: ${P.add.alreadyConfigured.join(", ")}`);if(P.add.commits.length>0)console.log(`Vendored at ${P.add.commits.map((j)=>j.slice(0,7)).join(", ")}.`);Qd(P,"Rule config updated.")}function Qd(P,O){for(let D of P.changes??[])console.log(D);console.log(O),console.log(""),Xy(P.entries)}function Xy(P){if(P.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${P.length}):`);for(let O of P)console.log(` - ${O.name} ${O.version} (${Qy(O.ruleCount)})`),console.log(` Source: ${O.spec}`)}function Qy(P){return`${P} ${P===1?"rule":"rules"}`}function eu(P){wt("Active sources",P.rulebooks,(O)=>[`[${O.source}] ${O.name} ${O.version}`,` Source: ${O.spec}`]),wt("Active rules",P.rules,(O)=>[`[${nv(P,O.name)}] ${O.name}`,...ev(O),` Reason: ${O.reason}`]),wt("Disabled rules",Zd(P,"off"),(O)=>[O.key]),wt("Reason overrides",Zd(P,"reason"),(O)=>[O.key,` Reason: ${O.value.reason}`]),wt("Transparent wrappers",P.transparent_wrappers,(O)=>[O]),wt("Issues",P.errors,(O)=>[O]),wt("Warnings",P.warnings,(O)=>[O])}function wt(P,O,D){if(O.length===0){console.log(`${P}: (none)`);return}console.log(`${P} (${O.length}):`);for(let j of O){let[J,...Y]=D(j);console.log(` - ${J}`);for(let re of Y)console.log(` ${re}`)}}function ev(P){if(!P.match)return[` Command: ${P.subcommand?`${P.command} ${P.subcommand}`:P.command}`,` Block args: ${P.block_args.join(", ")}`];return[` Command: ${[P.command,...P.match.command_path].join(" ")}`,...P.match.any_args?[` Any args: ${P.match.any_args.join(", ")}`]:[],...P.match.exclude_args?[` Exclude args: ${P.match.exclude_args.join(", ")}`]:[]]}function nv(P,O){return P.rulebooks.find((D)=>D.rules.includes(O))?.source??"project"}function Zd(P,O){return Object.entries({...P.userConfig?.overrides,...P.projectConfig?.overrides}).filter((D)=>{if(O==="off")return D[1]==="off";return!!D[1]&&typeof D[1]==="object"}).map(([D,j])=>({key:D,value:j}))}function nu(P){for(let O of P.errors)console.error(O)}import{dirname as Su,join as go}from"node:path";import{join as rs,resolve as fv}from"node:path";function Qi(P){let O=m(P);if(O.errors.length>0)return{ok:!1,result:{ok:!1,errors:O.errors,entries:[]}};return{ok:!0,config:O.config??ut}}function tu(P){wn(P,{version:1,rules:[],overrides:{},transparent_wrappers:[]})}function ru(P){wn(P,{rulebook_version:1,name:"example-rules",version:"1.0.0",description:"Project-specific CC Safety Net rules.",author:"project",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as uo}from"node:path";var tv="custom.";function ao(P){if(P.rulebook_version!==2)return[];let O=P.rules.map((D)=>({name:D.name,command:D.command,block_args:[],match:D.match,reason:D.reason,intent:D.intent}));return(P.tests??[]).flatMap((D,j)=>{let J=es(y(D.command));if(J.length===0)return[`tests[${j}]: could not parse fixture command: ${D.command}`];let Y=J.reduce((re,ie)=>re??A(ie,O)?.id.slice(tv.length),void 0);if(D.expect==="blocked"){if(Y===D.rule)return[];let re=Y?`"${Y}" matched first`:"no rule matched";return[`tests[${j}]: expected "${D.rule}" to block "${D.command}" but ${re}`]}return Y?[`tests[${j}]: expected "${D.command}" to be allowed but "${Y}" matched`]:[]})}function es(P){return P.nodes.flatMap((O)=>{if(O.kind==="group"||O.kind==="function")return es(O.body);if(O.kind!=="command")return[];let D=ve(ne(O.dialect,O.words)).words.map(t);return[...D.length>0?[D]:[],...O.nested.flatMap((j)=>es(j))]})}var lo=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function co(P={}){return{requests:0,responseBytes:0,maxRequests:P.maxRequests??lo.maxRequests,maxResponseBytes:P.maxResponseBytes??lo.maxResponseBytes}}function Mn(P){return{controller:new AbortController,budget:co(),resolveUrl:P}}function ou(P){return P instanceof Error&&P.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function iu(P){if(P.requests>=P.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.requests++}function su(P,O){if(O>P.maxResponseBytes-P.responseBytes)throw P.responseBytes+=O,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.responseBytes+=O}var cu=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function au(P,O,D=v(uo(uo(O)),"rules policy"),j=Mn()){if(S(P))return sv(P,j);return iv(P,O,D)}async function du(P,O,D,j,J,Y){if(!S(P))return au(P,O,D,j);let re=J?null:rv(P,O,D);if(re)return re;if(!J&&!Y)throw Error(`${P} is not vendored; run rule update ${P} to vendor it`);return au(P,O,D,j)}function rv(P,O,D=v(uo(uo(O)),"rules policy")){let j=N(P),J=F(O,j.name),Y=r(i(D,J));if(Y===null)return null;let re=le(ns(Y,`Invalid rulebook ${J}.`));if(re.name!==j.name)throw Error(`rulebook name "${re.name}" in ${J} must match "${j.name}"`);return{spec:P,rulebook:re,content:Y}}async function uu(P,O={}){if(!Z(P))throw Error(`Invalid GitHub repository source: ${P}`);let[D,j]=P.split("/");if(!D||!j)throw Error(`Invalid GitHub repository source: ${P}`);if(O.ref!==void 0&&!ae(O.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${O.ref}`);let J=O.operation??Mn(),Y=O.ref??await ov(D,j,P,J),re=await fu(D,j,Y,P,J),ie=await po(`https://api.github.com/repos/${D}/${j}/git/trees/${re}?recursive=1`,"tree",J),de=ie.response;if(!de.ok)throw Error(`Failed to inspect ${P}: GitHub tree returned ${de.status}`);let fe=JSON.parse(ie.content);if(!Array.isArray(fe?.tree))throw Error(`Failed to inspect ${P}: unexpected GitHub tree response`);let we=fe.tree,Ce=[...new Set(we.flatMap((Se)=>{if(!Se||typeof Se!=="object")return[];let Ie=Se;if(Ie.type!=="blob"||typeof Ie.path!=="string")return[];let Ee=Ie.path.match(ct);return Ee?.[1]?[Ee[1]]:[]}))].sort();if(Ce.length===0)throw Error(`No rulebooks found in ${P} under ${he}/`);return{source:P,owner:D,repo:j,ref:Y,commit:re,names:Ce}}async function ov(P,O,D,j){let J=await po(`https://api.github.com/repos/${P}/${O}`,"metadata",j),Y=J.response;if(!Y.ok)throw Error(`Failed to inspect ${D}: GitHub returned ${Y.status}`);let ie=JSON.parse(J.content)?.default_branch;if(typeof ie!=="string"||ie==="")throw Error(`Failed to inspect ${D}: missing default branch`);if(!ae(ie))throw Error(`GitHub returned an invalid default branch: ${ie}`);return ie}function iv(P,O,D){lt(P);let j=F(O,P),J=r(i(D,j));if(J===null)throw Error(`Rulebook source not found: ${P}`);let Y=pu(ns(J,"Invalid local rulebook source."));if(Y.name!==P)throw Error(`rulebook name "${Y.name}" must match local source "${P}"`);return{spec:P,rulebook:Y,content:J}}async function sv(P,O){let D=N(P),j=await fu(D.owner,D.repo,D.ref,P,O),J=await po(`https://raw.githubusercontent.com/${D.owner}/${D.repo}/${j}/${D.path}`,"raw",O),Y=J.response;if(!Y.ok)throw Error(`Failed to fetch ${P}: GitHub raw returned ${Y.status}`);let re=J.content,ie=pu(ns(re,"Invalid GitHub rulebook response."));if(ie.name!==D.name)throw Error(`rulebook name "${ie.name}" must match GitHub source "${D.name}"`);return{spec:P,rulebook:ie,content:re}}function pu(P){let O=le(P),D=ao(O);if(D.length>0)throw Error(D.join("; "));return O}function ns(P,O){try{return JSON.parse(P)}catch{throw Error(O)}}async function fu(P,O,D,j,J){let Y=await po(`https://api.github.com/repos/${P}/${O}/commits/${encodeURIComponent(D)}`,"commit",J),re=Y.response;if(!re.ok)throw Error(`Failed to resolve ${j}: GitHub returned ${re.status}`);let ie=JSON.parse(Y.content);if(typeof ie?.sha!=="string"||ie.sha==="")throw Error(`Failed to resolve commit for ${j}`);return ie.sha}async function av(P,O,D={}){if(D.signal?.aborted)throw D.signal.reason;let j=D.budget??co(),J=new AbortController,Y=()=>J.abort(D.signal?.reason);D.signal?.addEventListener("abort",Y,{once:!0});let re=!1,ie=setTimeout(()=>{if(J.signal.aborted)return;re=!0,J.abort()},D.timeoutMs??cu.timeoutMs);try{if(D.signal?.aborted)throw D.signal.reason;iu(j);let de=await fetch(P,{signal:J.signal,redirect:"error"});if(!de.ok)return mu(de),{response:de,content:""};return{response:de,content:await lv(de,O,j,()=>J.abort())}}catch(de){if(re)throw Error("GitHub request timed out",{cause:de});if(D.signal?.aborted)throw D.signal.reason;throw de}finally{clearTimeout(ie),D.signal?.removeEventListener("abort",Y)}}function po(P,O,D){return av(D.resolveUrl?.(P)??P,O,{budget:D.budget,signal:D.controller.signal})}async function lv(P,O,D=co(),j){let J=cu[`${O}Bytes`],Y=Number(P.headers.get("content-length"));if(Number.isFinite(Y)&&Y>J)throw mu(P),Error(`GitHub ${O} response exceeds ${J} bytes`);if(!P.body)return"";let re=P.body.getReader(),ie=[],de=0;while(!0){let fe=await re.read();if(fe.done)break;try{su(D,fe.value.byteLength)}catch(we){throw j?.(),lu(re),we}if(de+=fe.value.byteLength,de>J)throw j?.(),lu(re),Error(`GitHub ${O} response exceeds ${J} bytes`);ie.push(Buffer.from(fe.value))}return Buffer.concat(ie,de).toString("utf-8")}function mu(P){if(!P.body)return;gu(()=>P.body?.cancel())}function lu(P){gu(()=>P.cancel())}function gu(P){try{Promise.resolve(P()).catch(()=>{})}catch{}}var cv=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function hu(P,O){let D=bu(P.rules,O);if(D.length>0)return{ok:!0,specs:D};return vu(P.rules,O)}function yu(P,O){let D=bu(P,O);if(D.length>0)return{ok:!0,specs:D};let j=uv(P,O);if(j.length>0)return{ok:!0,specs:j};let J=pv(P,O);if(!J.ok)return J;if(J.specs.length>0)return{ok:!0,specs:J.specs};return vu(P,O)}function vu(P,O){let D=P.filter((j)=>ts(j)?.name===O);if(D.length===1)return{ok:!0,specs:D};return dv(O,D)}function dv(P,O){return{ok:!1,result:{ok:!1,errors:O.length===0?[`No configured rulebook matches ${P}`]:[`Ambiguous rulebook match ${P}: ${O.join(", ")}`],entries:[]}}}function bu(P,O){return P.filter((D)=>D===O)}function uv(P,O){let D=O.match(cv),j=D?.[1],J=D?.[2],Y=D?.[3];if(!j||!J||!Y||!ae(Y))return[];return wu(P,(re)=>re.owner===j&&re.repo===J&&re.ref===Y)}function pv(P,O){if(!Z(O))return{ok:!0,specs:[]};let[D,j]=O.split("/"),J=wu(P,(re)=>re.owner===D&&re.repo===j);if(new Set(J.map((re)=>ts(re)?.ref).filter((re)=>!!re)).size<2)return{ok:!0,specs:J};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${O}. Use an explicit ref:`,` cc-safety-net rule remove ${O}#<ref>`],entries:[]}}}function ts(P){try{return N(P)}catch{return null}}function wu(P,O){return P.filter((D)=>{let j=ts(D);return j?O(j):!1})}async function mo(P,O={}){let D=os(O);return mv(P,D,await fo(P,D,Mn()))}function mv(P,O,D){if(!D.ok)return D;let j=kn(P,O),J=[...new Set(B(j.configPath,j.filesystemScope))];if(J.length===0)return D;return{ok:!1,errors:J,entries:D.entries}}async function fo(P,O,D,j={},J=new Set,Y=new Set){try{let re=kn(P,O),ie=Qi(re.configTarget);if(!ie.ok)return ie.result;let de=ie.config,fe=O.only?hu(de,O.only):{ok:!0,specs:de.rules};if(!fe.ok)return fe.result;let we=new Set([...O.refresh?fe.specs:[],...J]),Ce=(rn)=>du(rn,re.configDir,re.filesystemScope,D,we.has(rn),!O.refresh||we.has(rn)),Se=await Rv(de.rules,O.refresh?(rn)=>Ce(rn).then((fn)=>({ok:!0,item:fn})).catch((fn)=>{if(ou(fn))throw fn;return{ok:!1,spec:rn,message:fn instanceof Error?fn.message:String(fn)}}):async(rn)=>({ok:!0,item:await Ce(rn)}),D),Ie=Se.filter((rn)=>!rn.ok),Ee=Se.filter((rn)=>rn.ok).map((rn)=>rn.item),qe=Ee.flatMap((rn)=>gv(rn,de.rules)),Fe=Ee.flatMap((rn)=>hv(rn,Y,re)),en=new Set([...qe,...Fe].map((rn)=>rn.spec)),on=[...Ie,...qe,...Fe],sn=[],an=vv(sn,()=>Ee.flatMap((rn)=>en.has(rn.spec)||on.length>0&&Y.has(rn.spec)?[]:yv(rn,re,j,sn)));return{ok:on.length===0,errors:on.map((rn)=>`Failed to update ${rn.spec}: ${rn.message}`),entries:Ee.map(wv),changes:an}}catch(re){return cr(re)}}function gv(P,O){if(!S(P.spec))return[];let D=Ne(P.spec),j=O.filter((J)=>J!==P.spec&&Ne(J).toLowerCase()===D.toLowerCase());if(j.length===0)return[];return[{ok:!1,spec:P.spec,message:`rulebook name "${D}" is also claimed by ${j.join(", ")}; rename one of them`}]}function hv(P,O,D){if(!O.has(P.spec)||!S(P.spec))return[];let j=F(D.configDir,P.rulebook.name),J=r(i(D.filesystemScope,j));if(J===null||J===P.content)return[];return[{ok:!1,spec:P.spec,message:`${j} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function yv(P,O,D,j){if(!S(P.spec))return[];let J=F(O.configDir,P.rulebook.name),Y=i(O.filesystemScope,J),re=r(Y);if(re===P.content)return[];return j?.push({target:Y,previous:re}),g(Y,P.content,void 0,D._testAfterPolicyRename),bv(P,re)}function vv(P,O){try{return O()}catch(D){for(let j of[...P].reverse()){if(j.previous===null){H(j.target);continue}g(j.target,j.previous)}throw D}}function bv(P,O){if(O===null)return[`Vendored ${P.spec} (${P.rulebook.version})`];let D=xe(O),j="problem"in D?null:D.rulebook,J=new Map(j?.rules.map((re)=>[re.name,JSON.stringify(re)])??[]),Y=new Set(P.rulebook.rules.map((re)=>re.name));return[`Updated ${P.spec} (${j?.version??"unreadable"} -> ${P.rulebook.version})`,...[...Y].filter((re)=>!J.has(re)).map((re)=>` + ${re}`),...[...J.keys()].filter((re)=>!Y.has(re)).map((re)=>` - ${re}`),...P.rulebook.rules.filter((re)=>{let ie=J.get(re.name);return ie!==void 0&&ie!==JSON.stringify(re)}).map((re)=>` ~ ${re.name}`)]}function wv(P){return{spec:P.spec,name:P.rulebook.name,version:P.rulebook.version,ruleCount:P.rulebook.rules.length}}async function ku(P,O,D={}){return kv(P,O,Ev(D),Mn())}async function kv(P,O,D,j,J={}){let Y=null,re=!1;try{let ie=kn(P,D),de=r(ie.configTarget);Y={target:ie.configTarget,content:de};let fe=Qi(ie.configTarget);if(!fe.ok)return fe.result;let we=fe.config,Ce=Z(O);xv(O,D,Ce);let Se=Ce?await uu(O,{ref:D.ref,operation:j}):null,Ie=Se?Cv(Se,D.rulebooks):[],Ee=Se?Ie.map((sn)=>Sv(we.rules,Se,sn)??`${O}#${Se.ref}/${sn}`):[O],qe=Ee.filter((sn)=>!we.rules.includes(sn)),Fe=[...we.rules,...qe];if(Fe.length>ye)return Pv();if(Fe.length!==we.rules.length)re=!0,wn(ie.configTarget,{version:1,rules:Fe,overrides:we.overrides??{},transparent_wrappers:we.transparent_wrappers??[]},void 0,J._testAfterPolicyRename);let en=await fo(P,D,j,J,new Set(qe),new Set(qe));if(!en.ok)lr(ie.configTarget,de);if(!en.ok||!Se)return en;let on=Ie.filter((sn,an)=>qe.includes(Ee[an]??""));return{...en,add:{source:O,ref:Se.ref,selected:Ie,added:on,alreadyConfigured:Ie.filter((sn)=>!on.includes(sn)),commits:qe.length>0?[Se.commit]:[]}}}catch(ie){if(re&&Y)try{lr(Y.target,Y.content)}catch(de){return cr(de)}return cr(ie)}}function xv(P,O,D){if(!D&&O.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!D&&O.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${P}`);if(O.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let j=O.rulebooks?.filter((J)=>!d.test(J))??[];if(j.length>0)throw Error(`Invalid rulebook names: ${j.join(", ")}`)}function Cv(P,O){let D=O?[...new Set(O)]:P.names,j=D.filter((J)=>!P.names.includes(J));if(j.length>0)throw Error(`Rulebooks not found in ${P.source} at ${P.ref}: ${j.join(", ")}
276
+ Available rulebooks: ${P.names.join(", ")}`);return D}function Sv(P,O,D){let j=`${O.source}#${O.ref}/${D}`;if(P.includes(j))return j;let J=`${O.source}#${O.commit}/${D}`;return P.find((Y)=>Y===J)}async function Rv(P,O,D=Mn()){if(P.length>ye)throw Error(be);let j=[],J=0,Y,re=Array.from({length:Math.min(P.length,lo.concurrency)},async()=>{while(!Y){let ie=J;if(ie>=P.length)return;J++;try{j[ie]=await O(P[ie],ie,D.controller.signal)}catch(de){if(!Y)Y={value:de},J=P.length,D.controller.abort(de);return}}});if(await Promise.all(re),Y)throw Y.value;return j}function Pv(){return{ok:!1,errors:[be],entries:[]}}function os(P){return{cwd:P.cwd,userConfigDir:P.userConfigDir,userConfigPath:P.userConfigPath,projectConfigPath:P.projectConfigPath,global:P.global,only:P.only,refresh:P.refresh}}function Ev(P){return{...os(P),ref:P.ref,rulebooks:P.rulebooks}}function Av(P){return{...os(P),deleteSource:P.deleteSource}}async function xu(P,O,D={}){try{return await Iv(P,O,Av(D),{})}catch(j){return cr(j)}}async function Iv(P,O,D,j){let J=kn(P,D),Y=m(J.configTarget);if(Y.errors.length>0)return{ok:!1,errors:Y.errors,entries:[]};if(!Y.config)return{ok:!1,errors:[`No config found at ${J.configPath}`],entries:[]};let re=yu(Y.config.rules,O);if(!re.ok)return re.result;let ie=D.deleteSource?_v(J.configDir,re.specs,J.filesystemScope):{ok:!0,dirs:[]};if(!ie.ok)return ie.result;let de=r(J.configTarget);if(de===null)return cr(Error("Rules config is unavailable."));try{wn(J.configTarget,{version:1,rules:Y.config.rules.filter((Ce)=>!re.specs.includes(Ce)),overrides:Y.config.overrides??{},transparent_wrappers:Y.config.transparent_wrappers??[]},void 0,j._testAfterPolicyRename)}catch(Ce){throw lr(J.configTarget,de),Ce}let fe=await fo(P,D,Mn(),j);if(!fe.ok)return lr(J.configTarget,de),fe;let we=Tv(ie.dirs,j,J.filesystemScope);if(!we.ok){lr(J.configTarget,de);let Ce=await fo(P,D,Mn(),j);if(!Ce.ok)return{ok:!1,errors:[...we.result.errors,...Ce.errors],entries:Ce.entries};return we.result}return fe}function _v(P,O,D){let j=O.flatMap((ie)=>d.test(ie)?[]:["--delete-source can only delete local rulebook sources"]),J=O.map((ie)=>rs(P,ie)),Y=j.length>0?[]:J.flatMap((ie)=>Cu(ie,D)),re=[...j,...Y];return re.length>0?{ok:!1,result:{ok:!1,errors:re,entries:[]}}:{ok:!0,dirs:J}}function Cu(P,O){let D=fv(P),j=i(O,D),J=me(j);if(!J)return[`Local rulebook source directory not found: ${P}`];let Y=J.find((re)=>re.name==="rulebook.json");if(!Y)return[`Local rulebook source directory is missing rulebook.json: ${P}`];if(Y.kind!=="file")throw new o(O.label);if(r(i(O,rs(D,"rulebook.json"))),J.length>1)return[`Local rulebook source directory contains extra files: ${P}. delete manually if you really want to remove the directory.`];return[]}function Tv(P,O,D){let j=P.flatMap((J)=>{try{if(!me(i(D,J)))return[];let Y=Cu(J,D);if(Y.length>0)return Y;return $v(J,O,D),[]}catch(Y){return[`Failed to delete local rulebook source ${J}: ${Y instanceof Error?Y.message:String(Y)}`]}});return j.length>0?{ok:!1,result:{ok:!1,errors:j,entries:[]}}:{ok:!0}}function $v(P,O,D){if(O._testDeleteLocalSourceDir){O._testDeleteLocalSourceDir(P);return}H(i(D,rs(P,ge))),at(i(D,P))}function lr(P,O){if(O===null){H(P);return}g(P,O)}function cr(P){return{ok:!1,errors:[P instanceof Error?P.message:String(P)],entries:[]}}var Ov=".safety-net.json",Dv="~/.cc-safety-net/config.json";async function Eu(P,O){let D=L(P,{cwd:O.cwd});if(D)console.log(`Skipped the project scope: ${_(O.cwd)} is the user rule config, not a project rule config`);return[D||await Ru(P,{legacyPath:pa({cwd:O.cwd}),configPath:_(O.cwd),defaultRulebookName:"project-rules",migratedFrom:Ov,cleanup:O.cleanup,syncOptions:{cwd:O.cwd}}),await Ru(P,{legacyPath:Ct(P),configPath:W(P),defaultRulebookName:"user-rules",migratedFrom:Dv,cleanup:O.cleanup,syncOptions:{cwd:O.cwd,global:!0}})].every((J)=>J)?0:1}async function Ru(P,O){let D=kn(P,O.syncOptions),j=i(D.filesystemScope,O.legacyPath),J=r(j);if(J===null)return console.log(`No legacy config found at ${O.legacyPath}`),!0;let Y=Nv(J);if(!Y.ok){for(let Ie of Y.errors)console.error(Ie);return!1}let re=m(D.configTarget);if(re.errors.length>0){for(let Ie of re.errors)console.error(Ie);return!1}let ie=re.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},de=jv(Su(O.configPath),ie.rules,O.defaultRulebookName,O.migratedFrom,D.filesystemScope),fe=go(Su(O.configPath),de,"rulebook.json"),we=i(D.filesystemScope,fe),Ce=[Pu(D.configTarget),Pu(we)],Se=await Lv(P,O,D.configTarget,we,de,Y.config.rules,ie.rules.includes(de)?ie.rules:[...ie.rules,de],ie.overrides??{},ie.transparent_wrappers??[]);if(!Se.ok){Mv(Ce);for(let Ie of Se.errors)console.error(Ie);return!1}if(!O.cleanup)return console.log(`Migrated legacy config at ${O.legacyPath}. Legacy file is no longer used.`),!0;if(!Hv(D.configTarget,we,de,O.migratedFrom,Y.config.rules))return console.error(`Migration cleanup verification failed for ${O.legacyPath}`),!1;return H(j),console.log(`Deleted legacy config at ${O.legacyPath}`),!0}async function Lv(P,O,D,j,J,Y,re,ie,de){try{return wn(D,{version:1,rules:re,overrides:ie,transparent_wrappers:de}),wn(j,Fv(J,O.migratedFrom,Y)),await mo(P,O.syncOptions)}catch(fe){return{ok:!1,errors:[fe instanceof Error?fe.message:String(fe)]}}}function Nv(P){try{let O=JSON.parse(P),D=Po(O);if(D.errors.length>0)return{ok:!1,errors:D.errors};return{ok:!0,config:{version:1,rules:O.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function jv(P,O,D,j,J){let Y=O.find((re)=>Uv(i(J,go(P,re,"rulebook.json")))===j);if(Y)return Y;if(r(i(J,go(P,D,"rulebook.json")))===null)return D;for(let re=2;;re++){let ie=`${D}-${re}`;if(r(i(J,go(P,ie,"rulebook.json")))===null)return ie}}function Fv(P,O,D){return{rulebook_version:1,name:P,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:O,allowed_commands:[...new Set(D.map((j)=>j.command))],rules:D,tests:D.map((j)=>({command:[j.command,j.subcommand,j.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:j.name}))}}function Hv(P,O,D,j,J){if(!m(P).config?.rules.includes(D))return!1;try{let re=r(O);if(re===null)return!1;let ie=JSON.parse(re);return ie.migrated_from===j&&JSON.stringify(ie.rules)===JSON.stringify(J)}catch{return!1}}function Pu(P){return{target:P,content:r(P)}}function Mv(P){for(let O of P){if(O.content===null){H(O.target);continue}g(O.target,O.content)}}function Uv(P){let O=r(P);if(O===null)return null;try{let D=JSON.parse(O);return typeof D.migrated_from==="string"?D.migrated_from:null}catch{return null}}import{mkdir as Gv,readFile as Bv,writeFile as qv}from"node:fs/promises";import{dirname as Vv,join as Jv}from"node:path";var zv=86400000,Kv=604800000;async function Iu(P,O=Date.now()){if(P.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let D=We(P);if(!D)return null;let j=Jv(D,".cc-safety-net","update-check.json"),J=await Wv(j,O);if(!J.lastCheck||O-J.lastCheck>zv){let ie=await Gn();if(J.lastCheck=O,ie.latestVersion)J.latestVersion=ie.latestVersion;if(!await Au(j,J))return null;if(ie.error)return null}let Y=J.latestVersion,re=pn();if(!Y||!$o(Y,re))return null;if(J.notifiedVersion===Y&&J.notifiedAt!==void 0&&O-J.notifiedAt<Kv)return null;if(J.notifiedVersion=Y,J.notifiedAt=O,!await Au(j,J))return null;return`UPDATE_AVAILABLE: cc-safety-net v${Y} is available (running v${re}). 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 Wv(P,O){let D=await Bv(P,"utf8").then((Y)=>JSON.parse(Y)).catch(()=>{return});if(!D||typeof D!=="object"||Array.isArray(D))return{};let j=D,J=(Y)=>typeof Y==="number"&&Number.isFinite(Y)&&Y<=O?Y:void 0;return{lastCheck:J(j.lastCheck),latestVersion:typeof j.latestVersion==="string"?j.latestVersion:void 0,notifiedVersion:typeof j.notifiedVersion==="string"?j.notifiedVersion:void 0,notifiedAt:J(j.notifiedAt)}}async function Au(P,O){return Gv(Vv(P),{recursive:!0,mode:448}).then(()=>qv(P,JSON.stringify(O),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as Yv,resolve as is}from"node:path";var _u="CC Safety Net Config",Zv="═".repeat(_u.length),Xv="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",Qv=new Set(["rule.json","rule.lock","cache"]);function Tu(P,O={}){try{return eb(P,O)}catch(D){if(D instanceof o)return console.error(D.message),1;throw D}}function eb(P,O){let D=O.cwd??process.cwd(),j=X(P,{cwd:D}),J=Ct(P),Y=vr(D),re=is(D,he),ie=i(j.userScope,J),de=i(j.projectScope,Y),fe=!1,we=!1,Ce=[],Se=[],Ie=nb(i(j.projectScope,re));if(rb(),r(j.userConfigTarget)!==null){let Ee=Un(j.userConfigTarget);if(Ee.errors.push(...B(j.userConfigPath,j.userScope)),Ce.push({scope:"User",path:j.userConfigPath,result:Ee,schema:"rules",target:j.userConfigTarget}),Ee.errors.length>0)fe=!0}if(r(ie)!==null)if(we=!0,r(j.userConfigTarget)!==null)Se.push(ho("user","cleanup"));else{let Ee=Eo(ie);if(Ce.push({scope:"User",path:J,result:Ee,schema:"legacy",inactive:!0,target:ie}),Se.push(ho("user",Ee.errors.length>0?"fix-or-delete":"migrate")),Ee.errors.length>0)fe=!0}if(r(j.projectConfigTarget)!==null){let Ee=Un(j.projectConfigTarget);if(Ee.errors.push(...B(j.projectConfigPath,j.projectScope)),Ce.push({scope:"Project",path:is(j.projectConfigPath),result:Ee,schema:"rules",target:j.projectConfigTarget}),Ee.errors.length>0)fe=!0;if(r(de)!==null)we=!0,Se.push(ho("project","cleanup"))}else if(r(de)!==null){we=!0,fe=!0;let Ee=Eo(de);Ce.push({scope:"Project",path:is(Y),result:Ee,schema:"legacy",inactive:!0,target:de}),Se.push(ho("project",Ee.errors.length>0?"fix-or-delete":"migrate"))}if(Ie?.result.errors.length)fe=!0;if(Ce.length===0&&!Ie)return console.log(`
277
+ No config files found. Using built-in rules only.`),0;for(let Ee of Ce)if(Ee.inactive)ib(Ee.scope,Ee.path,Ee.result);else if(Ee.result.errors.length>0)sb(Ee.scope,Ee.path,Ee.result.errors);else{if(Ee.schema==="rules"&&cb(Ee.target))console.log(`
278
+ Added $schema to ${Ee.scope.toLowerCase()} config.`);ob(Ee.scope,Ee.path,Ee.result,Ee.schema)}for(let Ee of Se)console.error(`
279
+ ${nn.red(Ee)}`);if(Ie)if(Ie.result.errors.length>0)lb(Ie.path,Ie.result.errors);else ab(Ie.path,Ie.result);if(fe)return console.error(`
280
+ Config validation failed.`),1;return console.log(we?`
279
281
  Configs valid with warnings.`:`
280
- All configs valid.`),0}function oo(_,I){let O=`legacy ${_} config`;if(I==="cleanup")return`Warning: Legacy ${_} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(I==="migrate")return`Warning: Legacy ${_} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${_} config is no longer supported. Fix or delete the ${O}, then run \`npx -y cc-safety-net rule migrate\`.`}function av(_){if(pe(_)===null)return null;let I=lv(_);if(I.ruleNames.size===0&&I.errors.length===0)return null;return{path:_.path,result:I}}function lv(_){let I=[],O=new Set,L=(pe(_)??[]).filter((J)=>!iv.has(J.name)).sort((J,K)=>J.name.localeCompare(K.name));if(L.length===0)return{errors:I,ruleNames:O};for(let J of L){if(!u.test(J.name)){I.push(`rulebook directory names must match ${u}: ${J.name}`);continue}if(J.kind!=="directory"){I.push(`${J.name} must be a rulebook directory`);continue}let K=i(_.scope,tv(_.path,J.name,"rulebook.json")),ne=n(K);if(ne===null){I.push(`${J.name}/rulebook.json is required`);continue}try{let oe;try{oe=JSON.parse(ne)}catch{I.push(`${J.name}/rulebook.json: invalid JSON`);continue}let de=ce(oe);if(de.name!==J.name){I.push(`rulebook name "${de.name}" must match folder "${J.name}"`);continue}let ue=Yr(de);if(ue.length>0){I.push(...ue.map((ve)=>`${J.name}/rulebook.json: ${ve}`));continue}O.add(J.name)}catch(oe){I.push(oe instanceof Error?`${J.name}/rulebook.json: ${oe.message}`:`${J.name}/rulebook.json: ${String(oe)}`)}}return{errors:I,ruleNames:O}}function cv(){console.log(Zd),console.log(rv)}function dv(_,I,O,L){if(console.log(`
281
- ✓ ${_} config: ${I}`),console.log(` Schema: ${L==="rules"?"rulebook sources":"legacy inline rules"}`),O.ruleNames.size>0){console.log(` ${L==="rules"?"Sources":"Rules"}:`);let J=1;for(let K of O.ruleNames)console.log(` ${J}. ${K}`),J++}else console.log(` ${L==="rules"?"Sources":"Rules"}: (none)`)}function uv(_,I,O){if(console.error(`
282
- ✗ Legacy ${_.toLowerCase()} config: ${I}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),O.errors.length>0){console.error(" Errors:");let L=1;for(let J of O.errors)for(let K of J.split("; "))console.error(` ${L}. ${K}`),L++;return}if(O.ruleNames.size>0){console.error(" Rules:");let L=1;for(let J of O.ruleNames)console.error(` ${L}. ${J}`),L++;return}console.error(" Rules: (none)")}function pv(_,I,O){Qd(`${_} config`,I,O)}function fv(_,I){console.log(`
283
- ✓ GitHub source rules: ${_}`),console.log(" Rulebooks:");let O=1;for(let L of I.ruleNames)console.log(` ${O}. ${L}`),O++}function mv(_,I){Qd("GitHub source rules",_,I)}function Qd(_,I,O){console.error(`
284
- ✗ ${_}: ${I}`),console.error(" Errors:");let L=1;for(let J of O)for(let K of J.split("; "))console.error(` ${L}. ${K}`),L++}function gv(_){try{let I=n(_);if(I===null)return!1;let O=JSON.parse(I);if(O.$schema)return!1;return g(_,JSON.stringify({$schema:ov,...O},null,2)),!0}catch(I){if(I instanceof r)throw I;return!1}}var eu=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),yv=new Set(["add","remove","list"]),vv="cc-safety-net/rulebooks";async function nu(_,I){try{return await bv(_,I)}catch(O){if(O instanceof r)return console.error(O.message),1;throw O}}async function bv(_,I){let O=kv(I),L=O.help?wv(O.positionals):null;if(L)return Pt(L),0;if(O.errors.length>0){for(let oe of O.errors)console.error(oe);return 1}let J=O.positionals[0];if(!J)return Pt(yt,console.error),1;let K=O.positionals[1],ne={global:O.global};if(J==="init"){let oe=wn(_,ne);Rv(oe.configTarget);let de=hv(oe.configDir,"example-rules","rulebook.json"),ue=i(oe.filesystemScope,de);if(O.example&&n(ue)===null)Cd(ue);let ve=H(oe.configPath,oe.filesystemScope);for(let xe of ve)console.error(xe);if(ve.length>0)return 1;return console.log("Rule config initialized."),0}if(J==="add"){let oe=tu(O);if(!oe)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let de=wn(_,ne),ue=await Gd(_,oe,{...ne,ref:O.ref,rulebooks:O.only.length>0?O.only:void 0});return bd(ue,oe,`Scope: ${O.global?"user":"project"} (${de.configDir})`),ue.ok?0:1}if(J==="remove"){if(!K)return console.error("rule remove requires a source"),1;let oe=await Bd(_,K,{...ne,deleteSource:O.deleteSource});return Kr(oe,`Removed rulebook source: ${K}`),oe.ok?0:1}if(J==="update"){let oe=await to(_,{...ne,only:K,refresh:!0});return Kr(oe,"Rule config updated."),oe.ok?0:1}if(J==="sync")return Qs(_,{global:O.global});if(J==="list"){let oe=X(_,{cwd:process.cwd()});return kd(oe),oe.errors.length>0?1:0}if(J==="wrapper")return Pv(_,O);if(J==="migrate")return Wd(_,{cleanup:O.cleanup,cwd:process.cwd()});if(J==="doc"){console.log(yd);let oe=await Yd(_);if(oe)console.error(oe);return 0}if(J==="verify")return Xd(_);return 1}function wv(_){if(_.length===0)return yt;let I=yt.subcommands.filter((L)=>L.usage.split(" ")[0]===_[0]);if(I.length===0)return null;if(_.length===1&&I.length>1)return{name:`rule ${_[0]}`,description:`Subcommands of rule ${_[0]}`,usage:`rule ${_[0]} <subcommand>`,subcommands:I,options:[]};let O=_.length===1?I[0]:I.find((L)=>L.usage.split(" ")[1]===_[1]);if(!O)return null;return{name:`rule ${_[0]}`,description:O.description,usage:`rule ${O.usage}`,options:_[0]==="add"?po:[],examples:_[0]==="add"?fo:void 0}}function kv(_){let I=gn({label:"rule",booleans:{global:["-g","--global"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},_),O={...I.flags,ref:I.values.ref,only:I.lists.only??[],help:I.help,positionals:I.positionals,errors:I.errors};return xv(O),O}function xv(_){let[I]=_.positionals;if(I&&!eu.has(I))_.errors.push(`Unknown rule subcommand: ${I}`);if(_.deleteSource&&I!=="remove")if(I&&eu.has(I))_.errors.push(`Unknown option for rule ${I}: --delete-source`);else _.errors.push("--delete-source is only valid with 'rule remove'");if(_.cleanup&&I!=="migrate")_.errors.push(rr(I,"--cleanup"));if(_.example&&I!=="init")_.errors.push(rr(I,"--example"));if(_.ref&&I!=="add")_.errors.push(rr(I,"--ref"));if(_.only.length>0&&I!=="add")_.errors.push(rr(I,"--only"));if(I==="add")Sv(_);if(I==="migrate"){if(_.global)_.errors.push(rr(I,"--global"));if(_.positionals.length>1)_.errors.push(`Unexpected rule migrate argument: ${_.positionals[1]}`)}else if(I==="wrapper")Cv(_);else if(_.positionals.length>2)_.errors.push(`Unexpected rule argument: ${_.positionals[2]}`);if(I==="list"&&_.global)_.errors.push("Unknown option for rule list: --global")}function tu(_){if(_.positionals[1])return _.positionals[1];if(_.ref||_.only.length>0)return vv;return}function Sv(_){let I=tu(_);if(!I)return;if((_.ref||_.only.length>0)&&!Y(I)){if(_.ref)_.errors.push(`--ref can only select a ref for an owner/repo source: ${I}`);if(_.only.length>0)_.errors.push("--only can only select rulebooks from an owner/repo source");return}if(_.ref&&!se(_.ref))_.errors.push(`--ref must use valid path segments: ${_.ref}`);let O=_.only.filter((L)=>!u.test(L));if(O.length>0)_.errors.push(`Invalid rulebook names: ${O.join(", ")}`)}function rr(_,I){return _?`Unknown option for rule ${_}: ${I}`:`Unknown option for rule: ${I}`}function Cv(_){let I=_.positionals[1],O=_.positionals[2];if(!I){_.errors.push("rule wrapper requires add, remove, or list");return}if(!yv.has(I)){_.errors.push(`Unknown rule wrapper action: ${I}`);return}if(I==="list"){if(O)_.errors.push(`Unexpected rule wrapper argument: ${O}`);return}if(!O){_.errors.push(`rule wrapper ${I} requires a command`);return}if(_.positionals.length>3)_.errors.push(`Unexpected rule wrapper argument: ${_.positionals[3]}`)}function Rv(_){if(n(_)===null){Sd(_);return}let I=m(_);if(!I.config)return;bn(_,{version:1,rules:I.config.rules,overrides:I.config.overrides??{},transparent_wrappers:I.config.transparent_wrappers??[]})}async function Pv(_,I){let O=I.positionals[1],L=I.positionals[2],J=wn(_,{global:I.global}).configTarget;if(O==="list"){let de=m(J);if(de.errors.length>0){for(let ue of de.errors)console.error(ue);return 1}return Ev(de.config?.transparent_wrappers??[]),0}if(!L||!w.test(L))return console.error("transparent wrapper must match command pattern"),1;if(Ae(L))return console.error(`reserved command "${L}" cannot be a wrapper`),1;let K=m(J);if(K.errors.length>0){for(let de of K.errors)console.error(de);return 1}let ne=K.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},oe=O==="add"?[...new Set([...ne.transparent_wrappers??[],L])]:(ne.transparent_wrappers??[]).filter((de)=>de!==L);return bn(J,{version:1,rules:ne.rules,overrides:ne.overrides??{},transparent_wrappers:oe}),console.log(O==="add"?`Added transparent wrapper: ${L}`:`Removed transparent wrapper: ${L}`),0}function Ev(_){if(_.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${_.length}):`);for(let I of _)console.log(` - ${I}`)}import{sep as Ov}from"node:path";import{existsSync as Av,readFileSync as _v}from"node:fs";import{join as Iv}from"node:path";async function Tv(_){if(_.isTTY)return null;return(await qe(_).catch(()=>null))?.trim()||null}function $v(_){let I=_.env.get("CLAUDE_SETTINGS_PATH");if(I)return I;return Iv(kr(_),"settings.json")}function Bi(_){let I=$v(_);if(!Av(I))return!1;try{let O=_v(I,"utf-8"),L=JSON.parse(O);if(!L.enabledPlugins)return!1;let J="cc-safety-net@cc-marketplace";if(!(J in L.enabledPlugins))return!1;return L.enabledPlugins[J]===!0}catch(O){if(T(o.debug,_.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${I}: ${O instanceof Error?O.message:String(O)}`);return!1}}async function qi(_,I=process.stdin){let O=Bi(_),L;if(!O)L="\uD83D\uDEE1️ CC Safety Net ❌";else{let K=E(_,{cwd:process.cwd()}),ne=K.policy,oe=R(ne,_.env),de=Object.values(B(ne,oe.capabilities)).some((xe)=>xe.changesInherited),ue={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[de?"custom":oe.effectiveLevel],ve=(K.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";L=`\uD83D\uDEE1️ CC Safety Net ${ue}${oe.worktreeMode?"\uD83C\uDF33":""}${ve}${K.state==="degraded"?"⚠️":""}`}let J=await Tv(I);if(J&&!J.startsWith("{"))console.log(`${J} | ${L}`);else console.log(L)}function ru(_){let I=E(_,{cwd:process.cwd()}),O=I.policy,L=R(O,_.env),J=!!process.env.NO_COLOR||!process.stdout.isTTY,K=Math.min(process.stdout.columns||80,100),ne=J?"ok":"✔",oe=J?"OFF":"✘",de=(Le,en)=>{let Ve=` ${Le.padEnd(13)}${en}`;return(Ve.length>K?`${Ve.slice(0,K-1)}…`:Ve).replaceAll(oe,nn.red(oe))},ue=Object.values(B(O,L.capabilities)).some((Le)=>Le.changesInherited),ve=(Le)=>Le===_.home||Le.startsWith(`${_.home}${Ov}`)?`~${Le.slice(_.home.length)}`:Le,xe={ready:nn.green,degraded:nn.yellow}[I.state],Se=I.policyScopes?.weakenings??[],Pe=[...Bi(_)?[]:["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."],...I.diagnostics],we=J?"-":"·";console.log([`${J?"":"\uD83D\uDEE1️ "}CC Safety Net — ${xe(I.state)}`,"",de("Protection",`destructive ${O.destructiveCommandProtectionEnabled?ne:oe} secrets ${O.secretProtection.enabled?ne:oe}`),de("Level",ue?`${L.effectiveLevel} (customised)`:L.effectiveLevel),de("Rules",O.rules.length===0?"none active":`${O.rules.length} active`),de("Policy",ve(d(_))),...I.policyScopes?[de("Project",ve(b(process.cwd())))]:[],...L.worktreeMode?[de("Worktree","relaxations active")]:[],"",...Se.length===0?[]:[" Project policy",...Se.flatMap((Le)=>Vt(Le," ",K-6).map((en,Ve)=>Ve===0?` ${en}`:en)),""],...Pe.length===0?[" Everything configured is active."]:[" Not active",...Pe.flatMap((Le)=>Vt(Le," ",K-6).map((en,Ve)=>Ve===0?` ${we} ${en}`:en)),""," Full report: cc-safety-net doctor"]].join(`
285
- `))}import{spawn as mu}from"node:child_process";import{randomBytes as Bv}from"node:crypto";import{existsSync as qv}from"node:fs";import{createServer as Vv}from"node:http";import{Writable as zv}from"node:stream";var io=500;function Dv(_){let I=_.filter((J)=>J.decision!=="allow"),O=_.filter((J)=>J.decision==="allow"),L=Math.min(I.length,Math.max(io-O.length,Math.ceil(io/2)));return[...I.slice(0,L),...O.slice(0,io-L)]}function ou(_,I,O=F(_)){if(O)q(_,O);let L=(en)=>new Date(en.getFullYear(),en.getMonth(),en.getDate()).getTime(),J=L(new Date),K=new Date(J);K.setDate(K.getDate()-(I-1));let ne=K.getTime(),oe=[],de={count:0};for(let en of O?zn(O,de):[])for(let Ve of ht(en,de)){let on=new Date(Ve.ts).getTime();if(!Number.isFinite(on))continue;if(on>=ne)oe.push(Ve)}oe.sort((en,Ve)=>new Date(Ve.ts).getTime()-new Date(en.ts).getTime());let ue=Array.from({length:I},()=>0),ve=Array.from({length:I},()=>0),xe={},Se={},Pe={},we=0,Le=0;for(let en of oe){let Ve=en.agent||"unknown";xe[Ve]=(xe[Ve]??0)+1;let on=Math.round((J-L(new Date(en.ts)))/86400000),sn=I-1-on,an=on>=0&&on<I;if(an)ve[sn]=(ve[sn]??0)+1;if(en.decision!=="allow"){if(we++,en.ruleId)Se[en.ruleId]=(Se[en.ruleId]??0)+1;let rn=co(en.segment||en.command);if(rn)Pe[rn]=(Pe[rn]??0)+1;if(en.failureStage)Le++;if(an)ue[sn]=(ue[sn]??0)+1}}return{days:I,logsDir:O,homeDir:_.home,totalInWindow:oe.length,truncated:oe.length>io,unreadable:de.count,counts:{blocked:we,allowed:oe.length-we,agents:xe,blockedByDay:ue,analyzedByDay:ve,rules:Se,commands:Pe,errors:Le},entries:Dv(oe).sort((en,Ve)=>new Date(Ve.ts).getTime()-new Date(en.ts).getTime())}}import{spawn as Lv}from"node:child_process";import{existsSync as Nv,statSync as iu}from"node:fs";import{delimiter as jv,join as Fv}from"node:path";var Hv=120000,so="Choose the project folder",Mv=`try
286
- return POSIX path of (choose folder with prompt "${so}")
282
+ All configs valid.`),0}function ho(P,O){let D=`legacy ${P} config`;if(O==="cleanup")return`Warning: Legacy ${P} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(O==="migrate")return`Warning: Legacy ${P} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${P} config is no longer supported. Fix or delete the ${D}, then run \`npx -y cc-safety-net rule migrate\`.`}function nb(P){if(me(P)===null)return null;let O=tb(P);if(O.ruleNames.size===0&&O.errors.length===0)return null;return{path:P.path,result:O}}function tb(P){let O=[],D=new Set,j=(me(P)??[]).filter((J)=>!Qv.has(J.name)).sort((J,Y)=>J.name.localeCompare(Y.name));if(j.length===0)return{errors:O,ruleNames:D};for(let J of j){if(!d.test(J.name)){O.push(`rulebook directory names must match ${d}: ${J.name}`);continue}if(J.kind!=="directory"){O.push(`${J.name} must be a rulebook directory`);continue}let Y=i(P.scope,Yv(P.path,J.name,"rulebook.json")),re=r(Y);if(re===null){O.push(`${J.name}/rulebook.json is required`);continue}try{let ie;try{ie=JSON.parse(re)}catch{O.push(`${J.name}/rulebook.json: invalid JSON`);continue}let de=le(ie);if(de.name!==J.name){O.push(`rulebook name "${de.name}" must match folder "${J.name}"`);continue}let fe=ao(de);if(fe.length>0){O.push(...fe.map((we)=>`${J.name}/rulebook.json: ${we}`));continue}D.add(J.name)}catch(ie){O.push(ie instanceof Error?`${J.name}/rulebook.json: ${ie.message}`:`${J.name}/rulebook.json: ${String(ie)}`)}}return{errors:O,ruleNames:D}}function rb(){console.log(_u),console.log(Zv)}function ob(P,O,D,j){if(console.log(`
283
+ ✓ ${P} config: ${O}`),console.log(` Schema: ${j==="rules"?"rulebook sources":"legacy inline rules"}`),D.ruleNames.size>0){console.log(` ${j==="rules"?"Sources":"Rules"}:`);let J=1;for(let Y of D.ruleNames)console.log(` ${J}. ${Y}`),J++}else console.log(` ${j==="rules"?"Sources":"Rules"}: (none)`)}function ib(P,O,D){if(console.error(`
284
+ ✗ Legacy ${P.toLowerCase()} config: ${O}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),D.errors.length>0){console.error(" Errors:");let j=1;for(let J of D.errors)for(let Y of J.split("; "))console.error(` ${j}. ${Y}`),j++;return}if(D.ruleNames.size>0){console.error(" Rules:");let j=1;for(let J of D.ruleNames)console.error(` ${j}. ${J}`),j++;return}console.error(" Rules: (none)")}function sb(P,O,D){$u(`${P} config`,O,D)}function ab(P,O){console.log(`
285
+ ✓ GitHub source rules: ${P}`),console.log(" Rulebooks:");let D=1;for(let j of O.ruleNames)console.log(` ${D}. ${j}`),D++}function lb(P,O){$u("GitHub source rules",P,O)}function $u(P,O,D){console.error(`
286
+ ✗ ${P}: ${O}`),console.error(" Errors:");let j=1;for(let J of D)for(let Y of J.split("; "))console.error(` ${j}. ${Y}`),j++}function cb(P){try{let O=r(P);if(O===null)return!1;let D=JSON.parse(O);if(D.$schema)return!1;return g(P,JSON.stringify({$schema:Xv,...D},null,2)),!0}catch(O){if(O instanceof o)throw O;return!1}}var Ou=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),ub=new Set(["init","add","remove","update","sync","wrapper"]),pb=new Set(["add","remove","list"]),fb="cc-safety-net/rulebooks";async function Du(P,O){try{return await mb(P,O)}catch(D){if(D instanceof o)return console.error(D.message),1;throw D}}async function mb(P,O){let D=hb(O),j=D.help?gb(D.positionals):null;if(j)return Lt(j),0;if(D.errors.length>0){for(let fe of D.errors)console.error(fe);return 1}let J=D.positionals[0];if(!J)return Lt(xt,console.error),1;let Y=D.positionals[1],re={global:D.global},ie=process.cwd();if(!D.global&&ub.has(J)&&!(J==="wrapper"&&Y==="list")&&L(P,{cwd:ie}))return console.error(`${_(ie)} is the user rule config, not a project rule config; use --global for the user scope, or run from a project directory`),1;if(J==="init"){let fe=kn(P,re);wb(fe.configTarget);let we=db(fe.configDir,"example-rules","rulebook.json"),Ce=i(fe.filesystemScope,we);if(D.example&&r(Ce)===null)ru(Ce);let Se=B(fe.configPath,fe.filesystemScope);for(let Ie of Se)console.error(Ie);if(Se.length>0)return 1;return console.log("Rule config initialized."),0}if(J==="add"){let fe=Lu(D);if(!fe)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let we=kn(P,re),Ce=await ku(P,fe,{...re,ref:D.ref,rulebooks:D.only.length>0?D.only:void 0});return Xd(Ce,fe,`Scope: ${D.global?"user":"project"} (${we.configDir})`),Ce.ok?0:1}if(J==="remove"){if(!Y)return console.error("rule remove requires a source"),1;let fe=await xu(P,Y,{...re,deleteSource:D.deleteSource});return so(fe,`Removed rulebook source: ${Y}`),fe.ok?0:1}if(J==="update"){let fe=await mo(P,{...re,only:Y,refresh:!0});return so(fe,"Rule config updated."),fe.ok?0:1}if(J==="sync")return ga(P,{global:D.global});if(J==="list"){let fe=Q(P,{cwd:ie});return eu(fe),fe.errors.length>0?1:0}if(J==="wrapper")return kb(P,D);if(J==="migrate")return Eu(P,{cleanup:D.cleanup,cwd:ie});if(J==="doc"){console.log(Yd);let fe=await Iu(P);if(fe)console.error(fe);return 0}if(J==="verify")return Tu(P);return 1}function gb(P){if(P.length===0)return xt;let O=xt.subcommands.filter((j)=>j.usage.split(" ")[0]===P[0]);if(O.length===0)return null;if(P.length===1&&O.length>1)return{name:`rule ${P[0]}`,description:`Subcommands of rule ${P[0]}`,usage:`rule ${P[0]} <subcommand>`,subcommands:O,options:[]};let D=P.length===1?O[0]:O.find((j)=>j.usage.split(" ")[1]===P[1]);if(!D)return null;return{name:`rule ${P[0]}`,description:D.description,usage:`rule ${D.usage}`,options:P[0]==="add"?Co:[],examples:P[0]==="add"?So:void 0}}function hb(P){let O=gn({label:"rule",booleans:{global:["-g","--global"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},P),D={...O.flags,ref:O.values.ref,only:O.lists.only??[],help:O.help,positionals:O.positionals,errors:O.errors};return yb(D),D}function yb(P){let[O]=P.positionals;if(O&&!Ou.has(O))P.errors.push(`Unknown rule subcommand: ${O}`);if(P.deleteSource&&O!=="remove")if(O&&Ou.has(O))P.errors.push(`Unknown option for rule ${O}: --delete-source`);else P.errors.push("--delete-source is only valid with 'rule remove'");if(P.cleanup&&O!=="migrate")P.errors.push(dr(O,"--cleanup"));if(P.example&&O!=="init")P.errors.push(dr(O,"--example"));if(P.ref&&O!=="add")P.errors.push(dr(O,"--ref"));if(P.only.length>0&&O!=="add")P.errors.push(dr(O,"--only"));if(O==="add")vb(P);if(O==="migrate"){if(P.global)P.errors.push(dr(O,"--global"));if(P.positionals.length>1)P.errors.push(`Unexpected rule migrate argument: ${P.positionals[1]}`)}else if(O==="wrapper")bb(P);else if(P.positionals.length>2)P.errors.push(`Unexpected rule argument: ${P.positionals[2]}`);if(O==="list"&&P.global)P.errors.push("Unknown option for rule list: --global")}function Lu(P){if(P.positionals[1])return P.positionals[1];if(P.ref||P.only.length>0)return fb;return}function vb(P){let O=Lu(P);if(!O)return;if((P.ref||P.only.length>0)&&!Z(O)){if(P.ref)P.errors.push(`--ref can only select a ref for an owner/repo source: ${O}`);if(P.only.length>0)P.errors.push("--only can only select rulebooks from an owner/repo source");return}if(P.ref&&!ae(P.ref))P.errors.push(`--ref must use valid path segments: ${P.ref}`);let D=P.only.filter((j)=>!d.test(j));if(D.length>0)P.errors.push(`Invalid rulebook names: ${D.join(", ")}`)}function dr(P,O){return P?`Unknown option for rule ${P}: ${O}`:`Unknown option for rule: ${O}`}function bb(P){let O=P.positionals[1],D=P.positionals[2];if(!O){P.errors.push("rule wrapper requires add, remove, or list");return}if(!pb.has(O)){P.errors.push(`Unknown rule wrapper action: ${O}`);return}if(O==="list"){if(D)P.errors.push(`Unexpected rule wrapper argument: ${D}`);return}if(!D){P.errors.push(`rule wrapper ${O} requires a command`);return}if(P.positionals.length>3)P.errors.push(`Unexpected rule wrapper argument: ${P.positionals[3]}`)}function wb(P){if(r(P)===null){tu(P);return}let O=m(P);if(!O.config)return;wn(P,{version:1,rules:O.config.rules,overrides:O.config.overrides??{},transparent_wrappers:O.config.transparent_wrappers??[]})}async function kb(P,O){let D=O.positionals[1],j=O.positionals[2],J=kn(P,{global:O.global}).configTarget;if(D==="list"){let de=m(J);if(de.errors.length>0){for(let fe of de.errors)console.error(fe);return 1}return xb(de.config?.transparent_wrappers??[]),0}if(!j||!w.test(j))return console.error("transparent wrapper must match command pattern"),1;if(Ae(j))return console.error(`reserved command "${j}" cannot be a wrapper`),1;let Y=m(J);if(Y.errors.length>0){for(let de of Y.errors)console.error(de);return 1}let re=Y.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},ie=D==="add"?[...new Set([...re.transparent_wrappers??[],j])]:(re.transparent_wrappers??[]).filter((de)=>de!==j);return wn(J,{version:1,rules:re.rules,overrides:re.overrides??{},transparent_wrappers:ie}),console.log(D==="add"?`Added transparent wrapper: ${j}`:`Removed transparent wrapper: ${j}`),0}function xb(P){if(P.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${P.length}):`);for(let O of P)console.log(` - ${O}`)}import{sep as Ab}from"node:path";import{existsSync as Cb,readFileSync as Sb}from"node:fs";import{join as Rb}from"node:path";async function Pb(P){if(P.isTTY)return null;return(await Ke(P).catch(()=>null))?.trim()||null}function Eb(P){let O=P.env.get("CLAUDE_SETTINGS_PATH");if(O)return O;return Rb(Ar(P),"settings.json")}function ss(P){let O=Eb(P);if(!Cb(O))return!1;try{let D=Sb(O,"utf-8"),j=JSON.parse(D);if(!j.enabledPlugins)return!1;let J="cc-safety-net@cc-marketplace";if(!(J in j.enabledPlugins))return!1;return j.enabledPlugins[J]===!0}catch(D){if(x(n.debug,P.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${O}: ${D instanceof Error?D.message:String(D)}`);return!1}}async function as(P,O=process.stdin){let D=ss(P),j;if(!D)j="\uD83D\uDEE1️ CC Safety Net ❌";else{let Y=E(P,{cwd:process.cwd()}),re=Y.policy,ie=T(re,P.env),de=Object.values(V(re,ie.capabilities)).some((Ce)=>Ce.changesInherited),fe={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[de?"custom":ie.effectiveLevel],we=Y.policyScopes&&!Y.policyScopes.weakeningsIgnored&&Y.policyScopes.weakenings.length>0?"\uD83D\uDD3B":"";j=`\uD83D\uDEE1️ CC Safety Net ${fe}${ie.worktreeMode?"\uD83C\uDF33":""}${we}${Y.state==="degraded"?"⚠️":""}`}let J=await Pb(O);if(J&&!J.startsWith("{"))console.log(`${J} | ${j}`);else console.log(j)}function Nu(P){let O=E(P,{cwd:process.cwd()}),D=O.policy,j=T(D,P.env),J=!!process.env.NO_COLOR||!process.stdout.isTTY,Y=Math.min(process.stdout.columns||80,100),re=J?"ok":"✔",ie=J?"OFF":"✘",de=(qe,Fe)=>{let en=` ${qe.padEnd(13)}${Fe}`;return(en.length>Y?`${en.slice(0,Y-1)}…`:en).replaceAll(ie,nn.red(ie))},fe=Object.values(V(D,j.capabilities)).some((qe)=>qe.changesInherited),we=(qe)=>qe===P.home||qe.startsWith(`${P.home}${Ab}`)?`~${qe.slice(P.home.length)}`:qe,Ce={ready:nn.green,degraded:nn.yellow}[O.state],Se=O.policyScopes?.weakenings??[],Ie=[...ss(P)?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...O.diagnostics],Ee=J?"-":"·";console.log([`${J?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ce(O.state)}`,"",de("Protection",`destructive ${D.destructiveCommandProtectionEnabled?re:ie} secrets ${D.secretProtection.enabled?re:ie}`),de("Level",fe?`${j.effectiveLevel} (customised)`:j.effectiveLevel),de("Rules",D.rules.length===0?"none active":`${D.rules.length} active`),de("Policy",we(l(P))),...O.policyScopes?[de("Project",we(h(process.cwd())))]:[],...j.worktreeMode?[de("Worktree","relaxations active")]:[],"",...Se.length===0?[]:[O.policyScopes?.weakeningsIgnored?" Project policy (ignored)":" Project policy",...Se.flatMap((qe)=>Xt(qe," ",Y-6).map((Fe,en)=>en===0?` ${Fe}`:Fe)),""],...Ie.length===0?[" Everything configured is active."]:[" Not active",...Ie.flatMap((qe)=>Xt(qe," ",Y-6).map((Fe,en)=>en===0?` ${Ee} ${Fe}`:Fe)),""," Full report: cc-safety-net doctor"]].join(`
287
+ `))}import{spawn as zu}from"node:child_process";import{randomBytes as Fb}from"node:crypto";import{existsSync as Hb}from"node:fs";import{createServer as Mb}from"node:http";import{Writable as Ub}from"node:stream";var yo=500;function Ib(P){let O=P.filter((J)=>J.decision!=="allow"),D=P.filter((J)=>J.decision==="allow"),j=Math.min(O.length,Math.max(yo-D.length,Math.ceil(yo/2)));return[...O.slice(0,j),...D.slice(0,yo-j)]}function ju(P,O,D=U(P)){if(D)K(P,D);let j=(Fe)=>new Date(Fe.getFullYear(),Fe.getMonth(),Fe.getDate()).getTime(),J=j(new Date),Y=new Date(J);Y.setDate(Y.getDate()-(O-1));let re=Y.getTime(),ie=[],de={count:0};for(let Fe of D?zn(D,de):[])for(let en of kt(Fe,de)){let on=new Date(en.ts).getTime();if(!Number.isFinite(on))continue;if(on>=re)ie.push(en)}ie.sort((Fe,en)=>new Date(en.ts).getTime()-new Date(Fe.ts).getTime());let fe=Array.from({length:O},()=>0),we=Array.from({length:O},()=>0),Ce={},Se={},Ie={},Ee=0,qe=0;for(let Fe of ie){let en=Fe.agent||"unknown";Ce[en]=(Ce[en]??0)+1;let on=Math.round((J-j(new Date(Fe.ts)))/86400000),sn=O-1-on,an=on>=0&&on<O;if(an)we[sn]=(we[sn]??0)+1;if(Fe.decision!=="allow"){if(Ee++,Fe.ruleId)Se[Fe.ruleId]=(Se[Fe.ruleId]??0)+1;let rn=ko(Fe.segment||Fe.command);if(rn)Ie[rn]=(Ie[rn]??0)+1;if(Fe.failureStage)qe++;if(an)fe[sn]=(fe[sn]??0)+1}}return{days:O,logsDir:D,homeDir:P.home,totalInWindow:ie.length,truncated:ie.length>yo,unreadable:de.count,counts:{blocked:Ee,allowed:ie.length-Ee,agents:Ce,blockedByDay:fe,analyzedByDay:we,rules:Se,commands:Ie,errors:qe},entries:Ib(ie).sort((Fe,en)=>new Date(en.ts).getTime()-new Date(Fe.ts).getTime())}}import{spawn as _b}from"node:child_process";import{existsSync as Tb,statSync as Fu}from"node:fs";import{delimiter as $b,join as Ob}from"node:path";var Db=120000,vo="Choose the project folder",Lb=`try
288
+ return POSIX path of (choose folder with prompt "${vo}")
287
289
  on error number -128
288
290
  return ""
289
- end try`,Uv=`Add-Type -AssemblyName System.Windows.Forms
291
+ end try`,Nb=`Add-Type -AssemblyName System.Windows.Forms
290
292
  $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
291
- $dialog.Description = '${so}'
292
- if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,su=[{binary:"zenity",args:["--file-selection","--directory",`--title=${so}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",so]}],au=(_,I)=>(I.PATH??"").split(jv).some((O)=>{if(O.length===0)return!1;try{let L=iu(Fv(O,_));return L.isFile()&&(L.mode&73)!==0}catch{return!1}});function Vi(_,I){if(_==="darwin"||_==="win32")return!0;if(_!=="linux")return!1;if(!I.DISPLAY&&!I.WAYLAND_DISPLAY)return!1;return su.some((O)=>au(O.binary,I))}function Gv(_,I){if(_==="darwin")return{cmd:"osascript",args:["-e",Mv]};if(_==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",Uv]};let O=su.find((L)=>au(L.binary,I));return O?{cmd:O.binary,args:O.args}:null}function zi(_=process.platform,I=process.env){let O=Gv(_,I);if(!O)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((L)=>{let J=Lv(O.cmd,O.args,{env:I,stdio:["ignore","pipe","pipe"]}),K="",ne=!1,oe=(ue)=>{if(ne)return;ne=!0,clearTimeout(de),L(ue)},de=setTimeout(()=>{J.kill(),oe({error:"The folder dialog timed out"})},Hv);J.stdout.on("data",(ue)=>{K+=ue.toString()}),J.on("error",()=>oe({error:`Could not open the folder dialog (${O.cmd})`})),J.on("close",()=>{let ue=K.trim().replace(/\/+$/,"");if(!ue)return oe({cancelled:!0});if(!Nv(ue)||!iu(ue).isDirectory())return oe({error:"That selection is not a folder on disk"});oe({path:ue})})})}var lu=`<!doctype html>
293
+ $dialog.Description = '${vo}'
294
+ if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,Hu=[{binary:"zenity",args:["--file-selection","--directory",`--title=${vo}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",vo]}],Mu=(P,O)=>(O.PATH??"").split($b).some((D)=>{if(D.length===0)return!1;try{let j=Fu(Ob(D,P));return j.isFile()&&(j.mode&73)!==0}catch{return!1}});function ls(P,O){if(P==="darwin"||P==="win32")return!0;if(P!=="linux")return!1;if(!O.DISPLAY&&!O.WAYLAND_DISPLAY)return!1;return Hu.some((D)=>Mu(D.binary,O))}function jb(P,O){if(P==="darwin")return{cmd:"osascript",args:["-e",Lb]};if(P==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",Nb]};let D=Hu.find((j)=>Mu(j.binary,O));return D?{cmd:D.binary,args:D.args}:null}function cs(P=process.platform,O=process.env){let D=jb(P,O);if(!D)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((j)=>{let J=_b(D.cmd,D.args,{env:O,stdio:["ignore","pipe","pipe"]}),Y="",re=!1,ie=(fe)=>{if(re)return;re=!0,clearTimeout(de),j(fe)},de=setTimeout(()=>{J.kill(),ie({error:"The folder dialog timed out"})},Db);J.stdout.on("data",(fe)=>{Y+=fe.toString()}),J.on("error",()=>ie({error:`Could not open the folder dialog (${D.cmd})`})),J.on("close",()=>{let fe=Y.trim().replace(/\/+$/,"");if(!fe)return ie({cancelled:!0});if(!Tb(fe)||!Fu(fe).isDirectory())return ie({error:"That selection is not a folder on disk"});ie({path:fe})})})}var Uu=`<!doctype html>
293
295
  <html lang="en">
294
296
  <head>
295
297
  <meta charset="utf-8">
@@ -3269,15 +3271,15 @@ var catalog = [
3269
3271
  {
3270
3272
  id: "copilot-cli",
3271
3273
  displayName: "GitHub Copilot CLI",
3272
- doctorOrder: 8,
3274
+ doctorOrder: 10,
3273
3275
  runtime: {
3274
- order: 6,
3276
+ order: 8,
3275
3277
  flags: ["-cp", "--copilot-cli"],
3276
3278
  description: "Run as GitHub Copilot CLI PreToolUse hook",
3277
3279
  legacyTopLevelFlags: ["-cp", "--copilot-cli"]
3278
3280
  },
3279
3281
  install: {
3280
- order: 8,
3282
+ order: 10,
3281
3283
  flag: "--copilot-cli",
3282
3284
  artifactKind: "plugin",
3283
3285
  probeCommand: ["copilot", "--binary-version"]
@@ -3286,15 +3288,15 @@ var catalog = [
3286
3288
  {
3287
3289
  id: "gemini-cli",
3288
3290
  displayName: "Gemini CLI",
3289
- doctorOrder: 7,
3291
+ doctorOrder: 9,
3290
3292
  runtime: {
3291
- order: 5,
3293
+ order: 7,
3292
3294
  flags: ["-gc", "--gemini-cli"],
3293
3295
  description: "Run as Gemini CLI BeforeTool hook",
3294
3296
  legacyTopLevelFlags: ["-gc", "--gemini-cli"]
3295
3297
  },
3296
3298
  install: {
3297
- order: 7,
3299
+ order: 9,
3298
3300
  flag: "--gemini-cli",
3299
3301
  artifactKind: "extension",
3300
3302
  probeCommand: ["gemini", "--version"]
@@ -3303,15 +3305,15 @@ var catalog = [
3303
3305
  {
3304
3306
  id: "grok-build",
3305
3307
  displayName: "Grok Build",
3306
- doctorOrder: 9,
3308
+ doctorOrder: 11,
3307
3309
  runtime: {
3308
- order: 7,
3310
+ order: 9,
3309
3311
  flags: ["-gb", "--grok-build"],
3310
3312
  description: "Run as Grok Build PreToolUse hook",
3311
3313
  legacyTopLevelFlags: []
3312
3314
  },
3313
3315
  install: {
3314
- order: 9,
3316
+ order: 11,
3315
3317
  flag: "--grok-build",
3316
3318
  artifactKind: "hook config",
3317
3319
  probeCommand: ["grok", "--version"]
@@ -3320,15 +3322,15 @@ var catalog = [
3320
3322
  {
3321
3323
  id: "hermes-agent",
3322
3324
  displayName: "Hermes Agent",
3323
- doctorOrder: 10,
3325
+ doctorOrder: 12,
3324
3326
  runtime: {
3325
- order: 8,
3327
+ order: 10,
3326
3328
  flags: ["-ha", "--hermes-agent"],
3327
3329
  description: "Run as Hermes Agent pre_tool_call hook",
3328
3330
  legacyTopLevelFlags: []
3329
3331
  },
3330
3332
  install: {
3331
- order: 10,
3333
+ order: 12,
3332
3334
  flag: "--hermes-agent",
3333
3335
  artifactKind: "plugin",
3334
3336
  probeCommand: ["hermes", "--version"]
@@ -3337,15 +3339,15 @@ var catalog = [
3337
3339
  {
3338
3340
  id: "kimi-code",
3339
3341
  displayName: "Kimi Code",
3340
- doctorOrder: 11,
3342
+ doctorOrder: 13,
3341
3343
  runtime: {
3342
- order: 9,
3344
+ order: 11,
3343
3345
  flags: ["-kc", "--kimi-code"],
3344
3346
  description: "Run as Kimi Code PreToolUse hook",
3345
3347
  legacyTopLevelFlags: []
3346
3348
  },
3347
3349
  install: {
3348
- order: 11,
3350
+ order: 13,
3349
3351
  flag: "--kimi-code",
3350
3352
  artifactKind: "hook config",
3351
3353
  probeCommand: ["kimi", "--version"]
@@ -3354,9 +3356,9 @@ var catalog = [
3354
3356
  {
3355
3357
  id: "openclaw",
3356
3358
  displayName: "OpenClaw",
3357
- doctorOrder: 12,
3359
+ doctorOrder: 14,
3358
3360
  install: {
3359
- order: 12,
3361
+ order: 14,
3360
3362
  flag: "--openclaw",
3361
3363
  artifactKind: "plugin",
3362
3364
  probeCommand: ["openclaw", "--version"]
@@ -3365,9 +3367,9 @@ var catalog = [
3365
3367
  {
3366
3368
  id: "opencode",
3367
3369
  displayName: "OpenCode",
3368
- doctorOrder: 13,
3370
+ doctorOrder: 15,
3369
3371
  install: {
3370
- order: 13,
3372
+ order: 15,
3371
3373
  flag: "--opencode",
3372
3374
  artifactKind: "plugin",
3373
3375
  probeCommand: ["opencode", "--version"]
@@ -3376,9 +3378,9 @@ var catalog = [
3376
3378
  {
3377
3379
  id: "pi",
3378
3380
  displayName: "Pi",
3379
- doctorOrder: 14,
3381
+ doctorOrder: 16,
3380
3382
  install: {
3381
- order: 14,
3383
+ order: 16,
3382
3384
  flag: "--pi",
3383
3385
  artifactKind: "package",
3384
3386
  probeCommand: ["pi", "--version"]
@@ -3412,6 +3414,40 @@ var catalog = [
3412
3414
  probeCommand: DEEPSEEK_HARNESS_NPM_PROBE
3413
3415
  }
3414
3416
  },
3417
+ {
3418
+ id: "devin",
3419
+ displayName: "Devin CLI",
3420
+ doctorOrder: 7,
3421
+ runtime: {
3422
+ order: 5,
3423
+ flags: ["-dv", "--devin"],
3424
+ description: "Run as Devin CLI PreToolUse hook",
3425
+ legacyTopLevelFlags: []
3426
+ },
3427
+ install: {
3428
+ order: 7,
3429
+ flag: "--devin",
3430
+ artifactKind: "hook config",
3431
+ probeCommand: ["devin", "--version"]
3432
+ }
3433
+ },
3434
+ {
3435
+ id: "droid",
3436
+ displayName: "Factory Droid",
3437
+ doctorOrder: 8,
3438
+ runtime: {
3439
+ order: 6,
3440
+ flags: ["-fd", "--droid"],
3441
+ description: "Run as Factory Droid PreToolUse hook",
3442
+ legacyTopLevelFlags: []
3443
+ },
3444
+ install: {
3445
+ order: 8,
3446
+ flag: "--droid",
3447
+ artifactKind: "hook config",
3448
+ probeCommand: ["droid", "--version"]
3449
+ }
3450
+ },
3415
3451
  {
3416
3452
  id: "amp",
3417
3453
  displayName: "Amp Code",
@@ -5931,6 +5967,6 @@ load().then((loaded) => {
5931
5967
  </script>
5932
5968
  </body>
5933
5969
  </html>
5934
- `;var cu='<script id="ccsn-data" type="application/json">';function du(_){return lu.replace(cu,()=>cu+JSON.stringify({token:_}).replaceAll("<","\\u003c"))}var ao="kenryu42/cc-safety-net",Jv=`https://github.com/${ao}`,Ki=1e4,Wv=7,Kv="The project draft directory changed; reload the draft before applying.",Yv="audit settings are user scope only; remove the audit section from a project proposal";async function gu(_,I={}){let O=gn({label:"gui",booleans:{noOpen:["--no-open"]}},_),L=I.log??console.log,J=I.error??console.error;if(O.errors.length>0){for(let ne of O.errors)J(ne);return J("Usage: cc-safety-net gui [--no-open]"),1}let K=await Zv(c,I);if(L(`CC Safety Net policy GUI: ${K.url}`),!O.flags.noOpen)try{await(I.openBrowser??lb)(K.url)}catch(ne){J(`Failed to open browser: ${ne instanceof Error?ne.message:String(ne)}`),J(`Open this URL manually: ${K.url}`)}if(I.keepAlive===!1)return await K.close(),0;return await ab(K),0}async function Zv(_,I={}){let O=Bv(24).toString("base64url"),L={dir:null,revision:0},J=Vv((oe,de)=>{Xv(_,oe,de,O,I,L)});await new Promise((oe,de)=>{J.once("error",de),J.listen(0,"127.0.0.1",()=>{J.off("error",de),oe()})});let ne=`http://127.0.0.1:${J.address().port}`;return{origin:ne,token:O,url:`${ne}/?token=${encodeURIComponent(O)}`,close:()=>sb(J)}}async function Xv(_,I,O,L,J,K){let ne=_(),oe=new URL(I.url??"/","http://127.0.0.1");if(I.method==="GET"&&oe.pathname==="/favicon.ico"){O.writeHead(204,{"cache-control":"no-store"}),O.end();return}if(!rb(I,oe,L)){ln(O,403,{error:"Forbidden"});return}if(I.method==="GET"&&oe.pathname==="/"){ib(O,du(L));return}if(I.method==="GET"&&oe.pathname==="/api/policy"){let de=dd(ne,J),ue=E(ne,Ji(J));ln(O,200,{...de,configState:$e(ue),...ue.policyScopes?{projectPolicy:{path:b(J.cwd??process.cwd()),weakenings:ue.policyScopes.weakenings}}:{},destructiveCommandRules:W,secretPatterns:Xe,version:un(),preview:de.errors.length>0?null:Ne(de.policy,ne.env)});return}if(I.method==="POST"&&oe.pathname==="/api/policy/preview"){let de=await or(I);if(!de.ok){ln(O,de.status,{errors:[de.error]});return}let ue=ud(ne,de.value);ln(O,ue.errors.length>0?400:200,ue);return}if(I.method==="POST"&&oe.pathname==="/api/policy/explain"){let de=await or(I);if(!de.ok){ln(O,de.status,{errors:[de.error]});return}let ue=de.value;if(ue===null||typeof ue.command!=="string"){ln(O,400,{errors:["command must be a string"]});return}let ve=Qt(ue.policy,ne.home);if(ve.length>0){ln(O,400,{errors:ve});return}ln(O,200,nb(ne,ue.command,ue.policy,J));return}if(I.method==="POST"&&oe.pathname==="/api/policy"){let de=await or(I);if(!de.ok){ln(O,de.status,{errors:[de.error]});return}let ue=Fn(ne,de.value,J);ln(O,ue.errors.length>0?400:200,ue);return}if(I.method==="POST"&&oe.pathname==="/api/reset"){ln(O,200,Fn(ne,ee,J));return}if(I.method==="POST"&&oe.pathname==="/api/repair"){ln(O,200,pd(ne,J));return}if(I.method==="POST"&&oe.pathname==="/api/policy/project/choose-directory"){let de=await(J.chooseDirectory??zi)();if("path"in de)K.dir=de.path,K.revision+=1;ln(O,200,{cancelled:"cancelled"in de,..."error"in de?{error:de.error}:{}});return}if(I.method==="GET"&&oe.pathname==="/api/policy/project"){let de=hu(K,J),ue=uu(de,ne.home),ve=er(ne,J);ln(O,200,{path:b(de),revision:K.revision,baseline:ve.baseline,userPolicyDiagnostics:ve.diagnostics,projection:ue.projection,projectionDiagnostics:ue.diagnostics,canPickDirectory:Vi(process.platform,process.env)});return}if(I.method==="POST"&&oe.pathname==="/api/policy/project/diff"){let de=await pu(ne,I,O,K,J);if(!de)return;let ue=uu(de.dir,ne.home),ve=er(ne,J).baseline,xe=Q(ve,le(de.proposal,ne.home).policy);ln(O,200,{rows:Jr(Q(ve,ue.projection).policy,xe.policy,!1),weakenings:xe.weakenings,existingFileDiagnostics:ue.diagnostics});return}if(I.method==="POST"&&oe.pathname==="/api/policy/project/apply"){let de=await pu(ne,I,O,K,J);if(!de)return;let ue=eb(de.dir,de.proposal,ne.home);ln(O,ue.errors.length>0?500:200,ue);return}if(I.method==="GET"&&oe.pathname==="/api/activity"){let de=re(ne,J),ue=tb(oe.searchParams.get("days"),de);if(ue===null){ln(O,400,{error:`days must be an integer between 1 and ${de}`});return}ln(O,200,ou(ne,ue,J.activityLogsDir));return}if(I.method==="POST"&&oe.pathname==="/api/rules/choose-directory"){ln(O,200,await zi());return}if(I.method==="GET"&&oe.pathname==="/api/rules"){let de=X(ne,Ji(J)),ue=new Map(de.rules.map((ve)=>[ve.name,ve]));ln(O,200,{projectPath:J.cwd??process.cwd(),canPickDirectory:Vi(process.platform,process.env),rulebooks:de.rulebooks.map((ve)=>({source:ve.source,spec:ve.spec,name:ve.name,version:ve.version,rules:ve.rules.flatMap((xe)=>{let Se=ue.get(xe);if(!Se)return[];return[{name:Se.name,command:Se.command,subcommand:Se.subcommand,block_args:Se.block_args,reason:Se.reason}]})})),errors:de.errors,warnings:de.warnings});return}if(I.method==="GET"&&oe.pathname==="/api/star/context"){ln(O,200,await(J.fetchStarContext??(()=>mb(ne,{logsDir:J.activityLogsDir})))());return}if(I.method==="POST"&&oe.pathname==="/api/star"){let de=await(J.starRepo??cb)();ln(O,200,de.ok?{ok:!0}:{ok:!1,fallbackUrl:Jv});return}if(I.method==="GET"&&oe.pathname==="/api/integrations"){ln(O,200,await(J.fetchIntegrations??(()=>db(ne)))());return}if(I.method==="GET"&&oe.pathname==="/api/health"){ln(O,200,await(J.fetchHealth??pb)());return}if(I.method==="POST"&&(oe.pathname==="/api/install"||oe.pathname==="/api/uninstall")){let de=await or(I);if(!de.ok){ln(O,de.status,{errors:[de.error]});return}let ue=de.value?.target;if(typeof ue!=="string"||!$n.some((xe)=>xe.target===ue)){ln(O,400,{error:"unknown target"});return}let ve=oe.pathname==="/api/install"?"install":"uninstall";ln(O,200,await(J.runIntegration??fb)(ve,ue));return}ln(O,404,{error:"Not found"})}function Ji(_){return{..._,cwd:_.cwd??process.cwd()}}function hu(_,I){return _.dir??I.cwd??process.cwd()}function uu(_,I){let O=b(_),L=qv(O)?mt(O):{value:void 0,errors:[]},J=le(L.value,I);return{projection:J.policy,diagnostics:[...L.errors,...J.diagnostics]}}async function pu(_,I,O,L,J){let K=hu(L,J),ne=L.revision,oe=await or(I);if(!oe.ok)return ln(O,oe.status,{errors:[oe.error]}),null;let de=oe.value;if(typeof de?.revision!=="number")return ln(O,400,{errors:["revision must be a number"]}),null;if(de.revision!==ne)return ln(O,409,{errors:[Kv]}),null;let ue=Qv(de.proposal,_.home);if(ue.length>0)return ln(O,400,{errors:ue}),null;return{dir:K,proposal:de.proposal}}function Qv(_,I){let O=Qt(_,I);if(O.length>0)return O;return _?.audit===void 0?[]:[Yv]}function eb(_,I,O){let L=b(_),J=Wr(I,C(I,O));try{return g(i(v(_,"project policy"),L),`${JSON.stringify(J,null,2)}
5935
- `),{path:L,errors:[]}}catch(K){return{path:L,errors:[K instanceof Error?K.message:String(K)]}}}function nb(_,I,O,L){let J=C(O,_.home),K=E(_,Ji(L)),ne=Te({rules:K.policy.rules,transparentWrappers:K.policy.transparentWrappers,safety:Me(J.safety),worktreeMode:J.workflow.worktree_mode,destructiveCommandProtectionEnabled:J.destructive_command_protection.enabled,destructiveCommandRuleOverrides:J.destructive_command_protection.overrides,destructiveCommandAllowPaths:J.destructive_command_protection.allow_paths,secretProtection:{enabled:J.secret_protection.enabled,disabledRules:Fe(J.secret_protection.overrides),denyPaths:J.secret_protection.deny_paths,allowPaths:J.secret_protection.allow_paths}});return zt(I,{policySnapshot:ne,cwd:L.cwd,userConfigDir:L.userConfigDir},_)}function tb(_,I){if(_===null)return Math.min(Wv,I);let O=Number(_);if(!Number.isInteger(O)||O<1||O>I)return null;return O}function rb(_,I,O){if(I.searchParams.get("token")!==O)return!1;if(_.method!=="POST")return!0;return _.headers["x-cc-safety-net-token"]===O}var ob=1048576;async function or(_){let I=[],O=0;for await(let L of _){let J=L;if(O+=J.byteLength,O>ob)return{ok:!1,status:413,error:"Request body is too large"};I.push(J)}try{return{ok:!0,value:JSON.parse(Buffer.concat(I).toString("utf-8")||"{}")}}catch(L){return{ok:!1,status:400,error:`Invalid JSON: ${L instanceof Error?L.message:String(L)}`}}}function ib(_,I){_.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),_.end(I)}function ln(_,I,O){_.writeHead(I,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),_.end(JSON.stringify(O))}function sb(_){return new Promise((I,O)=>{_.close((L)=>L?O(L):I())})}function ab(_){return new Promise((I)=>{let O=()=>{process.off("SIGINT",L),process.off("SIGTERM",L)},L=()=>{O(),_.close().then(I)};process.once("SIGINT",L),process.once("SIGTERM",L)})}function lb(_){let I=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",O=process.platform==="win32"?["/c","start","",_]:[_];return new Promise((L,J)=>{let K=mu(I,O,{detached:!0,stdio:"ignore"}),ne=(de)=>{K.off("spawn",oe),J(de)},oe=()=>{K.off("error",ne),K.unref(),L()};K.once("error",ne),K.once("spawn",oe)})}async function cb(_="gh",I=Ki){return{ok:await Wi(_,["api","-X","PUT",`/user/starred/${ao}`],I)===0}}async function db(_,I={}){let O=await gr((J)=>Ct({environment:_,cwd:process.cwd(),openCodeVersion:J}).status!=="n/a",I.fetcher),L=ub(_,O);return{targets:En.map((J)=>{let K=L.find((ne)=>ne.platform===J.id);return{target:J.id,label:fn(J.id),version:O.versions[J.id]??null,status:K?.configured?"active":K?.detected?"disabled":K?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:O.version,nodeVersion:O.nodeVersion,platform:O.platform}}}function ub(_,I){return Rt(_,process.cwd(),{ampPluginListOutput:I.ampPluginListOutput,codexPluginListOutput:I.codexPluginListOutput,copilotCliVersion:I.versions["copilot-cli"],openCodeVersion:I.versions.opencode,openCodePluginListOutput:I.openCodePluginListOutput})}async function pb(_={}){let I=await(_.checkUpdates??Un)();return{update:{latestVersion:I.latestVersion??null,updateAvailable:I.updateAvailable}}}var fu=Promise.resolve();function fb(_,I,O={}){let L=async()=>{let K=[],{log:ne,error:oe}=console;console.log=(...de)=>K.push(de.map(String).join(" ")),console.error=console.log;try{return{ok:await Xt(_,[],{selectTargets:async()=>[I],output:new zv({write(ue,ve,xe){K.push(String(ue).replace(/\n$/,"")),xe()}}),...O})===0,output:K.join(`
5936
- `)}}finally{console.log=ne,console.error=oe}},J=fu.then(L);return fu=J.then(()=>{return},()=>{return}),J}async function mb(_,I={}){let[O,L,J]=await Promise.all([gb(I.command),hb(I.fetchRepo),Promise.resolve(dr(_,re(_),I.logsDir).totalBlocked)]);return{starred:O,starCount:L,blockedTotal:J}}async function gb(_="gh",I=Ki){if(await Wi(_,["auth","status"],I)!==0)return null;let O=await Wi(_,["api",`/user/starred/${ao}`],I);if(O===0)return!0;if(O===null)return null;return!1}function Wi(_,I,O){return new Promise((L)=>{let J=mu(_,I,{stdio:"ignore",windowsHide:!0}),K=!1,ne=setTimeout(()=>{J.kill(),oe(null)},O),oe=(de)=>{if(K)return;K=!0,clearTimeout(ne),L(de)};J.once("error",()=>oe(null)),J.once("close",oe)})}async function hb(_=fetch){try{let I=await _(`https://api.github.com/repos/${ao}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(Ki)});if(!I.ok)return null;let O=await I.json();return typeof O.stargazers_count==="number"?O.stargazers_count:null}catch{return null}}function yb(_){if(_[0]!=="help")return!1;let I=_[1];if(!I)vi(),process.exit(0);if(Jt(I))process.exit(0);console.error(`Unknown command: ${I}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var vb={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),Jt("hook",console.error),process.exit(1)},install:async(_)=>{process.exit(await Xt("install",_))},update:async(_)=>{process.exit(await Oi(_))},uninstall:async(_)=>{process.exit(await Xt("uninstall",_))},rule:async(_)=>{process.exit(await nu(c(),_))},policy:async(_)=>{process.exit(await hd(c(),_))},status:async(_)=>{if(On(gn({label:"status"},_).errors))process.exit(1);ru(c())},statusline:async(_)=>{let I=gn({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},_);if(I.errors.length===0&&I.flags.claudeCode){await qi(c());return}if(On(I.errors),!I.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");Jt("statusline",console.error),process.exit(1)},doctor:async(_)=>{let I=di(_);if(!I)process.exit(1);let O=await $l(c(),{json:I.json,skipUpdateCheck:I.skipUpdateCheck});process.exit(O)},logs:async(_)=>{process.exit(await rs(c(),_))},gui:async(_)=>{process.exit(await gu(_))},explain:async(_)=>{process.exit(await Bl(c(),_))}};async function bb(_){let I=gn({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},_);if(yb(_))return;let O=_[0],L=O?cr(O):void 0;if(I.help&&L&&L.name!=="rule")Jt(L.name),process.exit(0);if(!O||I.help&&!L)vi(),process.exit(0);if(I.flags.version)zl(),process.exit(0);if(L){await vb[L.name](_.slice(1));return}if(O==="--statusline"){await qi(c());return}console.error(O.startsWith("-")?`Unknown option: ${O}`:`Unknown command: ${O}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{bb as runCli};
5970
+ `;var Gu='<script id="ccsn-data" type="application/json">';function Bu(P){return Uu.replace(Gu,()=>Gu+JSON.stringify({token:P}).replaceAll("<","\\u003c"))}var bo="kenryu42/cc-safety-net",Gb=`https://github.com/${bo}`,ps=1e4,Bb=7,qb="The project draft directory changed; reload the draft before applying.",Vb="audit settings are user scope only; remove the audit section from a project proposal";async function Ku(P,O={}){let D=gn({label:"gui",booleans:{noOpen:["--no-open"]}},P),j=O.log??console.log,J=O.error??console.error;if(D.errors.length>0){for(let re of D.errors)J(re);return J("Usage: cc-safety-net gui [--no-open]"),1}let Y=await Jb(c,O);if(j(`CC Safety Net policy GUI: ${Y.url}`),!D.flags.noOpen)try{await(O.openBrowser??rw)(Y.url)}catch(re){J(`Failed to open browser: ${re instanceof Error?re.message:String(re)}`),J(`Open this URL manually: ${Y.url}`)}if(O.keepAlive===!1)return await Y.close(),0;return await tw(Y),0}async function Jb(P,O={}){let D=Fb(24).toString("base64url"),j={dir:null,revision:0},J=Mb((ie,de)=>{zb(P,ie,de,D,O,j)});await new Promise((ie,de)=>{J.once("error",de),J.listen(0,"127.0.0.1",()=>{J.off("error",de),ie()})});let re=`http://127.0.0.1:${J.address().port}`;return{origin:re,token:D,url:`${re}/?token=${encodeURIComponent(D)}`,close:()=>nw(J)}}async function zb(P,O,D,j,J,Y){let re=P(),ie=new URL(O.url??"/","http://127.0.0.1");if(O.method==="GET"&&ie.pathname==="/favicon.ico"){D.writeHead(204,{"cache-control":"no-store"}),D.end();return}if(!Xb(O,ie,j)){ln(D,403,{error:"Forbidden"});return}if(O.method==="GET"&&ie.pathname==="/"){ew(D,Bu(j));return}if(O.method==="GET"&&ie.pathname==="/api/policy"){let de=Bd(re,J),fe=E(re,ds(J));ln(D,200,{...de,configState:je(fe),...fe.policyScopes?{projectPolicy:{path:h(J.cwd??process.cwd()),weakenings:fe.policyScopes.weakeningsIgnored?[]:fe.policyScopes.weakenings}}:{},destructiveCommandRules:z,secretPatterns:Qe,version:pn(),preview:de.errors.length>0?null:Le(de.policy,re.env)});return}if(O.method==="POST"&&ie.pathname==="/api/policy/preview"){let de=await ur(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=qd(re,de.value);ln(D,fe.errors.length>0?400:200,fe);return}if(O.method==="POST"&&ie.pathname==="/api/policy/explain"){let de=await ur(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=de.value;if(fe===null||typeof fe.command!=="string"){ln(D,400,{errors:["command must be a string"]});return}let we=sr(fe.policy,re.home);if(we.length>0){ln(D,400,{errors:we});return}ln(D,200,Yb(re,fe.command,fe.policy,J));return}if(O.method==="POST"&&ie.pathname==="/api/policy"){let de=await ur(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=Hn(re,de.value,J);ln(D,fe.errors.length>0?400:200,fe);return}if(O.method==="POST"&&ie.pathname==="/api/reset"){ln(D,200,Hn(re,te,J));return}if(O.method==="POST"&&ie.pathname==="/api/repair"){ln(D,200,Vd(re,J));return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/choose-directory"){let de=await(J.chooseDirectory??cs)();if("path"in de)Y.dir=de.path,Y.revision+=1;ln(D,200,{cancelled:"cancelled"in de,..."error"in de?{error:de.error}:{}});return}if(O.method==="GET"&&ie.pathname==="/api/policy/project"){let de=Wu(Y,J),fe=Yu(re,de,J),we=fe?{projection:{},diagnostics:[fe]}:qu(de,re.home),Ce=ar(re,J);ln(D,200,{path:h(de),revision:Y.revision,baseline:Ce.baseline,userPolicyDiagnostics:Ce.diagnostics,projection:we.projection,projectionDiagnostics:we.diagnostics,canPickDirectory:ls(process.platform,process.env)});return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/diff"){let de=await Vu(re,O,D,Y,J);if(!de)return;let fe=qu(de.dir,re.home),we=ar(re,J).baseline,Ce=ee(we,ue(de.proposal,re.home).policy);ln(D,200,{rows:oo(ee(we,fe.projection).policy,Ce.policy,!1),weakenings:Ce.weakenings,existingFileDiagnostics:fe.diagnostics});return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/apply"){let de=await Vu(re,O,D,Y,J);if(!de)return;let fe=Wb(de.dir,de.proposal,re.home);ln(D,fe.errors.length>0?500:200,fe);return}if(O.method==="GET"&&ie.pathname==="/api/activity"){let de=oe(re,J),fe=Zb(ie.searchParams.get("days"),de);if(fe===null){ln(D,400,{error:`days must be an integer between 1 and ${de}`});return}ln(D,200,ju(re,fe,J.activityLogsDir));return}if(O.method==="POST"&&ie.pathname==="/api/rules/choose-directory"){ln(D,200,await cs());return}if(O.method==="GET"&&ie.pathname==="/api/rules"){let de=Q(re,ds(J)),fe=new Map(de.rules.map((we)=>[we.name,we]));ln(D,200,{projectPath:J.cwd??process.cwd(),canPickDirectory:ls(process.platform,process.env),rulebooks:de.rulebooks.map((we)=>({source:we.source,spec:we.spec,name:we.name,version:we.version,rules:we.rules.flatMap((Ce)=>{let Se=fe.get(Ce);if(!Se)return[];return[{name:Se.name,command:Se.command,subcommand:Se.subcommand,block_args:Se.block_args,reason:Se.reason}]})})),errors:de.errors,warnings:de.warnings});return}if(O.method==="GET"&&ie.pathname==="/api/star/context"){ln(D,200,await(J.fetchStarContext??(()=>cw(re,{logsDir:J.activityLogsDir})))());return}if(O.method==="POST"&&ie.pathname==="/api/star"){let de=await(J.starRepo??ow)();ln(D,200,de.ok?{ok:!0}:{ok:!1,fallbackUrl:Gb});return}if(O.method==="GET"&&ie.pathname==="/api/integrations"){ln(D,200,await(J.fetchIntegrations??(()=>iw(re)))());return}if(O.method==="GET"&&ie.pathname==="/api/health"){ln(D,200,await(J.fetchHealth??aw)());return}if(O.method==="POST"&&(ie.pathname==="/api/install"||ie.pathname==="/api/uninstall")){let de=await ur(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=de.value?.target;if(typeof fe!=="string"||!$n.some((Ce)=>Ce.target===fe)){ln(D,400,{error:"unknown target"});return}let we=ie.pathname==="/api/install"?"install":"uninstall";ln(D,200,await(J.runIntegration??lw)(we,fe));return}ln(D,404,{error:"Not found"})}function ds(P){return{...P,cwd:P.cwd??process.cwd()}}function Wu(P,O){return P.dir??O.cwd??process.cwd()}function Yu(P,O,D){if(!L(P,{...D,cwd:O}))return null;return`${h(O)} is the user policy, not a project policy; choose a project directory, or run the GUI from one`}function qu(P,O){let D=h(P),j=Hb(D)?bt(D):{value:void 0,errors:[]},J=ue(j.value,O);return{projection:J.policy,diagnostics:[...j.errors,...J.diagnostics]}}async function Vu(P,O,D,j,J){let Y=Wu(j,J),re=j.revision,ie=await ur(O);if(!ie.ok)return ln(D,ie.status,{errors:[ie.error]}),null;let de=ie.value;if(typeof de?.revision!=="number")return ln(D,400,{errors:["revision must be a number"]}),null;if(de.revision!==re)return ln(D,409,{errors:[qb]}),null;let fe=Yu(P,Y,J);if(fe)return ln(D,400,{errors:[fe]}),null;let we=Kb(de.proposal,P.home);if(we.length>0)return ln(D,400,{errors:we}),null;return{dir:Y,proposal:de.proposal}}function Kb(P,O){let D=sr(P,O);if(D.length>0)return D;return P?.audit===void 0?[]:[Vb]}function Wb(P,O,D){let j=h(P),J=io(O,C(O,D));try{return g(i(v(P,"project policy"),j),`${JSON.stringify(J,null,2)}
5971
+ `),{path:j,errors:[]}}catch(Y){return{path:j,errors:[Y instanceof Error?Y.message:String(Y)]}}}function Yb(P,O,D,j){let J=C(D,P.home),Y=E(P,ds(j)),re=_e({rules:Y.policy.rules,transparentWrappers:Y.policy.transparentWrappers,safety:$e(J.safety),worktreeMode:J.workflow.worktree_mode,destructiveCommandProtectionEnabled:J.destructive_command_protection.enabled,destructiveCommandRuleOverrides:J.destructive_command_protection.overrides,destructiveCommandAllowPaths:J.destructive_command_protection.allow_paths,secretProtection:{enabled:J.secret_protection.enabled,disabledRules:Me(J.secret_protection.overrides),denyPaths:J.secret_protection.deny_paths,allowPaths:J.secret_protection.allow_paths}});return Qt(O,{policySnapshot:re,cwd:j.cwd,userConfigDir:j.userConfigDir},P)}function Zb(P,O){if(P===null)return Math.min(Bb,O);let D=Number(P);if(!Number.isInteger(D)||D<1||D>O)return null;return D}function Xb(P,O,D){if(O.searchParams.get("token")!==D)return!1;if(P.method!=="POST")return!0;return P.headers["x-cc-safety-net-token"]===D}var Qb=1048576;async function ur(P){let O=[],D=0;for await(let j of P){let J=j;if(D+=J.byteLength,D>Qb)return{ok:!1,status:413,error:"Request body is too large"};O.push(J)}try{return{ok:!0,value:JSON.parse(Buffer.concat(O).toString("utf-8")||"{}")}}catch(j){return{ok:!1,status:400,error:`Invalid JSON: ${j instanceof Error?j.message:String(j)}`}}}function ew(P,O){P.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),P.end(O)}function ln(P,O,D){P.writeHead(O,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),P.end(JSON.stringify(D))}function nw(P){return new Promise((O,D)=>{P.close((j)=>j?D(j):O())})}function tw(P){return new Promise((O)=>{let D=()=>{process.off("SIGINT",j),process.off("SIGTERM",j)},j=()=>{D(),P.close().then(O)};process.once("SIGINT",j),process.once("SIGTERM",j)})}function rw(P){let O=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",D=process.platform==="win32"?["/c","start","",P]:[P];return new Promise((j,J)=>{let Y=zu(O,D,{detached:!0,stdio:"ignore"}),re=(de)=>{Y.off("spawn",ie),J(de)},ie=()=>{Y.off("error",re),Y.unref(),j()};Y.once("error",re),Y.once("spawn",ie)})}async function ow(P="gh",O=ps){return{ok:await us(P,["api","-X","PUT",`/user/starred/${bo}`],O)===0}}async function iw(P,O={}){let D=await xr((J)=>Ot({environment:P,cwd:process.cwd(),openCodeVersion:J}).status!=="n/a",O.fetcher),j=sw(P,D);return{targets:En.map((J)=>{let Y=j.find((re)=>re.platform===J.id);return{target:J.id,label:mn(J.id),version:D.versions[J.id]??null,status:Y?.configured?"active":Y?.detected?"disabled":Y?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:D.version,nodeVersion:D.nodeVersion,platform:D.platform}}}function sw(P,O){return Dt(P,process.cwd(),{ampPluginListOutput:O.ampPluginListOutput,codexPluginListOutput:O.codexPluginListOutput,copilotCliVersion:O.versions["copilot-cli"],openCodeVersion:O.versions.opencode,openCodePluginListOutput:O.openCodePluginListOutput})}async function aw(P={}){let O=await(P.checkUpdates??Gn)();return{update:{latestVersion:O.latestVersion??null,updateAvailable:O.updateAvailable}}}var Ju=Promise.resolve();function lw(P,O,D={}){let j=async()=>{let Y=[],{log:re,error:ie}=console;console.log=(...de)=>Y.push(de.map(String).join(" ")),console.error=console.log;try{return{ok:await ir(P,[],{selectTargets:async()=>[O],output:new Ub({write(fe,we,Ce){Y.push(String(fe).replace(/\n$/,"")),Ce()}}),...D})===0,output:Y.join(`
5972
+ `)}}finally{console.log=re,console.error=ie}},J=Ju.then(j);return Ju=J.then(()=>{return},()=>{return}),J}async function cw(P,O={}){let[D,j,J]=await Promise.all([dw(O.command),uw(O.fetchRepo),Promise.resolve(yr(P,oe(P),O.logsDir).totalBlocked)]);return{starred:D,starCount:j,blockedTotal:J}}async function dw(P="gh",O=ps){if(await us(P,["auth","status"],O)!==0)return null;let D=await us(P,["api",`/user/starred/${bo}`],O);if(D===0)return!0;if(D===null)return null;return!1}function us(P,O,D){return new Promise((j)=>{let J=zu(P,O,{stdio:"ignore",windowsHide:!0}),Y=!1,re=setTimeout(()=>{J.kill(),ie(null)},D),ie=(de)=>{if(Y)return;Y=!0,clearTimeout(re),j(de)};J.once("error",()=>ie(null)),J.once("close",ie)})}async function uw(P=fetch){try{let O=await P(`https://api.github.com/repos/${bo}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(ps)});if(!O.ok)return null;let D=await O.json();return typeof D.stargazers_count==="number"?D.stargazers_count:null}catch{return null}}function pw(P){if(P[0]!=="help")return!1;let O=P[1];if(!O)Li(),process.exit(0);if(er(O))process.exit(0);console.error(`Unknown command: ${O}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var fw={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),er("hook",console.error),process.exit(1)},install:async(P)=>{process.exit(await ir("install",P))},update:async(P)=>{process.exit(await Yi(P))},uninstall:async(P)=>{process.exit(await ir("uninstall",P))},rule:async(P)=>{process.exit(await Du(c(),P))},policy:async(P)=>{process.exit(await Wd(c(),P))},status:async(P)=>{if(Dn(gn({label:"status"},P).errors))process.exit(1);Nu(c())},statusline:async(P)=>{let O=gn({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},P);if(O.errors.length===0&&O.flags.claudeCode){await as(c());return}if(Dn(O.errors),!O.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");er("statusline",console.error),process.exit(1)},doctor:async(P)=>{let O=Ei(P);if(!O)process.exit(1);let D=await uc(c(),{json:O.json,skipUpdateCheck:O.skipUpdateCheck});process.exit(D)},logs:async(P)=>{process.exit(await ws(c(),P))},gui:async(P)=>{process.exit(await Ku(P))},explain:async(P)=>{process.exit(await xc(c(),P))}};async function mw(P){let O=gn({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},P);if(pw(P))return;let D=P[0],j=D?hr(D):void 0;if(O.help&&j&&j.name!=="rule")er(j.name),process.exit(0);if(!D||O.help&&!j)Li(),process.exit(0);if(O.flags.version)Rc(),process.exit(0);if(j){await fw[j.name](P.slice(1));return}if(D==="--statusline"){await as(c());return}console.error(D.startsWith("-")?`Unknown option: ${D}`:`Unknown command: ${D}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{mw as runCli};