cc-safety-net 2.4.0 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,47 +1,47 @@
1
- import{n,a,Oe,Ye,R,ot,Je,l,i,Ze,P,_,Le,st,f,Xe,u,o,S,s,D,r,y,ue,G,lt,ct,c,pe,fe,dt,O,Y,ie,x,ut,A,w,me,T,d,H,Qe,et,N,L,I,J,ge,Me,pt,m,e,g,$e,ke,tt,nt,se,Ee,ae,Fe,Z,W,Re,je,he,Pe,U,rt,_e,Ae,Te,Ie,ye,ve,B,X,Q,le,h,z,Ge,We,Ue,k,Be,De,ze,v,t,ee,be,b,C,E,ft,Ve,qe,p,V}from"./chunks/index-chc1n91k.js";import{ne,q,Ke,M,F}from"./chunks/index-ver1bgty.js";var su=["-h","--help"];function At(j,K){let te=Object.entries(j.booleans??{}),re=Object.entries(j.values??{}),oe=Object.entries(j.lists??{}),ce=Object.fromEntries(te.map(([He])=>[He,!1])),de={},we=Object.fromEntries(oe.map(([He])=>[He,[]])),xe=[],Ce=[],Se=!1,Ne=-1;for(let[He,at]of K.entries()){if(He<=Ne)continue;if(at==="--"){xe.push(...K.slice(He+1));break}if(su.includes(at)){Se=!0;continue}let mt=te.find(([,ht])=>ht.includes(at));if(mt){ce[mt[0]]=!0;continue}let it=re.find(([,ht])=>ht.includes(at));if(it){let ht=K[He+1];if(ht===void 0||ht.startsWith("-")){Ce.push(`${at} requires a value`);continue}de[it[0]]=ht,Ne=He+1;continue}let gt=oe.find(([,ht])=>ht.includes(at));if(gt){let ht=K.slice(He+1),vt=ht.findIndex((kt)=>kt.startsWith("-")),yt=ht.slice(0,vt===-1?ht.length:vt);if(yt.length===0){Ce.push(`${at} requires at least one value`);continue}we[gt[0]]=[...we[gt[0]]??[],...yt],Ne=He+yt.length;continue}if(at.startsWith("-")){Ce.push(`Unknown option for ${j.label}: ${at}`);continue}if(j.positionals==="tail"){xe.push(...K.slice(He));break}xe.push(at)}if(j.positionals!=="list"&&j.positionals!=="tail")Ce.push(...xe.map((He)=>`Unexpected argument for ${j.label}: ${He}`));return{flags:ce,values:de,lists:we,positionals:xe,help:Se,errors:Ce}}function Kt(j){for(let K of j)console.error(K);return j.length>0}import{readdirSync as fu,statSync as Zi,unlinkSync as mu}from"node:fs";import{basename as Xi,dirname as gu,isAbsolute as yu,join as hu,relative as vu,resolve as bu,sep as Lu}from"node:path";import{existsSync as au,readdirSync as lu,readFileSync as cu}from"node:fs";import{join as du}from"node:path";var Wi=(j)=>{let K=Date.now()-new Date(j).getTime();if(!Number.isFinite(K))return"";let te=Math.floor(K/60000),re=Math.floor(te/60),oe=Math.floor(re/24);if(oe>0)return`${oe}d ago`;if(re>0)return`${re}h ago`;if(te>0)return`${te}m ago`;return"just now"},dr=(j)=>{let K=(j??"").trim().split(/\s+/).filter((oe)=>oe&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(oe)),te=K[0]?.split("/").pop();if(!te)return null;let re=K[1];return re&&/^[a-z][a-z0-9-]*$/.test(re)?`${te} ${re}`:te};function an(j,K){try{return lu(j,{withFileTypes:!0,encoding:"utf8"}).flatMap((te)=>{let re=du(j,te.name);if(te.isDirectory())return an(re,K);if(te.name.endsWith(".jsonl"))return[re];return[]})}catch{if(K&&au(j))K.count++;return[]}}function Ki(j){let K=(oe)=>`${oe.sessionId}
2
- ${dr(oe.segment||oe.command)}`,te=j.filter((oe)=>oe.decision!=="allow"),re=te.filter((oe)=>oe.sessionId).reduce((oe,ce)=>oe.set(K(ce),(oe.get(K(ce))??0)+1),new Map);return new Set(te.filter((oe)=>oe.failureStage||(re.get(K(oe))??0)>=2))}var uu=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function pu(j){if(!j||typeof j!=="object"||Array.isArray(j))return!1;let K=j;if(typeof K.ts!=="string"||typeof K.command!=="string")return!1;return uu.every((te)=>K[te]===void 0||typeof K[te]==="string")}function wn(j,K){try{return cu(j,"utf-8").split(`
3
- `).filter(Boolean).flatMap((te)=>{try{let re=JSON.parse(te);if(!pu(re)){if(K)K.count++;return[]}return[re]}catch{if(K)K.count++;return[]}})}catch{if(K)K.count++;return[]}}function _t(j){return Array.from(j,(K)=>{let te=K.charCodeAt(0);if(te<=31||te>=127&&te<=159)return`\\x${te.toString(16).padStart(2,"0")}`;return K}).join("")}function wu(j,K){let te=ne(j),re=At({label:"logs",booleans:{all:["--all"],suspect:["--suspect"],json:["--json"],pruneLegacy:["--prune-legacy"],dryRun:["--dry-run"]},values:{id:["--id"],limit:["--limit"],since:["--since"],agent:["--agent"],rule:["--rule"],session:["--session"],project:["--project"]}},K);if(Kt(re.errors))return null;if(re.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(re.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let oe=re.values.limit===void 0?20:Yi(re.values.limit);if(oe===null)return console.error("--limit must be a positive number"),null;let ce=re.values.since===void 0?Math.min(30,te):Yi(re.values.since);if(ce===null||ce>te)return console.error(`--since must be a positive number of days no greater than ${te}`),null;let de={limit:oe,limitExplicit:re.values.limit!==void 0,since:ce,sinceExplicit:re.values.since!==void 0,all:re.flags.all,json:re.flags.json,suspect:re.flags.suspect,pruneLegacy:re.flags.pruneLegacy,dryRun:re.flags.dryRun,id:re.values.id,agent:re.values.agent,rule:re.values.rule,session:re.values.session,project:re.values.project===void 0?void 0:bu(re.values.project)};if(de.id&&(de.agent!==void 0||de.rule!==void 0||de.session!==void 0||de.project!==void 0||de.suspect||de.sinceExplicit||de.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(de.pruneLegacy&&(de.id!==void 0||de.agent!==void 0||de.rule!==void 0||de.session!==void 0||de.project!==void 0||de.suspect||de.all||de.sinceExplicit||de.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(de.dryRun&&!de.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return de}async function Qi(j,K,te={}){let re=wu(j,K);if(!re)return 1;let oe=te.logsDir??M(j);if(re.pruneLegacy)return ku(oe,re.json,re.dryRun);if(!oe)return console.log(re.json?"[]":re.id?`No retained audit log entry found for id ${_t(re.id)}.`:"No audit log entries found."),0;q(j,oe);let ce={count:0},de=an(oe,ce).flatMap((Ne)=>wn(Ne,ce).map((He)=>({entry:He,file:Ne})));if(ce.count>0)console.error(`warning: ${ce.count} audit log ${ce.count===1?"source":"sources"} could not be read; these results are incomplete`);if(re.id)return Ru(de,re,te.timeZone);let we=Date.now()-re.since*24*60*60*1000,xe=de.filter((Ne)=>Pu(Ne,re,oe,we)),Ce=re.suspect?Ki(xe.map((Ne)=>Ne.entry)):null,Se=(Ce?xe.filter((Ne)=>Ce.has(Ne.entry)):xe).sort((Ne,He)=>Date.parse(He.entry.ts)-Date.parse(Ne.entry.ts)).slice(0,re.limit);if(re.json)return console.log(JSON.stringify(Se.map((Ne)=>Ne.entry),null,2)),0;if(Se.length===0)return console.log("No audit log entries found."),0;for(let Ne of Se)console.log(Au(Ne.entry,te.timeZone));return 0}function ku(j,K,te){let re=j?Cu(j).map((we)=>hu(j,we)):[];if(te)return xu(re,K);let oe=[],ce=0,de=0;for(let we of re){let xe=Zi(we,{throwIfNoEntry:!1})?.size??0,Ce=Su(we);if(Ce){oe.push(`${Xi(we)}: ${Ce}`);continue}ce++,de+=xe}if(K)return console.log(JSON.stringify({removedFiles:ce,removedBytes:de,failedFiles:oe.length})),oe.length===0?0:1;console.log(ce===0&&oe.length===0?"No legacy audit log files found.":`Removed ${ce} legacy audit log ${ce===1?"file":"files"} (${es(de)}).`);for(let we of oe)console.error(`Could not remove ${_t(we)}`);if(console.log("Nested v2 audit logs were not changed."),ce>0)console.log("This deletion cannot be undone.");return oe.length===0?0:1}function xu(j,K){let te=j.reduce((re,oe)=>re+(Zi(oe,{throwIfNoEntry:!1})?.size??0),0);if(K)return console.log(JSON.stringify({dryRun:!0,files:j.length,bytes:te})),0;if(console.log(j.length===0?"No legacy audit log files found.":`Would remove ${j.length} legacy audit log ${j.length===1?"file":"files"} (${es(te)}).`),console.log("Nested v2 audit logs are not included."),j.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Cu(j){try{return fu(j,{withFileTypes:!0}).filter((K)=>K.isFile()&&K.name.endsWith(".jsonl")).map((K)=>K.name)}catch{return[]}}function Su(j){try{return mu(j),null}catch(K){return K instanceof Error?K.message:String(K)}}function es(j){let K=["B","KiB","MiB","GiB"],te=Math.min(Math.floor(Math.log2(Math.max(j,1))/10),K.length-1);return`${Math.round(j/1024**te*10)/10} ${K[te]}`}function Ru(j,K,te){let re=j.filter((ce)=>ce.entry.id===K.id);if(re.length>1)return console.error(`Multiple audit log entries found for id ${_t(K.id??"")}.`),1;if(K.json)return console.log(JSON.stringify(re.map((ce)=>ce.entry),null,2)),0;let oe=re[0];if(!oe)return console.log(`No retained audit log entry found for id ${_t(K.id??"")}.`),0;return console.log(_u(oe.entry,te)),0}function Pu(j,K,te,re){if(!K.all&&j.entry.decision==="allow")return!1;if(Date.parse(j.entry.ts)<re)return!1;if(K.agent!==void 0&&j.entry.agent!==K.agent)return!1;if(K.rule!==void 0&&j.entry.ruleId!==K.rule)return!1;if(K.session!==void 0&&!Eu(j,te,K.session))return!1;if(K.project!==void 0&&!Du(j.entry.cwd,K.project))return!1;return!0}function Eu(j,K,te){if(j.entry.sessionId===te)return!0;return gu(j.file)===K&&Xi(j.file,".jsonl")===te}function Du(j,K){if(!j)return!1;let te=vu(K,j);return te!==".."&&!te.startsWith(`..${Lu}`)&&!yu(te)}function Au(j,K){let te=_t(j.id??"-"),re=_t(j.decision??"deny"),oe=j.cwd?` [${_t(j.cwd)}]`:"",ce=j.segment||j.command,de=ce===j.command?"":"↳ ",we=ce.length>50?`${ce.slice(0,50)}…`:ce;return`${te.padEnd(16)} ${_t(ts(j.ts,K))} ${re.padEnd(5)} ${_t(j.agent??"-").padEnd(15)} ${_t(j.ruleId??"-").padEnd(20)} ${de}${_t(we)}${oe}`}function _u(j,K){let te=(oe)=>_t(oe===void 0||oe===null||oe===""?"-":oe),re=j.shape?`${j.agent??"-"} (shape: ${j.shape})`:j.agent??"-";return[`id: ${te(j.id)}`,`ts: ${te(ts(j.ts,K))}`,`decision: ${te(j.decision)}`,`agent: ${te(re)}`,`level: ${te(j.level)}`,`tool: ${te(j.toolName)}`,`rule: ${te(j.ruleId)}`,`intent: ${te(j.intent)}`,`stage: ${te(j.failureStage)}`,`error: ${te(j.errorCode)}`,`session: ${te(j.sessionId)}`,`cwd: ${te(j.cwd)}`,`version: ${te(j.v)}`,`truncated: ${te(j.truncated===!0?"yes":void 0)}`,`reason: ${te(j.reason)}`,`command: ${te(j.command)}`,`segment: ${te(j.segment)}`].join(`
4
- `)}function ts(j,K){let te=new Date(j);if(Number.isNaN(te.getTime()))return j;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:K}).format(te)}function Yi(j){let K=Number(j);return Number.isFinite(K)&&K>0?K:null}var ns={name:"doctor",aliases:["--doctor"],description:"Run diagnostic checks to verify installation and configuration",usage:"doctor [options]",options:[{flags:"--json",description:"Output diagnostics as JSON"},{flags:"--skip-update-check",description:"Skip npm registry version check"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net doctor","cc-safety-net doctor --json","cc-safety-net doctor --skip-update-check"]};var rs={name:"explain",description:"Show step-by-step analysis trace of how a command would be analyzed",usage:"explain [options] <command>",argument:"<command>",options:[{flags:"--json",description:"Output analysis as JSON"},{flags:"--cwd",argument:"<path>",description:"Use custom working directory"},{flags:"-h, --help",description:"Show this help"}],examples:['cc-safety-net explain "git reset --hard"','cc-safety-net explain --json "rm -rf /"','cc-safety-net explain --cwd /tmp "git status"']};var os={name:"gui",description:"Open the local policy editor GUI",usage:"gui [options]",options:[{flags:"--no-open",description:"Print the URL without opening a browser"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net gui","cc-safety-net gui --no-open"]};var Nn=[{id:"antigravity-cli",displayName:"Antigravity CLI",doctorOrder:3,runtime:{order:1,flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:2,flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",doctorOrder:1,runtime:{order:2,displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{order:3,flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",doctorOrder:4,runtime:{order:3,flags:["-cx","--codex"],description:"Run as a Codex PreToolUse hook",legacyTopLevelFlags:[]},install:{order:4,flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",doctorOrder:7,runtime:{order:6,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:7,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:6,runtime:{order:5,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:6,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",doctorOrder:8,runtime:{order:7,flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:9,runtime:{order:8,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:9,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:10,runtime:{order:9,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:10,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:11,install:{order:11,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:12,install:{order:12,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:13,install:{order:13,flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",doctorOrder:5,runtime:{order:4,flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{order:5,flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],ur=Nn.slice().sort((j,K)=>j.doctorOrder-K.doctorOrder).map((j)=>j.id),Mn=Nn.filter((j)=>("runtime"in j)).slice().sort((j,K)=>j.runtime.order-K.runtime.order).map((j)=>({id:j.id,displayName:"displayName"in j.runtime?j.runtime.displayName:j.displayName,flags:j.runtime.flags,legacyFlags:"legacyFlags"in j.runtime?j.runtime.legacyFlags:[],description:j.runtime.description,legacyTopLevelFlags:j.runtime.legacyTopLevelFlags})),Nt=Nn.slice().sort((j,K)=>j.install.order-K.install.order).map((j)=>({id:j.id,...j.install})).map(({order:j,...K})=>K),d0=Object.fromEntries(Nn.map((j)=>[j.id,j.displayName]));function St(j){return Nn.find((K)=>K.id===j)?.displayName??j}var Tu=Mn.map((j)=>({flags:j.flags.join(", "),description:j.description})),Iu=Mn.flatMap((j)=>j.flags.map((K)=>`cc-safety-net hook ${K}`)),is={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Tu,{flags:"-h, --help",description:"Show this help"}],examples:Iu};var ss={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...Nt.map((j)=>({flags:j.flag,description:`Install ${St(j.id)} ${j.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...Nt.map((j)=>`cc-safety-net install ${j.flag}`)]},as={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...Nt.map((j)=>({flags:j.flag,description:`Uninstall ${St(j.id)} ${j.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...Nt.map((j)=>`cc-safety-net uninstall ${j.flag}`)]},ls={name:"update",description:"Update every installed CC Safety Net integration to the latest version",usage:"update",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net update"]};var cs={name:"logs",description:"Browse audit log entries recorded by hooks",usage:"logs [options]",options:[{flags:"--id",argument:"<id>",description:"Show one entry from retained history by its 16-character id (not guaranteed once it is older than the configured retention)"},{flags:"--limit",argument:"<n>",description:"Maximum entries to print",default:"20"},{flags:"--since",argument:"<days>",description:"Only include entries newer than this many days (max: the configured audit retention, 1-365)",default:"30"},{flags:"--agent",argument:"<name>",description:"Filter by agent name"},{flags:"--rule",argument:"<ruleId>",description:"Filter by rule id"},{flags:"--session",argument:"<id>",description:"Filter by session id"},{flags:"--project",argument:"<path>",description:"Filter by project path"},{flags:"--suspect",description:"Only denials that look like false positives"},{flags:"--all",description:"Include allow entries"},{flags:"--prune-legacy",description:"Permanently delete all legacy root-level logs; nested logs are untouched"},{flags:"--dry-run",description:"With --prune-legacy, report what would be deleted and delete nothing"},{flags:"--json",description:"Output entries as JSON"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net logs --id 3fa9c2d1a70e8b42","cc-safety-net logs --agent claude-code","cc-safety-net logs --project . --since 7","cc-safety-net logs --suspect --since 7","cc-safety-net logs --json","cc-safety-net logs --prune-legacy --dry-run","cc-safety-net logs --prune-legacy"]};var pr={name:"policy",description:"Check and apply project or user policy proposals",usage:"policy <subcommand>",subcommands:[{usage:"check <file>",description:"Validate a policy proposal and print its diff"},{usage:"apply <file>",description:"Apply a proposal after confirming in a terminal"}],options:[{flags:"-g, --global",description:"Use the user-scope policy instead of the project one"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net policy check proposal.json","cc-safety-net policy apply proposal.json","cc-safety-net policy apply proposal.json --global"]};var go=[{flags:"--ref",argument:"<ref>",description:"Use a branch, tag, or commit"},{flags:"--only",argument:"<rulebook...>",description:"Add only these repository rulebooks"},{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"-h, --help",description:"Show this help"}],yo=["cc-safety-net rule add project-rules","cc-safety-net rule add acme/safety-rules","cc-safety-net rule add acme/safety-rules --only aws gcloud","cc-safety-net rule add acme/safety-rules --ref v2 --only aws","cc-safety-net rule add --only terraform aws"],kn={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add [source] [--ref <ref>] [--only <rulebook...>]",description:"Add rulebook sources and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Re-fetch and vendor remote rulebooks"},{usage:"sync",description:"Deprecated: migrate lock and cache leftovers"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},...go.slice(0,2),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net rule init","cc-safety-net rule init --example","cc-safety-net rule wrapper add rtk",...yo,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var ds={name:"status",description:"Show what the runtime is enforcing right now",usage:"status",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net status"]};var us={name:"statusline",description:"Print status line with mode indicators for shell integration",usage:"statusline --claude-code",options:[{flags:"-cc, --claude-code",description:"Print status line for Claude Code"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net statusline -cc","cc-safety-net statusline --claude-code"]};var fr=[ds,ns,cs,rs,kn,pr,ss,ls,as,is,os,us];function $u(j){return j.aliases??[]}function mr(j){let K=j.toLowerCase();return fr.find((te)=>te.name.toLowerCase()===K||$u(te).some((re)=>re.toLowerCase()===K))}import{basename as Ou}from"node:path";function gr(j,K=7,te=M(j)){let re=Date.now()-K*24*60*60*1000,oe=[],ce=new Set,de=0,we,xe,Ce,Se;if(te)q(j,te);let Ne={count:0},He=te?an(te,Ne):[];for(let mt of He)for(let it of wn(mt,Ne)){if(it.decision==="allow")continue;let gt=new Date(it.ts).getTime();if(gt>=re){if(de++,ce.add(it.sessionId??Ou(mt,".jsonl")),xe===void 0||gt<=xe)we=it.ts,xe=gt;if(Se===void 0||gt>Se)Ce=it.ts,Se=gt;ju(oe,it,gt)}}let at=oe.map((mt)=>({timestamp:mt.ts,command:mt.command,reason:mt.reason,relativeTime:Wi(new Date(mt.ts))}));return{totalBlocked:de,sessionCount:ce.size,recentEntries:at,oldestEntry:we,newestEntry:Ce,unreadable:Ne.count}}function ju(j,K,te){let re=j.findIndex((oe)=>te>new Date(oe.ts).getTime());if(re===-1){if(j.length<3)j.push(K);return}if(j.splice(re,0,K),j.length>3)j.pop()}import{dirname as Wu}from"node:path";import{dirname as Fu,join as Nu,resolve as Mu}from"node:path";var Hu="config.json";function It(j,K,te,re){y(Uu(j),`${JSON.stringify(K,null,2)}
5
- `,te,re)}function Uu(j){return typeof j==="string"?D(j):j}function vo(j){return{errors:se(Bu(j),": "," "),ruleNames:new Set(Fe(j).map((K)=>K.toLowerCase()))}}var Gu="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",ps="must match pattern (letters, numbers, hyphens, underscores)";function Bu(j){if(!fs(j))return[e([],"Config must be an object")];return[...j.version===1?[]:[e(["version"],"must be 1")],...qu(j.rules)]}function qu(j){if(j===void 0)return[];if(!Array.isArray(j))return[e(["rules"],"must be an array")];return[...j.flatMap((K,te)=>fs(K)?Vu(K,["rules",te]):[e(["rules",te],"must be an object")]),...$e(j)]}function Vu(j,K){return[...ho(j.name,[...K,"name"],"required string",c,Gu),...ho(j.command,[...K,"command"],"required string",L,ps),...j.subcommand===void 0?[]:ho(j.subcommand,[...K,"subcommand"],"must be a string if provided",L,ps),...zu(j.block_args,[...K,"block_args"]),...Ju(j.reason,[...K,"reason"]),...j.intent===void 0||Ee(j.intent)?[]:[e([...K,"intent"],ke)]]}function ho(j,K,te,re,oe){if(typeof j!=="string")return[e(K,te)];return re.test(j)?[]:[e(K,oe)]}function zu(j,K){if(!Array.isArray(j))return[e(K,"required array")];if(j.length===0)return[e(K,"must have at least one element")];return j.flatMap((te,re)=>{if(typeof te!=="string")return[e([...K,re],"must be a string")];return te===""?[e([...K,re],"must not be empty")]:[]})}function Ju(j,K){if(typeof j!=="string")return[e(K,"required string")];if(j==="")return[e(K,"must not be empty")];return j.length>I?[e(K,`must be at most ${I} characters`)]:[]}function fs(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function bo(j){let K=ms(j);if(!K.ok)return K.result;return vo(K.parsed)}function ms(j){let K=[],te=new Set;try{let re=typeof j==="string"?D(j):j,oe=r(re);if(oe===null)return K.push(`File not found: ${re.path}`),{ok:!1,result:{errors:K,ruleNames:te}};if(!oe.trim())return K.push("Config file is empty"),{ok:!1,result:{errors:K,ruleNames:te}};return{ok:!0,parsed:JSON.parse(oe)}}catch(re){if(re instanceof o)return K.push(re.message),{ok:!1,result:{errors:K,ruleNames:te}};let oe=re instanceof Error?re.message:String(re);return K.push(re instanceof SyntaxError?"Invalid JSON":oe),{ok:!1,result:{errors:K,ruleNames:te}}}}function gs(j){return Mu(j,".safety-net.json")}function en(j){let K=ms(j);if(!K.ok)return K.result;let te=tt(K.parsed);return{errors:te.errors,ruleNames:te.sources}}function yr(j,K={}){return Nu(Fu(me(j,K)),Hu)}function ys(j,K,te){let re;try{if(r(K)===null)return{path:j,exists:!1,valid:!1,ruleCount:0};re=en(K),re.errors.push(...W(j,te))}catch(oe){if(!(oe instanceof o))throw oe;re={errors:[oe.message],ruleNames:new Set}}return{path:j,exists:!0,valid:re.errors.length===0,ruleCount:re.ruleNames.size,...re.errors.length>0?{errors:re.errors}:{}}}function Ku(j,K){return{source:K,name:j.name,command:j.command,subcommand:j.subcommand,blockArgs:[...j.block_args],reason:j.reason}}function hs(j,K,te){let re=te?.userConfigPath??T(j),oe=te?.projectConfigPath??A(K),ce=Wu(re),de=Z(j,{cwd:K,userConfigPath:re,projectConfigPath:oe,userConfigDir:ce}),we=H(j,{cwd:K,userConfigPath:re,projectConfigPath:oe,userConfigDir:ce}),xe=new Map(de.rulebooks.flatMap((Ce)=>Ce.rules.map((Se)=>[Se,Ce.source])));return{userConfig:ys(re,we.userConfigTarget,we.userScope),projectConfig:ys(oe,we.projectConfigTarget,we.projectScope),effectiveRules:de.rules.map((Ce)=>Ku(Ce,xe.get(Ce.name)??"project")),shadowedRules:[]}}var Yu=[{flag:i.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:i.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:i.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:i.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:i.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:i.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:i.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:i.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function vs(j){return[...Yu.map((K)=>({name:K.flag.name,value:Le(K.flag,j.env),isSet:st(K.flag,j.env),legacyName:K.flag.legacyName,legacyValue:K.flag.legacyName?j.env.get(K.flag.legacyName):void 0,legacyIsSet:K.flag.legacyName?j.env.get(K.flag.legacyName)!==void 0:void 0,description:K.description,defaultBehavior:K.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:j.env.get("CC_SAFETY_NET_HOME"),isSet:j.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var bs={error:0,warning:1,info:2},Zu=["policy","config","audit"];function Xu(j){return j.map((K)=>{if(K==="ownership")return"is not owned by the current user";if(K==="permissions")return"has unsafe permissions";if(K==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Qu=[{derive:(j)=>j.hooks.length>0&&j.hooks.every((K)=>!K.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(j)=>j.hooks.filter((K)=>K.inspectionStatus==="failed").map((K)=>{let te=St(K.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${te} inspection failed`,detail:`Doctor could not verify the ${te} integration configuration.`,fixHint:`Correct the reported ${te} configuration error, then run \`cc-safety-net doctor\` again.`,integration:K.platform}})},{derive:(j)=>j.userConfig.exists&&!j.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:j.userConfig.path}]:[]},{derive:(j)=>j.projectConfig.exists&&!j.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:j.projectConfig.path}]:[]},{derive:(j)=>j.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${j.configState.reason}`,fixHint:"Fix the file named in the reason, or run `cc-safety-net rule update` to vendor a remote source, then rerun doctor."}]:[]},{derive:(j)=>j.v2Leftovers&&j.v2Leftovers.length>0?[{checkId:"config.v2-leftovers",severity:"info",title:"Rulebook lock and cache leftovers detected",detail:`Files an earlier version left behind are no longer read: ${j.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(j)=>{let K=j.environment.find((te)=>te.name==="CC_SAFETY_NET_AUDIT_SCOPE");return Ze(K?.value)==="invalid"?[{checkId:"environment.audit-scope-invalid",severity:"warning",title:"Audit scope value is invalid",detail:"CC_SAFETY_NET_AUDIT_SCOPE is not `all` or `blocked`, so allowed command decisions are not recorded.",fixHint:"Set CC_SAFETY_NET_AUDIT_SCOPE to `all` or `blocked`, then restart the integration."}]:[]}},...Zu.map((j)=>({derive:(K)=>K.posture.directories.filter((te)=>te.kind===j&&te.status==="unsafe").map((te)=>({checkId:`posture.${j}-directory-unsafe`,severity:"error",title:`${j[0]?.toUpperCase()}${j.slice(1)} directory is unsafe`,detail:`The ${j} directory ${Xu(te.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...te.path?{path:te.path}:{}}))})),{derive:(j)=>{let K=[...j.effectiveSafety.weakenedRuleOverrides].sort();return K.length>0?[{checkId:"posture.rule-overrides-weaken-preset",severity:"warning",title:"Rule overrides weaken the selected preset",detail:`Explicit overrides disable rules the resolved preset would enable: ${K.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${K.join(", ")}.`}]:[]}}];function Ls(j){return Qu.flatMap((K,te)=>K.derive(j).map((re,oe)=>({finding:re,catalogOrder:te,occurrence:oe}))).sort((K,te)=>bs[K.finding.severity]-bs[te.finding.severity]||K.catalogOrder-te.catalogOrder||K.occurrence-te.occurrence).map((K)=>K.finding)}function Bt(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var ep=(j)=>Bt()?`\x1B[32m${j}\x1B[0m`:j,tp=(j)=>Bt()?`\x1B[33m${j}\x1B[0m`:j,np=(j)=>Bt()?`\x1B[34m${j}\x1B[0m`:j,rp=(j)=>Bt()?`\x1B[35m${j}\x1B[0m`:j,op=(j)=>Bt()?`\x1B[36m${j}\x1B[0m`:j,ip=(j)=>Bt()?`\x1B[31m${j}\x1B[0m`:j,sp=(j)=>Bt()?`\x1B[2m${j}\x1B[0m`:j,ap=(j)=>Bt()?`\x1B[1m${j}\x1B[0m`:j,bt={green:ep,yellow:tp,blue:np,magenta:rp,cyan:op,red:ip,dim:sp,bold:ap},lp="\x1B[0m",cp=[39,82,198,226,208,51,196,46,201,214,93,154,220,27,49,190,200,33,129,227,45,160,63,118,123,202];function dp(j){let K=j;return()=>(K=(K*1664525+1013904223)%4294967296,K/4294967296)}function up(j){let K=[...cp],te=dp(j);for(let re=K.length-1;re>0;re--){let oe=Math.floor(te()*(re+1)),ce=K[re];K[re]=K[oe],K[oe]=ce}return K}function pp(j,K=0){if(!Bt())return"";let te=up(K);return`\x1B[38;5;${te[j%te.length]}m`}function ws(j,K,te=0){if(!Bt())return`"${j}"`;return`${pp(K,te)}"${j}"${lp}`}function hr(j){return j==="default"?"built-in default":`${j} policy`}var fp=new RegExp("\x1B\\[[0-9;]*m","g"),Lo=(j)=>j.replace(fp,"").length;function ln(j){let K=(j.headers??j.rows[0]??[]).map((de,we)=>{let xe=Math.max(...j.rows.map((Ce)=>Lo(Ce[we]??"")));return Math.max(Lo(de),xe)}),te=(de,we)=>de+" ".repeat(Math.max(0,we-Lo(de))),re=(de,we)=>we[0]+K.map((xe)=>de.repeat(xe+2)).join(we[1])+we[2],oe=(de)=>`│ ${de.map((we,xe)=>te(we,K[xe]??0)).join(" │ ")} │`,ce=j.headers?[` ${oe(j.headers)}`,` ${re("─",["├","┼","┤"])}`]:[];return[` ${re("─",["┌","┬","┐"])}`,...ce,...j.rows.map((de)=>` ${oe(de)}`),` ${re("─",["└","┴","┘"])}`].join(`
6
- `)}function ks(j){let K=[];K.push("Hook Integration"),K.push(mp(j));let te=[],re=[];for(let oe of j){let ce=St(oe.platform);if(oe.errors&&oe.errors.length>0)for(let de of oe.errors)if(oe.configured)te.push({platform:ce,message:de});else re.push({platform:ce,message:de})}for(let oe of te)K.push(` Warning (${oe.platform}): ${oe.message}`);for(let oe of re)K.push(bt.red(` Error (${oe.platform}): ${oe.message}`));return K.join(`
7
- `)}function mp(j){let K=["Platform","Discovery","Configuration","Inspection"],te=j.map((re)=>{let oe=St(re.platform);if(re.inspectionStatus==="not-inspected"){let xe=bt.dim("Not inspected");return[oe,xe,xe,xe]}let ce=re.detected?bt.green("Detected"):re.inspectionStatus==="failed"?bt.red("Unknown"):bt.dim("Not detected"),de=re.configured?bt.green("Configured"):re.detected?bt.yellow("Not configured"):re.inspectionStatus==="failed"?bt.red("Unknown"):bt.dim("Not applicable"),we=re.inspectionStatus==="verified"?bt.green("Verified"):re.inspectionStatus==="failed"?bt.red("Failed"):bt.dim("Not applicable");return[oe,ce,de,we]});return ln({headers:K,rows:te})}function xs(j){let te=["Guard Engine Verification",` Synthetic self-test: ${j.failed>0?bt.red(`${j.passed}/${j.total} FAIL`):bt.green(`${j.passed}/${j.total} passed`)}`],re=j.results.filter((oe)=>!oe.passed);if(re.length>0){te.push(""),te.push(bt.red(" Failures:"));for(let oe of re)te.push(bt.red(` • ${oe.description}`)),te.push(bt.red(` expected ${oe.expected}, got ${oe.actual}`))}return te.join(`
8
- `)}function gp(j){if(j.length===0)return" (no custom rules)";let K=["Source","Name","Command","Block Args"],te=j.map((re)=>[re.source,re.name,re.subcommand?`${re.command} ${re.subcommand}`:re.command,re.blockArgs.join(", ")]);return ln({headers:K,rows:te})}function Cs(j){let K=[];if(K.push("Configuration"),K.push(yp(j.userConfig,j.projectConfig)),K.push(""),j.effectiveRules.length>0)K.push(` Effective rules (${j.effectiveRules.length} total):`),K.push(gp(j.effectiveRules));else K.push(" Effective rules: (none - using built-in rules only)");for(let te of j.shadowedRules)K.push(""),K.push(` Note: Project rule "${te.name}" shadows user rule with same name`);return K.join(`
9
- `)}function yp(j,K){let te=["Scope","Status"],re=(ce)=>{if(!ce.exists)return bt.dim("N/A");if(!ce.valid)return bt.red(`Invalid (${ce.errors?.[0]??"unknown error"})`);return bt.green("Configured")},oe=[["User",re(j)],["Project",re(K)]];return ln({headers:te,rows:oe})}function Ss(j){let K=[];return K.push("Environment"),K.push(hp(j)),K.join(`
10
- `)}function Rs(j){let K=j.effectiveSafety.policyScopes,te=["Effective Safety",` Selected preset: ${j.effectiveSafety.selectedPreset}${K?` (${hr(K.levelScope)})`:""}`,` Effective: ${j.effectiveSafety.level}`],re=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[oe,ce]of re){let de=j.effectiveSafety.capabilities[oe],we=de.enabled?bt.green("ON"):bt.dim("OFF"),xe=de.sources.length>0?` (${de.sources.join(", ")})`:"";te.push(` ${ce}: ${we} via ${de.source}${xe}`)}if(K&&K.weakenings.length>0){te.push(" Project policy deltas:");for(let oe of K.weakenings)te.push(` ${oe}`)}te.push(` Stored rule customizations: ${j.effectiveSafety.ruleCounts.stored}`),te.push(` Effective rule customizations: ${j.effectiveSafety.ruleCounts.effective}`);for(let[oe,ce]of Object.entries(j.effectiveSafety.ruleOverrides))te.push(` ${oe}: ${ce}`);return te.join(`
11
- `)}function Ps(j){let K=["Findings"];if(j.length===0)return K.push(" No findings from inspected doctor facts."),K.join(`
12
- `);for(let te of j){let re=`[${te.severity.toUpperCase()}] ${te.checkId}: ${_t(te.title)}`,oe=te.severity==="error"?bt.red:te.severity==="warning"?bt.yellow:bt.blue;if(K.push(` ${oe(re)}`),K.push(` ${_t(te.detail)}`),te.path)K.push(` Path: ${_t(te.path)}`);if(te.fixHint)K.push(` Fix: ${_t(te.fixHint)}`)}return K.join(`
13
- `)}function hp(j){let K=["Variable","Status","Legacy"],te=j.map((re)=>{let oe=re.isSet?bt.green("✓"):bt.dim("✗"),ce=re.legacyName&&re.legacyIsSet?`${re.legacyName} ${bt.green("✓")}`:re.legacyName??"";return[re.name,oe,ce]});return ln({headers:K,rows:te})}function Es(j){let K=[];if(j.totalBlocked===0)K.push("Recent Activity"),K.push(" No blocked commands in the last 7 days"),K.push(" Tip: This is normal for new installations");else K.push(`Recent Activity · last 7 days (${j.totalBlocked} blocked / ${j.sessionCount} sessions)`),K.push(vp(j.recentEntries));if(j.unreadable>0)K.push(` Warning: ${j.unreadable} audit log ${j.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return K.join(`
14
- `)}function vp(j){let K=["Time","Command"],te=j.map((re)=>{let oe=_t(re.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),ce=oe.length>40?`${oe.slice(0,37)}...`:oe;return[re.relativeTime,ce]});return ln({headers:K,rows:te})}function Ds(j){let K=[];if(K.push("Update Check"),j.latestVersion===null&&!j.error)return K.push(vr([["Status",bt.dim("Skipped")],["Installed",j.currentVersion]])),K.join(`
15
- `);if(j.error)return K.push(vr([["Status",`${bt.yellow("⚠")} Error`],["Installed",j.currentVersion],["Error",bt.dim(j.error)]])),K.join(`
16
- `);if(j.updateAvailable)return K.push(vr([["Status",`${bt.yellow("⚠")} Update Available`],["Current",j.currentVersion],["Latest",bt.green(j.latestVersion??"")]])),K.push(""),K.push(" Run: bunx cc-safety-net@latest doctor"),K.push(" Or: npx cc-safety-net@latest doctor"),K.join(`
17
- `);return K.push(vr([["Status",`${bt.green("✓")} Up to date`],["Version",j.currentVersion]])),K.join(`
18
- `)}function vr(j){return ln({rows:j})}function As(j){let K=[];return K.push("System Info"),K.push(bp(j)),K.join(`
19
- `)}function bp(j){let K=["Component","Version"],te=(ce)=>{if(ce===null)return bt.dim("not found");return ce},oe=[{label:"cc-safety-net",value:j.version},...ur.map((ce)=>({label:St(ce),value:j.versions[ce]??null})),{label:"Node.js",value:j.nodeVersion},{label:"npm",value:j.npmVersion},{label:"Bun",value:j.bunVersion},{label:"Platform",value:j.platform}].map((ce)=>[ce.label,te(ce.value)]);return ln({headers:K,rows:oe})}function _s(j){if(j.findings.length===0)return bt.green(`
20
- No findings from inspected doctor facts.`);let K={error:j.findings.filter((ce)=>ce.severity==="error").length,warning:j.findings.filter((ce)=>ce.severity==="warning").length,info:j.findings.filter((ce)=>ce.severity==="info").length},te=["error","warning","info"].filter((ce)=>K[ce]>0).map((ce)=>`${K[ce]} ${ce}`),re=j.findings.length===1?"finding":"findings",oe=`
21
- ${j.findings.length} ${re}: ${te.join(", ")}.`;if(K.error>0)return bt.red(oe);if(K.warning>0)return bt.yellow(oe);return bt.blue(oe)}import{lstatSync as Lp}from"node:fs";import{dirname as wo}from"node:path";function ko(j,K){try{let te=Lp(K);if(te.isSymbolicLink())return{kind:j,path:K,status:"unsafe",issues:["symlink"]};if(!te.isDirectory())return{kind:j,path:K,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:j,path:K,status:"unknown",issues:[]};let re=[...te.uid!==process.getuid()?["ownership"]:[],...(te.mode&18)!==0?["permissions"]:[]];return{kind:j,path:K,status:re.length>0?"unsafe":"safe",issues:re}}catch(te){if(typeof te==="object"&&te!==null&&"code"in te&&te.code==="ENOENT")return{kind:j,path:K,status:"not-applicable",issues:[]};return{kind:j,path:K,status:"unknown",issues:[]}}}function Ts(j,K){let te=M(j);return{directories:[ko("policy",wo(wo(K))),ko("config",wo(K)),...te?[ko("audit",te)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as wp}from"node:child_process";import{existsSync as Is}from"node:fs";import{delimiter as kp,extname as xp,join as Cp}from"node:path";import{stripVTControlCharacters as $s}from"node:util";var js="2.4.0",Sp=5000,Rp="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function Et(){return js}function xo(j,K){let te=j[K];if(te)return te;let re=Object.keys(j).find((oe)=>oe.toLowerCase()===K.toLowerCase()&&!!j[oe]);return re?j[re]:te}function Pp(j){return(xo(j,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((K)=>K.length>0)}function Ep(j,K){let te=xp(j)?[j]:[...Pp(K).map((re)=>`${j}${re}`),j];if(j.includes("/")||j.includes("\\"))return te.find((re)=>Is(re))??j;return(xo(K,"PATH")??"").split(kp).flatMap((re)=>te.map((oe)=>Cp(re,oe))).find((re)=>Is(re))??j}function Os(j){if(!/[\s"&|<>^]/.test(j))return j;return`"${j.replace(/"/g,'""')}"`}function cn(j,K){let[te,...re]=j,oe=K[Rp]==="win32"?"win32":process.platform;if(!te||oe!=="win32")return{cmd:te??"",args:re};let ce=Ep(te,K);if(!/\.(?:bat|cmd)$/i.test(ce))return{cmd:ce,args:re};return{cmd:xo(K,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",Os(ce),...re.map(Os)].join(" ")]}}var xn=async(j,K=Sp)=>{let te=await Dp(j,{timeoutMs:K});if(te.code!==0)return null;return $s(te.stdout).trim()||$s(te.stderr).trim()||null};function Dp(j,K){let[te,...re]=j;if(!te)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((oe)=>{try{let ce=cn([te,...re],process.env),de=wp(ce.cmd,ce.args,{stdio:["ignore","pipe","pipe"]}),we=!1,xe="",Ce="";de.stdout.on("data",(He)=>{xe+=He.toString()}),de.stderr.on("data",(He)=>{Ce+=He.toString()});let Se=(He)=>{if(we)return;we=!0,clearTimeout(Ne),oe(He)},Ne=setTimeout(()=>{de.kill(),Se({code:null,stdout:xe,stderr:Ce})},K.timeoutMs);de.on("close",(He)=>{Se({code:He,stdout:xe,stderr:Ce})}),de.on("error",()=>{Se({code:null,stdout:xe,stderr:Ce})})}catch{oe({code:null,stdout:"",stderr:""})}})}function br(j){if(!j)return null;let K=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(j);if(K)return K[1]??null;let te=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(j);if(te)return te[1]??null;return j.split(`
22
- `)[0]?.trim()||null}async function Hn(j=xn){let[K,te,re,oe,ce,de]=await Promise.all([Promise.all(Nt.map(async(we)=>[we.id,br(await j([...we.probeCommand]))])),j(["codex","plugin","list"],30000),j(["amp","plugins","list"],30000),j(["node","--version"]),j(["npm","--version"]),j(["bun","--version"])]);return{version:js,versions:Object.fromEntries(K),codexPluginListOutput:te,ampPluginListOutput:re,nodeVersion:br(oe),npmVersion:br(ce),bunVersion:br(de),platform:`${process.platform} ${process.arch}`}}function Co(j,K){if(K==="dev")return!1;let te=j.split(".").map(Number),re=K.split(".").map(Number),[oe=0,ce=0,de=0]=te,[we=0,xe=0,Ce=0]=re;if(oe!==we)return oe>we;if(ce!==xe)return ce>xe;return de>Ce}async function tn(){let j=Et(),K=new AbortController,te=setTimeout(()=>K.abort(),3000);try{let re=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:K.signal});if(!re.ok)return{currentVersion:j,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${re.status}`};let oe=await re.json(),ce=Co(oe.version,j);return{currentVersion:j,latestVersion:oe.version,updateAvailable:ce}}catch(re){return{currentVersion:j,latestVersion:null,updateAvailable:!1,error:re instanceof Error?re.message:"Network error"}}finally{clearTimeout(te)}}import*as qs from"node:readline";var Hs=(j)=>`\x1B[${j}B`,Ap=(j)=>`\x1B[${j}A`;var Fs=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function _p(j){return new Promise((K)=>setTimeout(K,j))}function Tp(j,K,te){if(!te)return K(j);if(te.aborted)return Promise.resolve();return new Promise((re,oe)=>{let ce=()=>te.removeEventListener("abort",de),de=()=>{ce(),re()};te.addEventListener("abort",de,{once:!0}),K(j).then(()=>{ce(),re()},(we)=>{ce(),oe(we)})})}function Un(j,K){return j&&j>0?j:K}function Lr(j){return Math.max(0,Math.min(1,j))}function Cn(j){return Math.max(0,Math.min(255,Math.round(j)))}function So(j){return j<=0.0031308?12.92*j:1.055*j**0.4166666666666667-0.055}function Ip(j,K,te){let re=te*Math.PI/180,oe=K*Math.cos(re),ce=K*Math.sin(re),de=(j+0.3963377774*oe+0.2158037573*ce)**3,we=(j-0.1055613458*oe-0.0638541728*ce)**3,xe=(j-0.0894841775*oe-1.291485548*ce)**3;return{blue:Cn(So(Lr(-0.0041960863*de-0.7034186147*we+1.707614701*xe))*255),green:Cn(So(Lr(-1.2684380046*de+2.6097574011*we-0.3413193965*xe))*255),red:Cn(So(Lr(4.0767416621*de-3.3077115913*we+0.2309699292*xe))*255)}}function Ro(j,K){let te=(K*j*180/Math.PI%360+360)%360;return Ip(0.72,0.15,te)}function Us(j,K=0.1){let te=Ro(K,j);return`\x1B[38;2;${te.red};${te.green};${te.blue}m`}function $p(j,K){return{blue:Cn(j.blue+(255-j.blue)*K),green:Cn(j.green+(255-j.green)*K),red:Cn(j.red+(255-j.red)*K)}}function Gs(j,K,te){let re=Math.imul(j+2654435769,2246822507)^Math.imul(K+3266489909,668265263)^Math.imul(te+374761393,2654435761),oe=re^re>>>15,ce=Math.imul(oe,739982445),de=ce^ce>>>12,we=Math.imul(de,695872825);return((we^we>>>15)>>>0)/4294967296}function Op(j,K,te){let re=Math.floor(Gs(j,K,te)*Fs.length);return Fs[re]??"░"}function Ns(j){let K=Lr(j);return K*K*K*(K*(K*6-15)+10)}function jp(j){if(j.length===0)return"";let K=[],te=!1,re="";for(let oe of j){let ce=`${oe.red};${oe.green};${oe.blue}`;if(oe.bold!==te)K.push(oe.bold?"\x1B[1m":"\x1B[22m"),te=oe.bold;if(ce!==re)K.push(`\x1B[38;2;${ce}m`),re=ce;K.push(oe.character)}return`${K.join("")}\x1B[22m\x1B[39m`}function Fp(j,K,te,re,oe){return j.map((ce,de)=>({...Ro(te,re+K+de/oe),bold:!1,character:ce}))}function Np(j,K,te,re,oe,ce,de,we){let xe=Math.max(1,re*0.75),Ce=Math.min(1,te/xe),Se=oe*Ns(Ce),Ne=Math.max(0,(te-xe)/Math.max(1,re-xe)),He=(1-Ns(te/re))*we*2,at=0.35*Math.max(0,1-Ne*2),mt=Ce>=1,it=Math.min(j.length,Math.ceil(Se+2+1));return j.slice(0,it).map((gt,ht)=>{let vt=Ro(ce,de+K+ht/we+He),yt=ht+Gs(K,ht,7919)*2-1;if(yt>Se+2)return{...vt,bold:!1,character:" "};let kt=Se-yt,Lt=0.8*Math.exp(-(kt*kt)/12.5),Ct=Math.min(0.9,Lt+at),sn=!mt&&yt>Se-4;return{...$p(vt,Ct),bold:Ct>0.3,character:sn?Op(K,ht,te):gt}})}function Ms(j){return`\x1B[?2026h${j.map((K,te)=>`\x1B8${te>0?Hs(te):""}${jp(K)}`).join("")}\x1B[?2026l`}async function Po(j,K={}){if(!j)return;let te=K.output??process.stdout,re=K.sleep??_p,oe=Un(K.frequency,0.1),ce=K.seed??0,de=Un(K.speed,40),we=Un(K.spread,3),xe=Un(K.frameRate,60),Ce=Math.max(1,Math.floor(Un(K.duration,12))),Se=j.split(`
23
- `).map((it)=>Array.from(it)),Ne=Math.max(...Se.map((it)=>it.length)),He=1000*Ce*Se.filter((it)=>it.length>0).length/de,at=Ne>0?Math.max(1,Math.ceil(He/(1000/xe))):0,mt=at>0?He/at:0;te.write(`\x1B[?25l${Se.length>1?`${`
24
- `.repeat(Se.length-1)}${Ap(Se.length-1)}`:""}\x1B7`);try{for(let it=1;it<=at;it+=1){if(K.signal?.aborted)break;te.write(Ms(Se.map((gt,ht)=>Np(gt,ht,it,at,Ne,oe,ce,we)))),await Tp(mt,re,K.signal)}}finally{if(te.write(Ms(Se.map((it,gt)=>Fp(it,gt,oe,ce,we)))),te.write("\x1B8"),Se.length>1)te.write(Hs(Se.length-1));te.write(`
25
- \x1B[0m\x1B[?25h`)}}var Bs=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
- `);function Mp(j){return Boolean(j.isTTY)}async function Gn(j={}){let K=j.output??process.stdout;if(!Mp(K))return;let te=j.input??process.stdin,re={duration:j.duration,frequency:j.frequency,output:K,seed:j.seed??Math.random()*8192,sleep:j.sleep,speed:j.speed,spread:j.spread};if(!te.isTTY||typeof te.setRawMode!=="function"){await Po(Bs,re);return}let oe=new AbortController,ce=te.readableFlowing===!0,de=te.isRaw===!0,we=!1,xe=(Ce,Se)=>{if(Se.ctrl&&Se.name==="c")we=!0;if(we||Se.name==="return"||Se.name==="enter")oe.abort()};qs.emitKeypressEvents(te),te.on("keypress",xe),te.setRawMode(!0),te.resume();try{await Po(Bs,{...re,signal:oe.signal})}finally{if(te.off("keypress",xe),te.setRawMode(de),!ce)te.pause()}if(!we)return;if(j.onInterrupt){j.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as qp}from"node:crypto";import{existsSync as Js}from"node:fs";import{dirname as wr,join as Ws}from"node:path";import{dirname as Vs,join as Hp,resolve as Up}from"node:path";var Gp="rule.lock";function Bp(j){return Hp(Vs(j),Gp)}function zs(j={}){return Up(j.cwd??process.cwd(),".safety-net.json")}function $t(j,K){let te=K.global?K.userConfigPath??T(j,K):K.projectConfigPath??A(K.cwd??process.cwd()),re=K.global?Qe(j,K):et(te,K.cwd??process.cwd()),oe=Bp(te);return{configDir:Vs(te),configPath:te,lockPath:oe,filesystemScope:re,configTarget:s(re,te),lockTarget:s(re,oe)}}var Vp="`cc-safety-net rule sync` is deprecated: rulebooks are live files that need no synchronization. This run only migrates the lock and cache an earlier version left behind.",zp="cache",Jp="rulebooks";function Ks(j,K={}){let te=$t(j,K),re=s(te.filesystemScope,Zs(te.configDir)),oe=r(te.lockTarget);if(console.log(Vp),oe===null&&!Js(re.path))return console.log(`No v2 lock or cache leftovers found in ${wr(te.configDir)}; nothing to migrate.`),0;let ce=Xp(oe),de=m(te.configTarget);if(!de.config&&(r(te.configTarget)!==null||ce.size>0))return console.error(`Cannot migrate: the rules config in ${wr(te.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let we=de.config?.rules??[];for(let xe of we.flatMap((Ce)=>Wp(Ce,ce,te,re,K.global===!0)))console.log(xe);return G(te.lockTarget),lt(re),console.log(`Removed the v2 lock and cache under ${wr(te.configDir)}.`),0}function Ys(j,K){return[...new Set([{cwd:K},{cwd:K,global:!0}].flatMap((te)=>{let re=$t(j,te);return[re.lockPath,Zs(re.configDir)]}))].filter((te)=>Js(te))}function Wp(j,K,te,re,oe){if(!x(j))return[];let ce=O(j).name,de=s(te.filesystemScope,N(te.configDir,ce)),we=r(de);if(we!==null&&Kp(we,ce))return[];let xe=K.get(j),Ce=xe?Yp(xe,ce,re.path,te.filesystemScope):null;if(Ce===null)return[`Could not migrate ${j} from the v2 cache. Run \`cc-safety-net rule update ${j}${oe?" --global":""}\` to vendor it.`];if(y(de,Ce),we!==null)return[`Restored ${j} from the v2 cache over an invalid file.`];return[`Vendored ${j} from the v2 cache.`]}function Kp(j,K){let te=he(j);return!("problem"in te)&&te.rulebook.name===K}function Yp(j,K,te,re){let oe=Ws(te,Jp,`${Zp(j)}--${j.digest.replace("sha256:","").slice(0,12)}`,pe),ce=r(s(re,oe));if(ce===null||t2(ce)!==j.digest)return null;let de=he(ce);if("problem"in de||de.rulebook.name!==K)return null;return ce}function Zs(j){return Ws(wr(j),zp)}function Zp(j){return([j.owner,j.repo,j.display_ref,j.name].every((re)=>typeof re==="string"&&re!=="")?`${j.owner}/${j.repo}#${j.display_ref}/${j.name}`:j.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function Xp(j){let K=j===null?null:e2(j),te=Xs(K)&&Array.isArray(K.rulebooks)?K.rulebooks:[];return new Map(te.filter(Qp).map((re)=>[re.spec,re]))}function Qp(j){return Xs(j)&&typeof j.spec==="string"&&typeof j.digest==="string"}function Xs(j){return!!j&&typeof j==="object"}function e2(j){try{return JSON.parse(j)}catch{return null}}function t2(j){return`sha256:${qp("sha256").update(j).digest("hex")}`}var Qs="\r\x1B[2K",n2="\x1B[?25l",r2="\x1B[39m",o2="\x1B[?25h",i2=100,s2=0.55,a2=80,ea=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function l2(j){return new Promise((K)=>setTimeout(K,j))}async function kr(j,K={}){let te=K.output??process.stdout;if(!te.isTTY)return j;let re=K.sleep??l2,oe=!1,ce=j.then((we)=>(oe=!0,we),(we)=>{throw oe=!0,we});if(await Promise.race([ce.then(()=>!0),re(i2).then(()=>!1)]))return ce;te.write(n2);try{for(let we=0;!oe;we+=1)te.write(`${Qs}${Us(we*s2)}${ea[we%ea.length]}${r2} ${K.loadingMessage??"Loading…"}`),await Promise.race([ce,re(a2)]);return await ce}finally{te.write(`${Qs}${o2}`)}}async function Bn(j,K,te,re={}){let oe=K();if(j)await te();if(j&&oe.ready)await kr(oe.ready,re);return oe.finish()}import{stripVTControlCharacters as c2}from"node:util";var xr="amp plugins list",d2=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function ta(j){if(!j.ampPluginListOutput)return{platform:"amp",status:"n/a"};let K=c2(j.ampPluginListOutput).split(`
27
- `).map((te)=>d2.exec(te)?.[1]).find((te)=>te!==void 0);if(!K)return{platform:"amp",status:"n/a"};if(K!=="active")return{platform:"amp",status:"disabled",method:xr,configPath:xr,errors:[`Amp personal plugin cc-safety-net is ${K}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:xr,configPath:xr}}import{existsSync as f2,readFileSync as m2}from"node:fs";import{isAbsolute as vv,join as p2,relative as bv}from"node:path";function qn(j){return p2(j,".gemini","config","hooks.json")}var g2=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function y2(j){if(!j||typeof j!=="object"||Array.isArray(j))return[];return Object.values(j).flatMap((K)=>{if(!K||typeof K!=="object"||Array.isArray(K))return[];let te=K,re=te.PreToolUse;if(!Array.isArray(re))return[];return re.flatMap((oe)=>{if(!oe||typeof oe!=="object"||Array.isArray(oe))return[];let ce=oe.hooks;if(!Array.isArray(ce))return[];return ce.flatMap((de)=>{if(!de||typeof de!=="object"||Array.isArray(de))return[];let we=de.command;if(typeof we!=="string"||!g2.test(we))return[];return[{command:we,enabled:te.enabled!==!1}]})})})}function na(j){let K=qn(j.environment.home);if(!f2(K))return{platform:"antigravity-cli",status:"n/a",configPath:K};let te;try{te=y2(JSON.parse(m2(K,"utf-8")))}catch(re){return{platform:"antigravity-cli",status:"n/a",configPath:K,errors:[`Failed to parse Antigravity hooks config ${K}: ${re instanceof Error?re.message:String(re)}`]}}if(te.some((re)=>re.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:K};if(te.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:K};return{platform:"antigravity-cli",status:"n/a",configPath:K}}import{join as ra}from"node:path";import{existsSync as h2,lstatSync as v2,readFileSync as b2}from"node:fs";function qt(j,K=(te)=>te){if(!h2(j))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(K(b2(j,"utf-8")))}}catch{return{kind:"unreadable"}}}function Pt(j){try{return v2(j)}catch{return}}function Cr(j,K){let te=Pt(K);if(!te)return{platform:j,status:"n/a",configPath:K};if(!te.isSymbolicLink()&&te.isDirectory())return;return{platform:j,status:"n/a",configPath:K,errors:[`${K} is a symlink or not a directory; move or remove it before installing`]}}function wt(j,K){return typeof j==="object"&&j!==null?j[K]:void 0}var Eo="cc-safety-net@cc-marketplace";function oa(j){return ra(j.home,".claude","plugins","installed_plugins.json")}function ia(j,K){let te=wt(wt(j,"plugins"),K);return Array.isArray(te)&&te.length>0}function Sr(j,K){let te=qt(oa(j));return te.kind==="ok"&&ia(te.value,K)}function Do(j){let K=oa(j),te=qt(K);if(te.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(te.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!ia(te.value,Eo))return{platform:"claude-code",status:"n/a"};let re=ra(j.home,".claude","settings.json"),oe=qt(re);if(oe.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(oe.kind==="ok"&&wt(wt(oe.value,"enabledPlugins"),Eo)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:re,errors:[`${Eo} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:K}}function sa(j){return Do(j.environment)}function aa(j){if(!j.codexPluginListOutput)return{platform:"codex",status:"n/a"};let K=j.codexPluginListOutput.split(`
28
- `).find((te)=>te.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!K)return{platform:"codex",status:"n/a"};if(!K.includes("installed,"))return{platform:"codex",status:"n/a"};if(!K.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list"}}import{existsSync as _r,readdirSync as L2,readFileSync as w2}from"node:fs";import{join as Tt}from"node:path";function jt(j){let K="",te=0,re=!1,oe=!1,ce=-1;while(te<j.length){let de=j[te],we=j[te+1];if(oe){K+=de,oe=!1,te++;continue}if(de==='"'&&!re){re=!0,ce=-1,K+=de,te++;continue}if(de==='"'&&re){re=!1,K+=de,te++;continue}if(de==="\\"&&re){oe=!0,K+=de,te++;continue}if(re){K+=de,te++;continue}if(de==="/"&&we==="/"){while(te<j.length&&j[te]!==`
29
- `)te++;continue}if(de==="/"&&we==="*"){te+=2;while(te<j.length-1){if(j[te]==="*"&&j[te+1]==="/"){te+=2;break}te++}continue}if(de===","){ce=K.length,K+=de,te++;continue}if(de==="}"||de==="]"){if(ce!==-1){let xe=K.slice(ce+1);if(/^\s*$/.test(xe))K=K.slice(0,ce)+xe}ce=-1,K+=de,te++;continue}if(!/\s/.test(de))ce=-1;K+=de,te++}return K}function Ao(j,K,te){let re=K+1,oe=!1;while(re<j.length){if(oe){oe=!1,re++;continue}if(j[re]==="\\"){oe=!0,re++;continue}if(j[re]==='"')return re+1;re++}throw Error(te)}function _o(j,K,te){let re=j[K],oe=re==="["?"]":"}",ce=0,de=K;while(de<j.length){let we=te.skipComment?.(j,de)??de;if(we!==de){de=we;continue}if(j[de]==='"'){de=Ao(j,de,te.stringError);continue}if(j[de]===re)ce++;if(j[de]===oe){if(ce--,ce===0)return de}de++}throw Error(te.bracketError)}function ca(j,K){let te=j.lastIndexOf(`
30
- `,K)+1;return/^[ \t]*/.exec(j.slice(te))?.[0]??""}function Pr(j,K){let te=K.end+(/^\s*/.exec(j.slice(K.end))?.[0].length??0);if(j[te]===","){let de=j[te+1]===`
31
- `?te+2:te+1;return`${j.slice(0,K.start)}${j.slice(de)}`}let re=j.slice(0,K.start).search(/\s*$/)-1;if(j[re]!==",")return`${j.slice(0,K.start)}${j.slice(K.end)}`;let oe=j.lastIndexOf(`
32
- `,re-1),ce=oe!==-1&&/^\s*$/.test(j.slice(oe+1,re))?oe:re;return`${j.slice(0,ce)}${j.slice(K.end)}`}function Rr(j,K){if(j.startsWith("//",K)){let te=j.indexOf(`
33
- `,K+2);return te===-1?j.length:te+1}if(j.startsWith("/*",K)){let te=j.indexOf("*/",K+2);return te===-1?j.length:te+2}return K}function la(j,K){let te=K;while(te<j.length){if(/\s/.test(j[te]??"")){te++;continue}let re=Rr(j,te);if(re===te)return te;te=re}return te}function da(j,K,te){let re=0,oe=0;while(oe<j.length){let ce=Rr(j,oe);if(ce!==oe){oe=ce;continue}if(j[oe]==='"'){let de=Ao(j,oe,te.stringError);if(re===1&&JSON.parse(j.slice(oe,de))===K){let we=la(j,de),xe=la(j,we+1);if(j[we]===":"&&j[xe]==="[")return{start:xe,end:_o(j,xe,{skipComment:Rr,...te})}}oe=de;continue}if(j[oe]==="{"||j[oe]==="[")re++;if(j[oe]==="}"||j[oe]==="]")re--;oe++}return}function ua(j,K,te){let re=[],oe=K.start+1;while(oe<K.end){let ce=Rr(j,oe);if(ce!==oe){oe=ce;continue}if(j[oe]==='"'){let de=Ao(j,oe,te),we=JSON.parse(j.slice(oe,de));if(typeof we==="string")re.push({range:{start:oe,end:de},value:we});oe=de;continue}oe++}return re}var Vt="cc-safety-net@cc-marketplace",Er=["cc-marketplace","cc-safety-net"],pa=["_direct","copilot-safety-net"],fa=["cc-marketplace","safety-net"],ma="safety-net@cc-marketplace";function Dr(j,K){let te=K.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${te}([^a-z0-9-]|$)`,"m").test(j??"")}function ga(j){return Dr(j,"cc-safety-net@cc-marketplace")}function ya(j){return Dr(j,"cc-marketplace")}function ha(j){return Dr(j,"copilot-safety-net")}function va(j){return Dr(j,"safety-net@cc-marketplace")}function To(j){if(!j?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(j)}function La(j,K){if(!j)return null;let te=j.match(/(\d+)\.(\d+)\.(\d+)/);if(!te)return null;let re=[Number(te[1]),Number(te[2]),Number(te[3])];for(let oe=0;oe<K.length;oe++){let ce=re[oe]??0,de=K[oe]??0;if(ce!==de)return ce>de}return!0}function k2(j){return La(j,[0,0,422])}function x2(j){return La(j,[1,0,8])}function Vn(j){return j.env.get("COPILOT_HOME")||Tt(j.home,".copilot")}function Io(j){return(j.hooks?.preToolUse??[]).some((te)=>{if(te.type!=="command")return!1;return To(te.command)||To(te.bash)||To(te.powershell)})}function Ar(j){return j===void 0||typeof j==="string"}function C2(j){if(!j||typeof j!=="object"||Array.isArray(j))return!1;let K=j;if(K.disableAllHooks!==void 0&&typeof K.disableAllHooks!=="boolean")return!1;if(K.hooks===void 0)return!0;if(!K.hooks||typeof K.hooks!=="object"||Array.isArray(K.hooks))return!1;let te=K.hooks.preToolUse;if(te===void 0)return!0;return Array.isArray(te)&&te.every((re)=>re!==null&&typeof re==="object"&&!Array.isArray(re)&&Ar(re.type)&&Ar(re.command)&&Ar(re.bash)&&Ar(re.powershell))}function $o(j,K){try{let te=JSON.parse(jt(w2(j,"utf-8")));if(!C2(te)){K?.push(`Invalid hook config ${j}: hooks.preToolUse must be an array of hook objects`);return}return te}catch(te){K?.push(`Failed to parse ${j}: ${te instanceof Error?te.message:String(te)}`);return}}function wa(j,K){try{return L2(j).filter((te)=>te.endsWith(".json")).sort((te,re)=>te.localeCompare(re))}catch(te){return K?.push(`Failed to read ${j}: ${te instanceof Error?te.message:String(te)}`),[]}}function S2(j,K){if(!_r(j))return[];let te=[];for(let re of wa(j,K)){let oe=Tt(j,re),ce=$o(oe,K);if(ce&&Io(ce))te.push(oe)}return te}function Sn(j,K){if(!_r(j))return;let te=$o(j,K);if(!te)return;return{path:j,config:te}}function ba(j,K,te,re){if(K){j.push(`GitHub Copilot CLI ${K} does not support ${te}; requires ${re}+`);return}j.push(`GitHub Copilot CLI version unavailable; skipping ${te} because it requires ${re}+`)}function R2(j){for(let K of j){if(K?.config.disableAllHooks===!0)return K.path;if(K?.config.disableAllHooks===!1)return}return}function P2(j,K,te,re){let oe=Vn(j),ce=Tt(K,".github","hooks"),de=Tt(oe,"hooks"),we=Tt(K,".github","copilot"),xe=Tt(K,".claude"),Ce=x2(te),Se=Ce===!0?re:void 0,Ne=[Sn(Tt(we,"settings.local.json"),Se),Sn(Tt(we,"settings.json"),Se),Sn(Tt(xe,"settings.local.json"),Se),Sn(Tt(xe,"settings.json"),Se)],He=[Sn(Tt(oe,"settings.json"),Se),Sn(Tt(oe,"config.json"),Se)];if(Ce!==!1){let kt=R2([...Ne,...He]);if(kt){if(Ce===null)re.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${kt} as active`);return{activeConfigPaths:[],disabledBy:kt}}}let at=S2(ce,re),mt=k2(te),it=mt===!0?re:void 0,gt=_r(de)?wa(de,it):[],ht=[];for(let kt of gt){let Lt=Tt(de,kt),Ct=$o(Lt,it);if(Ct&&Io(Ct))ht.push(Lt)}if(mt!==!0&&ht.length>0)ba(re,te,`user hook files in ${de}`,"0.0.422"),ht.length=0;let vt=[];for(let kt of[...Ne,...He]){if(!kt)continue;if(!Io(kt.config))continue;if(Ce===!0){vt.push(kt);continue}ba(re,te,"inline hook definitions in Copilot config files","1.0.8");break}let yt=(kt)=>kt.filter((Lt)=>!!Lt&&vt.includes(Lt)).map((Lt)=>Lt.path);return{activeConfigPaths:[...yt(Ne),...at,...yt(He),...ht]}}function ka(j){let K=[],te=P2(j.environment,j.cwd,j.copilotCliVersion,K);if(te.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:te.disabledBy,configPaths:[te.disabledBy],errors:K.length>0?K:void 0};let re=Vn(j.environment),oe=Tt(re,"installed-plugins",...Er),ce=_r(oe),de=Tt(re,"settings.json"),we=qt(de,jt);if(ce&&we.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(ce&&we.kind==="ok"&&wt(wt(we.value,"enabledPlugins"),Vt)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:de,errors:[`${Vt} is installed but not enabled in Copilot CLI`]};if(ce||te.activeConfigPaths.length>0){let xe=ce,Ce=te.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:xe?"plugin config":"hook config",configPath:Ce??(xe?oe:void 0),configPaths:te.activeConfigPaths.length>0?te.activeConfigPaths:void 0,errors:K.length>0?K:void 0}}return{platform:"copilot-cli",status:"n/a",errors:K.length>0?K:void 0}}import{existsSync as F2,readFileSync as N2}from"node:fs";import{existsSync as xa,mkdirSync as A2,readFileSync as _2}from"node:fs";import{dirname as T2,join as I2}from"node:path";import{renameSync as E2,writeFileSync as D2}from"node:fs";function Dt(j,K){let te=`${j}.${process.pid}.tmp`;D2(te,K),E2(te,j)}var zt=Object.fromEntries(Mn.map((j)=>[j.id,`npx -y cc-safety-net hook ${j.flags[1]}`]));var zn=zt.cursor,Ca=30;function Ir(j){return I2(j.home,".cursor","hooks.json")}function dn(j){return typeof j==="object"&&j!==null&&!Array.isArray(j)}function Oo(){return{command:zn,timeout:Ca,failClosed:!0}}function Tr(j){return dn(j)&&j.command===zn}function $2(j){return Object.keys(j).length===3&&j.command===zn&&j.timeout===Ca&&j.failClosed===!0}function O2(j){try{return JSON.parse(_2(j,"utf-8"))}catch(K){if(K instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${j}: ${K.message}`);throw K}}function Sa(j){let K=O2(j);if(!dn(K))throw Error(`Cursor hooks config ${j} must be a JSON object`);if(K.version!==1)throw Error(`Cursor hooks config ${j} must set "version": 1`);if(K.hooks!==void 0&&!dn(K.hooks))throw Error(`Cursor hooks config ${j} "hooks" must be an object`);let te=dn(K.hooks)?K.hooks.preToolUse:void 0;if(te!==void 0&&!Array.isArray(te))throw Error(`Cursor hooks config ${j} "hooks.preToolUse" must be an array`);return K}function Ra(j){let K=dn(j.hooks)?j.hooks.preToolUse:void 0;return Array.isArray(K)?K:[]}function j2(j){if(!j.some(Tr))return[...j,Oo()];return j.reduce((K,te)=>{if(!Tr(te))return K.result.push(te),K;if(!K.inserted)K.result.push(Oo()),K.inserted=!0;return K},{result:[],inserted:!1}).result}function Pa(j,K,te){let re=dn(K.hooks)?K.hooks:{},oe={...K,hooks:{...re,preToolUse:te}};Dt(j,`${JSON.stringify(oe,null,2)}
34
- `)}function Ea(j){let K=Ir(j);if(!xa(K))return A2(T2(K),{recursive:!0}),Dt(K,`${JSON.stringify({version:1,hooks:{preToolUse:[Oo()]}},null,2)}
35
- `),{path:K,alreadyInstalled:!1};let te=Sa(K),re=Ra(te),oe=re.filter(Tr);if(dn(te.hooks)&&Array.isArray(te.hooks.preToolUse)&&oe.length===1&&oe[0]!==void 0&&$2(oe[0]))return{path:K,alreadyInstalled:!0};return Pa(K,te,j2(re)),{path:K,alreadyInstalled:!1}}function Da(j){let K=Ir(j);if(!xa(K))return{path:K,alreadyInstalled:!1};let te=Sa(K),re=Ra(te),oe=re.filter((ce)=>!Tr(ce));if(oe.length===re.length)return{path:K,alreadyInstalled:!1};return Pa(K,te,oe),{path:K,alreadyInstalled:!0}}function M2(j){if(!j||typeof j!=="object"||Array.isArray(j))return[];let K=j.hooks;if(!K||typeof K!=="object"||Array.isArray(K))return[];let te=K.preToolUse;if(!Array.isArray(te))return[];return te.filter((re)=>!!re&&typeof re==="object"&&!Array.isArray(re)&&re.command===zn)}function H2(j){let K=[];if(j.length>1)K.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let te=j[0];if(te&&te.failClosed!==!0)K.push('Managed hook is missing "failClosed": true; reinstall to repair');if(te&&te.timeout!==30)K.push('Managed hook "timeout" is not 30; reinstall to repair');return K}function Aa(j){let K=Ir(j.environment);if(!F2(K))return{platform:"cursor",status:"n/a",configPath:K};let te;try{te=JSON.parse(N2(K,"utf-8"))}catch(ce){return{platform:"cursor",status:"n/a",configPath:K,errors:[`Failed to parse Cursor hooks config ${K}: ${ce instanceof Error?ce.message:String(ce)}`]}}let re=M2(te);if(re.length===0)return{platform:"cursor",status:"n/a",configPath:K};let oe=H2(re);return{platform:"cursor",status:"configured",method:"hook config",configPath:K,errors:oe.length>0?oe:void 0}}import{existsSync as U2}from"node:fs";import{join as jo}from"node:path";var Fo="gemini-safety-net";function No(j){let K=jo(j.home,".gemini","extensions"),te=jo(K,Fo);if(!U2(te))return{platform:"gemini-cli",status:"n/a"};let re=jo(K,"extension-enablement.json"),oe=qt(re);if(oe.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let ce=oe.kind==="ok"?wt(wt(oe.value,Fo),"overrides"):void 0;if(Array.isArray(ce)&&ce.some((we)=>typeof we==="string"&&we.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:re,errors:[`${Fo} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:te}}function _a(j){return No(j.environment)}import{existsSync as V2,readFileSync as z2}from"node:fs";import{existsSync as Ia,mkdirSync as G2,readFileSync as $a,rmSync as B2}from"node:fs";import{dirname as q2,join as Ta}from"node:path";var Jn=zt["grok-build"],jr=30;function Fr(j){return Ta(j.env.get("GROK_HOME")??Ta(j.home,".grok"),"hooks","cc-safety-net.json")}function un(j){return typeof j==="object"&&j!==null&&!Array.isArray(j)}function $r(){return{hooks:[{type:"command",command:Jn,timeout:jr}]}}function Oa(j){return un(j)&&j.command===Jn}function ja(j){return j.flatMap((K)=>{if(!un(K)||!Array.isArray(K.hooks))return[K];let te=K.hooks.filter((re)=>!Oa(re));if(te.length===K.hooks.length)return[K];return te.length===0?[]:[{...K,hooks:te}]})}function Fa(j){try{let K=JSON.parse(j);return un(K)?K:null}catch{return null}}function Na(j){let K=un(j.hooks)?j.hooks.PreToolUse:void 0;return Array.isArray(K)?K:[]}function Or(j,K,te){let re=un(K.hooks)?K.hooks:{};Dt(j,`${JSON.stringify({...K,hooks:{...re,PreToolUse:te}},null,2)}
36
- `)}function Ma(j){let K=Fr(j);if(!Ia(K))return G2(q2(K),{recursive:!0}),Or(K,{},[$r()]),{path:K,alreadyInstalled:!1};let te=Fa($a(K,"utf-8"));if(!te)return Or(K,{},[$r()]),{path:K,alreadyInstalled:!1};let re=Na(te),oe=re.filter((ce)=>un(ce)&&Array.isArray(ce.hooks)&&ce.hooks.some(Oa));if(oe.length===1&&JSON.stringify(oe[0])===JSON.stringify($r()))return{path:K,alreadyInstalled:!0};return Or(K,te,[...ja(re),$r()]),{path:K,alreadyInstalled:!1}}function Ha(j){let K=Fr(j);if(!Ia(K))return{path:K,alreadyInstalled:!1};let te=Fa($a(K,"utf-8"));if(!te)return{path:K,alreadyInstalled:!1};let re=Na(te),oe=ja(re);if(JSON.stringify(oe)===JSON.stringify(re))return{path:K,alreadyInstalled:!1};let ce=un(te.hooks)?te.hooks:{};if(oe.length===0&&Object.keys(te).length===1&&Object.keys(ce).length===1)return B2(K),{path:K,alreadyInstalled:!0};return Or(K,te,oe),{path:K,alreadyInstalled:!0}}function Wn(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function J2(j){if(!Wn(j)||!Wn(j.hooks))return[];let K=j.hooks.PreToolUse;if(!Array.isArray(K))return[];return K.filter((te)=>Wn(te)&&Array.isArray(te.hooks)&&te.hooks.some((re)=>Wn(re)&&re.command===Jn))}function W2(j){let te=(Array.isArray(j.hooks)?j.hooks.filter(Wn):[]).find((re)=>re.command===Jn);return[...j.matcher===void 0||j.matcher===""||j.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...te?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...te?.timeout===jr?[]:[`Managed hook "timeout" is not ${jr}; reinstall to repair`]]}function Ua(j){let K=Fr(j.environment);if(!V2(K))return{platform:"grok-build",status:"n/a",configPath:K};let te;try{te=JSON.parse(z2(K,"utf-8"))}catch(ce){return{platform:"grok-build",status:"n/a",configPath:K,errors:[`Failed to parse Grok Build hooks config ${K}: ${ce instanceof Error?ce.message:String(ce)}`]}}let re=J2(te)[0];if(!re)return{platform:"grok-build",status:"n/a",configPath:K};let oe=W2(re);return{platform:"grok-build",status:"configured",method:"hook config",configPath:K,errors:oe.length>0?oe:void 0}}import{readFileSync as Ka}from"node:fs";import{join as Ya}from"node:path";var Ft="cc-safety-net",Mo="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",K2=30;function Ga(j){return`${Mo}
37
- # version: ${j}
38
- `}function Y2(j){return`${Ga(j)}name: ${Ft}
39
- version: "${j}"
1
+ import{a,s,ke,Ge,k,Ze,He,l,o,We,E,R,we,Qe,f,Ue,u,r,w,i,ne,n,g,ce,N,tt,nt,c,de,ue,rt,T,V,re,C,ot,M,v,Ce,F,d,q,Be,ze,I,S,P,pe,fe,Re,it,m,e,Pe,Se,Ve,qe,oe,xe,ie,_e,K,j,Ae,me,G,Ke,H,Y,J,se,Ye,Je,x,W,Te,De,Oe,L,Ne,Le,Me,h,t,Z,ge,y,b,_,st,$e,Fe,p,U}from"./chunks/index-pmd634p1.js";import{Q,B,je,D,O}from"./chunks/index-jfmgn339.js";var Hd=["-h","--help"];function xt(A,z){let X=Object.entries(A.booleans??{}),ee=Object.entries(A.values??{}),te=Object.entries(A.lists??{}),ae=Object.fromEntries(X.map(([Xe])=>[Xe,!1])),le={},ye=Object.fromEntries(te.map(([Xe])=>[Xe,[]])),he=[],ve=[],be=!1,Ie=-1;for(let[Xe,et]of z.entries()){if(Xe<=Ie)continue;if(et==="--"){he.push(...z.slice(Xe+1));break}if(Hd.includes(et)){be=!0;continue}let Ee=X.find(([,lt])=>lt.includes(et));if(Ee){ae[Ee[0]]=!0;continue}let at=ee.find(([,lt])=>lt.includes(et));if(at){let lt=z[Xe+1];if(lt===void 0||lt.startsWith("-")){ve.push(`${et} requires a value`);continue}le[at[0]]=lt,Ie=Xe+1;continue}let ct=te.find(([,lt])=>lt.includes(et));if(ct){let lt=z.slice(Xe+1),pt=lt.findIndex((gt)=>gt.startsWith("-")),mt=lt.slice(0,pt===-1?lt.length:pt);if(mt.length===0){ve.push(`${et} requires at least one value`);continue}ye[ct[0]]=[...ye[ct[0]]??[],...mt],Ie=Xe+mt.length;continue}if(et.startsWith("-")){ve.push(`Unknown option for ${A.label}: ${et}`);continue}if(A.positionals==="tail"){he.push(...z.slice(Xe));break}he.push(et)}if(A.positionals!=="list"&&A.positionals!=="tail")ve.push(...he.map((Xe)=>`Unexpected argument for ${A.label}: ${Xe}`));return{flags:ae,values:le,lists:ye,positionals:he,help:be,errors:ve}}function Ht(A){for(let z of A)console.error(z);return A.length>0}import{readdirSync as Jd,statSync as Oi,unlinkSync as Wd}from"node:fs";import{basename as Fi,dirname as Kd,isAbsolute as Yd,join as Zd,relative as Xd,resolve as Qd,sep as eu}from"node:path";var Ti=(A)=>{let z=Date.now()-new Date(A).getTime();if(!Number.isFinite(z))return"";let X=Math.floor(z/60000),ee=Math.floor(X/60),te=Math.floor(ee/24);if(te>0)return`${te}d ago`;if(ee>0)return`${ee}h ago`;if(X>0)return`${X}m ago`;return"just now"},Xr=(A)=>{let z=(A??"").trim().split(/\s+/).filter((te)=>te&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(te)),X=z[0]?.split("/").pop();if(!X)return null;let ee=z[1];return ee&&/^[a-z][a-z0-9-]*$/.test(ee)?`${X} ${ee}`:X};function $i(A){let z=(te)=>`${te.sessionId}
2
+ ${Xr(te.segment||te.command)}`,X=A.filter((te)=>te.decision!=="allow"),ee=X.filter((te)=>te.sessionId).reduce((te,ae)=>te.set(z(ae),(te.get(z(ae))??0)+1),new Map);return new Set(X.filter((te)=>te.failureStage||(ee.get(z(te))??0)>=2))}import{existsSync as Ud,readdirSync as Gd,readFileSync as Bd}from"node:fs";import{join as qd}from"node:path";function Yt(A,z){try{return Gd(A,{withFileTypes:!0,encoding:"utf8"}).flatMap((X)=>{let ee=qd(A,X.name);if(X.isDirectory())return Yt(ee,z);if(X.name.endsWith(".jsonl"))return[ee];return[]})}catch{if(z&&Ud(A))z.count++;return[]}}var Vd=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function zd(A){if(!A||typeof A!=="object"||Array.isArray(A))return!1;let z=A;if(typeof z.ts!=="string"||typeof z.command!=="string")return!1;return Vd.every((X)=>z[X]===void 0||typeof z[X]==="string")}function un(A,z){try{return Bd(A,"utf-8").split(`
3
+ `).filter(Boolean).flatMap((X)=>{try{let ee=JSON.parse(X);if(!zd(ee)){if(z)z.count++;return[]}return[ee]}catch{if(z)z.count++;return[]}})}catch{if(z)z.count++;return[]}}function Ct(A){return Array.from(A,(z)=>{let X=z.charCodeAt(0);if(X<=31||X>=127&&X<=159)return`\\x${X.toString(16).padStart(2,"0")}`;return z}).join("")}function tu(A,z){let X=Q(A),ee=xt({label:"logs",booleans:{all:["--all"],suspect:["--suspect"],json:["--json"],pruneLegacy:["--prune-legacy"],dryRun:["--dry-run"]},values:{id:["--id"],limit:["--limit"],since:["--since"],agent:["--agent"],rule:["--rule"],session:["--session"],project:["--project"]}},z);if(Ht(ee.errors))return null;if(ee.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(ee.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let te=ee.values.limit===void 0?20:Ii(ee.values.limit);if(te===null)return console.error("--limit must be a positive number"),null;let ae=ee.values.since===void 0?Math.min(30,X):Ii(ee.values.since);if(ae===null||ae>X)return console.error(`--since must be a positive number of days no greater than ${X}`),null;let le={limit:te,limitExplicit:ee.values.limit!==void 0,since:ae,sinceExplicit:ee.values.since!==void 0,all:ee.flags.all,json:ee.flags.json,suspect:ee.flags.suspect,pruneLegacy:ee.flags.pruneLegacy,dryRun:ee.flags.dryRun,id:ee.values.id,agent:ee.values.agent,rule:ee.values.rule,session:ee.values.session,project:ee.values.project===void 0?void 0:Qd(ee.values.project)};if(le.id&&(le.agent!==void 0||le.rule!==void 0||le.session!==void 0||le.project!==void 0||le.suspect||le.sinceExplicit||le.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(le.pruneLegacy&&(le.id!==void 0||le.agent!==void 0||le.rule!==void 0||le.session!==void 0||le.project!==void 0||le.suspect||le.all||le.sinceExplicit||le.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(le.dryRun&&!le.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return le}async function ji(A,z,X={}){let ee=tu(A,z);if(!ee)return 1;let te=X.logsDir??D(A);if(ee.pruneLegacy)return nu(te,ee.json,ee.dryRun);if(!te)return console.log(ee.json?"[]":ee.id?`No retained audit log entry found for id ${Ct(ee.id)}.`:"No audit log entries found."),0;B(A,te);let ae={count:0},le=Yt(te,ae).flatMap((Ie)=>un(Ie,ae).map((Xe)=>({entry:Xe,file:Ie})));if(ae.count>0)console.error(`warning: ${ae.count} audit log ${ae.count===1?"source":"sources"} could not be read; these results are incomplete`);if(ee.id)return su(le,ee,X.timeZone);let ye=Date.now()-ee.since*24*60*60*1000,he=le.filter((Ie)=>au(Ie,ee,te,ye)),ve=ee.suspect?$i(he.map((Ie)=>Ie.entry)):null,be=(ve?he.filter((Ie)=>ve.has(Ie.entry)):he).sort((Ie,Xe)=>Date.parse(Xe.entry.ts)-Date.parse(Ie.entry.ts)).slice(0,ee.limit);if(ee.json)return console.log(JSON.stringify(be.map((Ie)=>Ie.entry),null,2)),0;if(be.length===0)return console.log("No audit log entries found."),0;for(let Ie of be)console.log(du(Ie.entry,X.timeZone));return 0}function nu(A,z,X){let ee=A?ou(A).map((ye)=>Zd(A,ye)):[];if(X)return ru(ee,z);let te=[],ae=0,le=0;for(let ye of ee){let he=Oi(ye,{throwIfNoEntry:!1})?.size??0,ve=iu(ye);if(ve){te.push(`${Fi(ye)}: ${ve}`);continue}ae++,le+=he}if(z)return console.log(JSON.stringify({removedFiles:ae,removedBytes:le,failedFiles:te.length})),te.length===0?0:1;console.log(ae===0&&te.length===0?"No legacy audit log files found.":`Removed ${ae} legacy audit log ${ae===1?"file":"files"} (${Ni(le)}).`);for(let ye of te)console.error(`Could not remove ${Ct(ye)}`);if(console.log("Nested v2 audit logs were not changed."),ae>0)console.log("This deletion cannot be undone.");return te.length===0?0:1}function ru(A,z){let X=A.reduce((ee,te)=>ee+(Oi(te,{throwIfNoEntry:!1})?.size??0),0);if(z)return console.log(JSON.stringify({dryRun:!0,files:A.length,bytes:X})),0;if(console.log(A.length===0?"No legacy audit log files found.":`Would remove ${A.length} legacy audit log ${A.length===1?"file":"files"} (${Ni(X)}).`),console.log("Nested v2 audit logs are not included."),A.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function ou(A){try{return Jd(A,{withFileTypes:!0}).filter((z)=>z.isFile()&&z.name.endsWith(".jsonl")).map((z)=>z.name)}catch{return[]}}function iu(A){try{return Wd(A),null}catch(z){return z instanceof Error?z.message:String(z)}}function Ni(A){let z=["B","KiB","MiB","GiB"],X=Math.min(Math.floor(Math.log2(Math.max(A,1))/10),z.length-1);return`${Math.round(A/1024**X*10)/10} ${z[X]}`}function su(A,z,X){let ee=A.filter((ae)=>ae.entry.id===z.id);if(ee.length>1)return console.error(`Multiple audit log entries found for id ${Ct(z.id??"")}.`),1;if(z.json)return console.log(JSON.stringify(ee.map((ae)=>ae.entry),null,2)),0;let te=ee[0];if(!te)return console.log(`No retained audit log entry found for id ${Ct(z.id??"")}.`),0;return console.log(uu(te.entry,X)),0}function au(A,z,X,ee){if(!z.all&&A.entry.decision==="allow")return!1;if(Date.parse(A.entry.ts)<ee)return!1;if(z.agent!==void 0&&A.entry.agent!==z.agent)return!1;if(z.rule!==void 0&&A.entry.ruleId!==z.rule)return!1;if(z.session!==void 0&&!lu(A,X,z.session))return!1;if(z.project!==void 0&&!cu(A.entry.cwd,z.project))return!1;return!0}function lu(A,z,X){if(A.entry.sessionId===X)return!0;return Kd(A.file)===z&&Fi(A.file,".jsonl")===X}function cu(A,z){if(!A)return!1;let X=Xd(z,A);return X!==".."&&!X.startsWith(`..${eu}`)&&!Yd(X)}function du(A,z){let X=Ct(A.id??"-"),ee=Ct(A.decision??"deny"),te=A.cwd?` [${Ct(A.cwd)}]`:"",ae=A.segment||A.command,le=ae===A.command?"":"↳ ",ye=ae.length>50?`${ae.slice(0,50)}…`:ae;return`${X.padEnd(16)} ${Ct(Mi(A.ts,z))} ${ee.padEnd(5)} ${Ct(A.agent??"-").padEnd(15)} ${Ct(A.ruleId??"-").padEnd(20)} ${le}${Ct(ye)}${te}`}function uu(A,z){let X=(te)=>Ct(te===void 0||te===null||te===""?"-":te),ee=A.shape?`${A.agent??"-"} (shape: ${A.shape})`:A.agent??"-";return[`id: ${X(A.id)}`,`ts: ${X(Mi(A.ts,z))}`,`decision: ${X(A.decision)}`,`agent: ${X(ee)}`,`level: ${X(A.level)}`,`tool: ${X(A.toolName)}`,`rule: ${X(A.ruleId)}`,`intent: ${X(A.intent)}`,`stage: ${X(A.failureStage)}`,`error: ${X(A.errorCode)}`,`session: ${X(A.sessionId)}`,`cwd: ${X(A.cwd)}`,`version: ${X(A.v)}`,`truncated: ${X(A.truncated===!0?"yes":void 0)}`,`reason: ${X(A.reason)}`,`command: ${X(A.command)}`,`segment: ${X(A.segment)}`].join(`
4
+ `)}function Mi(A,z){let X=new Date(A);if(Number.isNaN(X.getTime()))return A;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:z}).format(X)}function Ii(A){let z=Number(A);return Number.isFinite(z)&&z>0?z:null}var Hi={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 Ui={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 Gi={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 Kn=[{id:"antigravity-cli",displayName:"Antigravity CLI",doctorOrder:3,runtime:{order:1,flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:2,flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",doctorOrder:1,runtime:{order:2,displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{order:3,flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",doctorOrder:4,runtime:{order:3,flags:["-cx","--codex"],description:"Run as a Codex PreToolUse hook",legacyTopLevelFlags:[]},install:{order:4,flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",doctorOrder:7,runtime:{order:6,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:7,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:6,runtime:{order:5,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:6,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",doctorOrder:8,runtime:{order:7,flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:9,runtime:{order:8,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:9,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:10,runtime:{order:9,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:10,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:11,install:{order:11,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:12,install:{order:12,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:13,install:{order:13,flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",doctorOrder:5,runtime:{order:4,flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{order:5,flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],Yn=Kn.slice().sort((A,z)=>A.doctorOrder-z.doctorOrder).map((A)=>A.id),Cn=Kn.filter((A)=>("runtime"in A)).slice().sort((A,z)=>A.runtime.order-z.runtime.order).map((A)=>({id:A.id,displayName:"displayName"in A.runtime?A.runtime.displayName:A.displayName,flags:A.runtime.flags,legacyFlags:"legacyFlags"in A.runtime?A.runtime.legacyFlags:[],description:A.runtime.description,legacyTopLevelFlags:A.runtime.legacyTopLevelFlags})),Tt=Kn.slice().sort((A,z)=>A.install.order-z.install.order).map((A)=>({id:A.id,...A.install})).map(({order:A,...z})=>z),pu=Object.fromEntries(Kn.map((A)=>[A.id,A.displayName]));function bt(A){return pu[A]}var fu=Cn.map((A)=>({flags:A.flags.join(", "),description:A.description})),mu=Cn.flatMap((A)=>A.flags.map((z)=>`cc-safety-net hook ${z}`)),Bi={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...fu,{flags:"-h, --help",description:"Show this help"}],examples:mu};var qi={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...Tt.map((A)=>({flags:A.flag,description:`Install ${bt(A.id)} ${A.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...Tt.map((A)=>`cc-safety-net install ${A.flag}`)]},Vi={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...Tt.map((A)=>({flags:A.flag,description:`Uninstall ${bt(A.id)} ${A.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...Tt.map((A)=>`cc-safety-net uninstall ${A.flag}`)]},zi={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 Ji={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 Zn={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 Qr=[{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"}],eo=["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"],pn={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"},...Qr.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",...eo,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var Wi={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 Ki={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 Xn=[Wi,Hi,Ji,Ui,pn,Zn,qi,zi,Vi,Bi,Gi,Ki];function gu(A){return A.aliases??[]}function Qn(A){let z=A.toLowerCase();return Xn.find((X)=>X.name.toLowerCase()===z||gu(X).some((ee)=>ee.toLowerCase()===z))}import{basename as yu}from"node:path";function er(A,z=7,X=D(A)){let ee=Date.now()-z*24*60*60*1000,te=[],ae=new Set,le=0,ye,he,ve,be;if(X)B(A,X);let Ie={count:0},Xe=X?Yt(X,Ie):[];for(let Ee of Xe)for(let at of un(Ee,Ie)){if(at.decision==="allow")continue;let ct=new Date(at.ts).getTime();if(ct>=ee){if(le++,ae.add(at.sessionId??yu(Ee,".jsonl")),he===void 0||ct<=he)ye=at.ts,he=ct;if(be===void 0||ct>be)ve=at.ts,be=ct;hu(te,at,ct)}}let et=te.map((Ee)=>({timestamp:Ee.ts,command:Ee.command,reason:Ee.reason,relativeTime:Ti(new Date(Ee.ts))}));return{totalBlocked:le,sessionCount:ae.size,recentEntries:et,oldestEntry:ye,newestEntry:ve,unreadable:Ie.count}}function hu(A,z,X){let ee=A.findIndex((te)=>X>new Date(te.ts).getTime());if(ee===-1){if(A.length<3)A.push(z);return}if(A.splice(ee,0,z),A.length>3)A.pop()}import{dirname as Du}from"node:path";import{dirname as vu,join as bu,resolve as Lu}from"node:path";var wu="config.json";function Rt(A,z,X,ee){g(ku(A),`${JSON.stringify(z,null,2)}
5
+ `,X,ee)}function ku(A){return typeof A==="string"?ne(A):A}function no(A){return{errors:oe(Cu(A),": "," "),ruleNames:new Set(_e(A).map((z)=>z.toLowerCase()))}}var xu="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",Yi="must match pattern (letters, numbers, hyphens, underscores)";function Cu(A){if(!Zi(A))return[e([],"Config must be an object")];return[...A.version===1?[]:[e(["version"],"must be 1")],...Su(A.rules)]}function Su(A){if(A===void 0)return[];if(!Array.isArray(A))return[e(["rules"],"must be an array")];return[...A.flatMap((z,X)=>Zi(z)?Ru(z,["rules",X]):[e(["rules",X],"must be an object")]),...Pe(A)]}function Ru(A,z){return[...to(A.name,[...z,"name"],"required string",c,xu),...to(A.command,[...z,"command"],"required string",S,Yi),...A.subcommand===void 0?[]:to(A.subcommand,[...z,"subcommand"],"must be a string if provided",S,Yi),...Pu(A.block_args,[...z,"block_args"]),...Eu(A.reason,[...z,"reason"]),...A.intent===void 0||xe(A.intent)?[]:[e([...z,"intent"],Se)]]}function to(A,z,X,ee,te){if(typeof A!=="string")return[e(z,X)];return ee.test(A)?[]:[e(z,te)]}function Pu(A,z){if(!Array.isArray(A))return[e(z,"required array")];if(A.length===0)return[e(z,"must have at least one element")];return A.flatMap((X,ee)=>{if(typeof X!=="string")return[e([...z,ee],"must be a string")];return X===""?[e([...z,ee],"must not be empty")]:[]})}function Eu(A,z){if(typeof A!=="string")return[e(z,"required string")];if(A==="")return[e(z,"must not be empty")];return A.length>P?[e(z,`must be at most ${P} characters`)]:[]}function Zi(A){return!!A&&typeof A==="object"&&!Array.isArray(A)}function ro(A){let z=Xi(A);if(!z.ok)return z.result;return no(z.parsed)}function Xi(A){let z=[],X=new Set;try{let ee=typeof A==="string"?ne(A):A,te=n(ee);if(te===null)return z.push(`File not found: ${ee.path}`),{ok:!1,result:{errors:z,ruleNames:X}};if(!te.trim())return z.push("Config file is empty"),{ok:!1,result:{errors:z,ruleNames:X}};return{ok:!0,parsed:JSON.parse(te)}}catch(ee){if(ee instanceof r)return z.push(ee.message),{ok:!1,result:{errors:z,ruleNames:X}};let te=ee instanceof Error?ee.message:String(ee);return z.push(ee instanceof SyntaxError?"Invalid JSON":te),{ok:!1,result:{errors:z,ruleNames:X}}}}function Qi(A){return Lu(A,".safety-net.json")}function Jt(A){let z=Xi(A);if(!z.ok)return z.result;let X=Ve(z.parsed);return{errors:X.errors,ruleNames:X.sources}}function tr(A,z={}){return bu(vu(Ce(A,z)),wu)}function es(A,z,X){let ee;try{if(n(z)===null)return{path:A,exists:!1,valid:!1,ruleCount:0};ee=Jt(z),ee.errors.push(...j(A,X))}catch(te){if(!(te instanceof r))throw te;ee={errors:[te.message],ruleNames:new Set}}return{path:A,exists:!0,valid:ee.errors.length===0,ruleCount:ee.ruleNames.size,...ee.errors.length>0?{errors:ee.errors}:{}}}function Au(A,z){return{source:z,name:A.name,command:A.command,subcommand:A.subcommand,blockArgs:[...A.block_args],reason:A.reason}}function ts(A,z){let X=F(A),ee=M(z),te=Du(X),ae=K(A,{cwd:z,userConfigPath:X,projectConfigPath:ee,userConfigDir:te}),le=q(A,{cwd:z,userConfigPath:X,projectConfigPath:ee,userConfigDir:te}),ye=new Map(ae.rulebooks.flatMap((he)=>he.rules.map((ve)=>[ve,he.source])));return{userConfig:es(X,le.userConfigTarget,le.userScope),projectConfig:es(ee,le.projectConfigTarget,le.projectScope),effectiveRules:ae.rules.map((he)=>Au(he,ye.get(he.name)??"project"))}}var _u=[{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 ns(A){return[..._u.map((z)=>({name:z.flag.name,value:we(z.flag,A.env),isSet:Qe(z.flag,A.env),legacyName:z.flag.legacyName,legacyValue:z.flag.legacyName?A.env.get(z.flag.legacyName):void 0,legacyIsSet:z.flag.legacyName?A.env.get(z.flag.legacyName)!==void 0:void 0,description:z.description,defaultBehavior:z.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:A.env.get("CC_SAFETY_NET_HOME"),isSet:A.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var rs={error:0,warning:1,info:2},Tu=["policy","config","audit"];function $u(A){return A.map((z)=>{if(z==="ownership")return"is not owned by the current user";if(z==="permissions")return"has unsafe permissions";if(z==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Iu=[{derive:(A)=>A.hooks.length>0&&A.hooks.every((z)=>!z.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:(A)=>A.hooks.filter((z)=>z.inspectionStatus==="failed").map((z)=>{let X=bt(z.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${X} inspection failed`,detail:`Doctor could not verify the ${X} integration configuration.`,fixHint:`Correct the reported ${X} configuration error, then run \`cc-safety-net doctor\` again.`,integration:z.platform}})},{derive:(A)=>A.userConfig.exists&&!A.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:A.userConfig.path}]:[]},{derive:(A)=>A.projectConfig.exists&&!A.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:A.projectConfig.path}]:[]},{derive:(A)=>A.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${A.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:(A)=>A.v2Leftovers&&A.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: ${A.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(A)=>{let z=A.environment.find((X)=>X.name==="CC_SAFETY_NET_AUDIT_SCOPE");return We(z?.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."}]:[]}},...Tu.map((A)=>({derive:(z)=>z.posture.directories.filter((X)=>X.kind===A&&X.status==="unsafe").map((X)=>({checkId:`posture.${A}-directory-unsafe`,severity:"error",title:`${A[0]?.toUpperCase()}${A.slice(1)} directory is unsafe`,detail:`The ${A} directory ${$u(X.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...X.path?{path:X.path}:{}}))})),{derive:(A)=>{let z=[...A.effectiveSafety.weakenedRuleOverrides].sort();return z.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: ${z.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${z.join(", ")}.`}]:[]}}];function os(A){return Iu.flatMap((z,X)=>z.derive(A).map((ee,te)=>({finding:ee,catalogOrder:X,occurrence:te}))).sort((z,X)=>rs[z.finding.severity]-rs[X.finding.severity]||z.catalogOrder-X.catalogOrder||z.occurrence-X.occurrence).map((z)=>z.finding)}function Ut(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var Ou=(A)=>Ut()?`\x1B[32m${A}\x1B[0m`:A,Fu=(A)=>Ut()?`\x1B[33m${A}\x1B[0m`:A,ju=(A)=>Ut()?`\x1B[34m${A}\x1B[0m`:A,Nu=(A)=>Ut()?`\x1B[36m${A}\x1B[0m`:A,Mu=(A)=>Ut()?`\x1B[31m${A}\x1B[0m`:A,Hu=(A)=>Ut()?`\x1B[2m${A}\x1B[0m`:A,Uu=(A)=>Ut()?`\x1B[1m${A}\x1B[0m`:A,dt={green:Ou,yellow:Fu,blue:ju,cyan:Nu,red:Mu,dim:Hu,bold:Uu},Gu="\x1B[0m",Bu=[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 qu(A){let z=A;return()=>(z=(z*1664525+1013904223)%4294967296,z/4294967296)}function Vu(A){let z=[...Bu],X=qu(A);for(let ee=z.length-1;ee>0;ee--){let te=Math.floor(X()*(ee+1)),ae=z[ee];z[ee]=z[te],z[te]=ae}return z}function zu(A,z=0){if(!Ut())return"";let X=Vu(z);return`\x1B[38;5;${X[A%X.length]}m`}function is(A,z,X=0){if(!Ut())return`"${A}"`;return`${zu(z,X)}"${A}"${Gu}`}function nr(A){return A==="default"?"built-in default":`${A} policy`}var Ju=new RegExp("\x1B\\[[0-9;]*m","g"),oo=(A)=>A.replace(Ju,"").length;function Zt(A){let z=(A.headers??A.rows[0]??[]).map((le,ye)=>{let he=Math.max(...A.rows.map((ve)=>oo(ve[ye]??"")));return Math.max(oo(le),he)}),X=(le,ye)=>le+" ".repeat(Math.max(0,ye-oo(le))),ee=(le,ye)=>ye[0]+z.map((he)=>le.repeat(he+2)).join(ye[1])+ye[2],te=(le)=>`│ ${le.map((ye,he)=>X(ye,z[he]??0)).join(" │ ")} │`,ae=A.headers?[` ${te(A.headers)}`,` ${ee("─",["├","┼","┤"])}`]:[];return[` ${ee("─",["┌","┬","┐"])}`,...ae,...A.rows.map((le)=>` ${te(le)}`),` ${ee("─",["└","┴","┘"])}`].join(`
6
+ `)}function ss(A){let z=[];z.push("Hook Integration"),z.push(Wu(A));let X=[],ee=[];for(let te of A){let ae=bt(te.platform);if(te.errors&&te.errors.length>0)for(let le of te.errors)if(te.configured)X.push({platform:ae,message:le});else ee.push({platform:ae,message:le})}for(let te of X)z.push(` Warning (${te.platform}): ${te.message}`);for(let te of ee)z.push(dt.red(` Error (${te.platform}): ${te.message}`));return z.join(`
7
+ `)}function Wu(A){let z=["Platform","Discovery","Configuration","Inspection"],X=A.map((ee)=>{let te=bt(ee.platform);if(ee.inspectionStatus==="not-inspected"){let he=dt.dim("Not inspected");return[te,he,he,he]}let ae=ee.detected?dt.green("Detected"):ee.inspectionStatus==="failed"?dt.red("Unknown"):dt.dim("Not detected"),le=ee.configured?dt.green("Configured"):ee.detected?dt.yellow("Not configured"):ee.inspectionStatus==="failed"?dt.red("Unknown"):dt.dim("Not applicable"),ye=ee.inspectionStatus==="verified"?dt.green("Verified"):ee.inspectionStatus==="failed"?dt.red("Failed"):dt.dim("Not applicable");return[te,ae,le,ye]});return Zt({headers:z,rows:X})}function as(A){let X=["Guard Engine Verification",` Synthetic self-test: ${A.failed>0?dt.red(`${A.passed}/${A.total} FAIL`):dt.green(`${A.passed}/${A.total} passed`)}`],ee=A.results.filter((te)=>!te.passed);if(ee.length>0){X.push(""),X.push(dt.red(" Failures:"));for(let te of ee)X.push(dt.red(` • ${te.description}`)),X.push(dt.red(` expected ${te.expected}, got ${te.actual}`))}return X.join(`
8
+ `)}function Ku(A){if(A.length===0)return" (no custom rules)";let z=["Source","Name","Command","Block Args"],X=A.map((ee)=>[ee.source,ee.name,ee.subcommand?`${ee.command} ${ee.subcommand}`:ee.command,ee.blockArgs.join(", ")]);return Zt({headers:z,rows:X})}function ls(A){let z=[];if(z.push("Configuration"),z.push(Yu(A.userConfig,A.projectConfig)),z.push(""),A.effectiveRules.length>0)z.push(` Effective rules (${A.effectiveRules.length} total):`),z.push(Ku(A.effectiveRules));else z.push(" Effective rules: (none - using built-in rules only)");return z.join(`
9
+ `)}function Yu(A,z){let X=["Scope","Status"],ee=(ae)=>{if(!ae.exists)return dt.dim("N/A");if(!ae.valid)return dt.red(`Invalid (${ae.errors?.[0]??"unknown error"})`);return dt.green("Configured")},te=[["User",ee(A)],["Project",ee(z)]];return Zt({headers:X,rows:te})}function cs(A){let z=[];return z.push("Environment"),z.push(Zu(A)),z.join(`
10
+ `)}function ds(A){let z=A.effectiveSafety.policyScopes,X=["Effective Safety",` Selected preset: ${A.effectiveSafety.selectedPreset}${z?` (${nr(z.levelScope)})`:""}`,` Effective: ${A.effectiveSafety.level}`],ee=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[te,ae]of ee){let le=A.effectiveSafety.capabilities[te],ye=le.enabled?dt.green("ON"):dt.dim("OFF"),he=le.sources.length>0?` (${le.sources.join(", ")})`:"";X.push(` ${ae}: ${ye} via ${le.source}${he}`)}if(z&&z.weakenings.length>0){X.push(" Project policy deltas:");for(let te of z.weakenings)X.push(` ${te}`)}X.push(` Stored rule customizations: ${A.effectiveSafety.ruleCounts.stored}`),X.push(` Effective rule customizations: ${A.effectiveSafety.ruleCounts.effective}`);for(let[te,ae]of Object.entries(A.effectiveSafety.ruleOverrides))X.push(` ${te}: ${ae}`);return X.join(`
11
+ `)}function us(A){let z=["Findings"];if(A.length===0)return z.push(" No findings from inspected doctor facts."),z.join(`
12
+ `);for(let X of A){let ee=`[${X.severity.toUpperCase()}] ${X.checkId}: ${Ct(X.title)}`,te=X.severity==="error"?dt.red:X.severity==="warning"?dt.yellow:dt.blue;if(z.push(` ${te(ee)}`),z.push(` ${Ct(X.detail)}`),X.path)z.push(` Path: ${Ct(X.path)}`);if(X.fixHint)z.push(` Fix: ${Ct(X.fixHint)}`)}return z.join(`
13
+ `)}function Zu(A){let z=["Variable","Status","Legacy"],X=A.map((ee)=>{let te=ee.isSet?dt.green("✓"):dt.dim("✗"),ae=ee.legacyName&&ee.legacyIsSet?`${ee.legacyName} ${dt.green("✓")}`:ee.legacyName??"";return[ee.name,te,ae]});return Zt({headers:z,rows:X})}function ps(A){let z=[];if(A.totalBlocked===0)z.push("Recent Activity"),z.push(" No blocked commands in the last 7 days"),z.push(" Tip: This is normal for new installations");else z.push(`Recent Activity · last 7 days (${A.totalBlocked} blocked / ${A.sessionCount} sessions)`),z.push(Xu(A.recentEntries));if(A.unreadable>0)z.push(` Warning: ${A.unreadable} audit log ${A.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return z.join(`
14
+ `)}function Xu(A){let z=["Time","Command"],X=A.map((ee)=>{let te=Ct(ee.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),ae=te.length>40?`${te.slice(0,37)}...`:te;return[ee.relativeTime,ae]});return Zt({headers:z,rows:X})}function fs(A){let z=[];if(z.push("Update Check"),A.latestVersion===null&&!A.error)return z.push(rr([["Status",dt.dim("Skipped")],["Installed",A.currentVersion]])),z.join(`
15
+ `);if(A.error)return z.push(rr([["Status",`${dt.yellow("⚠")} Error`],["Installed",A.currentVersion],["Error",dt.dim(A.error)]])),z.join(`
16
+ `);if(A.updateAvailable)return z.push(rr([["Status",`${dt.yellow("⚠")} Update Available`],["Current",A.currentVersion],["Latest",dt.green(A.latestVersion??"")]])),z.push(""),z.push(" Run: bunx cc-safety-net@latest doctor"),z.push(" Or: npx cc-safety-net@latest doctor"),z.join(`
17
+ `);return z.push(rr([["Status",`${dt.green("✓")} Up to date`],["Version",A.currentVersion]])),z.join(`
18
+ `)}function rr(A){return Zt({rows:A})}function ms(A){let z=[];return z.push("System Info"),z.push(Qu(A)),z.join(`
19
+ `)}function Qu(A){let z=["Component","Version"],X=(ae)=>{if(ae===null)return dt.dim("not found");return ae},te=[{label:"cc-safety-net",value:A.version},...Yn.map((ae)=>({label:bt(ae),value:A.versions[ae]??null})),{label:"Node.js",value:A.nodeVersion},{label:"npm",value:A.npmVersion},{label:"Bun",value:A.bunVersion},{label:"Platform",value:A.platform}].map((ae)=>[ae.label,X(ae.value)]);return Zt({headers:z,rows:te})}function gs(A){if(A.findings.length===0)return dt.green(`
20
+ No findings from inspected doctor facts.`);let z={error:A.findings.filter((ae)=>ae.severity==="error").length,warning:A.findings.filter((ae)=>ae.severity==="warning").length,info:A.findings.filter((ae)=>ae.severity==="info").length},X=["error","warning","info"].filter((ae)=>z[ae]>0).map((ae)=>`${z[ae]} ${ae}`),ee=A.findings.length===1?"finding":"findings",te=`
21
+ ${A.findings.length} ${ee}: ${X.join(", ")}.`;if(z.error>0)return dt.red(te);if(z.warning>0)return dt.yellow(te);return dt.blue(te)}import{lstatSync as ep}from"node:fs";import{dirname as io}from"node:path";function so(A,z){try{let X=ep(z);if(X.isSymbolicLink())return{kind:A,path:z,status:"unsafe",issues:["symlink"]};if(!X.isDirectory())return{kind:A,path:z,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:A,path:z,status:"unknown",issues:[]};let ee=[...X.uid!==process.getuid()?["ownership"]:[],...(X.mode&18)!==0?["permissions"]:[]];return{kind:A,path:z,status:ee.length>0?"unsafe":"safe",issues:ee}}catch(X){if(typeof X==="object"&&X!==null&&"code"in X&&X.code==="ENOENT")return{kind:A,path:z,status:"not-applicable",issues:[]};return{kind:A,path:z,status:"unknown",issues:[]}}}function ys(A,z){let X=D(A);return{directories:[so("policy",io(io(z))),so("config",io(z)),...X?[so("audit",X)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as tp}from"node:child_process";import{existsSync as hs}from"node:fs";import{delimiter as np,extname as rp,join as op}from"node:path";import{stripVTControlCharacters as vs}from"node:util";var Ls="2.4.2",ip=5000,sp="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function wt(){return Ls}function ao(A,z){let X=A[z];if(X)return X;let ee=Object.keys(A).find((te)=>te.toLowerCase()===z.toLowerCase()&&!!A[te]);return ee?A[ee]:X}function ap(A){return(ao(A,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((z)=>z.length>0)}function lp(A,z){let X=rp(A)?[A]:[...ap(z).map((ee)=>`${A}${ee}`),A];if(A.includes("/")||A.includes("\\"))return X.find((ee)=>hs(ee))??A;return(ao(z,"PATH")??"").split(np).flatMap((ee)=>X.map((te)=>op(ee,te))).find((ee)=>hs(ee))??A}function bs(A){if(!/[\s"&|<>^]/.test(A))return A;return`"${A.replace(/"/g,'""')}"`}function Xt(A,z){let[X,...ee]=A,te=z[sp]==="win32"?"win32":process.platform;if(!X||te!=="win32")return{cmd:X??"",args:ee};let ae=lp(X,z);if(!/\.(?:bat|cmd)$/i.test(ae))return{cmd:ae,args:ee};return{cmd:ao(z,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",bs(ae),...ee.map(bs)].join(" ")]}}var fn=async(A,z=ip)=>{let X=await cp(A,{timeoutMs:z});if(X.code!==0)return null;return vs(X.stdout).trim()||vs(X.stderr).trim()||null};function cp(A,z){let[X,...ee]=A;if(!X)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((te)=>{try{let ae=Xt([X,...ee],process.env),le=tp(ae.cmd,ae.args,{stdio:["ignore","pipe","pipe"]}),ye=!1,he="",ve="";le.stdout.on("data",(Xe)=>{he+=Xe.toString()}),le.stderr.on("data",(Xe)=>{ve+=Xe.toString()});let be=(Xe)=>{if(ye)return;ye=!0,clearTimeout(Ie),te(Xe)},Ie=setTimeout(()=>{le.kill(),be({code:null,stdout:he,stderr:ve})},z.timeoutMs);le.on("close",(Xe)=>{be({code:Xe,stdout:he,stderr:ve})}),le.on("error",()=>{be({code:null,stdout:he,stderr:ve})})}catch{te({code:null,stdout:"",stderr:""})}})}function or(A){if(!A)return null;let z=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(A);if(z)return z[1]??null;let X=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(A);if(X)return X[1]??null;return A.split(`
22
+ `)[0]?.trim()||null}async function ir(A=fn){let[z,X,ee,te,ae,le]=await Promise.all([Promise.all(Tt.map(async(ye)=>[ye.id,or(await A([...ye.probeCommand]))])),A(["codex","plugin","list"],30000),A(["amp","plugins","list"],30000),A(["node","--version"]),A(["npm","--version"]),A(["bun","--version"])]);return{version:Ls,versions:Object.fromEntries(z),codexPluginListOutput:X,ampPluginListOutput:ee,nodeVersion:or(te),npmVersion:or(ae),bunVersion:or(le),platform:`${process.platform} ${process.arch}`}}function lo(A,z){if(z==="dev")return!1;let X=A.split(".").map(Number),ee=z.split(".").map(Number),[te=0,ae=0,le=0]=X,[ye=0,he=0,ve=0]=ee;if(te!==ye)return te>ye;if(ae!==he)return ae>he;return le>ve}async function Wt(){let A=wt(),z=new AbortController,X=setTimeout(()=>z.abort(),3000);try{let ee=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:z.signal});if(!ee.ok)return{currentVersion:A,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${ee.status}`};let te=await ee.json(),ae=lo(te.version,A);return{currentVersion:A,latestVersion:te.version,updateAvailable:ae}}catch(ee){return{currentVersion:A,latestVersion:null,updateAvailable:!1,error:ee instanceof Error?ee.message:"Network error"}}finally{clearTimeout(X)}}import*as Es from"node:readline";var Cs=(A)=>`\x1B[${A}B`,dp=(A)=>`\x1B[${A}A`;var ws=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function up(A){return new Promise((z)=>setTimeout(z,A))}function pp(A,z,X){if(!X)return z(A);if(X.aborted)return Promise.resolve();return new Promise((ee,te)=>{let ae=()=>X.removeEventListener("abort",le),le=()=>{ae(),ee()};X.addEventListener("abort",le,{once:!0}),z(A).then(()=>{ae(),ee()},(ye)=>{ae(),te(ye)})})}function sr(A){return Math.max(0,Math.min(1,A))}function mn(A){return Math.max(0,Math.min(255,Math.round(A)))}function co(A){return A<=0.0031308?12.92*A:1.055*A**0.4166666666666667-0.055}function fp(A,z,X){let ee=X*Math.PI/180,te=z*Math.cos(ee),ae=z*Math.sin(ee),le=(A+0.3963377774*te+0.2158037573*ae)**3,ye=(A-0.1055613458*te-0.0638541728*ae)**3,he=(A-0.0894841775*te-1.291485548*ae)**3;return{blue:mn(co(sr(-0.0041960863*le-0.7034186147*ye+1.707614701*he))*255),green:mn(co(sr(-1.2684380046*le+2.6097574011*ye-0.3413193965*he))*255),red:mn(co(sr(4.0767416621*le-3.3077115913*ye+0.2309699292*he))*255)}}function uo(A,z){let X=(z*A*180/Math.PI%360+360)%360;return fp(0.72,0.15,X)}function Ss(A,z=0.1){let X=uo(z,A);return`\x1B[38;2;${X.red};${X.green};${X.blue}m`}function mp(A,z){return{blue:mn(A.blue+(255-A.blue)*z),green:mn(A.green+(255-A.green)*z),red:mn(A.red+(255-A.red)*z)}}function Rs(A,z,X){let ee=Math.imul(A+2654435769,2246822507)^Math.imul(z+3266489909,668265263)^Math.imul(X+374761393,2654435761),te=ee^ee>>>15,ae=Math.imul(te,739982445),le=ae^ae>>>12,ye=Math.imul(le,695872825);return((ye^ye>>>15)>>>0)/4294967296}function gp(A,z,X){let ee=Math.floor(Rs(A,z,X)*ws.length);return ws[ee]??"░"}function ks(A){let z=sr(A);return z*z*z*(z*(z*6-15)+10)}function yp(A){if(A.length===0)return"";let z=[],X=!1,ee="";for(let te of A){let ae=`${te.red};${te.green};${te.blue}`;if(te.bold!==X)z.push(te.bold?"\x1B[1m":"\x1B[22m"),X=te.bold;if(ae!==ee)z.push(`\x1B[38;2;${ae}m`),ee=ae;z.push(te.character)}return`${z.join("")}\x1B[22m\x1B[39m`}function hp(A,z,X,ee,te){return A.map((ae,le)=>({...uo(X,ee+z+le/te),bold:!1,character:ae}))}function vp(A,z,X,ee,te,ae,le,ye){let he=Math.max(1,ee*0.75),ve=Math.min(1,X/he),be=te*ks(ve),Ie=Math.max(0,(X-he)/Math.max(1,ee-he)),Xe=(1-ks(X/ee))*ye*2,et=0.35*Math.max(0,1-Ie*2),Ee=ve>=1,at=Math.min(A.length,Math.ceil(be+2+1));return A.slice(0,at).map((ct,lt)=>{let pt=uo(ae,le+z+lt/ye+Xe),mt=lt+Rs(z,lt,7919)*2-1;if(mt>be+2)return{...pt,bold:!1,character:" "};let gt=be-mt,ut=0.8*Math.exp(-(gt*gt)/12.5),vt=Math.min(0.9,ut+et),Dt=!Ee&&mt>be-4;return{...mp(pt,vt),bold:vt>0.3,character:Dt?gp(z,lt,X):ct}})}function xs(A){return`\x1B[?2026h${A.map((z,X)=>`\x1B8${X>0?Cs(X):""}${yp(z)}`).join("")}\x1B[?2026l`}async function po(A,z={}){if(!A)return;let X=z.output??process.stdout,ee=z.sleep??up,te=z.seed??0,ae=A.split(`
23
+ `).map((be)=>Array.from(be)),le=Math.max(...ae.map((be)=>be.length)),ye=12000*ae.filter((be)=>be.length>0).length/40,he=le>0?Math.max(1,Math.ceil(ye/16.666666666666668)):0,ve=he>0?ye/he:0;X.write(`\x1B[?25l${ae.length>1?`${`
24
+ `.repeat(ae.length-1)}${dp(ae.length-1)}`:""}\x1B7`);try{for(let be=1;be<=he;be+=1){if(z.signal?.aborted)break;X.write(xs(ae.map((Ie,Xe)=>vp(Ie,Xe,be,he,le,0.1,te,3)))),await pp(ve,ee,z.signal)}}finally{if(X.write(xs(ae.map((be,Ie)=>hp(be,Ie,0.1,te,3)))),X.write("\x1B8"),ae.length>1)X.write(Cs(ae.length-1));X.write(`
25
+ \x1B[0m\x1B[?25h`)}}var Ps=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
+ `);function bp(A){return Boolean(A.isTTY)}async function Sn(A={}){let z=A.output??process.stdout;if(!bp(z))return;let X=A.input??process.stdin,ee={output:z,seed:A.seed??Math.random()*8192,sleep:A.sleep};if(!X.isTTY||typeof X.setRawMode!=="function"){await po(Ps,ee);return}let te=new AbortController,ae=X.readableFlowing===!0,le=X.isRaw===!0,ye=!1,he=(ve,be)=>{if(be.ctrl&&be.name==="c")ye=!0;if(ye||be.name==="return"||be.name==="enter")te.abort()};Es.emitKeypressEvents(X),X.on("keypress",he),X.setRawMode(!0),X.resume();try{await po(Ps,{...ee,signal:te.signal})}finally{if(X.off("keypress",he),X.setRawMode(le),!ae)X.pause()}if(!ye)return;if(A.onInterrupt){A.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as Cp}from"node:crypto";import{existsSync as _s}from"node:fs";import{dirname as ar,join as Ts}from"node:path";import{dirname as Ds,join as Lp,resolve as wp}from"node:path";var kp="rule.lock";function xp(A){return Lp(Ds(A),kp)}function As(A={}){return wp(A.cwd??process.cwd(),".safety-net.json")}function Pt(A,z){let X=z.global?z.userConfigPath??F(A,z):z.projectConfigPath??M(z.cwd??process.cwd()),ee=z.global?Be(A,z):ze(X,z.cwd??process.cwd()),te=xp(X);return{configDir:Ds(X),configPath:X,lockPath:te,filesystemScope:ee,configTarget:i(ee,X),lockTarget:i(ee,te)}}var Sp="`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.",Rp="cache",Pp="rulebooks";function $s(A,z={}){let X=Pt(A,z),ee=i(X.filesystemScope,Os(X.configDir)),te=n(X.lockTarget);if(console.log(Sp),te===null&&!_s(ee.path))return console.log(`No v2 lock or cache leftovers found in ${ar(X.configDir)}; nothing to migrate.`),0;let ae=Tp(te),le=m(X.configTarget);if(!le.config&&(n(X.configTarget)!==null||ae.size>0))return console.error(`Cannot migrate: the rules config in ${ar(X.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let ye=le.config?.rules??[];for(let he of ye.flatMap((ve)=>Ep(ve,ae,X,ee,z.global===!0)))console.log(he);return N(X.lockTarget),tt(ee),console.log(`Removed the v2 lock and cache under ${ar(X.configDir)}.`),0}function Is(A,z){return[...new Set([{cwd:z},{cwd:z,global:!0}].flatMap((X)=>{let ee=Pt(A,X);return[ee.lockPath,Os(ee.configDir)]}))].filter((X)=>_s(X))}function Ep(A,z,X,ee,te){if(!C(A))return[];let ae=T(A).name,le=i(X.filesystemScope,I(X.configDir,ae)),ye=n(le);if(ye!==null&&Dp(ye,ae))return[];let he=z.get(A),ve=he?Ap(he,ae,ee.path,X.filesystemScope):null;if(ve===null)return[`Could not migrate ${A} from the v2 cache. Run \`cc-safety-net rule update ${A}${te?" --global":""}\` to vendor it.`];if(g(le,ve),ye!==null)return[`Restored ${A} from the v2 cache over an invalid file.`];return[`Vendored ${A} from the v2 cache.`]}function Dp(A,z){let X=me(A);return!("problem"in X)&&X.rulebook.name===z}function Ap(A,z,X,ee){let te=Ts(X,Pp,`${_p(A)}--${A.digest.replace("sha256:","").slice(0,12)}`,de),ae=n(i(ee,te));if(ae===null||Op(ae)!==A.digest)return null;let le=me(ae);if("problem"in le||le.rulebook.name!==z)return null;return ae}function Os(A){return Ts(ar(A),Rp)}function _p(A){return([A.owner,A.repo,A.display_ref,A.name].every((ee)=>typeof ee==="string"&&ee!=="")?`${A.owner}/${A.repo}#${A.display_ref}/${A.name}`:A.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function Tp(A){let z=A===null?null:Ip(A),X=Fs(z)&&Array.isArray(z.rulebooks)?z.rulebooks:[];return new Map(X.filter($p).map((ee)=>[ee.spec,ee]))}function $p(A){return Fs(A)&&typeof A.spec==="string"&&typeof A.digest==="string"}function Fs(A){return!!A&&typeof A==="object"}function Ip(A){try{return JSON.parse(A)}catch{return null}}function Op(A){return`sha256:${Cp("sha256").update(A).digest("hex")}`}var js="\r\x1B[2K",Fp="\x1B[?25l",jp="\x1B[39m",Np="\x1B[?25h",Mp=100,Hp=0.55,Up=80,Ns=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function Gp(A){return new Promise((z)=>setTimeout(z,A))}async function lr(A,z={}){let X=z.output??process.stdout;if(!X.isTTY)return A;let ee=z.sleep??Gp,te=!1,ae=A.then((ye)=>(te=!0,ye),(ye)=>{throw te=!0,ye});if(await Promise.race([ae.then(()=>!0),ee(Mp).then(()=>!1)]))return ae;X.write(Fp);try{for(let ye=0;!te;ye+=1)X.write(`${js}${Ss(ye*Hp)}${Ns[ye%Ns.length]}${jp} ${z.loadingMessage??"Loading…"}`),await Promise.race([ae,ee(Up)]);return await ae}finally{X.write(`${js}${Np}`)}}async function Rn(A,z,X,ee={}){let te=z();if(A)await X();if(A&&te.ready)await lr(te.ready,ee);return te.finish()}import{stripVTControlCharacters as Bp}from"node:util";var cr="amp plugins list",qp=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function Ms(A){if(!A.ampPluginListOutput)return{platform:"amp",status:"n/a"};let z=Bp(A.ampPluginListOutput).split(`
27
+ `).map((X)=>qp.exec(X)?.[1]).find((X)=>X!==void 0);if(!z)return{platform:"amp",status:"n/a"};if(z!=="active")return{platform:"amp",status:"disabled",method:cr,configPath:cr,errors:[`Amp personal plugin cc-safety-net is ${z}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:cr,configPath:cr}}import{existsSync as Jp,readFileSync as Wp}from"node:fs";import{isAbsolute as K1,join as zp,relative as Y1}from"node:path";function Pn(A){return zp(A,".gemini","config","hooks.json")}var Kp=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Yp(A){if(!A||typeof A!=="object"||Array.isArray(A))return[];return Object.values(A).flatMap((z)=>{if(!z||typeof z!=="object"||Array.isArray(z))return[];let X=z,ee=X.PreToolUse;if(!Array.isArray(ee))return[];return ee.flatMap((te)=>{if(!te||typeof te!=="object"||Array.isArray(te))return[];let ae=te.hooks;if(!Array.isArray(ae))return[];return ae.flatMap((le)=>{if(!le||typeof le!=="object"||Array.isArray(le))return[];let ye=le.command;if(typeof ye!=="string"||!Kp.test(ye))return[];return[{command:ye,enabled:X.enabled!==!1}]})})})}function Hs(A){let z=Pn(A.environment.home);if(!Jp(z))return{platform:"antigravity-cli",status:"n/a",configPath:z};let X;try{X=Yp(JSON.parse(Wp(z,"utf-8")))}catch(ee){return{platform:"antigravity-cli",status:"n/a",configPath:z,errors:[`Failed to parse Antigravity hooks config ${z}: ${ee instanceof Error?ee.message:String(ee)}`]}}if(X.some((ee)=>ee.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:z};if(X.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:z};return{platform:"antigravity-cli",status:"n/a",configPath:z}}import{join as Us}from"node:path";import{existsSync as Zp,lstatSync as Xp,readFileSync as Qp}from"node:fs";function Ot(A,z=(X)=>X){if(!Zp(A))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(z(Qp(A,"utf-8")))}}catch{return{kind:"unreadable"}}}function Lt(A){try{return Xp(A)}catch{return}}function dr(A,z){let X=Lt(z);if(!X)return{platform:A,status:"n/a",configPath:z};if(!X.isSymbolicLink()&&X.isDirectory())return;return{platform:A,status:"n/a",configPath:z,errors:[`${z} is a symlink or not a directory; move or remove it before installing`]}}function ft(A,z){return typeof A==="object"&&A!==null?A[z]:void 0}var fo="cc-safety-net@cc-marketplace";function Gs(A){return Us(A.home,".claude","plugins","installed_plugins.json")}function Bs(A,z){let X=ft(ft(A,"plugins"),z);return Array.isArray(X)&&X.length>0}function ur(A,z){let X=Ot(Gs(A));return X.kind==="ok"&&Bs(X.value,z)}function mo(A){let z=Gs(A),X=Ot(z);if(X.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(X.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!Bs(X.value,fo))return{platform:"claude-code",status:"n/a"};let ee=Us(A.home,".claude","settings.json"),te=Ot(ee);if(te.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(te.kind==="ok"&&ft(ft(te.value,"enabledPlugins"),fo)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:ee,errors:[`${fo} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:z}}function qs(A){return mo(A.environment)}function Vs(A){if(!A.codexPluginListOutput)return{platform:"codex",status:"n/a"};let z=A.codexPluginListOutput.split(`
28
+ `).find((X)=>X.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!z)return{platform:"codex",status:"n/a"};if(!z.includes("installed,"))return{platform:"codex",status:"n/a"};if(!z.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list"}}import{existsSync as hr,readdirSync as e2,readFileSync as t2}from"node:fs";import{join as St}from"node:path";function At(A){let z="",X=0,ee=!1,te=!1,ae=-1;while(X<A.length){let le=A[X],ye=A[X+1];if(te){z+=le,te=!1,X++;continue}if(le==='"'&&!ee){ee=!0,ae=-1,z+=le,X++;continue}if(le==='"'&&ee){ee=!1,z+=le,X++;continue}if(le==="\\"&&ee){te=!0,z+=le,X++;continue}if(ee){z+=le,X++;continue}if(le==="/"&&ye==="/"){while(X<A.length&&A[X]!==`
29
+ `)X++;continue}if(le==="/"&&ye==="*"){X+=2;while(X<A.length-1){if(A[X]==="*"&&A[X+1]==="/"){X+=2;break}X++}continue}if(le===","){ae=z.length,z+=le,X++;continue}if(le==="}"||le==="]"){if(ae!==-1){let he=z.slice(ae+1);if(/^\s*$/.test(he))z=z.slice(0,ae)+he}ae=-1,z+=le,X++;continue}if(!/\s/.test(le))ae=-1;z+=le,X++}return z}function go(A,z,X){let ee=z+1,te=!1;while(ee<A.length){if(te){te=!1,ee++;continue}if(A[ee]==="\\"){te=!0,ee++;continue}if(A[ee]==='"')return ee+1;ee++}throw Error(X)}function yo(A,z,X){let ee=A[z],te=ee==="["?"]":"}",ae=0,le=z;while(le<A.length){let ye=X.skipComment?.(A,le)??le;if(ye!==le){le=ye;continue}if(A[le]==='"'){le=go(A,le,X.stringError);continue}if(A[le]===ee)ae++;if(A[le]===te){if(ae--,ae===0)return le}le++}throw Error(X.bracketError)}function Js(A,z){let X=A.lastIndexOf(`
30
+ `,z)+1;return/^[ \t]*/.exec(A.slice(X))?.[0]??""}function fr(A,z){let X=z.end+(/^\s*/.exec(A.slice(z.end))?.[0].length??0);if(A[X]===","){let le=A[X+1]===`
31
+ `?X+2:X+1;return`${A.slice(0,z.start)}${A.slice(le)}`}let ee=A.slice(0,z.start).search(/\s*$/)-1;if(A[ee]!==",")return`${A.slice(0,z.start)}${A.slice(z.end)}`;let te=A.lastIndexOf(`
32
+ `,ee-1),ae=te!==-1&&/^\s*$/.test(A.slice(te+1,ee))?te:ee;return`${A.slice(0,ae)}${A.slice(z.end)}`}function pr(A,z){if(A.startsWith("//",z)){let X=A.indexOf(`
33
+ `,z+2);return X===-1?A.length:X+1}if(A.startsWith("/*",z)){let X=A.indexOf("*/",z+2);return X===-1?A.length:X+2}return z}function zs(A,z){let X=z;while(X<A.length){if(/\s/.test(A[X]??"")){X++;continue}let ee=pr(A,X);if(ee===X)return X;X=ee}return X}function Ws(A,z,X){let ee=0,te=0;while(te<A.length){let ae=pr(A,te);if(ae!==te){te=ae;continue}if(A[te]==='"'){let le=go(A,te,X.stringError);if(ee===1&&JSON.parse(A.slice(te,le))===z){let ye=zs(A,le),he=zs(A,ye+1);if(A[ye]===":"&&A[he]==="[")return{start:he,end:yo(A,he,{skipComment:pr,...X})}}te=le;continue}if(A[te]==="{"||A[te]==="[")ee++;if(A[te]==="}"||A[te]==="]")ee--;te++}return}function Ks(A,z,X){let ee=[],te=z.start+1;while(te<z.end){let ae=pr(A,te);if(ae!==te){te=ae;continue}if(A[te]==='"'){let le=go(A,te,X),ye=JSON.parse(A.slice(te,le));if(typeof ye==="string")ee.push({range:{start:te,end:le},value:ye});te=le;continue}te++}return ee}var Ft="cc-safety-net@cc-marketplace",mr=["cc-marketplace","cc-safety-net"],Ys=["_direct","copilot-safety-net"],Zs=["cc-marketplace","safety-net"],Xs="safety-net@cc-marketplace";function gr(A,z){let X=z.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${X}([^a-z0-9-]|$)`,"m").test(A??"")}function Qs(A){return gr(A,"cc-safety-net@cc-marketplace")}function ea(A){return gr(A,"cc-marketplace")}function ta(A){return gr(A,"copilot-safety-net")}function na(A){return gr(A,"safety-net@cc-marketplace")}function ho(A){if(!A?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(A)}function oa(A,z){if(!A)return null;let X=A.match(/(\d+)\.(\d+)\.(\d+)/);if(!X)return null;let ee=[Number(X[1]),Number(X[2]),Number(X[3])];for(let te=0;te<z.length;te++){let ae=ee[te]??0,le=z[te]??0;if(ae!==le)return ae>le}return!0}function n2(A){return oa(A,[0,0,422])}function r2(A){return oa(A,[1,0,8])}function En(A){return A.env.get("COPILOT_HOME")||St(A.home,".copilot")}function vo(A){return(A.hooks?.preToolUse??[]).some((X)=>{if(X.type!=="command")return!1;return ho(X.command)||ho(X.bash)||ho(X.powershell)})}function yr(A){return A===void 0||typeof A==="string"}function o2(A){if(!A||typeof A!=="object"||Array.isArray(A))return!1;let z=A;if(z.disableAllHooks!==void 0&&typeof z.disableAllHooks!=="boolean")return!1;if(z.hooks===void 0)return!0;if(!z.hooks||typeof z.hooks!=="object"||Array.isArray(z.hooks))return!1;let X=z.hooks.preToolUse;if(X===void 0)return!0;return Array.isArray(X)&&X.every((ee)=>ee!==null&&typeof ee==="object"&&!Array.isArray(ee)&&yr(ee.type)&&yr(ee.command)&&yr(ee.bash)&&yr(ee.powershell))}function bo(A,z){try{let X=JSON.parse(At(t2(A,"utf-8")));if(!o2(X)){z?.push(`Invalid hook config ${A}: hooks.preToolUse must be an array of hook objects`);return}return X}catch(X){z?.push(`Failed to parse ${A}: ${X instanceof Error?X.message:String(X)}`);return}}function ia(A,z){try{return e2(A).filter((X)=>X.endsWith(".json")).sort((X,ee)=>X.localeCompare(ee))}catch(X){return z?.push(`Failed to read ${A}: ${X instanceof Error?X.message:String(X)}`),[]}}function i2(A,z){if(!hr(A))return[];let X=[];for(let ee of ia(A,z)){let te=St(A,ee),ae=bo(te,z);if(ae&&vo(ae))X.push(te)}return X}function gn(A,z){if(!hr(A))return;let X=bo(A,z);if(!X)return;return{path:A,config:X}}function ra(A,z,X,ee){if(z){A.push(`GitHub Copilot CLI ${z} does not support ${X}; requires ${ee}+`);return}A.push(`GitHub Copilot CLI version unavailable; skipping ${X} because it requires ${ee}+`)}function s2(A){for(let z of A){if(z?.config.disableAllHooks===!0)return z.path;if(z?.config.disableAllHooks===!1)return}return}function a2(A,z,X,ee){let te=En(A),ae=St(z,".github","hooks"),le=St(te,"hooks"),ye=St(z,".github","copilot"),he=St(z,".claude"),ve=r2(X),be=ve===!0?ee:void 0,Ie=[gn(St(ye,"settings.local.json"),be),gn(St(ye,"settings.json"),be),gn(St(he,"settings.local.json"),be),gn(St(he,"settings.json"),be)],Xe=[gn(St(te,"settings.json"),be),gn(St(te,"config.json"),be)];if(ve!==!1){let gt=s2([...Ie,...Xe]);if(gt){if(ve===null)ee.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${gt} as active`);return{activeConfigPaths:[],disabledBy:gt}}}let et=i2(ae,ee),Ee=n2(X),at=Ee===!0?ee:void 0,ct=hr(le)?ia(le,at):[],lt=[];for(let gt of ct){let ut=St(le,gt),vt=bo(ut,at);if(vt&&vo(vt))lt.push(ut)}if(Ee!==!0&&lt.length>0)ra(ee,X,`user hook files in ${le}`,"0.0.422"),lt.length=0;let pt=[];for(let gt of[...Ie,...Xe]){if(!gt)continue;if(!vo(gt.config))continue;if(ve===!0){pt.push(gt);continue}ra(ee,X,"inline hook definitions in Copilot config files","1.0.8");break}let mt=(gt)=>gt.filter((ut)=>!!ut&&pt.includes(ut)).map((ut)=>ut.path);return{activeConfigPaths:[...mt(Ie),...et,...mt(Xe),...lt]}}function sa(A){let z=[],X=a2(A.environment,A.cwd,A.copilotCliVersion,z);if(X.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:X.disabledBy,configPaths:[X.disabledBy],errors:z.length>0?z:void 0};let ee=En(A.environment),te=St(ee,"installed-plugins",...mr),ae=hr(te),le=St(ee,"settings.json"),ye=Ot(le,At);if(ae&&ye.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(ae&&ye.kind==="ok"&&ft(ft(ye.value,"enabledPlugins"),Ft)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:le,errors:[`${Ft} is installed but not enabled in Copilot CLI`]};if(ae||X.activeConfigPaths.length>0){let he=ae,ve=X.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:he?"plugin config":"hook config",configPath:ve??(he?te:void 0),configPaths:X.activeConfigPaths.length>0?X.activeConfigPaths:void 0,errors:z.length>0?z:void 0}}return{platform:"copilot-cli",status:"n/a",errors:z.length>0?z:void 0}}import{existsSync as h2,readFileSync as v2}from"node:fs";import{existsSync as aa,mkdirSync as d2,readFileSync as u2}from"node:fs";import{dirname as p2,join as f2}from"node:path";import{renameSync as l2,writeFileSync as c2}from"node:fs";function kt(A,z){let X=`${A}.${process.pid}.tmp`;c2(X,z),l2(X,A)}var jt=Object.fromEntries(Cn.map((A)=>[A.id,`npx -y cc-safety-net hook ${A.flags[1]}`]));var Dn=jt.cursor,la=30;function br(A){return f2(A.home,".cursor","hooks.json")}function Qt(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function Lo(){return{command:Dn,timeout:la,failClosed:!0}}function vr(A){return Qt(A)&&A.command===Dn}function m2(A){return Object.keys(A).length===3&&A.command===Dn&&A.timeout===la&&A.failClosed===!0}function g2(A){try{return JSON.parse(u2(A,"utf-8"))}catch(z){if(z instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${A}: ${z.message}`);throw z}}function ca(A){let z=g2(A);if(!Qt(z))throw Error(`Cursor hooks config ${A} must be a JSON object`);if(z.version!==1)throw Error(`Cursor hooks config ${A} must set "version": 1`);if(z.hooks!==void 0&&!Qt(z.hooks))throw Error(`Cursor hooks config ${A} "hooks" must be an object`);let X=Qt(z.hooks)?z.hooks.preToolUse:void 0;if(X!==void 0&&!Array.isArray(X))throw Error(`Cursor hooks config ${A} "hooks.preToolUse" must be an array`);return z}function da(A){let z=Qt(A.hooks)?A.hooks.preToolUse:void 0;return Array.isArray(z)?z:[]}function y2(A){if(!A.some(vr))return[...A,Lo()];return A.reduce((z,X)=>{if(!vr(X))return z.result.push(X),z;if(!z.inserted)z.result.push(Lo()),z.inserted=!0;return z},{result:[],inserted:!1}).result}function ua(A,z,X){let ee=Qt(z.hooks)?z.hooks:{},te={...z,hooks:{...ee,preToolUse:X}};kt(A,`${JSON.stringify(te,null,2)}
34
+ `)}function pa(A){let z=br(A);if(!aa(z))return d2(p2(z),{recursive:!0}),kt(z,`${JSON.stringify({version:1,hooks:{preToolUse:[Lo()]}},null,2)}
35
+ `),{path:z,alreadyInstalled:!1};let X=ca(z),ee=da(X),te=ee.filter(vr);if(Qt(X.hooks)&&Array.isArray(X.hooks.preToolUse)&&te.length===1&&te[0]!==void 0&&m2(te[0]))return{path:z,alreadyInstalled:!0};return ua(z,X,y2(ee)),{path:z,alreadyInstalled:!1}}function fa(A){let z=br(A);if(!aa(z))return{path:z,alreadyInstalled:!1};let X=ca(z),ee=da(X),te=ee.filter((ae)=>!vr(ae));if(te.length===ee.length)return{path:z,alreadyInstalled:!1};return ua(z,X,te),{path:z,alreadyInstalled:!0}}function b2(A){if(!A||typeof A!=="object"||Array.isArray(A))return[];let z=A.hooks;if(!z||typeof z!=="object"||Array.isArray(z))return[];let X=z.preToolUse;if(!Array.isArray(X))return[];return X.filter((ee)=>!!ee&&typeof ee==="object"&&!Array.isArray(ee)&&ee.command===Dn)}function L2(A){let z=[];if(A.length>1)z.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let X=A[0];if(X&&X.failClosed!==!0)z.push('Managed hook is missing "failClosed": true; reinstall to repair');if(X&&X.timeout!==30)z.push('Managed hook "timeout" is not 30; reinstall to repair');return z}function ma(A){let z=br(A.environment);if(!h2(z))return{platform:"cursor",status:"n/a",configPath:z};let X;try{X=JSON.parse(v2(z,"utf-8"))}catch(ae){return{platform:"cursor",status:"n/a",configPath:z,errors:[`Failed to parse Cursor hooks config ${z}: ${ae instanceof Error?ae.message:String(ae)}`]}}let ee=b2(X);if(ee.length===0)return{platform:"cursor",status:"n/a",configPath:z};let te=L2(ee);return{platform:"cursor",status:"configured",method:"hook config",configPath:z,errors:te.length>0?te:void 0}}import{existsSync as w2}from"node:fs";import{join as wo}from"node:path";var ko="gemini-safety-net";function xo(A){let z=wo(A.home,".gemini","extensions"),X=wo(z,ko);if(!w2(X))return{platform:"gemini-cli",status:"n/a"};let ee=wo(z,"extension-enablement.json"),te=Ot(ee);if(te.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let ae=te.kind==="ok"?ft(ft(te.value,ko),"overrides"):void 0;if(Array.isArray(ae)&&ae.some((ye)=>typeof ye==="string"&&ye.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:ee,errors:[`${ko} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:X}}function ga(A){return xo(A.environment)}import{existsSync as S2,readFileSync as R2}from"node:fs";import{existsSync as ha,mkdirSync as k2,readFileSync as va,rmSync as x2}from"node:fs";import{dirname as C2,join as ya}from"node:path";var An=jt["grok-build"],kr=30;function xr(A){return ya(A.env.get("GROK_HOME")??ya(A.home,".grok"),"hooks","cc-safety-net.json")}function en(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function Lr(){return{hooks:[{type:"command",command:An,timeout:kr}]}}function ba(A){return en(A)&&A.command===An}function La(A){return A.flatMap((z)=>{if(!en(z)||!Array.isArray(z.hooks))return[z];let X=z.hooks.filter((ee)=>!ba(ee));if(X.length===z.hooks.length)return[z];return X.length===0?[]:[{...z,hooks:X}]})}function wa(A){try{let z=JSON.parse(A);return en(z)?z:null}catch{return null}}function ka(A){let z=en(A.hooks)?A.hooks.PreToolUse:void 0;return Array.isArray(z)?z:[]}function wr(A,z,X){let ee=en(z.hooks)?z.hooks:{};kt(A,`${JSON.stringify({...z,hooks:{...ee,PreToolUse:X}},null,2)}
36
+ `)}function xa(A){let z=xr(A);if(!ha(z))return k2(C2(z),{recursive:!0}),wr(z,{},[Lr()]),{path:z,alreadyInstalled:!1};let X=wa(va(z,"utf-8"));if(!X)return wr(z,{},[Lr()]),{path:z,alreadyInstalled:!1};let ee=ka(X),te=ee.filter((ae)=>en(ae)&&Array.isArray(ae.hooks)&&ae.hooks.some(ba));if(te.length===1&&JSON.stringify(te[0])===JSON.stringify(Lr()))return{path:z,alreadyInstalled:!0};return wr(z,X,[...La(ee),Lr()]),{path:z,alreadyInstalled:!1}}function Ca(A){let z=xr(A);if(!ha(z))return{path:z,alreadyInstalled:!1};let X=wa(va(z,"utf-8"));if(!X)return{path:z,alreadyInstalled:!1};let ee=ka(X),te=La(ee);if(JSON.stringify(te)===JSON.stringify(ee))return{path:z,alreadyInstalled:!1};let ae=en(X.hooks)?X.hooks:{};if(te.length===0&&Object.keys(X).length===1&&Object.keys(ae).length===1)return x2(z),{path:z,alreadyInstalled:!0};return wr(z,X,te),{path:z,alreadyInstalled:!0}}function _n(A){return!!A&&typeof A==="object"&&!Array.isArray(A)}function P2(A){if(!_n(A)||!_n(A.hooks))return[];let z=A.hooks.PreToolUse;if(!Array.isArray(z))return[];return z.filter((X)=>_n(X)&&Array.isArray(X.hooks)&&X.hooks.some((ee)=>_n(ee)&&ee.command===An))}function E2(A){let X=(Array.isArray(A.hooks)?A.hooks.filter(_n):[]).find((ee)=>ee.command===An);return[...A.matcher===void 0||A.matcher===""||A.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...X?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...X?.timeout===kr?[]:[`Managed hook "timeout" is not ${kr}; reinstall to repair`]]}function Sa(A){let z=xr(A.environment);if(!S2(z))return{platform:"grok-build",status:"n/a",configPath:z};let X;try{X=JSON.parse(R2(z,"utf-8"))}catch(ae){return{platform:"grok-build",status:"n/a",configPath:z,errors:[`Failed to parse Grok Build hooks config ${z}: ${ae instanceof Error?ae.message:String(ae)}`]}}let ee=P2(X)[0];if(!ee)return{platform:"grok-build",status:"n/a",configPath:z};let te=E2(ee);return{platform:"grok-build",status:"configured",method:"hook config",configPath:z,errors:te.length>0?te:void 0}}import{readFileSync as $a}from"node:fs";import{join as Ia}from"node:path";var _t="cc-safety-net",Co="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",D2=30;function Ra(A){return`${Co}
37
+ # version: ${A}
38
+ `}function A2(A){return`${Ra(A)}name: ${_t}
39
+ version: "${A}"
40
40
  description: "Block destructive commands and secret-file access before Hermes runs a tool."
41
41
  author: "cc-safety-net"
42
42
  provides_hooks:
43
43
  - pre_tool_call
44
- `}function Z2(j){return`${Ga(j)}"""CC Safety Net guard for Hermes Agent.
44
+ `}function _2(A){return`${Ra(A)}"""CC Safety Net guard for Hermes Agent.
45
45
 
46
46
  Registers pre_tool_call and forwards the tool call to the packaged CC Safety Net
47
47
  adapter (cc-safety-net hook --hermes-agent) over JSON stdin. The adapter prints nothing
@@ -58,8 +58,8 @@ import subprocess
58
58
 
59
59
  HOOK_EVENT = "pre_tool_call"
60
60
  SUPPORTED_TOOLS = ("patch", "read_file", "terminal", "write_file")
61
- ANALYZER = [${zt["hermes-agent"].split(" ").map((K)=>`"${K}"`).join(", ")}]
62
- TIMEOUT_SECONDS = ${K2}
61
+ ANALYZER = [${jt["hermes-agent"].split(" ").map((z)=>`"${z}"`).join(", ")}]
62
+ TIMEOUT_SECONDS = ${D2}
63
63
 
64
64
 
65
65
  def _block(detail):
@@ -203,84 +203,83 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
203
203
 
204
204
  def register(ctx):
205
205
  ctx.register_hook("pre_tool_call", _pre_tool_call)
206
- `}function Kn(j){return[{name:"__init__.py",content:Z2(j)},{name:"plugin.yaml",content:Y2(j)}]}import{mkdirSync as X2,readdirSync as Q2,readFileSync as ef,rmSync as Ho}from"node:fs";import{join as pn}from"node:path";var tf="__pycache__";function Uo(j){let K=j.env.get("HERMES_HOME")?.trim();return K?K:pn(j.home,".hermes")}function Go(j){return pn(Uo(j),"plugins",Ft)}function Bo(j){return j.startsWith(Mo)}function qo(j,K){let te=Go(j),re=Pt(te);if(re&&(re.isSymbolicLink()||!re.isDirectory()))throw Error(`Refusing to ${K} ${te}: not a regular directory. Move or remove it and rerun ${K==="install"?"install":"uninstall"} --hermes-agent.`);return te}function Ba(j,K){let te=Pt(j);if(!te)return;if(te.isSymbolicLink()||!te.isFile())throw Error(`Refusing to ${K} ${j}: not a regular file. Move or remove it.`);let re=ef(j,"utf-8");if(!Bo(re))throw Error(`Refusing to ${K} unmanaged file at ${j}. Move or remove it.`);return re}function qa(j){let K=qo(j,"install"),te=Kn(Et());if(te.map((oe)=>Ba(pn(K,oe.name),"overwrite")).every((oe,ce)=>oe===te[ce]?.content))return{path:K,alreadyInstalled:!0};return X2(K,{recursive:!0}),te.forEach((oe)=>{Dt(pn(K,oe.name),oe.content)}),{path:K,alreadyInstalled:!1}}function Vo(j){let K=qo(j,"remove");if(!Pt(K))return[];return Kn(Et()).filter((te)=>Ba(pn(K,te.name),"remove")!==void 0)}function Va(j){let K=qo(j,"remove");if(!Pt(K))return{path:K,alreadyInstalled:!1};let te=Vo(j);if(te.forEach((re)=>{Ho(pn(K,re.name))}),Ho(pn(K,tf),{recursive:!0,force:!0}),Q2(K).length===0)Ho(K,{recursive:!0});return{path:K,alreadyInstalled:te.length>0}}var Nr="hermes-agent",za=/^([^\s#][^:]*):/,nf=/^\s+([A-Za-z_][\w-]*):/,Ja=/^\s+-\s*(.*)$/;function rf(j){return j.trim().replace(/^(["'])(.*)\1$/,"$2")}function of(j){let K=j.split(/\r?\n/),te=K.findIndex((ce)=>za.exec(ce)?.[1]?.trim()==="plugins");if(te===-1)return[];let re=K.slice(te+1),oe=re.findIndex((ce)=>za.test(ce));return oe===-1?re:re.slice(0,oe)}function Wa(j,K){let te=of(j),re=te.findIndex((de)=>nf.exec(de)?.[1]===K);if(re===-1)return[];let oe=te.slice(re+1),ce=oe.findIndex((de)=>!Ja.test(de));return(ce===-1?oe:oe.slice(0,ce)).map((de)=>rf(Ja.exec(de)?.[1]??""))}function sf(j){try{return Ka(Ya(Uo(j),"config.yaml"),"utf-8")}catch{return}}function zo(j){let K=sf(j)??"";return Wa(K,"enabled").includes(Ft)&&!Wa(K,"disabled").includes(Ft)}function Za(j){return/^# version:\s*(.+)$/m.exec(j)?.[1]?.trim()}function af(j,K){let te=Pt(j);if(!te)return{error:`${K.name} is missing from ${j}; run install --hermes-agent`};if(te.isSymbolicLink()||!te.isFile())return{error:`${j} is a symlink or not a regular file; move or remove it`};try{let re=Ka(j,"utf-8");if(!Bo(re))return{error:`Unmanaged ${K.name} occupies ${j}; move or remove it`};if(Za(re)===Et()&&re!==K.content)return{error:`Modified ${K.name} occupies ${j}; run install --hermes-agent to restore it`};return{content:re}}catch(re){return{error:`Failed to read ${j}: ${re instanceof Error?re.message:String(re)}`}}}function Xa(j){let K=Go(j.environment),te=Cr(Nr,K);if(te)return te;let re=Kn(Et()).map((we)=>af(Ya(K,we.name),we)),oe=re.flatMap((we)=>("error"in we)?[we.error]:[]);if(oe.length>0)return{platform:Nr,status:"n/a",configPath:K,errors:oe};let ce=re.some((we)=>("content"in we)&&Za(we.content)!==Et()),de=ce?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!zo(j.environment))return{platform:Nr,status:"disabled",method:"plugin directory",configPath:K,errors:[`${Ft} is not enabled in Hermes; run \`hermes plugins enable ${Ft}\``,...de]};return{platform:Nr,status:"configured",method:"plugin directory",configPath:K,errors:ce?de:void 0}}import{existsSync as lf,readFileSync as cf}from"node:fs";import{join as Qa}from"node:path";var df=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function uf(j){return Qa(j.env.get("KIMI_CODE_HOME")||Qa(j.home,".kimi-code"),"config.toml")}function Yn(j){let K=uf(j.environment);if(!lf(K))return{platform:"kimi-code",status:"n/a",configPath:K};try{if(!df.test(cf(K,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:K}}catch(te){return{platform:"kimi-code",status:"n/a",configPath:K,errors:[`Failed to read ${K}: ${te instanceof Error?te.message:String(te)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:K}}import{readFileSync as cl}from"node:fs";import{join as Xn}from"node:path";var Rt="cc-safety-net",Mt="index.js",Rn="openclaw.plugin.json",Pn="package.json";var Mr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as mf,lstatSync as gf,readdirSync as yf,readFileSync as hf}from"node:fs";import{dirname as nl,join as nn}from"node:path";import{fileURLToPath as vf}from"node:url";import{spawn as pf}from"node:child_process";function ff(j){return j.join(" ")}function Jo(j,K,te){return[`Failed to run ${ff(j)}${K===null?"":` (exit ${K})`}.`,te.trim()].filter(Boolean).join(`
207
- `)}function Wo(j){let K={stdout:"",stderr:""};return j.stdout.setEncoding("utf-8"),j.stderr.setEncoding("utf-8"),j.stdout.on("data",(te)=>{K.stdout+=te}),j.stderr.on("data",(te)=>{K.stderr+=te}),K}function Jt(j,K){return new Promise((te,re)=>{let oe=cn([...j],process.env),ce=pf(oe.cmd,oe.args,{stdio:["ignore","pipe","pipe"]}),de=Wo(ce),we=()=>[de.stdout,de.stderr].filter(Boolean).join(`
208
- `),xe=K?.timeoutMs??120000,Ce=setTimeout(()=>{ce.kill(),re(Error(Jo(j,null,`Timed out after ${xe}ms.
209
- ${we()}`.trim())))},xe);ce.on("error",(Se)=>{clearTimeout(Ce),re(Error(Jo(j,null,`${Se.message}
210
- ${we()}`.trim())))}),ce.on("close",(Se)=>{if(clearTimeout(Ce),Se!==0){re(Error(Jo(j,Se,we())));return}te(K?.stdoutOnly?de.stdout:we())})})}async function Ko(j){for(let K of j)await Jt(K)}async function el(j){for(let K of j)try{await Jt(K)}catch(te){console.warn(te instanceof Error?te.message:String(te))}}var tl=nn("openclaw",Rt),bf=[Mt,Rn,Pn];function Yo(j,K){if(j==="~")return K;if(j.startsWith("~/")||j.startsWith("~\\"))return nn(K,j.slice(2));return j}function rl(j){let K=j.env.get("OPENCLAW_STATE_DIR")?.trim();if(K)return Yo(K,j.home);let te=j.env.get("OPENCLAW_CONFIG_PATH")?.trim();return te?nl(Yo(te,j.home)):nn(j.home,".openclaw")}function ol(j){let K=j.env.get("OPENCLAW_CONFIG_PATH")?.trim();return K?Yo(K,j.home):nn(rl(j),"openclaw.json")}function Zo(j){return nn(rl(j),"extensions",Rt)}function Lf(j){let K=yf(j);if(K.length===0)return!0;if(K.some((oe)=>!bf.includes(oe)))return!1;let te=nn(j,Mt),re=Pt(te);return re!==void 0&&!re.isSymbolicLink()&&re.isFile()&&hf(te,"utf-8").startsWith(Mr)}function Xo(j){let K=Zo(j),te=Pt(K);if(!te)return;if(!te.isSymbolicLink()&&te.isDirectory()&&Lf(K))return;throw Error(`Refusing to modify ${K}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function il(){let j=nl(vf(import.meta.url));return[nn(j,"..",tl),nn(j,"..","..","..","dist",tl)]}function Qo(j=il()){return j.find((K)=>mf(K)&&gf(K).isDirectory())}function wf(j=il()){let K=Qo(j);if(!K)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return K}function sl(j=wf()){return[["openclaw","plugins","install",j,"--force"],["openclaw","plugins","enable",Rt]]}function kf(j){let K=(()=>{try{return JSON.parse(j)}catch{return}})(),te=wt(wt(K,"plugin"),"status");return typeof te==="string"?te:void 0}async function al(){let j=kf(await Jt(["openclaw","plugins","inspect",Rt,"--runtime","--json"],{stdoutOnly:!0}));if(j==="loaded")return;throw Error(`${j===void 0?`The ${Rt} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${Rt} plugin with status "${j}".`} Run \`openclaw plugins inspect ${Rt} --runtime\` for details.`)}var Hr="openclaw",Zn=`run \`openclaw plugins enable ${Rt}\``;function En(j,K){let te=Xn(j,K),re=Pt(te);if(!re)return{error:`${K} is missing from ${te}; run install --openclaw`};if(re.isSymbolicLink()||!re.isFile())return{error:`${te} is a symlink or not a regular file; move or remove it`};try{return{content:cl(te,"utf-8")}}catch(oe){return{error:`Failed to read ${te}: ${oe instanceof Error?oe.message:String(oe)}`}}}function dl(j){try{return JSON.parse(jt(j))}catch{return}}function xf(j){let K=En(j,Rn);if("error"in K)return K.error;if(wt(dl(K.content),"id")===Rt)return;return`${Xn(j,Rn)} is not a valid ${Rt} manifest; run install --openclaw`}function Cf(j){let K=En(j,Pn);if("error"in K)return K.error;let te=wt(wt(dl(K.content),"openclaw"),"extensions");if(Array.isArray(te)&&te.includes(`./${Mt}`))return;return`${Xn(j,Pn)} does not point OpenClaw at ${Mt}; run install --openclaw`}function ll(j){return Array.isArray(j)?j.filter((K)=>typeof K==="string"):[]}function Sf(j){let K=ol(j);if(!Pt(K))return`${Rt} is not enabled; ${Zn}`;let te=(()=>{try{return JSON.parse(jt(cl(K,"utf-8")))}catch{return}})();if(te===void 0)return`Failed to read ${K}; fix it, then ${Zn}`;let re=wt(te,"plugins");if(wt(re,"enabled")===!1)return`plugins.enabled is false in ${K}; no OpenClaw plugin loads`;let oe=wt(wt(wt(re,"entries"),Rt),"enabled");if(ll(wt(re,"deny")).includes(Rt)||oe===!1)return`${Rt} is disabled in ${K}; ${Zn}`;let ce=ll(wt(re,"allow"));if(ce.length>0&&!ce.includes(Rt))return`plugins.allow in ${K} does not list ${Rt}; add it, then ${Zn}`;if(ce.includes(Rt)||oe===!0)return;return`${Rt} is not enabled; ${Zn}`}function ul(j){return/^\/\/ version:\s*(.+)$/m.exec(j)?.[1]?.trim()}function Rf(j,K,te){if(te===void 0)return[];let re=En(te,Mt);if("error"in re||ul(re.content)!==K)return[];return[Mt,Rn,Pn].flatMap((oe)=>{let ce=En(j,oe),de=En(te,oe);if("error"in ce||"error"in de||ce.content===de.content)return[];return[`Modified ${oe} occupies ${Xn(j,oe)}; run install --openclaw to restore it`]})}function pl(j){let K=Zo(j.environment),te=Cr(Hr,K);if(te)return te;let re=En(K,Mt),ce=["error"in re?re.error:re.content.startsWith(Mr)?void 0:`Unmanaged ${Mt} occupies ${Xn(K,Mt)}; move or remove it`,xf(K),Cf(K)].filter((Se)=>Se!==void 0),de="content"in re?ul(re.content):void 0,we=ce.length>0?ce:Rf(K,de,Qo());if(we.length>0)return{platform:Hr,status:"n/a",configPath:K,errors:we};let xe=de===Et()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],Ce=Sf(j.environment);if(Ce)return{platform:Hr,status:"disabled",method:"plugin directory",configPath:K,errors:[Ce,...xe]};return{platform:Hr,status:"configured",method:"plugin directory",configPath:K,errors:xe.length>0?xe:void 0}}import{existsSync as If,readFileSync as $f}from"node:fs";import{join as Of}from"node:path";import{existsSync as ei,readFileSync as gl,rmSync as Pf}from"node:fs";import{join as Yt}from"node:path";import{pathToFileURL as Ef}from"node:url";var Ur="cc-safety-net",yl=`${Ur}@latest`,hl=["opencode.json","opencode.jsonc"],fl="CCSafetyNetPlugin",ml={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function Gr(j){return Yt(j.env.get("XDG_CONFIG_HOME")||Yt(j.home,".config"),"opencode")}function Df(j){return Yt(Gr(j),hl[0])}function Af(j){return hl.map((K)=>Yt(Gr(j),K))}function vl(j){return Yt(j.env.get("XDG_CACHE_HOME")||Yt(j.home,".cache"),"opencode","packages",yl)}function ti(j){Pf(vl(j),{recursive:!0,force:!0})}async function bl(j){let K=Yt(vl(j),"node_modules",Ur),te=Yt(K,"package.json");if(!ei(te))throw Error(`The OpenCode plugin cache at ${K} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${yl}\` for details.`);let re=wt(JSON.parse(gl(te,"utf-8")),"main");if(typeof re!=="string")throw Error(`The cached OpenCode plugin at ${K} declares no "main" entry.`);let oe=Yt(K,re);if(typeof(await import(Ef(oe).href))[fl]==="function")return;throw Error(`The cached OpenCode plugin at ${oe} does not export a callable ${fl}, so OpenCode would load nothing and fail open.`)}function Ll(j,K){try{return JSON.parse(jt(j))}catch(te){if(te instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${K}: ${te.message}`);throw te}}function _f(j){if(!j||typeof j!=="object"||Array.isArray(j))return!1;let K=j.plugin;if(!Array.isArray(K))return!1;return K.some((te)=>typeof te==="string"&&te.includes(Ur))}function Tf(j,K){let te=da(j,"plugin",ml);if(!te)throw Error(`Failed to locate OpenCode plugin array in ${K}`);let re=ua(j,te,ml.stringError).filter((oe)=>oe.value.includes(Ur)).map((oe)=>oe.range).reverse().reduce(Pr,j);return Ll(re,K),re}function wl(j){ti(j);let K=Af(j),te=K.find((oe)=>ei(oe)),re=[];for(let oe of K){if(!ei(oe))continue;try{let ce=gl(oe,"utf-8");if(!_f(Ll(ce,oe)))continue;return Dt(oe,Tf(ce,oe)),{path:oe,alreadyInstalled:!0}}catch(ce){re.push(ce instanceof Error?ce.message:String(ce))}}if(re.length>0)throw Error(re.join(`
211
- `));return{path:te??Df(j),alreadyInstalled:!1}}function kl(j){let K=[],te=Gr(j.environment),re=["opencode.json","opencode.jsonc"];for(let oe of re){let ce=Of(te,oe);if(If(ce))try{let de=$f(ce,"utf-8"),we=jt(de);if((JSON.parse(we).plugin??[]).some((Ne)=>Ne.includes("cc-safety-net")))return{platform:"opencode",status:"configured",method:"plugin array",configPath:ce,errors:K.length>0?K:void 0}}catch(de){K.push(`Failed to parse ${oe}: ${de instanceof Error?de.message:String(de)}`)}}return{platform:"opencode",status:"n/a",errors:K.length>0?K:void 0}}import{join as jf}from"node:path";function ni(j){return jf(j.home,".pi","agent","settings.json")}function ri(j){if(typeof j!=="string")return!1;return j==="npm:cc-safety-net"||j.startsWith("npm:cc-safety-net@")}function xl(j){let K=ni(j.environment),te=qt(K);if(te.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(te.kind==="missing")return{platform:"pi",status:"n/a"};let re=wt(te.value,"packages");if(!Array.isArray(re))return{platform:"pi",status:"n/a"};let oe=re.find((we)=>ri(typeof we==="string"?we:wt(we,"source")));if(oe===void 0)return{platform:"pi",status:"n/a"};let ce=wt(oe,"extensions");if(Array.isArray(ce)&&ce.some((we)=>typeof we==="string"&&we.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:K,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:K}}var Ff={amp:ta,"antigravity-cli":na,"claude-code":sa,codex:aa,"copilot-cli":ka,cursor:Aa,"gemini-cli":_a,"grok-build":Ua,"hermes-agent":Xa,"kimi-code":Yn,openclaw:pl,opencode:kl,pi:xl};function Dn(j,K,te){let re={...te,cwd:K,environment:j};return ur.map((oe)=>Nf(Ff[oe](re)))}function Nf(j){if(j.status==="not-inspected")return{platform:j.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:j.platform,detected:j.status!=="n/a",configured:j.status==="configured",inspectionStatus:j.status!=="n/a"?"verified":j.errors&&j.errors.length>0?"failed":"not-applicable",method:j.method,configPath:j.configPath,configPaths:j.configPaths,errors:j.errors}}import{join as Mf}from"node:path";var Hf=Object.freeze([{command:"git reset --hard",description:"git reset --hard",expectBlocked:!0},{command:"rm -rf /",description:"rm -rf /",expectBlocked:!0},{command:"rm -rf ./node_modules",description:"rm in cwd (safe)",expectBlocked:!1}]),Uf=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),safety:Object.freeze({}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),Gf={strict:!1,paranoidRm:!1,paranoidInterpreters:!1,worktreeMode:!1,effectiveLevel:"standard",capabilities:{fail_closed:{enabled:!1,source:"preset",sources:[]},paranoid_rm:{enabled:!1,source:"preset",sources:[]},paranoid_interpreters:{enabled:!1,source:"preset",sources:[]}}};function Cl(j){let K=Mf(j.tmpdir,"cc-safety-net-self-test"),te=Hf.map((re)=>{let oe=F(j,u("self-test",{command:re.command},{kind:"command",shell:"auto"},{configCwd:K,executionCwd:K},re.command),{guard:{dependencies:{loadPolicySnapshot:()=>Uf,getModes:()=>Gf,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),ce=re.expectBlocked?"blocked":"allowed",de=oe.decision.kind==="deny"?"blocked":"allowed";return{command:re.command,description:re.description,expected:ce,actual:de,passed:ce===de,reason:oe.decision.kind==="deny"?oe.decision.reason:void 0,ruleId:oe.decision.kind==="deny"?oe.decision.ruleId:void 0}});return{passed:te.filter((re)=>re.passed).length,failed:te.filter((re)=>!re.passed).length,total:te.length,results:te}}function oi(j){let K=At({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},j);if(Kt(K.errors))return null;return{json:K.flags.json,skipUpdateCheck:K.flags.skipUpdateCheck}}async function Sl(j,K={}){let te=await Bn(!K.json,()=>{let re=Bf(j,K);return{ready:re,finish:()=>re}},()=>Gn(),{loadingMessage:"Checking system status…"});if(K.json)console.log(JSON.stringify(te,null,2));else qf(te);return te.engineSelfTest.failed>0||te.findings.some((re)=>re.severity==="error")?1:0}async function Bf(j,K){let te=K.cwd??process.cwd(),re=await Hn(),oe=Dn(j,te,{ampPluginListOutput:re.ampPluginListOutput,codexPluginListOutput:re.codexPluginListOutput,copilotCliVersion:re.versions["copilot-cli"]}),ce=hs(j,te),de=vs(j),we=k(j,{cwd:te}),xe=we.policy,Ce=P(xe,j.env),Se=B(xe,Ce.capabilities),Ne=gr(j,7),He=Ys(j,te),at=K.skipUpdateCheck?{currentVersion:Et(),latestVersion:null,updateAvailable:!1}:await tn(),mt={hooks:oe,engineSelfTest:Cl(j),userConfig:ce.userConfig,projectConfig:ce.projectConfig,configState:Be(we),effectiveRules:ce.effectiveRules,shadowedRules:ce.shadowedRules,environment:de,effectiveSafety:{selectedPreset:xe.safety.level??"standard",level:Ce.effectiveLevel,capabilities:Ce.capabilities,ruleOverrides:xe.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(Se).filter(([,it])=>it.source==="rule_override"&&it.override==="off"&&it.inheritedEnabled&&it.changesInherited).map(([it])=>it),ruleCounts:{stored:Object.keys(xe.destructiveCommandRuleOverrides).length,effective:Object.values(Se).filter((it)=>it.changesInherited).length},...we.policyScopes?{policyScopes:we.policyScopes}:{}},...He.length>0?{v2Leftovers:He}:{},posture:Ts(j,ce.userConfig.path),activity:Ne,update:at,system:re};return{...mt,findings:Ls(mt)}}function qf(j){console.log(),console.log(ks(j.hooks)),console.log(),console.log(xs(j.engineSelfTest)),console.log(),console.log(Cs(j)),console.log(),console.log(Ss(j.environment)),console.log(),console.log(Rs(j)),console.log(),console.log(Ps(j.findings)),console.log(),console.log(Es(j.activity)),console.log(),console.log(As(j.system)),console.log(),console.log(Ds(j.update)),console.log(_s(j))}import{existsSync as Vf}from"node:fs";var zf=/^[A-Za-z0-9_@%+=:,./-]+$/,Rl="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function ii(j){let K=At({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},j);if(Kt(K.errors))return console.error(Rl),console.error("Pass -- before a command that starts with dashes."),null;if(K.values.cwd!==void 0&&!Vf(K.values.cwd))return console.error(`Error: --cwd path does not exist: ${K.values.cwd}`),null;let te=K.positionals.length===1?K.positionals[0]:K.positionals.map((re)=>zf.test(re)?re:`'${re.replaceAll("'","'\\''")}'`).join(" ");if(!te)return console.error("Error: No command provided"),console.error(Rl),null;return{json:K.flags.json,cwd:K.values.cwd,command:te}}function Pl(j){if(j)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function El(j,K){let re=K-18;return[`${j.dtl}${j.dh.repeat(K)}${j.dtr}`,`${j.dv} Command Analysis${" ".repeat(re)}${j.dv}`,`${j.dbl}${j.dh.repeat(K)}${j.dbr}`]}function si(j){return JSON.stringify(j)}function Dl(j,K=0){return`[${j.map((re,oe)=>ws(re,oe,K)).join(",")}]`}function Qn(j,K,te=70){let re=j.split(" "),oe=[],ce="";for(let de of re)if(ce&&ce.length+de.length+1>te)oe.push(ce),ce=de;else ce=ce?`${ce} ${de}`:de;if(ce)oe.push(ce);return oe.map((de,we)=>we===0?de:`${K}${de}`)}function Al(j,K,te){let re=[];switch(j.type){case"parse":return null;case"env-strip":return re.push(""),re.push(`STEP ${K} ${te.h} Strip environment variables`),re.push(` Removed: ${j.envVars.map((oe)=>`${oe}=<redacted>`).join(", ")}`),re.push(` Tokens: ${si(j.output)}`),{lines:re,incrementStep:!0};case"leading-tokens-stripped":return re.push(""),re.push(`STEP ${K} ${te.h} Strip wrappers`),re.push(` Removed: ${j.removed.join(", ")}`),re.push(` Tokens: ${si(j.output)}`),{lines:re,incrementStep:!0};case"shell-wrapper":return re.push(""),re.push(`STEP ${K} ${te.h} Detect shell wrapper`),re.push(` Wrapper: ${j.wrapper} -c`),re.push(` Inner: ${j.innerCommand}`),{lines:re,incrementStep:!0};case"interpreter":{if(re.push(""),re.push(`STEP ${K} ${te.h} Detect interpreter`),re.push(` Interpreter: ${j.interpreter}`),re.push(` Code: ${j.codeArg}`),j.paranoidBlocked)re.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:re,incrementStep:!0}}case"busybox":return re.push(""),re.push(`STEP ${K} ${te.h} Busybox wrapper`),re.push(` Subcommand: ${j.subcommand}`),{lines:re,incrementStep:!0};case"transparent-wrapper":return re.push(""),re.push(`STEP ${K} ${te.h} Transparent wrapper`),re.push(` Wrapper: ${j.wrapper}`),re.push(` Tokens: ${si(j.output)}`),{lines:re,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(re.push(""),re.push(`STEP ${K} ${te.h} Match rules`),re.push(` Rule: ${j.rule}()`),j.matched)re.push(" Result: MATCHED");else re.push(" Result: No match");return{lines:re,incrementStep:!0}}case"worktree-relaxation":return re.push(""),re.push(`STEP ${K} ${te.h} Worktree relaxation`),re.push(` Mode: ${i.worktree.name}`),re.push(` Git cwd: ${j.gitCwd}`),re.push(" Result: Allowed local discard in linked worktree"),{lines:re,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(j.embeddedCommandFound)return re.push(""),re.push(`STEP ${K} ${te.h} Fallback scan`),re.push(` Found: ${j.embeddedCommandFound}`),{lines:re,incrementStep:!0};return null}case"custom-rules-check":{if(j.rulesChecked){if(re.push(""),re.push(`STEP ${K} ${te.h} Custom rules`),j.matched)re.push(" Result: MATCHED");else re.push(" Result: No match");return{lines:re,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(j.matched)return re.push(""),re.push(`STEP ${K} ${te.h} Dangerous text check`),re.push(` Token: ${j.token}`),re.push(" Result: MATCHED"),{lines:re,incrementStep:!0};return null}case"strict-unparseable":return re.push(""),re.push(`STEP ${K} ${te.h} Strict mode check`),re.push(` Command: ${j.rawCommand}`),re.push(" Result: ✗ UNPARSEABLE"),{lines:re,incrementStep:!0};case"segment-skipped":return null;case"error":return re.push(""),re.push(`ERROR: ${j.message}`),{lines:re,incrementStep:!1};default:return j}}function ai(j,K){let te=Pl(K?.asciiOnly??!1),re=58,oe=[],ce=1;oe.push(...El(te,58)),oe.push("");let de=j.trace.steps.find((mt)=>mt.type==="error");if(de&&de.type==="error"){oe.push("ERROR"),oe.push(` ${de.message}`),oe.push(""),oe.push("RESULT"),oe.push(` Status: ${j.result==="blocked"?bt.red("BLOCKED"):bt.green("ALLOWED")}`),oe.push(""),oe.push("CONFIG");let mt=j.configSource??"none";return oe.push(` Path: ${mt}`),oe.join(`
212
- `)}let we=j.trace.steps.find((mt)=>mt.type==="parse");if(we&&we.type==="parse"){oe.push("INPUT"),oe.push(` ${we.input}`),oe.push(""),oe.push(`STEP ${ce} ${te.h} Split shell commands`),ce++;for(let mt=0;mt<we.segments.length;mt++){let it=we.segments[mt];if(it){let gt=Math.random();oe.push(` Segment ${mt+1}: ${Dl(it,gt)}`)}}}let xe=j.trace.segments,Ce=xe.length>1;for(let mt of xe){if(Ce){oe.push("");let vt="";if(we&&we.type==="parse"){let mo=we.segments[mt.index];if(mo)vt=mo.join(" ")}let yt=54,kt=vt,Lt=` Segment ${mt.index+1}: `,Ct=" ";if(vt){if(Lt.length+vt.length+Ct.length>yt){let iu=yt-Lt.length-Ct.length;kt=`${vt.substring(0,iu-1)}…`}}let sn=vt?`${Lt}${kt}${Ct}`:` Segment ${mt.index+1} `,Gt=vt?`${Lt}${bt.cyan(kt)}${Ct}`:sn,zi=58-sn.length,Ji=Math.floor(zi/2),ou=zi-Ji;oe.push(`${te.sh.repeat(Ji)}${Gt}${te.sh.repeat(ou)}`)}if(mt.steps.find((vt)=>vt.type==="segment-skipped")){oe.push(""),oe.push(" (skipped — prior segment blocked)");continue}let gt=!1,ht=!1;for(let vt of mt.steps){let yt=Al(vt,ce,te);if(yt){if(ht=!0,vt.type==="recurse"){oe.push("");let kt=" RECURSING ",Lt=58-kt.length-4;oe.push(` ${te.tl}${te.h}${kt}${te.h.repeat(Lt)}`),oe.push(` ${te.v}`),gt=!0;continue}for(let kt of yt.lines)if(gt)oe.push(` ${te.v} ${kt}`);else oe.push(kt);if(yt.incrementStep)ce++}}if(gt)oe.push(` ${te.v}`),oe.push(` ${te.bl}${te.h.repeat(56)}`),gt=!1;if(!ht)oe.push(""),oe.push(` ${bt.green("✓")} Allowed (no matching rules)`)}if(oe.push(""),oe.push("RESULT"),j.result==="blocked"){if(oe.push(` Status: ${bt.red("BLOCKED")}`),j.customRule){if(oe.push(` Rule: ${j.customRule.id}`),j.customRule.rulebook)oe.push(` Rulebook: ${j.customRule.rulebook.name} ${j.customRule.rulebook.version}`);if(j.customRule.source)oe.push(` Source: ${j.customRule.source}`);if(j.customRule.override)oe.push(` Override: reason ${j.customRule.override.reason}`)}if(j.reason){let mt=Qn(j.reason," ");oe.push(` Reason: ${mt[0]}`);for(let it=1;it<mt.length;it++)oe.push(mt[it]??"")}}else oe.push(` Status: ${bt.green("ALLOWED")}`);oe.push(""),oe.push("CONFIG");let Se=j.configSource??"none",Ne=j.configValid?"":" (invalid)";oe.push(` Path: ${Se}${Ne}`);let He=j.safetyPresetScope;oe.push(` Safety preset: ${j.selectedPreset??"standard"}${He?` (${hr(He)})`:""}`),oe.push(` Effective capabilities: ${j.effectiveLevel}`);let at=Object.entries(j.destructiveCommandRuleOverrides??{});if(oe.push(` Rule customizations: ${at.length}`),j.ruleActivation)oe.push(` Rule activation: ${j.ruleActivation.id} — ${j.ruleActivation.enabled?"on":"off"} via ${j.ruleActivation.source}`);return oe.join(`
213
- `)}function li(j){return JSON.stringify(j,null,2)}import{resolve as Xf}from"node:path";var Jf=["AKIA","ASIA","ghp_","gho_","ghu_","ghs_","ghr_","github_pat_","glpat-","xox","npm_","pypi-","rk_","sk-","sk_","gsk_","xai-","pplx-","bastn_","tgp_v1_","flp_","wfr_","fw_","fwp_","tp-","psk-"];function _l(j){let K=0,te={allocateSegment(){return K++},getNextSegmentIndex(){return K},recordGlobal(re){j.record({kind:"step",scope:"global",step:re})},recordSegment(re,oe=te.currentSegmentIndex){if(oe===void 0)return;j.record({kind:"step",scope:"segment",segmentIndex:oe,step:re})}};return te}function Tl(j={}){let K=[],te=j.maxEvents??512,re={maxTextLength:j.maxTextLength??2048,maxListLength:j.maxListLength??128,maxObjectProperties:j.maxObjectProperties??j.maxListLength??128,maxDepth:j.maxDepth??16},oe=0,ce,de=new Set;return{record(we){if(ce)return;try{if(!we||K.length>=te){oe++;return}K.push(di(Wf(we,re,de)))}catch{oe++}},finish(we){if(ce)return ce;try{ce=di({events:Object.freeze(K),droppedEvents:oe,terminal:Kf(we,re,de)})}catch{oe++,ce=Object.freeze({events:Object.freeze(K),droppedEvents:oe,terminal:Object.freeze({result:"blocked",reason:"trace unavailable".slice(0,re.maxTextLength),segment:"trace unavailable".slice(0,re.maxTextLength)})})}return ce}}}function Wf(j,K,te){if(j.kind!=="step")throw TypeError("invalid trace event");let{scope:re,step:oe}=j;Br(oe,te,K);let ce=An(oe,K,te);if(re==="global")return{kind:"step",scope:"global",step:ce};if(re!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:j.segmentIndex,step:ce}}function Kf(j,K,te){let re=j.result;if(re==="allowed")return Object.freeze({result:"allowed"});if(re!=="blocked")throw TypeError("invalid trace terminal");let oe=j.ruleId;return Object.freeze({result:"blocked",reason:An(j.reason,K,te),segment:An(j.segment,K,te),...oe?{ruleId:An(oe,K,te)}:{}})}function Br(j,K,te,re=0,oe=new WeakSet){if(typeof j==="string"){let we=j.slice(0,te.maxTextLength);if(!Je(we))return;for(let xe of ot(we))for(let Ce of xe.match(/[^\s"'()$]+/g)??[])K.add(Il(Ce));return}if(!j||typeof j!=="object"||re>=te.maxDepth||oe.has(j))return;if(oe.add(j),Array.isArray(j)){let we=Math.min(j.length,te.maxListLength);for(let xe=0;xe<we;xe++)Br(j[xe],K,te,re+1,oe);return}let ce=0,de=new Set;for(let we in j){if(!Object.hasOwn(j,we))continue;if(ce>=te.maxObjectProperties)break;ce++,Br(we,K,te);let xe=ci(we,te,K);if(de.has(xe))continue;de.add(xe),Br(j[we],K,te,re+1,oe)}}function An(j,K,te,re=0,oe=new WeakSet){if(typeof j==="string")return ci(j,K,te);if(!j||typeof j!=="object")return j;if(re>=K.maxDepth)return;if(oe.has(j))return;if(oe.add(j),Array.isArray(j)){let we=[],xe=Math.min(j.length,K.maxListLength);for(let Ce=0;Ce<xe;Ce++)we.push(An(j[Ce],K,te,re+1,oe));return we}let ce={},de=0;for(let we in j){if(!Object.hasOwn(j,we))continue;if(de>=K.maxObjectProperties)break;de++;let xe=ci(we,K,te);if(Object.hasOwn(ce,xe))continue;Object.defineProperty(ce,xe,{value:An(j[we],K,te,re+1,oe),enumerable:!0,configurable:!0,writable:!0})}return ce}function ci(j,K,te){let re=j.slice(0,K.maxTextLength),oe=Je(re)?Ye(re):re,ce=te.size>0?Zf(oe,te):oe;return(Yf(ce)?Oe(ce):ce).slice(0,K.maxTextLength)}function Yf(j){return j.includes("PRIVATE KEY")||j.includes("://")||j.includes("eyJ")||j.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(j)||j.length>=14&&Jf.some((K)=>j.includes(K))||j.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(j)}function Zf(j,K){return j.replace(/[^\s"'()$]+/g,(te)=>K.has(Il(te))?"<redacted>":te)}function Il(j){let K=2166136261,te=2166136261;for(let re=0;re<j.length;re++)K=Math.imul(K^j.charCodeAt(re),16777619),te=Math.imul(te^j.charCodeAt(j.length-re-1),16777619);return`${K>>>0}:${te>>>0}:${j.length}`}function di(j){if(j&&typeof j==="object"&&!Object.isFrozen(j)){for(let K of Object.values(j))di(K);Object.freeze(j)}return j}function er(j,K={},te){let re=Xf(K.cwd??process.cwd()),oe=K.policySnapshot??k(te,{cwd:re,userConfigDir:K.userConfigDir}),ce=P(oe.policy,te.env),de=K.strict,we=ze({policySnapshot:oe,effectiveCapabilities:ce.capabilities,strict:de??ce.strict,paranoidRm:ce.paranoidRm,paranoidInterpreters:ce.paranoidInterpreters,worktreeMode:ce.worktreeMode}),xe={effectiveLevel:we.effectiveLevel,selectedPreset:oe.policy.safety.level??"standard",...oe.policyScopes?{safetyPresetScope:oe.policyScopes.levelScope}:{},effectiveCapabilities:we.effectiveCapabilities,destructiveCommandRuleOverrides:oe.policy.destructiveCommandRuleOverrides},{configSource:Ce,configValid:Se}=em(te,{cwd:re,userConfigDir:K.userConfigDir});if(!j||!j.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:Ce,configValid:Se,...xe};let Ne=v(j,"auto");if(Ne.status==="limited")throw new b;let He=Ne.dialect==="powershell"?v(j,"posix"):Ne,at=ft(He),mt=Tl(),it=_l(mt);it.recordGlobal({type:"parse",input:j,segments:at.map((Gt)=>[...Gt])});let gt=u("Bash",{command:j},{kind:"command",shell:"auto"},{configCwd:re,executionCwd:re},j),ht=V(gt,{environment:te,trace:it,dependencies:{loadPolicySnapshot:()=>oe,...de===void 0?{}:{getModes:()=>({...ce,strict:de})}}}),vt=ht.decision.kind==="deny"?ht.decision:null;if(vt&&(ht.stage==="policy-protection"||ht.stage==="secret-protection")){let Gt=Qf(vt);return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Gt.rule,matched:!0,reason:vt.reason}]}]},result:"blocked",reason:R(vt.reason),segment:R(ui(vt,j)),...Gt.ruleId?{ruleId:R(Gt.ruleId)}:{},configSource:Ce,configValid:Se,...xe}}let yt=it.getNextSegmentIndex();if(vt&&yt>0&&yt<at.length)it.recordSegment({type:"segment-skipped",index:yt,reason:"prior-segment-blocked"},yt);let kt=mt.finish(vt?{result:"blocked",reason:vt.reason,segment:ui(vt,j),...vt.ruleId?{ruleId:vt.ruleId}:{}}:{result:"allowed"}),Lt=vt?.ruleId??tm(gt,oe,ce,te),Ct=U.find((Gt)=>Gt.id===Lt&&Gt.activationCapability),sn=Ct?we.policy.effectiveDestructiveCommandRules[Ct.id]:void 0;return{trace:rm(kt),result:vt?"blocked":"allowed",reason:vt?R(vt.reason):void 0,segment:vt?R(ui(vt,j)):void 0,ruleId:vt?.ruleId?R(vt.ruleId):void 0,customRule:nm(om(vt?.ruleId,oe)),configSource:Ce,configValid:Se,...xe,...Ct&&sn?{ruleActivation:{id:Ct.id,...sn}}:{}}}function ui(j,K){return j.evidence.find((te)=>te.kind==="command")?.segment??K}function Qf(j){if(j.reason===qe)return{ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};if(j.reason===Ve)return{ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};if(j.reason===C)return{ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};return{ruleId:j.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"}}function em(j,K){let te=A(K.cwd),re=K.userConfigPath??T(j,K),oe=H(j,{cwd:K.cwd,userConfigDir:K.userConfigDir,userConfigPath:K.userConfigPath});try{if(r(oe.projectConfigTarget)!==null){if(en(oe.projectConfigTarget).errors.length===0)return{configSource:te,configValid:!0};return{configSource:te,configValid:!1}}}catch(ce){if(ce instanceof o)return{configSource:te,configValid:!1};throw ce}try{if(r(oe.userConfigTarget)!==null){let ce=en(oe.userConfigTarget);return{configSource:re,configValid:ce.errors.length===0}}return{configSource:null,configValid:!0}}catch(ce){if(ce instanceof o)return{configSource:re,configValid:!1};throw ce}}function tm(j,K,te,re){let oe=K.policy,ce=De({...oe,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...oe.destructiveCommandRuleOverrides,...Object.fromEntries(U.flatMap((we)=>we.activationCapability?[[we.id,"on"]]:[]))}},K.state==="degraded"?{diagnostics:K.diagnostics,reason:K.reason}:void 0),de=V(j,{environment:re,dependencies:{loadPolicySnapshot:()=>ce,getModes:()=>({...te,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return de.decision.kind==="deny"?de.decision.ruleId:void 0}function nm(j){if(!j)return;return{id:R(j.id),...j.rulebook?{rulebook:{name:R(j.rulebook.name),version:R(j.rulebook.version)}}:{},...j.source?{source:R(j.source)}:{},...j.override?{override:{type:"reason",reason:R(j.override.reason)}}:{}}}function rm(j){let K=j.events.flatMap((re)=>re.kind==="step"&&re.scope==="global"?[re.step]:[]),te=new Map;for(let re of j.events){if(re.kind!=="step"||re.scope!=="segment")continue;let oe=te.get(re.segmentIndex)??{index:re.segmentIndex,steps:[]};oe.steps.push(re.step),te.set(re.segmentIndex,oe)}return{steps:K,segments:[...te.values()]}}function om(j,K){let te=j?.replace(/^custom\./,"");if(!te||!K.policy.rules.some((re)=>re.name===te))return;return K.ruleMetadata[te]??Object.freeze({id:te})}function $l(j){return new Promise((K)=>{process.stdout.write(`${j}
214
- `,()=>K())})}async function Ol(j,K){let te=ii(K);if(!te)return 1;try{let re=er(te.command,{cwd:te.cwd},j),oe=!!process.env.NO_COLOR||!process.stdout.isTTY;return await $l(te.json?li(re):ai(re,{asciiOnly:oe})),0}catch(re){let oe=im(re instanceof p?re.cause:re);if(oe===void 0)throw re;if(te.json)return await $l(JSON.stringify({error:oe})),1;return console.error(oe),1}}function im(j){if(j instanceof b)return j.message;if(j instanceof f)return j.message;if(j instanceof a&&n[j.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var jl="2.4.0",Ht=" ",fn="cc-safety-net";function Fl(j){return j.argument?`${j.flags} ${j.argument}`:j.flags}function sm(j){return Math.max(...j.map((K)=>Fl(K).length))}function am(j){return Math.max(...j.map((K)=>K.usage.length))}function lm(j){return Math.max(...j.map((K)=>`${fn} ${K.usage}`.length))}function cm(j,K){let te=`${fn} ${j.usage}`;return`${Ht}${te.padEnd(K+2)}${j.description}`}function Zt(j,K){return`${Ht}${j.padEnd(Math.max(40,j.length+2))}${K}`}function _n(j,K=console.log){let te=[];if(te.push(`${fn} ${j.name}`),te.push(""),te.push(`${Ht}${j.description}`),te.push(""),te.push("USAGE:"),te.push(`${Ht}${fn} ${j.usage}`),te.push(""),j.subcommands&&j.subcommands.length>0){te.push("SUBCOMMANDS:");let re=am(j.subcommands);for(let oe of j.subcommands)te.push(`${Ht}${oe.usage.padEnd(re+2)}${oe.description}`);te.push("")}if(j.options.length>0){te.push("OPTIONS:");let re=sm(j.options);for(let oe of j.options){let ce=Fl(oe),de=oe.default?`${oe.description} (default: ${oe.default})`:oe.description;te.push(`${Ht}${ce.padEnd(re+2)}${de}`)}te.push("")}if(j.examples&&j.examples.length>0){te.push("EXAMPLES:");for(let re of j.examples)te.push(`${Ht}${re}`)}K(te.join(`
215
- `))}function pi(){let j=lm(fr),K=[];K.push(`${fn} v${jl}`),K.push(""),K.push("Blocks destructive commands and secret access."),K.push(""),K.push("COMMANDS:");for(let te of fr)K.push(cm(te,j));K.push(""),K.push("GLOBAL OPTIONS:"),K.push(`${Ht}-h, --help Show help (use with command for command-specific help)`),K.push(`${Ht}-V, --version Show version`),K.push(""),K.push("HELP:"),K.push(`${Ht}${fn} help <command> Show help for a specific command`),K.push(`${Ht}${fn} <command> --help Show help for a specific command`),K.push(""),K.push("ENVIRONMENT VARIABLES:"),K.push(Zt(`${i.level.name}=standard|strict|paranoid`,"Set session safety level")),K.push(Zt(`${i.worktree.name}=1`,"Allow local git discards in linked worktrees")),K.push(Zt(`${i.debug.name}=1`,"Print diagnostic messages to stderr")),K.push(Zt(`${i.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),K.push(Zt("CC_SAFETY_NET_HOME","Override rule config home directory")),K.push(""),K.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),K.push(Zt(`${i.strict.name}=1`,"Force safety.overrides.fail_closed on")),K.push(Zt(`${i.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),K.push(Zt(`${i.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),K.push(Zt(`${i.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),K.push(""),K.push("Documentation: https://ccsafetynet.com/docs"),console.log(K.join(`
216
- `))}function Nl(){console.log(jl)}function tr(j,K=console.log){let te=mr(j);if(!te)return!1;if(te.name.toLowerCase()!==j.toLowerCase())return!1;return _n(te,K),!0}import{existsSync as Ci,readFileSync as Oc}from"node:fs";import{join as ki}from"node:path";import*as rn from"node:readline";function dm(j){return j==="install"?"Install":"Uninstall"}function um(j){return j==="install"?"Installing":"Uninstalling"}function pm(j){return j==="install"?"into":"from"}function Ul(j){return j?.available===!0}function fm(j,K){let te=new Set(K);return j.filter((re)=>te.has(re.target)).map((re)=>re.target)}function Ml(j,K,te){if(j.length===0||j.every((re)=>!re.available))return K;return Array.from({length:j.length},(re,oe)=>oe+1).map((re)=>(K+re*te+j.length)%j.length).find((re)=>Ul(j[re]))}function mm(j,K,te){if(te.ctrl&&te.name==="c")return"interrupt";if(te.name==="escape"||K==="q")return"abort";if(j==="install"&&(K==="u"||K==="U"))return"update";if(te.name==="up"||K==="k")return"up";if(te.name==="down"||K==="j")return"down";if(te.name==="space"||K===" ")return"toggle";if(te.name==="return"||te.name==="enter")return"confirm";return null}function gm(j){return{cursor:j.findIndex((K)=>K.available),selected:[]}}function ym(j,K,te){if(te==="confirm"||te==="update"||te==="abort"||te==="interrupt")return{state:j,done:te};if(te==="up")return{state:{...j,cursor:Ml(K,j.cursor,-1)}};if(te==="down")return{state:{...j,cursor:Ml(K,j.cursor,1)}};let re=K[j.cursor];if(!Ul(re))return{state:j};let oe=j.selected.includes(re.target)?j.selected.filter((ce)=>ce!==re.target):fm(K,[...j.selected,re.target]);return{state:{...j,selected:oe}}}var Gl="◉",Bl="◯",ql=">",Vl=" ";function hm(j,K,te,re={}){let oe=re.color!==!1,ce=oe?bt.dim:(xe)=>xe,de=oe?bt.green:(xe)=>xe,we=oe?bt.bold:(xe)=>xe;return["",`${dm(j)} CC Safety Net ${pm(j)}:`,"",...K.map((xe,Ce)=>{let Se=te.selected.includes(xe.target),Ne=Ce===te.cursor,He=Se?Gl:Bl,at=Ne?ql:Vl,mt=xe.available?"":` (${xe.unavailableReason??"not installed"})`,it=`${He} ${xe.label}${mt}`,gt=!xe.available?ce(it):Se?de(it):Ne?we(it):it;return`${at} ${gt}`}),"",j==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":K.some((xe)=>xe.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${j}. q/Esc: close`].join(`
217
- `)}var Hl=["global-hook","plugin"];function vm(j,K,te={}){let re=te.color!==!1?bt.bold:(ce)=>ce;return["","Install the Kimi Code integration as:","",...[`Global hook — ${K?"already installed; selecting it reports the current state":"write the hook into ~/.kimi-code/config.toml now"}`,"Native Kimi plugin — print the steps to run inside Kimi Code"].map((ce,de)=>{let we=de===j,xe=`${we?Gl:Bl} ${ce}`;return`${we?ql:Vl} ${we?re(xe):xe}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
218
- `)}function zl(j){let{input:K,output:te}=j;rn.emitKeypressEvents(K);let re=K.isRaw===!0;K.setRawMode(!0),K.resume();let oe=0,ce=()=>{if(oe===0)return;rn.moveCursor(te,0,-oe),rn.cursorTo(te,0),rn.clearScreenDown(te)},de=()=>{ce();let we=j.render();te.write(`${we}
219
- `),oe=we.split(`
220
- `).length};return new Promise((we)=>{let xe=(Se)=>{K.off("keypress",Ce),K.setRawMode(re),K.pause(),ce(),we(Se)};function Ce(Se,Ne){j.onKey(Se,Ne,{finish:xe,draw:de})}K.on("keypress",Ce),de()})}function Jl(j={}){let K=0;return zl({input:j.input??process.stdin,output:j.output??process.stdout,render:()=>vm(K,j.globalHookInstalled===!0),onKey:(te,re,oe)=>{if(re.ctrl&&re.name==="c"){oe.finish(null),(j.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(re.name==="escape"||te==="q")return oe.finish(null);if(re.name==="return"||re.name==="enter")return oe.finish(Hl[K]);if(re.name==="up"||re.name==="down"||te==="k"||te==="j")K=(K+1)%Hl.length,oe.draw()}})}function fi(j=process.stdin,K=process.stdout){return Boolean(j.isTTY&&K.isTTY&&typeof j.setRawMode==="function")}function Wl(j,K,te={}){let re=te.output??process.stdout,oe=gm(K);return zl({input:te.input??process.stdin,output:re,render:()=>hm(j,K,oe),onKey:(ce,de,we)=>{let xe=mm(j,ce,de);if(!xe)return;let Ce=ym(oe,K,xe);if(oe=Ce.state,Ce.done==="interrupt"){we.finish(null),(te.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(Ce.done==="abort")return we.finish(null);if(Ce.done==="update")return we.finish("update");if(Ce.done==="confirm"){if(oe.selected.length===0){re.write("\x07"),we.draw();return}we.finish([...oe.selected]),re.write(`${um(j)} selected integrations...
221
- `);return}we.draw()}})}import{existsSync as Yl,lstatSync as Lm,mkdirSync as wm,mkdtempSync as km,readdirSync as xm,readFileSync as In,rmSync as Vr}from"node:fs";import{basename as Cm,dirname as Sm,join as Ot}from"node:path";import{fileURLToPath as Rm}from"node:url";var mi="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",mn="cc-safety-net",gn="cc-safety-net/index.ts";import{spawn as bm}from"node:child_process";var gi=(j,K)=>{let te=cn([...j],process.env);return new Promise((re)=>{let oe=bm(te.cmd,te.args,{cwd:K,stdio:["ignore","pipe","pipe"]}),ce=Wo(oe),de=!1,we=setTimeout(()=>{de=!0,oe.kill()},120000);oe.on("error",(xe)=>{clearTimeout(we),re({status:null,errorCode:xe.code,stdout:ce.stdout,stderr:[xe.message,ce.stderr].filter(Boolean).join(`
222
- `)})}),oe.on("close",(xe)=>{clearTimeout(we),re({status:de?null:xe,errorCode:de?"ETIMEDOUT":void 0,stdout:ce.stdout,stderr:ce.stderr})})})};var Tn="cc-safety-net.ts",Kl=Ot("amp",gn);function Pm(j){return Ot(j.home,".config","amp","plugins","cc-safety-net.ts")}function Em(){let j=Sm(Rm(import.meta.url));return[Ot(j,"..",Kl),Ot(j,"..","..","..","dist",Kl)]}function Dm(j=Em()){let K=j.find((te)=>Yl(te)&&Lm(te).isFile());if(!K)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return K}function Zl(j){try{return JSON.parse(j)}catch{return}}function zr(j){return j.subarray(0,Buffer.byteLength(mi)).toString("utf-8")===mi}async function nr(j,K,te){let re=await j(K,te);if(re.status===0)return re;throw Error([`Failed to run ${K.join(" ")}${re.status===null?"":` (exit ${re.status})`}.`,[re.stdout,re.stderr].filter(Boolean).join(`
206
+ `}function Tn(A){return[{name:"__init__.py",content:_2(A)},{name:"plugin.yaml",content:A2(A)}]}import{mkdirSync as T2,readdirSync as $2,readFileSync as I2,rmSync as So}from"node:fs";import{join as tn}from"node:path";var O2="__pycache__";function Ro(A){let z=A.env.get("HERMES_HOME")?.trim();return z?z:tn(A.home,".hermes")}function Po(A){return tn(Ro(A),"plugins",_t)}function Eo(A){return A.startsWith(Co)}function Do(A,z){let X=Po(A),ee=Lt(X);if(ee&&(ee.isSymbolicLink()||!ee.isDirectory()))throw Error(`Refusing to ${z} ${X}: not a regular directory. Move or remove it and rerun ${z==="install"?"install":"uninstall"} --hermes-agent.`);return X}function Pa(A,z){let X=Lt(A);if(!X)return;if(X.isSymbolicLink()||!X.isFile())throw Error(`Refusing to ${z} ${A}: not a regular file. Move or remove it.`);let ee=I2(A,"utf-8");if(!Eo(ee))throw Error(`Refusing to ${z} unmanaged file at ${A}. Move or remove it.`);return ee}function Ea(A){let z=Do(A,"install"),X=Tn(wt());if(X.map((te)=>Pa(tn(z,te.name),"overwrite")).every((te,ae)=>te===X[ae]?.content))return{path:z,alreadyInstalled:!0};return T2(z,{recursive:!0}),X.forEach((te)=>{kt(tn(z,te.name),te.content)}),{path:z,alreadyInstalled:!1}}function Ao(A){let z=Do(A,"remove");if(!Lt(z))return[];return Tn(wt()).filter((X)=>Pa(tn(z,X.name),"remove")!==void 0)}function Da(A){let z=Do(A,"remove");if(!Lt(z))return{path:z,alreadyInstalled:!1};let X=Ao(A);if(X.forEach((ee)=>{So(tn(z,ee.name))}),So(tn(z,O2),{recursive:!0,force:!0}),$2(z).length===0)So(z,{recursive:!0});return{path:z,alreadyInstalled:X.length>0}}var Cr="hermes-agent",Aa=/^([^\s#][^:]*):/,F2=/^\s+([A-Za-z_][\w-]*):/,_a=/^\s+-\s*(.*)$/;function j2(A){return A.trim().replace(/^(["'])(.*)\1$/,"$2")}function N2(A){let z=A.split(/\r?\n/),X=z.findIndex((ae)=>Aa.exec(ae)?.[1]?.trim()==="plugins");if(X===-1)return[];let ee=z.slice(X+1),te=ee.findIndex((ae)=>Aa.test(ae));return te===-1?ee:ee.slice(0,te)}function Ta(A,z){let X=N2(A),ee=X.findIndex((le)=>F2.exec(le)?.[1]===z);if(ee===-1)return[];let te=X.slice(ee+1),ae=te.findIndex((le)=>!_a.test(le));return(ae===-1?te:te.slice(0,ae)).map((le)=>j2(_a.exec(le)?.[1]??""))}function M2(A){try{return $a(Ia(Ro(A),"config.yaml"),"utf-8")}catch{return}}function _o(A){let z=M2(A)??"";return Ta(z,"enabled").includes(_t)&&!Ta(z,"disabled").includes(_t)}function Oa(A){return/^# version:\s*(.+)$/m.exec(A)?.[1]?.trim()}function H2(A,z){let X=Lt(A);if(!X)return{error:`${z.name} is missing from ${A}; run install --hermes-agent`};if(X.isSymbolicLink()||!X.isFile())return{error:`${A} is a symlink or not a regular file; move or remove it`};try{let ee=$a(A,"utf-8");if(!Eo(ee))return{error:`Unmanaged ${z.name} occupies ${A}; move or remove it`};if(Oa(ee)===wt()&&ee!==z.content)return{error:`Modified ${z.name} occupies ${A}; run install --hermes-agent to restore it`};return{content:ee}}catch(ee){return{error:`Failed to read ${A}: ${ee instanceof Error?ee.message:String(ee)}`}}}function Fa(A){let z=Po(A.environment),X=dr(Cr,z);if(X)return X;let ee=Tn(wt()).map((ye)=>H2(Ia(z,ye.name),ye)),te=ee.flatMap((ye)=>("error"in ye)?[ye.error]:[]);if(te.length>0)return{platform:Cr,status:"n/a",configPath:z,errors:te};let ae=ee.some((ye)=>("content"in ye)&&Oa(ye.content)!==wt()),le=ae?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!_o(A.environment))return{platform:Cr,status:"disabled",method:"plugin directory",configPath:z,errors:[`${_t} is not enabled in Hermes; run \`hermes plugins enable ${_t}\``,...le]};return{platform:Cr,status:"configured",method:"plugin directory",configPath:z,errors:ae?le:void 0}}import{existsSync as U2,readFileSync as G2}from"node:fs";import{join as ja}from"node:path";var B2=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function q2(A){return ja(A.env.get("KIMI_CODE_HOME")||ja(A.home,".kimi-code"),"config.toml")}function $n(A){let z=q2(A.environment);if(!U2(z))return{platform:"kimi-code",status:"n/a",configPath:z};try{if(!B2.test(G2(z,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:z}}catch(X){return{platform:"kimi-code",status:"n/a",configPath:z,errors:[`Failed to read ${z}: ${X instanceof Error?X.message:String(X)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:z}}import{readFileSync as za}from"node:fs";import{join as On}from"node:path";var ht="cc-safety-net",$t="index.js",yn="openclaw.plugin.json",hn="package.json";var Sr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as J2,lstatSync as W2,readdirSync as K2,readFileSync as Y2}from"node:fs";import{dirname as Ma,join as Gt}from"node:path";import{fileURLToPath as Z2}from"node:url";import{spawn as V2}from"node:child_process";function z2(A){return A.join(" ")}function To(A,z,X){return[`Failed to run ${z2(A)}${z===null?"":` (exit ${z})`}.`,X.trim()].filter(Boolean).join(`
207
+ `)}function $o(A){let z={stdout:"",stderr:""};return A.stdout.setEncoding("utf-8"),A.stderr.setEncoding("utf-8"),A.stdout.on("data",(X)=>{z.stdout+=X}),A.stderr.on("data",(X)=>{z.stderr+=X}),z}function Nt(A,z){return new Promise((X,ee)=>{let te=Xt([...A],process.env),ae=V2(te.cmd,te.args,{stdio:["ignore","pipe","pipe"]}),le=$o(ae),ye=()=>[le.stdout,le.stderr].filter(Boolean).join(`
208
+ `),he=z?.timeoutMs??120000,ve=setTimeout(()=>{ae.kill(),ee(Error(To(A,null,`Timed out after ${he}ms.
209
+ ${ye()}`.trim())))},he);ae.on("error",(be)=>{clearTimeout(ve),ee(Error(To(A,null,`${be.message}
210
+ ${ye()}`.trim())))}),ae.on("close",(be)=>{if(clearTimeout(ve),be!==0){ee(Error(To(A,be,ye())));return}X(z?.stdoutOnly?le.stdout:ye())})})}async function Io(A){for(let z of A)await Nt(z)}async function Na(A){for(let z of A)try{await Nt(z)}catch(X){console.warn(X instanceof Error?X.message:String(X))}}var Oo=Gt("openclaw",ht),X2=[$t,yn,hn];function Fo(A,z){if(A==="~")return z;if(A.startsWith("~/")||A.startsWith("~\\"))return Gt(z,A.slice(2));return A}function Ha(A){let z=A.env.get("OPENCLAW_STATE_DIR")?.trim();if(z)return Fo(z,A.home);let X=A.env.get("OPENCLAW_CONFIG_PATH")?.trim();return X?Ma(Fo(X,A.home)):Gt(A.home,".openclaw")}function Ua(A){let z=A.env.get("OPENCLAW_CONFIG_PATH")?.trim();return z?Fo(z,A.home):Gt(Ha(A),"openclaw.json")}function jo(A){return Gt(Ha(A),"extensions",ht)}function Q2(A){let z=K2(A);if(z.length===0)return!0;if(z.some((te)=>!X2.includes(te)))return!1;let X=Gt(A,$t),ee=Lt(X);return ee!==void 0&&!ee.isSymbolicLink()&&ee.isFile()&&Y2(X,"utf-8").startsWith(Sr)}function No(A){let z=jo(A),X=Lt(z);if(!X)return;if(!X.isSymbolicLink()&&X.isDirectory()&&Q2(z))return;throw Error(`Refusing to modify ${z}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function Ga(){let A=Ma(Z2(import.meta.url));return[Gt(A,Oo),Gt(A,"..",Oo),Gt(A,"..","..","..","dist",Oo)]}function Mo(A=Ga()){return A.find((z)=>J2(z)&&W2(z).isDirectory())}function ef(A=Ga()){let z=Mo(A);if(!z)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return z}function Ba(A=ef()){return[["openclaw","plugins","install",A,"--force"],["openclaw","plugins","enable",ht]]}function tf(A){let z=(()=>{try{return JSON.parse(A)}catch{return}})(),X=ft(ft(z,"plugin"),"status");return typeof X==="string"?X:void 0}async function qa(){let A=tf(await Nt(["openclaw","plugins","inspect",ht,"--runtime","--json"],{stdoutOnly:!0}));if(A==="loaded")return;throw Error(`${A===void 0?`The ${ht} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${ht} plugin with status "${A}".`} Run \`openclaw plugins inspect ${ht} --runtime\` for details.`)}var Rr="openclaw",In=`run \`openclaw plugins enable ${ht}\``;function vn(A,z){let X=On(A,z),ee=Lt(X);if(!ee)return{error:`${z} is missing from ${X}; run install --openclaw`};if(ee.isSymbolicLink()||!ee.isFile())return{error:`${X} is a symlink or not a regular file; move or remove it`};try{return{content:za(X,"utf-8")}}catch(te){return{error:`Failed to read ${X}: ${te instanceof Error?te.message:String(te)}`}}}function Ja(A){try{return JSON.parse(At(A))}catch{return}}function nf(A){let z=vn(A,yn);if("error"in z)return z.error;if(ft(Ja(z.content),"id")===ht)return;return`${On(A,yn)} is not a valid ${ht} manifest; run install --openclaw`}function rf(A){let z=vn(A,hn);if("error"in z)return z.error;let X=ft(ft(Ja(z.content),"openclaw"),"extensions");if(Array.isArray(X)&&X.includes(`./${$t}`))return;return`${On(A,hn)} does not point OpenClaw at ${$t}; run install --openclaw`}function Va(A){return Array.isArray(A)?A.filter((z)=>typeof z==="string"):[]}function of(A){let z=Ua(A);if(!Lt(z))return`${ht} is not enabled; ${In}`;let X=(()=>{try{return JSON.parse(At(za(z,"utf-8")))}catch{return}})();if(X===void 0)return`Failed to read ${z}; fix it, then ${In}`;let ee=ft(X,"plugins");if(ft(ee,"enabled")===!1)return`plugins.enabled is false in ${z}; no OpenClaw plugin loads`;let te=ft(ft(ft(ee,"entries"),ht),"enabled");if(Va(ft(ee,"deny")).includes(ht)||te===!1)return`${ht} is disabled in ${z}; ${In}`;let ae=Va(ft(ee,"allow"));if(ae.length>0&&!ae.includes(ht))return`plugins.allow in ${z} does not list ${ht}; add it, then ${In}`;if(ae.includes(ht)||te===!0)return;return`${ht} is not enabled; ${In}`}function Wa(A){return/^\/\/ version:\s*(.+)$/m.exec(A)?.[1]?.trim()}function sf(A,z,X){if(X===void 0)return[];let ee=vn(X,$t);if("error"in ee||Wa(ee.content)!==z)return[];return[$t,yn,hn].flatMap((te)=>{let ae=vn(A,te),le=vn(X,te);if("error"in ae||"error"in le||ae.content===le.content)return[];return[`Modified ${te} occupies ${On(A,te)}; run install --openclaw to restore it`]})}function Ka(A){let z=jo(A.environment),X=dr(Rr,z);if(X)return X;let ee=vn(z,$t),ae=["error"in ee?ee.error:ee.content.startsWith(Sr)?void 0:`Unmanaged ${$t} occupies ${On(z,$t)}; move or remove it`,nf(z),rf(z)].filter((be)=>be!==void 0),le="content"in ee?Wa(ee.content):void 0,ye=ae.length>0?ae:sf(z,le,Mo());if(ye.length>0)return{platform:Rr,status:"n/a",configPath:z,errors:ye};let he=le===wt()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],ve=of(A.environment);if(ve)return{platform:Rr,status:"disabled",method:"plugin directory",configPath:z,errors:[ve,...he]};return{platform:Rr,status:"configured",method:"plugin directory",configPath:z,errors:he.length>0?he:void 0}}import{existsSync as ff,readFileSync as mf}from"node:fs";import{join as gf}from"node:path";import{existsSync as Ho,readFileSync as Xa,rmSync as af}from"node:fs";import{join as Bt}from"node:path";import{pathToFileURL as lf}from"node:url";var Pr="cc-safety-net",Qa=`${Pr}@latest`,el=["opencode.json","opencode.jsonc"],Ya="CCSafetyNetPlugin",Za={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function Er(A){return Bt(A.env.get("XDG_CONFIG_HOME")||Bt(A.home,".config"),"opencode")}function cf(A){return Bt(Er(A),el[0])}function df(A){return el.map((z)=>Bt(Er(A),z))}function tl(A){return Bt(A.env.get("XDG_CACHE_HOME")||Bt(A.home,".cache"),"opencode","packages",Qa)}function Uo(A){af(tl(A),{recursive:!0,force:!0})}async function nl(A){let z=Bt(tl(A),"node_modules",Pr),X=Bt(z,"package.json");if(!Ho(X))throw Error(`The OpenCode plugin cache at ${z} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${Qa}\` for details.`);let ee=ft(JSON.parse(Xa(X,"utf-8")),"main");if(typeof ee!=="string")throw Error(`The cached OpenCode plugin at ${z} declares no "main" entry.`);let te=Bt(z,ee);if(typeof(await import(lf(te).href))[Ya]==="function")return;throw Error(`The cached OpenCode plugin at ${te} does not export a callable ${Ya}, so OpenCode would load nothing and fail open.`)}function rl(A,z){try{return JSON.parse(At(A))}catch(X){if(X instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${z}: ${X.message}`);throw X}}function uf(A){if(!A||typeof A!=="object"||Array.isArray(A))return!1;let z=A.plugin;if(!Array.isArray(z))return!1;return z.some((X)=>typeof X==="string"&&X.includes(Pr))}function pf(A,z){let X=Ws(A,"plugin",Za);if(!X)throw Error(`Failed to locate OpenCode plugin array in ${z}`);let ee=Ks(A,X,Za.stringError).filter((te)=>te.value.includes(Pr)).map((te)=>te.range).reverse().reduce(fr,A);return rl(ee,z),ee}function ol(A){Uo(A);let z=df(A),X=z.find((te)=>Ho(te)),ee=[];for(let te of z){if(!Ho(te))continue;try{let ae=Xa(te,"utf-8");if(!uf(rl(ae,te)))continue;return kt(te,pf(ae,te)),{path:te,alreadyInstalled:!0}}catch(ae){ee.push(ae instanceof Error?ae.message:String(ae))}}if(ee.length>0)throw Error(ee.join(`
211
+ `));return{path:X??cf(A),alreadyInstalled:!1}}function il(A){let z=[],X=Er(A.environment),ee=["opencode.json","opencode.jsonc"];for(let te of ee){let ae=gf(X,te);if(ff(ae))try{let le=mf(ae,"utf-8"),ye=At(le);if((JSON.parse(ye).plugin??[]).some((Ie)=>Ie.includes("cc-safety-net")))return{platform:"opencode",status:"configured",method:"plugin array",configPath:ae,errors:z.length>0?z:void 0}}catch(le){z.push(`Failed to parse ${te}: ${le instanceof Error?le.message:String(le)}`)}}return{platform:"opencode",status:"n/a",errors:z.length>0?z:void 0}}import{join as yf}from"node:path";function Go(A){return yf(A.home,".pi","agent","settings.json")}function Bo(A){if(typeof A!=="string")return!1;return A==="npm:cc-safety-net"||A.startsWith("npm:cc-safety-net@")}function sl(A){let z=Go(A.environment),X=Ot(z);if(X.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(X.kind==="missing")return{platform:"pi",status:"n/a"};let ee=ft(X.value,"packages");if(!Array.isArray(ee))return{platform:"pi",status:"n/a"};let te=ee.find((ye)=>Bo(typeof ye==="string"?ye:ft(ye,"source")));if(te===void 0)return{platform:"pi",status:"n/a"};let ae=ft(te,"extensions");if(Array.isArray(ae)&&ae.some((ye)=>typeof ye==="string"&&ye.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:z,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:z}}var hf={amp:Ms,"antigravity-cli":Hs,"claude-code":qs,codex:Vs,"copilot-cli":sa,cursor:ma,"gemini-cli":ga,"grok-build":Sa,"hermes-agent":Fa,"kimi-code":$n,openclaw:Ka,opencode:il,pi:sl};function bn(A,z,X){let ee={...X,cwd:z,environment:A};return Yn.map((te)=>vf(hf[te](ee)))}function vf(A){if(A.status==="not-inspected")return{platform:A.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:A.platform,detected:A.status!=="n/a",configured:A.status==="configured",inspectionStatus:A.status!=="n/a"?"verified":A.errors&&A.errors.length>0?"failed":"not-applicable",method:A.method,configPath:A.configPath,configPaths:A.configPaths,errors:A.errors}}import{join as bf}from"node:path";var Lf=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}]),wf=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([])})})}),kf={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 al(A){let z=bf(A.tmpdir,"cc-safety-net-self-test"),X=Lf.map((ee)=>{let te=O(A,u("self-test",{command:ee.command},{kind:"command",shell:"auto"},{configCwd:z,executionCwd:z},ee.command),{guard:{dependencies:{loadPolicySnapshot:()=>wf,getModes:()=>kf,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),ae=ee.expectBlocked?"blocked":"allowed",le=te.decision.kind==="deny"?"blocked":"allowed";return{command:ee.command,description:ee.description,expected:ae,actual:le,passed:ae===le,reason:te.decision.kind==="deny"?te.decision.reason:void 0,ruleId:te.decision.kind==="deny"?te.decision.ruleId:void 0}});return{passed:X.filter((ee)=>ee.passed).length,failed:X.filter((ee)=>!ee.passed).length,total:X.length,results:X}}function qo(A){let z=xt({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},A);if(Ht(z.errors))return null;return{json:z.flags.json,skipUpdateCheck:z.flags.skipUpdateCheck}}async function ll(A,z={}){let X=await Rn(!z.json,()=>{let ee=xf(A,z);return{ready:ee,finish:()=>ee}},()=>Sn(),{loadingMessage:"Checking system status…"});if(z.json)console.log(JSON.stringify(X,null,2));else Cf(X);return X.engineSelfTest.failed>0||X.findings.some((ee)=>ee.severity==="error")?1:0}async function xf(A,z){let X=z.cwd??process.cwd(),ee=await ir(),te=bn(A,X,{ampPluginListOutput:ee.ampPluginListOutput,codexPluginListOutput:ee.codexPluginListOutput,copilotCliVersion:ee.versions["copilot-cli"]}),ae=ts(A,X),le=ns(A),ye=L(A,{cwd:X}),he=ye.policy,ve=E(he,A.env),be=H(he,ve.capabilities),Ie=er(A,7),Xe=Is(A,X),et=z.skipUpdateCheck?{currentVersion:wt(),latestVersion:null,updateAvailable:!1}:await Wt(),Ee={hooks:te,engineSelfTest:al(A),userConfig:ae.userConfig,projectConfig:ae.projectConfig,configState:Ne(ye),effectiveRules:ae.effectiveRules,environment:le,effectiveSafety:{selectedPreset:he.safety.level??"standard",level:ve.effectiveLevel,capabilities:ve.capabilities,ruleOverrides:he.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(be).filter(([,at])=>at.source==="rule_override"&&at.override==="off"&&at.inheritedEnabled&&at.changesInherited).map(([at])=>at),ruleCounts:{stored:Object.keys(he.destructiveCommandRuleOverrides).length,effective:Object.values(be).filter((at)=>at.changesInherited).length},...ye.policyScopes?{policyScopes:ye.policyScopes}:{}},...Xe.length>0?{v2Leftovers:Xe}:{},posture:ys(A,ae.userConfig.path),activity:Ie,update:et,system:ee};return{...Ee,findings:os(Ee)}}function Cf(A){console.log(),console.log(ss(A.hooks)),console.log(),console.log(as(A.engineSelfTest)),console.log(),console.log(ls(A)),console.log(),console.log(cs(A.environment)),console.log(),console.log(ds(A)),console.log(),console.log(us(A.findings)),console.log(),console.log(ps(A.activity)),console.log(),console.log(ms(A.system)),console.log(),console.log(fs(A.update)),console.log(gs(A))}import{existsSync as Sf}from"node:fs";var Rf=/^[A-Za-z0-9_@%+=:,./-]+$/,cl="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Vo(A){let z=xt({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},A);if(Ht(z.errors))return console.error(cl),console.error("Pass -- before a command that starts with dashes."),null;if(z.values.cwd!==void 0&&!Sf(z.values.cwd))return console.error(`Error: --cwd path does not exist: ${z.values.cwd}`),null;let X=z.positionals.length===1?z.positionals[0]:z.positionals.map((ee)=>Rf.test(ee)?ee:`'${ee.replaceAll("'","'\\''")}'`).join(" ");if(!X)return console.error("Error: No command provided"),console.error(cl),null;return{json:z.flags.json,cwd:z.values.cwd,command:X}}function dl(A){if(A)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 ul(A,z){let ee=z-18;return[`${A.dtl}${A.dh.repeat(z)}${A.dtr}`,`${A.dv} Command Analysis${" ".repeat(ee)}${A.dv}`,`${A.dbl}${A.dh.repeat(z)}${A.dbr}`]}function zo(A){return JSON.stringify(A)}function pl(A,z=0){return`[${A.map((ee,te)=>is(ee,te,z)).join(",")}]`}function Fn(A,z,X=70){let ee=A.split(" "),te=[],ae="";for(let le of ee)if(ae&&ae.length+le.length+1>X)te.push(ae),ae=le;else ae=ae?`${ae} ${le}`:le;if(ae)te.push(ae);return te.map((le,ye)=>ye===0?le:`${z}${le}`)}function fl(A,z,X){let ee=[];switch(A.type){case"parse":return null;case"env-strip":return ee.push(""),ee.push(`STEP ${z} ${X.h} Strip environment variables`),ee.push(` Removed: ${A.envVars.map((te)=>`${te}=<redacted>`).join(", ")}`),ee.push(` Tokens: ${zo(A.output)}`),{lines:ee,incrementStep:!0};case"leading-tokens-stripped":return ee.push(""),ee.push(`STEP ${z} ${X.h} Strip wrappers`),ee.push(` Removed: ${A.removed.join(", ")}`),ee.push(` Tokens: ${zo(A.output)}`),{lines:ee,incrementStep:!0};case"shell-wrapper":return ee.push(""),ee.push(`STEP ${z} ${X.h} Detect shell wrapper`),ee.push(` Wrapper: ${A.wrapper} -c`),ee.push(` Inner: ${A.innerCommand}`),{lines:ee,incrementStep:!0};case"interpreter":{if(ee.push(""),ee.push(`STEP ${z} ${X.h} Detect interpreter`),ee.push(` Interpreter: ${A.interpreter}`),ee.push(` Code: ${A.codeArg}`),A.paranoidBlocked)ee.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:ee,incrementStep:!0}}case"busybox":return ee.push(""),ee.push(`STEP ${z} ${X.h} Busybox wrapper`),ee.push(` Subcommand: ${A.subcommand}`),{lines:ee,incrementStep:!0};case"transparent-wrapper":return ee.push(""),ee.push(`STEP ${z} ${X.h} Transparent wrapper`),ee.push(` Wrapper: ${A.wrapper}`),ee.push(` Tokens: ${zo(A.output)}`),{lines:ee,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(ee.push(""),ee.push(`STEP ${z} ${X.h} Match rules`),ee.push(` Rule: ${A.rule}()`),A.matched)ee.push(" Result: MATCHED");else ee.push(" Result: No match");return{lines:ee,incrementStep:!0}}case"worktree-relaxation":return ee.push(""),ee.push(`STEP ${z} ${X.h} Worktree relaxation`),ee.push(` Mode: ${o.worktree.name}`),ee.push(` Git cwd: ${A.gitCwd}`),ee.push(" Result: Allowed local discard in linked worktree"),{lines:ee,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(A.embeddedCommandFound)return ee.push(""),ee.push(`STEP ${z} ${X.h} Fallback scan`),ee.push(` Found: ${A.embeddedCommandFound}`),{lines:ee,incrementStep:!0};return null}case"custom-rules-check":{if(A.rulesChecked){if(ee.push(""),ee.push(`STEP ${z} ${X.h} Custom rules`),A.matched)ee.push(" Result: MATCHED");else ee.push(" Result: No match");return{lines:ee,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(A.matched)return ee.push(""),ee.push(`STEP ${z} ${X.h} Dangerous text check`),ee.push(` Token: ${A.token}`),ee.push(" Result: MATCHED"),{lines:ee,incrementStep:!0};return null}case"strict-unparseable":return ee.push(""),ee.push(`STEP ${z} ${X.h} Strict mode check`),ee.push(` Command: ${A.rawCommand}`),ee.push(" Result: ✗ UNPARSEABLE"),{lines:ee,incrementStep:!0};case"segment-skipped":return null;case"error":return ee.push(""),ee.push(`ERROR: ${A.message}`),{lines:ee,incrementStep:!1};default:return A}}function Jo(A,z){let X=dl(z?.asciiOnly??!1),ee=58,te=[],ae=1;te.push(...ul(X,58)),te.push("");let le=A.trace.steps.find((Ee)=>Ee.type==="error");if(le&&le.type==="error"){te.push("ERROR"),te.push(` ${le.message}`),te.push(""),te.push("RESULT"),te.push(` Status: ${A.result==="blocked"?dt.red("BLOCKED"):dt.green("ALLOWED")}`),te.push(""),te.push("CONFIG");let Ee=A.configSource??"none";return te.push(` Path: ${Ee}`),te.join(`
212
+ `)}let ye=A.trace.steps.find((Ee)=>Ee.type==="parse");if(ye&&ye.type==="parse"){te.push("INPUT"),te.push(` ${ye.input}`),te.push(""),te.push(`STEP ${ae} ${X.h} Split shell commands`),ae++;for(let Ee=0;Ee<ye.segments.length;Ee++){let at=ye.segments[Ee];if(at){let ct=Math.random();te.push(` Segment ${Ee+1}: ${pl(at,ct)}`)}}}let he=A.trace.segments,ve=he.length>1;for(let Ee of he){if(ve){te.push("");let pt="";if(ye&&ye.type==="parse"){let Zr=ye.segments[Ee.index];if(Zr)pt=Zr.join(" ")}let mt=54,gt=pt,ut=` Segment ${Ee.index+1}: `,vt=" ";if(pt){if(ut.length+pt.length+vt.length>mt){let Md=mt-ut.length-vt.length;gt=`${pt.substring(0,Md-1)}…`}}let Dt=pt?`${ut}${gt}${vt}`:` Segment ${Ee.index+1} `,jd=pt?`${ut}${dt.cyan(gt)}${vt}`:Dt,Ai=58-Dt.length,_i=Math.floor(Ai/2),Nd=Ai-_i;te.push(`${X.sh.repeat(_i)}${jd}${X.sh.repeat(Nd)}`)}if(Ee.steps.find((pt)=>pt.type==="segment-skipped")){te.push(""),te.push(" (skipped — prior segment blocked)");continue}let ct=!1,lt=!1;for(let pt of Ee.steps){let mt=fl(pt,ae,X);if(mt){if(lt=!0,pt.type==="recurse"){te.push("");let gt=" RECURSING ",ut=58-gt.length-4;te.push(` ${X.tl}${X.h}${gt}${X.h.repeat(ut)}`),te.push(` ${X.v}`),ct=!0;continue}for(let gt of mt.lines)if(ct)te.push(` ${X.v} ${gt}`);else te.push(gt);if(mt.incrementStep)ae++}}if(ct)te.push(` ${X.v}`),te.push(` ${X.bl}${X.h.repeat(56)}`),ct=!1;if(!lt)te.push(""),te.push(` ${dt.green("✓")} Allowed (no matching rules)`)}if(te.push(""),te.push("RESULT"),A.result==="blocked"){if(te.push(` Status: ${dt.red("BLOCKED")}`),A.customRule){if(te.push(` Rule: ${A.customRule.id}`),A.customRule.rulebook)te.push(` Rulebook: ${A.customRule.rulebook.name} ${A.customRule.rulebook.version}`);if(A.customRule.source)te.push(` Source: ${A.customRule.source}`);if(A.customRule.override)te.push(` Override: reason ${A.customRule.override.reason}`)}if(A.reason){let Ee=Fn(A.reason," ");te.push(` Reason: ${Ee[0]}`);for(let at=1;at<Ee.length;at++)te.push(Ee[at]??"")}}else te.push(` Status: ${dt.green("ALLOWED")}`);te.push(""),te.push("CONFIG");let be=A.configSource??"none",Ie=A.configValid?"":" (invalid)";te.push(` Path: ${be}${Ie}`);let Xe=A.safetyPresetScope;te.push(` Safety preset: ${A.selectedPreset??"standard"}${Xe?` (${nr(Xe)})`:""}`),te.push(` Effective capabilities: ${A.effectiveLevel}`);let et=Object.entries(A.destructiveCommandRuleOverrides??{});if(te.push(` Rule customizations: ${et.length}`),A.ruleActivation)te.push(` Rule activation: ${A.ruleActivation.id} — ${A.ruleActivation.enabled?"on":"off"} via ${A.ruleActivation.source}`);return te.join(`
213
+ `)}function Wo(A){return JSON.stringify(A,null,2)}import{resolve as _f}from"node:path";var Pf=["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 ml(A){let z=0,X={allocateSegment(){return z++},getNextSegmentIndex(){return z},recordGlobal(ee){A.record({kind:"step",scope:"global",step:ee})},recordSegment(ee,te=X.currentSegmentIndex){if(te===void 0)return;A.record({kind:"step",scope:"segment",segmentIndex:te,step:ee})}};return X}function gl(A={}){let z=[],X=A.maxEvents??512,ee={maxTextLength:A.maxTextLength??2048,maxListLength:A.maxListLength??128,maxObjectProperties:A.maxObjectProperties??A.maxListLength??128,maxDepth:A.maxDepth??16},te,ae=new Set;return{record(le){if(te)return;if(!le||z.length>=X)return;try{z.push(Zo(Ef(le,ee,ae)))}catch{}},finish(){if(te)return te;return te=Zo({events:Object.freeze(z)}),te}}}function Ef(A,z,X){if(A.kind!=="step")throw TypeError("invalid trace event");let{scope:ee,step:te}=A;Dr(te,X,z);let ae=Ko(te,z,X);if(ee==="global")return{kind:"step",scope:"global",step:ae};if(ee!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:A.segmentIndex,step:ae}}function Dr(A,z,X,ee=0,te=new WeakSet){if(typeof A==="string"){let ye=A.slice(0,X.maxTextLength);if(!He(ye))return;for(let he of Ze(ye))for(let ve of he.match(/[^\s"'()$]+/g)??[])z.add(yl(ve));return}if(!A||typeof A!=="object"||ee>=X.maxDepth||te.has(A))return;if(te.add(A),Array.isArray(A)){let ye=Math.min(A.length,X.maxListLength);for(let he=0;he<ye;he++)Dr(A[he],z,X,ee+1,te);return}let ae=0,le=new Set;for(let ye in A){if(!Object.hasOwn(A,ye))continue;if(ae>=X.maxObjectProperties)break;ae++,Dr(ye,z,X);let he=Yo(ye,X,z);if(le.has(he))continue;le.add(he),Dr(A[ye],z,X,ee+1,te)}}function Ko(A,z,X,ee=0,te=new WeakSet){if(typeof A==="string")return Yo(A,z,X);if(!A||typeof A!=="object")return A;if(ee>=z.maxDepth)return;if(te.has(A))return;if(te.add(A),Array.isArray(A)){let ye=[],he=Math.min(A.length,z.maxListLength);for(let ve=0;ve<he;ve++)ye.push(Ko(A[ve],z,X,ee+1,te));return ye}let ae={},le=0;for(let ye in A){if(!Object.hasOwn(A,ye))continue;if(le>=z.maxObjectProperties)break;le++;let he=Yo(ye,z,X);if(Object.hasOwn(ae,he))continue;Object.defineProperty(ae,he,{value:Ko(A[ye],z,X,ee+1,te),enumerable:!0,configurable:!0,writable:!0})}return ae}function Yo(A,z,X){let ee=A.slice(0,z.maxTextLength),te=He(ee)?Ge(ee):ee,ae=X.size>0?Af(te,X):te;return(Df(ae)?ke(ae):ae).slice(0,z.maxTextLength)}function Df(A){return A.includes("PRIVATE KEY")||A.includes("://")||A.includes("eyJ")||A.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(A)||A.length>=14&&Pf.some((z)=>A.includes(z))||A.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(A)}function Af(A,z){return A.replace(/[^\s"'()$]+/g,(X)=>z.has(yl(X))?"<redacted>":X)}function yl(A){let z=2166136261,X=2166136261;for(let ee=0;ee<A.length;ee++)z=Math.imul(z^A.charCodeAt(ee),16777619),X=Math.imul(X^A.charCodeAt(A.length-ee-1),16777619);return`${z>>>0}:${X>>>0}:${A.length}`}function Zo(A){if(A&&typeof A==="object"&&!Object.isFrozen(A)){for(let z of Object.values(A))Zo(z);Object.freeze(A)}return A}function jn(A,z={},X){let ee=_f(z.cwd??process.cwd()),te=z.policySnapshot??L(X,{cwd:ee,userConfigDir:z.userConfigDir}),ae=E(te.policy,X.env),le=Me({policySnapshot:te,effectiveCapabilities:ae.capabilities,strict:ae.strict,paranoidRm:ae.paranoidRm,paranoidInterpreters:ae.paranoidInterpreters,worktreeMode:ae.worktreeMode}),ye={effectiveLevel:le.effectiveLevel,selectedPreset:te.policy.safety.level??"standard",...te.policyScopes?{safetyPresetScope:te.policyScopes.levelScope}:{},effectiveCapabilities:le.effectiveCapabilities,destructiveCommandRuleOverrides:te.policy.destructiveCommandRuleOverrides},{configSource:he,configValid:ve}=$f(X,{cwd:ee,userConfigDir:z.userConfigDir});if(!A||!A.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:he,configValid:ve,...ye};let be=h(A,"auto");if(be.status==="limited")throw new y;let Ie=be.dialect==="powershell"?h(A,"posix"):be,Xe=st(Ie),et=gl(),Ee=ml(et);Ee.recordGlobal({type:"parse",input:A,segments:Xe.map((Dt)=>[...Dt])});let at=u("Bash",{command:A},{kind:"command",shell:"auto"},{configCwd:ee,executionCwd:ee},A),ct=U(at,{environment:X,trace:Ee,dependencies:{loadPolicySnapshot:()=>te}}),lt=ct.decision.kind==="deny"?ct.decision:null;if(lt&&(ct.stage==="policy-protection"||ct.stage==="secret-protection")){let Dt=Tf(lt);return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Dt.rule,matched:!0,reason:lt.reason}]}]},result:"blocked",reason:k(lt.reason),segment:k(hl(lt,A)),...Dt.ruleId?{ruleId:k(Dt.ruleId)}:{},configSource:he,configValid:ve,...ye}}let pt=Ee.getNextSegmentIndex();if(lt&&pt>0&&pt<Xe.length)Ee.recordSegment({type:"segment-skipped",index:pt,reason:"prior-segment-blocked"},pt);let mt=et.finish(),gt=lt?.ruleId??If(at,te,ae,X),ut=G.find((Dt)=>Dt.id===gt&&Dt.activationCapability),vt=ut?le.policy.effectiveDestructiveCommandRules[ut.id]:void 0;return{trace:Ff(mt),result:lt?"blocked":"allowed",reason:lt?k(lt.reason):void 0,segment:lt?k(hl(lt,A)):void 0,ruleId:lt?.ruleId?k(lt.ruleId):void 0,customRule:Of(jf(lt?.ruleId,te)),configSource:he,configValid:ve,...ye,...ut&&vt?{ruleActivation:{id:ut.id,...vt}}:{}}}function hl(A,z){return A.evidence?.segment??z}function Tf(A){if(A.reason===Fe)return{ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};if(A.reason===$e)return{ruleId:"policy-apply-protection",rule:"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts"};if(A.reason===b)return{ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};return{ruleId:A.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"}}function $f(A,z){let X=M(z.cwd),ee=F(A,z),te=q(A,{cwd:z.cwd,userConfigDir:z.userConfigDir});try{if(n(te.projectConfigTarget)!==null){if(Jt(te.projectConfigTarget).errors.length===0)return{configSource:X,configValid:!0};return{configSource:X,configValid:!1}}}catch(ae){if(ae instanceof r)return{configSource:X,configValid:!1};throw ae}try{if(n(te.userConfigTarget)!==null){let ae=Jt(te.userConfigTarget);return{configSource:ee,configValid:ae.errors.length===0}}return{configSource:null,configValid:!0}}catch(ae){if(ae instanceof r)return{configSource:ee,configValid:!1};throw ae}}function If(A,z,X,ee){let te=z.policy,ae=Le({...te,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...te.destructiveCommandRuleOverrides,...Object.fromEntries(G.flatMap((ye)=>ye.activationCapability?[[ye.id,"on"]]:[]))}},z.state==="degraded"?{diagnostics:z.diagnostics,reason:z.reason}:void 0),le=U(A,{environment:ee,dependencies:{loadPolicySnapshot:()=>ae,getModes:()=>({...X,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return le.decision.kind==="deny"?le.decision.ruleId:void 0}function Of(A){if(!A)return;return{id:k(A.id),...A.rulebook?{rulebook:{name:k(A.rulebook.name),version:k(A.rulebook.version)}}:{},...A.source?{source:k(A.source)}:{},...A.override?{override:{type:"reason",reason:k(A.override.reason)}}:{}}}function Ff(A){let z=A.events.flatMap((ee)=>ee.kind==="step"&&ee.scope==="global"?[ee.step]:[]),X=new Map;for(let ee of A.events){if(ee.kind!=="step"||ee.scope!=="segment")continue;let te=X.get(ee.segmentIndex)??{index:ee.segmentIndex,steps:[]};te.steps.push(ee.step),X.set(ee.segmentIndex,te)}return{steps:z,segments:[...X.values()]}}function jf(A,z){let X=A?.replace(/^custom\./,"");if(!X||!z.policy.rules.some((ee)=>ee.name===X))return;return z.ruleMetadata[X]??Object.freeze({id:X})}function vl(A){return new Promise((z)=>{process.stdout.write(`${A}
214
+ `,()=>z())})}async function bl(A,z){let X=Vo(z);if(!X)return 1;try{let ee=jn(X.command,{cwd:X.cwd},A),te=!!process.env.NO_COLOR||!process.stdout.isTTY;return await vl(X.json?Wo(ee):Jo(ee,{asciiOnly:te})),0}catch(ee){let te=Nf(ee instanceof p?ee.cause:ee);if(te===void 0)throw ee;if(X.json)return await vl(JSON.stringify({error:te})),1;return console.error(te),1}}function Nf(A){if(A instanceof y)return A.message;if(A instanceof f)return A.message;if(A instanceof s&&a[A.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var Ll="2.4.2",It=" ",nn="cc-safety-net";function wl(A){return A.argument?`${A.flags} ${A.argument}`:A.flags}function Mf(A){return Math.max(...A.map((z)=>wl(z).length))}function Hf(A){return Math.max(...A.map((z)=>z.usage.length))}function Uf(A){return Math.max(...A.map((z)=>`${nn} ${z.usage}`.length))}function Gf(A,z){let X=`${nn} ${A.usage}`;return`${It}${X.padEnd(z+2)}${A.description}`}function qt(A,z){return`${It}${A.padEnd(Math.max(40,A.length+2))}${z}`}function Ln(A,z=console.log){let X=[];if(X.push(`${nn} ${A.name}`),X.push(""),X.push(`${It}${A.description}`),X.push(""),X.push("USAGE:"),X.push(`${It}${nn} ${A.usage}`),X.push(""),A.subcommands&&A.subcommands.length>0){X.push("SUBCOMMANDS:");let ee=Hf(A.subcommands);for(let te of A.subcommands)X.push(`${It}${te.usage.padEnd(ee+2)}${te.description}`);X.push("")}if(A.options.length>0){X.push("OPTIONS:");let ee=Mf(A.options);for(let te of A.options){let ae=wl(te),le=te.default?`${te.description} (default: ${te.default})`:te.description;X.push(`${It}${ae.padEnd(ee+2)}${le}`)}X.push("")}if(A.examples&&A.examples.length>0){X.push("EXAMPLES:");for(let ee of A.examples)X.push(`${It}${ee}`)}z(X.join(`
215
+ `))}function Xo(){let A=Uf(Xn),z=[];z.push(`${nn} v${Ll}`),z.push(""),z.push("Blocks destructive commands and secret access."),z.push(""),z.push("COMMANDS:");for(let X of Xn)z.push(Gf(X,A));z.push(""),z.push("GLOBAL OPTIONS:"),z.push(`${It}-h, --help Show help (use with command for command-specific help)`),z.push(`${It}-V, --version Show version`),z.push(""),z.push("HELP:"),z.push(`${It}${nn} help <command> Show help for a specific command`),z.push(`${It}${nn} <command> --help Show help for a specific command`),z.push(""),z.push("ENVIRONMENT VARIABLES:"),z.push(qt(`${o.level.name}=standard|strict|paranoid`,"Set session safety level")),z.push(qt(`${o.worktree.name}=1`,"Allow local git discards in linked worktrees")),z.push(qt(`${o.debug.name}=1`,"Print diagnostic messages to stderr")),z.push(qt(`${o.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),z.push(qt("CC_SAFETY_NET_HOME","Override rule config home directory")),z.push(""),z.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),z.push(qt(`${o.strict.name}=1`,"Force safety.overrides.fail_closed on")),z.push(qt(`${o.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),z.push(qt(`${o.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),z.push(qt(`${o.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),z.push(""),z.push("Documentation: https://ccsafetynet.com/docs"),console.log(z.join(`
216
+ `))}function kl(){console.log(Ll)}function Nn(A,z=console.log){let X=Qn(A);if(!X)return!1;if(X.name.toLowerCase()!==A.toLowerCase())return!1;return Ln(X,z),!0}import{existsSync as ui,readFileSync as vc}from"node:fs";import{join as ci}from"node:path";import*as Kt from"node:readline";function Bf(A){return A==="install"?"Install":"Uninstall"}function qf(A){return A==="install"?"Installing":"Uninstalling"}function Vf(A){return A==="install"?"into":"from"}function Sl(A){return A?.available===!0}function zf(A,z){let X=new Set(z);return A.filter((ee)=>X.has(ee.target)).map((ee)=>ee.target)}function xl(A,z,X){if(A.length===0||A.every((ee)=>!ee.available))return z;return Array.from({length:A.length},(ee,te)=>te+1).map((ee)=>(z+ee*X+A.length)%A.length).find((ee)=>Sl(A[ee]))}function Jf(A,z,X){if(X.ctrl&&X.name==="c")return"interrupt";if(X.name==="escape"||z==="q")return"abort";if(A==="install"&&(z==="u"||z==="U"))return"update";if(X.name==="up"||z==="k")return"up";if(X.name==="down"||z==="j")return"down";if(X.name==="space"||z===" ")return"toggle";if(X.name==="return"||X.name==="enter")return"confirm";return null}function Wf(A){return{cursor:A.findIndex((z)=>z.available),selected:[]}}function Kf(A,z,X){if(X==="confirm"||X==="update"||X==="abort"||X==="interrupt")return{state:A,done:X};if(X==="up")return{state:{...A,cursor:xl(z,A.cursor,-1)}};if(X==="down")return{state:{...A,cursor:xl(z,A.cursor,1)}};let ee=z[A.cursor];if(!Sl(ee))return{state:A};let te=A.selected.includes(ee.target)?A.selected.filter((ae)=>ae!==ee.target):zf(z,[...A.selected,ee.target]);return{state:{...A,selected:te}}}var Rl="◉",Pl="◯",El=">",Dl=" ";function Yf(A,z,X,ee={}){let te=ee.color!==!1,ae=te?dt.dim:(he)=>he,le=te?dt.green:(he)=>he,ye=te?dt.bold:(he)=>he;return["",`${Bf(A)} CC Safety Net ${Vf(A)}:`,"",...z.map((he,ve)=>{let be=X.selected.includes(he.target),Ie=ve===X.cursor,Xe=be?Rl:Pl,et=Ie?El:Dl,Ee=he.available?"":` (${he.unavailableReason??"not installed"})`,at=`${Xe} ${he.label}${Ee}`,ct=!he.available?ae(at):be?le(at):Ie?ye(at):at;return`${et} ${ct}`}),"",A==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":z.some((he)=>he.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${A}. q/Esc: close`].join(`
217
+ `)}var Cl=["global-hook","plugin"];function Zf(A,z,X={}){let ee=X.color!==!1?dt.bold:(ae)=>ae;return["","Install the Kimi Code integration as:","",...[`Global hook — ${z?"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((ae,le)=>{let ye=le===A,he=`${ye?Rl:Pl} ${ae}`;return`${ye?El:Dl} ${ye?ee(he):he}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
218
+ `)}function Al(A){let{input:z,output:X}=A;Kt.emitKeypressEvents(z);let ee=z.isRaw===!0;z.setRawMode(!0),z.resume();let te=0,ae=()=>{if(te===0)return;Kt.moveCursor(X,0,-te),Kt.cursorTo(X,0),Kt.clearScreenDown(X)},le=()=>{ae();let ye=A.render();X.write(`${ye}
219
+ `),te=ye.split(`
220
+ `).length};return new Promise((ye)=>{let he=(be)=>{z.off("keypress",ve),z.setRawMode(ee),z.pause(),ae(),ye(be)};function ve(be,Ie){A.onKey(be,Ie,{finish:he,draw:le})}z.on("keypress",ve),le()})}function _l(A={}){let z=0;return Al({input:A.input??process.stdin,output:A.output??process.stdout,render:()=>Zf(z,A.globalHookInstalled===!0),onKey:(X,ee,te)=>{if(ee.ctrl&&ee.name==="c"){te.finish(null),(A.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(ee.name==="escape"||X==="q")return te.finish(null);if(ee.name==="return"||ee.name==="enter")return te.finish(Cl[z]);if(ee.name==="up"||ee.name==="down"||X==="k"||X==="j")z=(z+1)%Cl.length,te.draw()}})}function Qo(A=process.stdin,z=process.stdout){return Boolean(A.isTTY&&z.isTTY&&typeof A.setRawMode==="function")}function Tl(A,z,X={}){let ee=X.output??process.stdout,te=Wf(z);return Al({input:X.input??process.stdin,output:ee,render:()=>Yf(A,z,te),onKey:(ae,le,ye)=>{let he=Jf(A,ae,le);if(!he)return;let ve=Kf(te,z,he);if(te=ve.state,ve.done==="interrupt"){ye.finish(null),(X.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(ve.done==="abort")return ye.finish(null);if(ve.done==="update")return ye.finish("update");if(ve.done==="confirm"){if(te.selected.length===0){ee.write("\x07"),ye.draw();return}ye.finish([...te.selected]),ee.write(`${qf(A)} selected integrations...
221
+ `);return}ye.draw()}})}import{existsSync as $l,lstatSync as Qf,mkdirSync as em,mkdtempSync as tm,readdirSync as nm,readFileSync as kn,rmSync as _r}from"node:fs";import{basename as rm,dirname as om,join as Et}from"node:path";import{fileURLToPath as im}from"node:url";var ei="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",rn="cc-safety-net",on="cc-safety-net/index.ts";import{spawn as Xf}from"node:child_process";var ti=(A,z)=>{let X=Xt([...A],process.env);return new Promise((ee)=>{let te=Xf(X.cmd,X.args,{cwd:z,stdio:["ignore","pipe","pipe"]}),ae=$o(te),le=!1,ye=setTimeout(()=>{le=!0,te.kill()},120000);te.on("error",(he)=>{clearTimeout(ye),ee({status:null,errorCode:he.code,stdout:ae.stdout,stderr:[he.message,ae.stderr].filter(Boolean).join(`
222
+ `)})}),te.on("close",(he)=>{clearTimeout(ye),ee({status:le?null:he,errorCode:le?"ETIMEDOUT":void 0,stdout:ae.stdout,stderr:ae.stderr})})})};var wn="cc-safety-net.ts",ni=Et("amp",on);function sm(A){return Et(A.home,".config","amp","plugins","cc-safety-net.ts")}function am(){let A=om(im(import.meta.url));return[Et(A,ni),Et(A,"..",ni),Et(A,"..","..","..","dist",ni)]}function lm(A=am()){let z=A.find((X)=>$l(X)&&Qf(X).isFile());if(!z)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return z}function Il(A){try{return JSON.parse(A)}catch{return}}function Tr(A){return A.subarray(0,Buffer.byteLength(ei)).toString("utf-8")===ei}async function Mn(A,z,X){let ee=await A(z,X);if(ee.status===0)return ee;throw Error([`Failed to run ${z.join(" ")}${ee.status===null?"":` (exit ${ee.status})`}.`,[ee.stdout,ee.stderr].filter(Boolean).join(`
223
223
  `).trim()].filter(Boolean).join(`
224
- `))}async function Xl(j){let K=await j(["amp","plugins","repositories","--json"]);if(K.status===null)throw Error(`${K.errorCode==="ENOENT"?'Amp CLI not found. Install the amp CLI, sign in with "amp login", and rerun install --amp.':`amp plugins repositories --json did not finish (${K.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
225
- ${K.stderr}`.trim());if(K.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${K.status}). Sign in with "amp login" and rerun install --amp.
226
- ${[K.stdout,K.stderr].filter(Boolean).join(`
227
- `)}`.trim());let te=Zl(K.stdout),re=(Array.isArray(te)?te:[]).filter((oe)=>wt(oe,"scope")==="user"&&wt(oe,"exists")===!0&&wt(oe,"viewerCanWrite")===!0).map((oe)=>wt(oe,"cloneRef")).find((oe)=>typeof oe==="string"&&oe.length>0);if(!re)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return re}async function Ql(j,K,te){let re=km(Ot(K.tmpdir,"cc-safety-net-amp-"));try{return await nr(j,["amp","clone","user-plugins",re]),await te(re)}finally{Vr(re,{recursive:!0,force:!0})}}function yi(j){return`rerun ${j==="overwrite"?"install":"uninstall"} --amp`}function ec(j,K,te){let re=Ot(j,K),oe=Pt(re);if(!oe)return;if(oe.isSymbolicLink()||!oe.isFile())throw Error(`Refusing to ${te} ${K} in your Amp personal plugins repository: not a regular file. Remove it there and ${yi(te)}.`);let ce=In(re);if(zr(ce))return ce;throw Error(`Refusing to ${te} unmanaged file ${K} in your Amp personal plugins repository. Remove it there and ${yi(te)}.`)}function tc(j,K){let te=Ot(j,mn),re=Pt(te);if(!re)return;if(re.isSymbolicLink()||!re.isDirectory())throw Error(`Refusing to ${K} ${mn} in your Amp personal plugins repository: not a regular directory. Remove it there and ${yi(K)}.`);return ec(j,gn,K)}function Am(j){let K=Ot(j,Tn),te=Pt(K);if(!te||te.isSymbolicLink()||!te.isFile())return;let re=In(K);return zr(re)?re:void 0}async function nc(j,K,te,re){if(await nr(j,te,K),(await nr(j,["git","status","--porcelain"],K)).stdout.trim()==="")return!1;return await nr(j,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",re],K),await nr(j,["git","push","origin","HEAD"],K),!0}function qr(j,K){_m(j,K),Tm(j,K)}function rc(j,K){if(K==="keep")return;throw Error(`Local Amp plugin ${j} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function _m(j,K){let te=Pm(j),re=Pt(te);if(!re)return;if(!re.isSymbolicLink()&&re.isFile()&&zr(In(te))){Vr(te);return}rc(te,K)}function Tm(j,K){let te=Ot(j.home,".config","amp","plugins",mn),re=Pt(te);if(!re)return;if(!re.isSymbolicLink()&&re.isDirectory()&&Im(te)){Vr(te,{recursive:!0});return}rc(te,K)}function Im(j){let K=Cm(gn);if(xm(j).join("\x00")!==K)return!1;let te=Ot(j,K),re=Pt(te);return!!re&&!re.isSymbolicLink()&&re.isFile()&&zr(In(te))}function $m(j){let K=d(j);if(!Yl(K))return"";let te=Zl(In(K,"utf-8"));if(!te||typeof te!=="object"||Array.isArray(te))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(h(te,j.home))};
228
- `}async function oc(j,K=Dm(),te=gi){let re=Buffer.concat([In(K),Buffer.from($m(j),"utf-8")]),oe=await Xl(te);return Ql(te,j,async(ce)=>{let de=`${oe}/${mn}`,we=tc(ce,"overwrite"),xe=ec(ce,Tn,"overwrite");if(we?.equals(re)&&!xe)return qr(j,"fail"),{path:de,alreadyInstalled:!0};if(wm(Ot(ce,mn),{recursive:!0}),Dt(Ot(ce,gn),re),xe)Vr(Ot(ce,Tn));let Ce=await nc(te,ce,["git","add","--",gn,...xe?[Tn]:[]],`chore: update cc-safety-net plugin to v${Et()}`);return qr(j,"fail"),{path:de,alreadyInstalled:!Ce}})}async function ic(j,K=gi){let te=await Xl(K);return Ql(K,j,async(re)=>{let oe=tc(re,"remove"),ce=Am(re),de=`${te}/${ce&&!oe?Tn:mn}`;if(!oe&&!ce)return qr(j,"keep"),{path:de,alreadyInstalled:!1};return await nc(K,re,["git","rm","--",...oe?[gn]:[],...ce?[Tn]:[]],`chore: remove cc-safety-net plugin v${Et()}`),qr(j,"keep"),{path:de,alreadyInstalled:!0}})}import{existsSync as sc,mkdirSync as Om,readFileSync as jm}from"node:fs";import{dirname as Fm}from"node:path";var hi=zt["antigravity-cli"],yn="cc-safety-net";function hn(j){return Boolean(j)&&typeof j==="object"&&!Array.isArray(j)}function Wr(){return{PreToolUse:[{hooks:[{type:"command",command:hi,timeout:30}]}]}}function ac(j){try{let K=JSON.parse(jm(j,"utf-8"));if(!K||typeof K!=="object"||Array.isArray(K))throw Error("Antigravity hooks config must be a JSON object");return K}catch(K){if(K instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${j}: ${K.message}`);throw K}}function lc(j){let K=j[yn];if(K===void 0){let re=Wr();return j[yn]=re,{definition:re,preToolUse:re.PreToolUse??[]}}if(!hn(K))throw Error(`Antigravity hooks config entry "${yn}" must be an object`);let te=Array.isArray(K.PreToolUse)?K.PreToolUse:[];return K.PreToolUse=te,{definition:K,preToolUse:te}}function cc(j){if(!Array.isArray(j.PreToolUse))return!1;return j.PreToolUse.some((K)=>hn(K)&&Array.isArray(K.hooks)&&K.hooks.some((te)=>hn(te)&&te.command===hi))}function Nm(j){return Object.values(j).some((K)=>hn(K)&&K.enabled!==!1&&cc(K))}function Mm(j){if(j[yn]===void 0)return!1;let K=lc(j);if(K.definition.enabled!==!1||!cc(K.definition))return!1;return K.definition.enabled=!0,!0}function Hm(j){if(j[yn]===void 0){j[yn]=Wr();return}let K=lc(j);K.definition.enabled=!0,K.preToolUse.push(Wr().PreToolUse?.[0]??{hooks:[]})}function Um(j){let K=!1;for(let te of Object.values(j)){if(!hn(te)||!Array.isArray(te.PreToolUse))continue;te.PreToolUse=te.PreToolUse.flatMap((re)=>{if(!hn(re)||!Array.isArray(re.hooks))return[re];let oe=re.hooks.filter((ce)=>!hn(ce)||ce.command!==hi);if(oe.length!==re.hooks.length)K=!0;return oe.length===0?[]:[{...re,hooks:oe}]})}return K}function Jr(j,K){Dt(j,`${JSON.stringify(K,null,2)}
229
- `)}function dc(j){let K=qn(j.home);if(Om(Fm(K),{recursive:!0}),!sc(K))return Jr(K,{[yn]:Wr()}),{path:K,alreadyInstalled:!1};let te=ac(K);if(Nm(te))return{path:K,alreadyInstalled:!0};if(Mm(te))return Jr(K,te),{path:K,alreadyInstalled:!1};return Hm(te),Jr(K,te),{path:K,alreadyInstalled:!1}}function uc(j){let K=qn(j.home);if(!sc(K))return{path:K,alreadyInstalled:!1};let te=ac(K);if(!Um(te))return{path:K,alreadyInstalled:!1};return Jr(K,te),{path:K,alreadyInstalled:!0}}import{existsSync as Gm,readdirSync as Bm,rmSync as qm}from"node:fs";import{join as Vm}from"node:path";function pc(j,K=process.platform,te){if(!Gm(j))return;let re=K==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);Bm(j).filter((oe)=>oe!==te&&re.test(oe)).forEach((oe)=>{qm(Vm(j,oe),{recursive:!0,force:!0})})}import{spawn as zm}from"node:child_process";var Wt=Nt.map((j)=>({target:j.id,flag:j.flag,label:St(j.id),probeCommand:j.probeCommand}));function vi(j){let K=new Set(j);return Wt.map((te)=>te.target).filter((te)=>K.has(te))}async function fc(j,K){for(let te of j)await K(te)}var Jm=5000;function bi(j,K=Jm){return new Promise((te)=>{let re=cn([...j],process.env),oe=zm(re.cmd,re.args,{env:process.env,stdio:"ignore"}),ce=!1,de=(xe)=>{if(ce)return;ce=!0,clearTimeout(we),te(xe)},we=setTimeout(()=>{oe.kill(),de(!1)},K);oe.on("error",()=>de(!1)),oe.on("close",(xe)=>de(xe===0))})}function mc(j=bi,K={}){let te=new Set(K.configuredTargets??[]);return Promise.all(Wt.map(async(re)=>({target:re.target,flag:re.flag,label:re.label,...yc(K.action,await j(re.probeCommand),te.has(re.target))})))}function gc(j,K){let te=new Set(K.configuredTargets??[]);return j.map((re)=>({...re,...yc(K.action,re.available,te.has(re.target))}))}function yc(j,K,te){if(j==="uninstall")return te?{available:!0}:{available:!1,unavailableReason:"not installed"};if(j==="install"&&te)return{available:!1,unavailableReason:"already installed"};if(!K)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}import{existsSync as hc,readdirSync as Wm,rmSync as Km}from"node:fs";import{join as $n}from"node:path";function Kr(j,K=process.platform){let te=$n(j.env.get("npm_config_cache")||(K==="win32"?$n(j.env.get("LOCALAPPDATA")||$n(j.home,"AppData","Local"),"npm-cache"):$n(j.home,".npm")),"_npx");if(!hc(te))return;Wm(te).filter((re)=>hc($n(te,re,"node_modules","cc-safety-net"))).forEach((re)=>{Km($n(te,re),{recursive:!0,force:!0})})}import{existsSync as xc,mkdirSync as Zm,readFileSync as Cc}from"node:fs";import{dirname as Xm,join as kc}from"node:path";function Ym(j,K){if(j[K]!=="#")return K;let te=j.indexOf(`
230
- `,K+1);return te===-1?j.length:te+1}function Li(j,K,te){let re=new RegExp(`^(\\s*)${K}\\s*=\\s*\\[`),oe=0;for(let ce of j.split(`
231
- `)){if(/^\s*\[/.test(ce))return;let de=re.exec(ce);if(de){let we=oe+de[0].lastIndexOf("[");return{start:we,end:_o(j,we,{skipComment:Ym,...te})}}oe+=ce.length+1}return}function vc(j,K,te){let re=j.slice(0,K.end).trimEnd(),oe=ca(j,K.end),ce=oe===""?" ":`${oe} `,de=!re.endsWith("[")&&!re.endsWith(",");return`${re}${de?",":""}
232
- ${ce}${te}${j.slice(K.end)}`}function bc(j,K,te){let re=j.indexOf(te,K.start);if(re===-1||re>K.end)return j;return Pr(j,{start:re,end:re+te.length})}function Lc(j,K){let te=new RegExp(`^\\s*${K}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),re=j.split(`
233
- `),oe=re.findIndex((we)=>/^\s*\[/.test(we)),ce=oe===-1?re:re.slice(0,oe),de=oe===-1?[]:re.slice(oe);return[...ce.filter((we)=>!te.test(we)),...de].join(`
234
- `)}function wc(j,K,te){let re=new RegExp(`^\\s*\\[\\[${K}]]\\s*$`,"m");return j.split(/(?=^\s*\[)/m).filter((oe)=>!re.test(oe)||!oe.includes(te)).join("").trimEnd()}var rr=zt["kimi-code"],wi=`[[hooks]]
224
+ `))}async function Ol(A){let z=await A(["amp","plugins","repositories","--json"]);if(z.status===null)throw Error(`${z.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 (${z.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
225
+ ${z.stderr}`.trim());if(z.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${z.status}). Sign in with "amp login" and rerun install --amp.
226
+ ${[z.stdout,z.stderr].filter(Boolean).join(`
227
+ `)}`.trim());let X=Il(z.stdout),ee=(Array.isArray(X)?X:[]).filter((te)=>ft(te,"scope")==="user"&&ft(te,"exists")===!0&&ft(te,"viewerCanWrite")===!0).map((te)=>ft(te,"cloneRef")).find((te)=>typeof te==="string"&&te.length>0);if(!ee)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 ee}async function Fl(A,z,X){let ee=tm(Et(z.tmpdir,"cc-safety-net-amp-"));try{return await Mn(A,["amp","clone","user-plugins",ee]),await X(ee)}finally{_r(ee,{recursive:!0,force:!0})}}function ri(A){return`rerun ${A==="overwrite"?"install":"uninstall"} --amp`}function jl(A,z,X){let ee=Et(A,z),te=Lt(ee);if(!te)return;if(te.isSymbolicLink()||!te.isFile())throw Error(`Refusing to ${X} ${z} in your Amp personal plugins repository: not a regular file. Remove it there and ${ri(X)}.`);let ae=kn(ee);if(Tr(ae))return ae;throw Error(`Refusing to ${X} unmanaged file ${z} in your Amp personal plugins repository. Remove it there and ${ri(X)}.`)}function Nl(A,z){let X=Et(A,rn),ee=Lt(X);if(!ee)return;if(ee.isSymbolicLink()||!ee.isDirectory())throw Error(`Refusing to ${z} ${rn} in your Amp personal plugins repository: not a regular directory. Remove it there and ${ri(z)}.`);return jl(A,on,z)}function cm(A){let z=Et(A,wn),X=Lt(z);if(!X||X.isSymbolicLink()||!X.isFile())return;let ee=kn(z);return Tr(ee)?ee:void 0}async function Ml(A,z,X,ee){if(await Mn(A,X,z),(await Mn(A,["git","status","--porcelain"],z)).stdout.trim()==="")return!1;return await Mn(A,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",ee],z),await Mn(A,["git","push","origin","HEAD"],z),!0}function Ar(A,z){dm(A,z),um(A,z)}function Hl(A,z){if(z==="keep")return;throw Error(`Local Amp plugin ${A} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function dm(A,z){let X=sm(A),ee=Lt(X);if(!ee)return;if(!ee.isSymbolicLink()&&ee.isFile()&&Tr(kn(X))){_r(X);return}Hl(X,z)}function um(A,z){let X=Et(A.home,".config","amp","plugins",rn),ee=Lt(X);if(!ee)return;if(!ee.isSymbolicLink()&&ee.isDirectory()&&pm(X)){_r(X,{recursive:!0});return}Hl(X,z)}function pm(A){let z=rm(on);if(nm(A).join("\x00")!==z)return!1;let X=Et(A,z),ee=Lt(X);return!!ee&&!ee.isSymbolicLink()&&ee.isFile()&&Tr(kn(X))}function fm(A){let z=d(A);if(!$l(z))return"";let X=Il(kn(z,"utf-8"));if(!X||typeof X!=="object"||Array.isArray(X))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(x(X,A.home))};
228
+ `}async function Ul(A,z=lm(),X=ti){let ee=Buffer.concat([kn(z),Buffer.from(fm(A),"utf-8")]),te=await Ol(X);return Fl(X,A,async(ae)=>{let le=`${te}/${rn}`,ye=Nl(ae,"overwrite"),he=jl(ae,wn,"overwrite");if(ye?.equals(ee)&&!he)return Ar(A,"fail"),{path:le,alreadyInstalled:!0};if(em(Et(ae,rn),{recursive:!0}),kt(Et(ae,on),ee),he)_r(Et(ae,wn));let ve=await Ml(X,ae,["git","add","--",on,...he?[wn]:[]],`chore: update cc-safety-net plugin to v${wt()}`);return Ar(A,"fail"),{path:le,alreadyInstalled:!ve}})}async function Gl(A,z=ti){let X=await Ol(z);return Fl(z,A,async(ee)=>{let te=Nl(ee,"remove"),ae=cm(ee),le=`${X}/${ae&&!te?wn:rn}`;if(!te&&!ae)return Ar(A,"keep"),{path:le,alreadyInstalled:!1};return await Ml(z,ee,["git","rm","--",...te?[on]:[],...ae?[wn]:[]],`chore: remove cc-safety-net plugin v${wt()}`),Ar(A,"keep"),{path:le,alreadyInstalled:!0}})}import{existsSync as Bl,mkdirSync as mm,readFileSync as gm}from"node:fs";import{dirname as ym}from"node:path";var oi=jt["antigravity-cli"],sn="cc-safety-net";function an(A){return Boolean(A)&&typeof A==="object"&&!Array.isArray(A)}function Ir(){return{PreToolUse:[{hooks:[{type:"command",command:oi,timeout:30}]}]}}function ql(A){try{let z=JSON.parse(gm(A,"utf-8"));if(!z||typeof z!=="object"||Array.isArray(z))throw Error("Antigravity hooks config must be a JSON object");return z}catch(z){if(z instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${A}: ${z.message}`);throw z}}function Vl(A){let z=A[sn];if(z===void 0){let ee=Ir();return A[sn]=ee,{definition:ee,preToolUse:ee.PreToolUse??[]}}if(!an(z))throw Error(`Antigravity hooks config entry "${sn}" must be an object`);let X=Array.isArray(z.PreToolUse)?z.PreToolUse:[];return z.PreToolUse=X,{definition:z,preToolUse:X}}function zl(A){if(!Array.isArray(A.PreToolUse))return!1;return A.PreToolUse.some((z)=>an(z)&&Array.isArray(z.hooks)&&z.hooks.some((X)=>an(X)&&X.command===oi))}function hm(A){return Object.values(A).some((z)=>an(z)&&z.enabled!==!1&&zl(z))}function vm(A){if(A[sn]===void 0)return!1;let z=Vl(A);if(z.definition.enabled!==!1||!zl(z.definition))return!1;return z.definition.enabled=!0,!0}function bm(A){if(A[sn]===void 0){A[sn]=Ir();return}let z=Vl(A);z.definition.enabled=!0,z.preToolUse.push(Ir().PreToolUse?.[0]??{hooks:[]})}function Lm(A){let z=!1;for(let X of Object.values(A)){if(!an(X)||!Array.isArray(X.PreToolUse))continue;X.PreToolUse=X.PreToolUse.flatMap((ee)=>{if(!an(ee)||!Array.isArray(ee.hooks))return[ee];let te=ee.hooks.filter((ae)=>!an(ae)||ae.command!==oi);if(te.length!==ee.hooks.length)z=!0;return te.length===0?[]:[{...ee,hooks:te}]})}return z}function $r(A,z){kt(A,`${JSON.stringify(z,null,2)}
229
+ `)}function Jl(A){let z=Pn(A.home);if(mm(ym(z),{recursive:!0}),!Bl(z))return $r(z,{[sn]:Ir()}),{path:z,alreadyInstalled:!1};let X=ql(z);if(hm(X))return{path:z,alreadyInstalled:!0};if(vm(X))return $r(z,X),{path:z,alreadyInstalled:!1};return bm(X),$r(z,X),{path:z,alreadyInstalled:!1}}function Wl(A){let z=Pn(A.home);if(!Bl(z))return{path:z,alreadyInstalled:!1};let X=ql(z);if(!Lm(X))return{path:z,alreadyInstalled:!1};return $r(z,X),{path:z,alreadyInstalled:!0}}import{existsSync as wm,readdirSync as km,rmSync as xm}from"node:fs";import{join as Cm}from"node:path";function Kl(A,z=process.platform,X){if(!wm(A))return;let ee=z==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);km(A).filter((te)=>te!==X&&ee.test(te)).forEach((te)=>{xm(Cm(A,te),{recursive:!0,force:!0})})}import{spawn as Sm}from"node:child_process";var Mt=Tt.map((A)=>({target:A.id,flag:A.flag,label:bt(A.id),probeCommand:A.probeCommand}));function ii(A){let z=new Set(A);return Mt.map((X)=>X.target).filter((X)=>z.has(X))}async function Yl(A,z){for(let X of A)await z(X)}var Rm=5000;function si(A,z=Rm){return new Promise((X)=>{let ee=Xt([...A],process.env),te=Sm(ee.cmd,ee.args,{env:process.env,stdio:"ignore"}),ae=!1,le=(he)=>{if(ae)return;ae=!0,clearTimeout(ye),X(he)},ye=setTimeout(()=>{te.kill(),le(!1)},z);te.on("error",()=>le(!1)),te.on("close",(he)=>le(he===0))})}function Zl(A=si,z={}){let X=new Set(z.configuredTargets??[]);return Promise.all(Mt.map(async(ee)=>({target:ee.target,flag:ee.flag,label:ee.label,...Ql(z.action,await A(ee.probeCommand),X.has(ee.target))})))}function Xl(A,z){let X=new Set(z.configuredTargets??[]);return A.map((ee)=>({...ee,...Ql(z.action,ee.available,X.has(ee.target))}))}function Ql(A,z,X){if(A==="uninstall")return X?{available:!0}:{available:!1,unavailableReason:"not installed"};if(A==="install"&&X)return{available:!1,unavailableReason:"already installed"};if(!z)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}import{existsSync as ec,readdirSync as Pm,rmSync as Em}from"node:fs";import{join as xn}from"node:path";function Or(A,z=process.platform){let X=xn(A.env.get("npm_config_cache")||(z==="win32"?xn(A.env.get("LOCALAPPDATA")||xn(A.home,"AppData","Local"),"npm-cache"):xn(A.home,".npm")),"_npx");if(!ec(X))return;Pm(X).filter((ee)=>ec(xn(X,ee,"node_modules","cc-safety-net"))).forEach((ee)=>{Em(xn(X,ee),{recursive:!0,force:!0})})}import{existsSync as sc,mkdirSync as Am,readFileSync as ac}from"node:fs";import{dirname as _m,join as ic}from"node:path";function Dm(A,z){if(A[z]!=="#")return z;let X=A.indexOf(`
230
+ `,z+1);return X===-1?A.length:X+1}function ai(A,z,X){let ee=new RegExp(`^(\\s*)${z}\\s*=\\s*\\[`),te=0;for(let ae of A.split(`
231
+ `)){if(/^\s*\[/.test(ae))return;let le=ee.exec(ae);if(le){let ye=te+le[0].lastIndexOf("[");return{start:ye,end:yo(A,ye,{skipComment:Dm,...X})}}te+=ae.length+1}return}function tc(A,z,X){let ee=A.slice(0,z.end).trimEnd(),te=Js(A,z.end),ae=te===""?" ":`${te} `,le=!ee.endsWith("[")&&!ee.endsWith(",");return`${ee}${le?",":""}
232
+ ${ae}${X}${A.slice(z.end)}`}function nc(A,z,X){let ee=A.indexOf(X,z.start);if(ee===-1||ee>z.end)return A;return fr(A,{start:ee,end:ee+X.length})}function rc(A,z){let X=new RegExp(`^\\s*${z}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),ee=A.split(`
233
+ `),te=ee.findIndex((ye)=>/^\s*\[/.test(ye)),ae=te===-1?ee:ee.slice(0,te),le=te===-1?[]:ee.slice(te);return[...ae.filter((ye)=>!X.test(ye)),...le].join(`
234
+ `)}function oc(A,z,X){let ee=new RegExp(`^\\s*\\[\\[${z}]]\\s*$`,"m");return A.split(/(?=^\s*\[)/m).filter((te)=>!ee.test(te)||!te.includes(X)).join("").trimEnd()}var Hn=jt["kimi-code"],li=`[[hooks]]
235
235
  event = "PreToolUse"
236
- command = "${rr}"`,Sc=`{ event = "PreToolUse", command = "${rr}" }`,Rc={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function Pc(j){return kc(j.env.get("KIMI_CODE_HOME")??kc(j.home,".kimi-code"),"config.toml")}function Qm(j){let K=Li(j,"hooks",Rc);if(K&&j.slice(K.start+1,K.end).trim())return vc(j,K,Sc);let te=Lc(j,"hooks").trimEnd();if(te==="")return`${wi}
237
- `;return`${te}
238
-
239
- ${wi}
240
- `}function Ec(j){let K=Pc(j);if(Zm(Xm(K),{recursive:!0}),!xc(K))return Dt(K,`${wi}
241
- `),{path:K,alreadyInstalled:!1};let te=Cc(K,"utf-8");if(te.includes(rr))return{path:K,alreadyInstalled:!0};return Dt(K,Qm(te)),{path:K,alreadyInstalled:!1}}function Dc(j){let K=Pc(j);if(!xc(K))return{path:K,alreadyInstalled:!1};let te=Cc(K,"utf-8");if(!te.includes(rr))return{path:K,alreadyInstalled:!1};let re=Li(te,"hooks",Rc),oe=re?bc(te,re,Sc):`${wc(te,"hooks",rr)}
242
- `;return Dt(K,oe),{path:K,alreadyInstalled:!0}}var xi="safety-net@cc-marketplace",Ac=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),_c=new Set(["antigravity-cli","cursor","grok-build","hermes-agent","kimi-code"]);function Si(j){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(j??"")}function jc(j){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(j??"")}function eg(j){return/^Marketplace `cc-marketplace`\s*$/m.test(j??"")}var Fc={"claude-code":{installCommands:(j)=>{let K=Sr(j,"cc-safety-net@cc-marketplace");return{commands:[...K?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...Do(j).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Sr(j,xi)?[["claude","plugin","uninstall",xi]]:[],update:K}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(j,K)=>{let te=K??await Jt(["codex","plugin","list"]),re=jc(te);return{commands:[re||eg(te)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:Si(te)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:re}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:"Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."},"copilot-cli":{installCommands:async()=>{let j=await Jt(["copilot","plugin","list"]),K=[...ha(j)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...va(j)?[["copilot","plugin","uninstall",ma]]:[]];if(ga(j))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",Vt]],cleanupCommands:K,update:!0};return{commands:[ya(await Jt(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",Vt]],cleanupCommands:K}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(j)=>{let K=No(j);if(K.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(K.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:Xo,installCommands:()=>({commands:sl()}),uninstallCommands:[["openclaw","plugins","uninstall",Rt,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
243
- `)},opencode:{beforeInstall:ti,installCommands:[["opencode","plugin","-g","-f","cc-safety-net@latest"]]},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]}};function Nc(j,K=(te)=>te){try{let te=JSON.parse(K(Oc(j,"utf-8")));if(!te||typeof te!=="object"||Array.isArray(te))throw Error(`Settings file ${j} must be a JSON object`);return te}catch(te){if(te instanceof SyntaxError)throw Error(`Failed to parse ${j}: ${te.message}`);throw te}}function tg(j){let K=ki(Vn(j),"settings.json");if(!Ci(K))return;let te=Nc(K,jt),re=te.enabledPlugins;if(!re||typeof re!=="object"||Array.isArray(re))return;if(re[Vt]!==!1)return;let oe=Oc(K,"utf-8"),ce=oe.replace(new RegExp(`("${Vt}"\\s*:\\s*)false`),"$1true");return re[Vt]=!0,Dt(K,ce!==oe?ce:`${JSON.stringify(te,null,2)}
244
- `),`Enabled ${Vt} plugin in ${K}`}function ng(j){let K=ni(j);if(!Ci(K))return;let te=Nc(K);if(!Array.isArray(te.packages))return;let re=te.packages.find((oe)=>!!oe&&typeof oe==="object"&&!Array.isArray(oe)&&ri(oe.source)&&("extensions"in oe));if(!re)return;return delete re.extensions,Dt(K,`${JSON.stringify(te,null,2)}
245
- `),`Enabled npm:cc-safety-net extensions in ${K}`}function Tc(j,K){let te=At({label:K,booleans:Object.fromEntries(Wt.map((ce)=>[ce.target,[ce.flag]]))},j),re=te.errors[0];if(re)throw Error(re);let oe=Wt.filter((ce)=>te.flags[ce.target]).map((ce)=>ce.target);if(oe.length!==1)throw Error(`Choose exactly one ${K} target: ${Wt.map((ce)=>ce.flag).join(", ")}`);return oe[0]}async function Mc(j,K=xn){let[te,re,oe]=await Promise.all([K(["amp","plugins","list"],30000),K(["codex","plugin","list"],30000),K(["copilot","--binary-version"])]);return{codexPluginListOutput:re,hooks:Dn(j,process.cwd(),{ampPluginListOutput:te,codexPluginListOutput:re,copilotCliVersion:oe})}}async function rg(j,K,te=xn){let re=await Mc(j,te);return re.hooks.filter((oe)=>K==="install"?oe.configured:oe.detected||oe.inspectionStatus==="not-inspected").filter((oe)=>oe.platform!=="codex"||!Si(re.codexPluginListOutput)||jc(re.codexPluginListOutput)).map((oe)=>oe.platform)}function og(j,K,te,re){if(te.length>0)return{finish:async()=>[Tc(te,K)]};if(!re.selectTargets&&!fi(re.input,re.output))return{finish:async()=>[Tc(te,K)]};let oe=re.detectConfiguredTargets??(()=>rg(j,K,re.fetchVersion)),ce=Promise.all([mc(re.probeTargets),oe()]);return{ready:ce,finish:async()=>{let[de,we]=await ce,xe=gc(de,{action:K,configuredTargets:we}),Ce=re.selectTargets?await re.selectTargets(K,$c(K,xe)):await Wl(K,$c(K,xe),{input:re.input,output:re.output});if(Ce==="update")return Ce;if(!Ce||Ce.length===0)return null;return vi(Ce)}}}async function vn(j,K,te=!1,re){let oe=Fc[j];oe.beforeInstall?.(K);let ce=typeof oe.installCommands==="function"?await oe.installCommands(K,re):{commands:oe.installCommands};return await Ko(ce.commands),await el(ce.cleanupCommands??[]),[`${ce.update||te?"Updated":"Installed"} ${St(j)} integration`,oe.postInstallMessage].filter(Boolean).join(`
246
- `)}async function On(j){let K=Fc[j];if(!K.uninstallCommands)throw Error(`${St(j)} uninstall is not supported`);return await Ko(K.uninstallCommands),`Uninstalled ${St(j)} integration`}function ig(j){let K=wl(j);return K.alreadyInstalled?`Uninstalled OpenCode plugin from ${K.path}`:`OpenCode plugin not installed in ${K.path}`}var sg={"antigravity-cli":{install:dc,uninstall:uc},cursor:{install:Ea,uninstall:Da},"grok-build":{install:Ma,uninstall:Ha},"kimi-code":{install:Ec,uninstall:Dc}};function on(j,K,te,re=!1){if(j==="install"&&!re)Kr(te);let oe=sg[K][j](te),ce=St(K),de=j!=="install"?"Uninstalled":re?"Updated":"Installed";return j==="install"&&oe.alreadyInstalled?re?`${ce} hook up to date in ${oe.path}`:`${ce} hook already installed in ${oe.path}`:j==="uninstall"&&!oe.alreadyInstalled?`${ce} hook not installed in ${oe.path}`:`${de} ${ce} hook ${j==="install"?"in":"from"} ${oe.path}`}var ag={amp:{install:oc,uninstall:ic,restartNote:'Amp personal plugins apply to every Amp session, including Orb threads. Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:qa,uninstall:Va,afterInstall:async(j)=>{let K=zo(j);return await Jt(["hermes","plugins","enable",Ft,"--no-allow-tool-override"]),!K},beforeUninstall:async(j)=>{Vo(j);try{await Jt(["hermes","plugins","disable",Ft])}catch(K){console.warn(`${K instanceof Error?K.message:String(K)}
247
- Removing the plugin files anyway; ${Ft} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function Yr(j,K,te,re=!1){let oe=ag[K];if(j==="uninstall")await oe.beforeUninstall?.(te);let ce=j==="install"?await oe.install(te):await oe.uninstall(te),de=j==="install"&&await oe.afterInstall?.(te),we=St(K),xe=!de&&(j==="install"&&ce.alreadyInstalled||j==="uninstall"&&!ce.alreadyInstalled);return[xe?j==="install"?`${we} plugin ${re?"up to date":"already installed"} at ${ce.path}`:`${we} plugin not installed at ${ce.path}`:`${j!=="install"?"Uninstalled":re?"Updated":"Installed"} ${we} plugin ${j==="install"?"at":"from"} ${ce.path}`,xe?void 0:oe.restartNote].filter(Boolean).join(`
248
- `)}var lg={amp:{install:(j,K)=>Yr("install","amp",j,K),uninstall:(j)=>Yr("uninstall","amp",j)},"antigravity-cli":{install:(j,K)=>on("install","antigravity-cli",j,K),uninstall:(j)=>on("uninstall","antigravity-cli",j)},"claude-code":{install:(j,K)=>vn("claude-code",j,K),uninstall:()=>On("claude-code")},codex:{install:(j,K,te)=>vn("codex",j,K,te),uninstall:()=>On("codex")},"copilot-cli":{install:async(j,K)=>[await vn("copilot-cli",j,K),tg(j)].filter(Boolean).join(`
249
- `),uninstall:()=>On("copilot-cli")},cursor:{install:(j,K)=>on("install","cursor",j,K),uninstall:(j)=>on("uninstall","cursor",j)},"gemini-cli":{install:(j,K)=>vn("gemini-cli",j,K),uninstall:()=>On("gemini-cli")},"grok-build":{install:(j,K)=>on("install","grok-build",j,K),uninstall:(j)=>on("uninstall","grok-build",j)},"hermes-agent":{install:(j,K)=>{if(!K)Kr(j);return Yr("install","hermes-agent",j,K)},uninstall:(j)=>Yr("uninstall","hermes-agent",j)},"kimi-code":{install:(j,K)=>on("install","kimi-code",j,K),uninstall:(j)=>on("uninstall","kimi-code",j)},openclaw:{install:async(j,K)=>{let te=await vn("openclaw",j,K);return await al(),te},uninstall:(j)=>(Xo(j),On("openclaw"))},opencode:{install:async(j,K)=>{let te=await vn("opencode",j,K);return await bl(j),te},uninstall:(j)=>ig(j)},pi:{install:async(j,K)=>[await vn("pi",j,K),ng(j)].filter(Boolean).join(`
250
- `),uninstall:()=>On("pi")}},Ic=["Install CC Safety Net as a native Kimi Code plugin:",""," 1. Start Kimi Code and run: /plugins install https://github.com/kenryu42/cc-safety-net"," Confirm the trust prompt; it defaults to cancel."," 2. Run /reload, or start a new session.","","Note: Kimi Code hooks are fail-open. When the hook process cannot start, crashes, or times","out, Kimi Code allows the tool call."].join(`
251
- `);function cg(j){if(Yn({environment:j,cwd:process.cwd()}).status!=="configured")return Ic;return[Ic,"",bt.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
236
+ command = "${Hn}"`,lc=`{ event = "PreToolUse", command = "${Hn}" }`,cc={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function dc(A){return ic(A.env.get("KIMI_CODE_HOME")??ic(A.home,".kimi-code"),"config.toml")}function Tm(A){let z=ai(A,"hooks",cc);if(z&&A.slice(z.start+1,z.end).trim())return tc(A,z,lc);let X=rc(A,"hooks").trimEnd();if(X==="")return`${li}
237
+ `;return`${X}
238
+
239
+ ${li}
240
+ `}function uc(A){let z=dc(A);if(Am(_m(z),{recursive:!0}),!sc(z))return kt(z,`${li}
241
+ `),{path:z,alreadyInstalled:!1};let X=ac(z,"utf-8");if(X.includes(Hn))return{path:z,alreadyInstalled:!0};return kt(z,Tm(X)),{path:z,alreadyInstalled:!1}}function pc(A){let z=dc(A);if(!sc(z))return{path:z,alreadyInstalled:!1};let X=ac(z,"utf-8");if(!X.includes(Hn))return{path:z,alreadyInstalled:!1};let ee=ai(X,"hooks",cc),te=ee?nc(X,ee,lc):`${oc(X,"hooks",Hn)}
242
+ `;return kt(z,te),{path:z,alreadyInstalled:!0}}var di="safety-net@cc-marketplace",fc=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),mc=new Set(["antigravity-cli","cursor","grok-build","hermes-agent","kimi-code"]);function pi(A){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(A??"")}function bc(A){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(A??"")}function $m(A){return/^Marketplace `cc-marketplace`\s*$/m.test(A??"")}var Lc={"claude-code":{installCommands:(A)=>{let z=ur(A,"cc-safety-net@cc-marketplace");return{commands:[...z?[["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"]],...mo(A).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:ur(A,di)?[["claude","plugin","uninstall",di]]:[],update:z}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(A,z)=>{let X=z??await Nt(["codex","plugin","list"]),ee=bc(X);return{commands:[ee||$m(X)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:pi(X)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:ee}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:"Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."},"copilot-cli":{installCommands:async()=>{let A=await Nt(["copilot","plugin","list"]),z=[...ta(A)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...na(A)?[["copilot","plugin","uninstall",Xs]]:[]];if(Qs(A))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",Ft]],cleanupCommands:z,update:!0};return{commands:[ea(await Nt(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",Ft]],cleanupCommands:z}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(A)=>{let z=xo(A);if(z.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(z.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:No,installCommands:()=>({commands:Ba()}),uninstallCommands:[["openclaw","plugins","uninstall",ht,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
243
+ `)},opencode:{beforeInstall:Uo,installCommands:[["opencode","plugin","-g","-f","cc-safety-net@latest"]]},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]}};function wc(A,z=(X)=>X){try{let X=JSON.parse(z(vc(A,"utf-8")));if(!X||typeof X!=="object"||Array.isArray(X))throw Error(`Settings file ${A} must be a JSON object`);return X}catch(X){if(X instanceof SyntaxError)throw Error(`Failed to parse ${A}: ${X.message}`);throw X}}function Im(A){let z=ci(En(A),"settings.json");if(!ui(z))return;let X=wc(z,At),ee=X.enabledPlugins;if(!ee||typeof ee!=="object"||Array.isArray(ee))return;if(ee[Ft]!==!1)return;let te=vc(z,"utf-8"),ae=te.replace(new RegExp(`("${Ft}"\\s*:\\s*)false`),"$1true");return ee[Ft]=!0,kt(z,ae!==te?ae:`${JSON.stringify(X,null,2)}
244
+ `),`Enabled ${Ft} plugin in ${z}`}function Om(A){let z=Go(A);if(!ui(z))return;let X=wc(z);if(!Array.isArray(X.packages))return;let ee=X.packages.find((te)=>!!te&&typeof te==="object"&&!Array.isArray(te)&&Bo(te.source)&&("extensions"in te));if(!ee)return;return delete ee.extensions,kt(z,`${JSON.stringify(X,null,2)}
245
+ `),`Enabled npm:cc-safety-net extensions in ${z}`}function gc(A,z){let X=xt({label:z,booleans:Object.fromEntries(Mt.map((ae)=>[ae.target,[ae.flag]]))},A),ee=X.errors[0];if(ee)throw Error(ee);let te=Mt.filter((ae)=>X.flags[ae.target]).map((ae)=>ae.target);if(te.length!==1)throw Error(`Choose exactly one ${z} target: ${Mt.map((ae)=>ae.flag).join(", ")}`);return te[0]}async function kc(A,z=fn){let[X,ee,te]=await Promise.all([z(["amp","plugins","list"],30000),z(["codex","plugin","list"],30000),z(["copilot","--binary-version"])]);return{codexPluginListOutput:ee,hooks:bn(A,process.cwd(),{ampPluginListOutput:X,codexPluginListOutput:ee,copilotCliVersion:te})}}async function Fm(A,z,X=fn){let ee=await kc(A,X);return ee.hooks.filter((te)=>z==="install"?te.configured:te.detected||te.inspectionStatus==="not-inspected").filter((te)=>te.platform!=="codex"||!pi(ee.codexPluginListOutput)||bc(ee.codexPluginListOutput)).map((te)=>te.platform)}function jm(A,z,X,ee){if(X.length>0)return{finish:async()=>[gc(X,z)]};if(!ee.selectTargets&&!Qo(ee.input,ee.output))return{finish:async()=>[gc(X,z)]};let te=ee.detectConfiguredTargets??(()=>Fm(A,z,ee.fetchVersion)),ae=Promise.all([Zl(ee.probeTargets),te()]);return{ready:ae,finish:async()=>{let[le,ye]=await ae,he=Xl(le,{action:z,configuredTargets:ye}),ve=ee.selectTargets?await ee.selectTargets(z,hc(z,he)):await Tl(z,hc(z,he),{input:ee.input,output:ee.output});if(ve==="update")return ve;if(!ve||ve.length===0)return null;return ii(ve)}}}async function Nm(A,z,X=!1,ee){let te=Lc[A];te.beforeInstall?.(z);let ae=typeof te.installCommands==="function"?await te.installCommands(z,ee):{commands:te.installCommands};return await Io(ae.commands),await Na(ae.cleanupCommands??[]),[`${ae.update||X?"Updated":"Installed"} ${bt(A)} integration`,te.postInstallMessage].filter(Boolean).join(`
246
+ `)}async function Mm(A){let z=Lc[A];if(!z.uninstallCommands)throw Error(`${bt(A)} uninstall is not supported`);return await Io(z.uninstallCommands),`Uninstalled ${bt(A)} integration`}function Hm(A){let z=ol(A);return z.alreadyInstalled?`Uninstalled OpenCode plugin from ${z.path}`:`OpenCode plugin not installed in ${z.path}`}var xc={"antigravity-cli":{install:Jl,uninstall:Wl},cursor:{install:pa,uninstall:fa},"grok-build":{install:xa,uninstall:Ca},"kimi-code":{install:uc,uninstall:pc}};function Um(A,z,X,ee=!1){if(A==="install"&&!ee)Or(X);let te=xc[z][A](X),ae=bt(z),le=A!=="install"?"Uninstalled":ee?"Updated":"Installed";return A==="install"&&te.alreadyInstalled?ee?`${ae} hook up to date in ${te.path}`:`${ae} hook already installed in ${te.path}`:A==="uninstall"&&!te.alreadyInstalled?`${ae} hook not installed in ${te.path}`:`${le} ${ae} hook ${A==="install"?"in":"from"} ${te.path}`}var Cc={amp:{install:Ul,uninstall:Gl,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:Ea,uninstall:Da,afterInstall:async(A)=>{let z=_o(A);return await Nt(["hermes","plugins","enable",_t,"--no-allow-tool-override"]),!z},beforeUninstall:async(A)=>{Ao(A);try{await Nt(["hermes","plugins","disable",_t])}catch(z){console.warn(`${z instanceof Error?z.message:String(z)}
247
+ Removing the plugin files anyway; ${_t} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function Gm(A,z,X,ee=!1){let te=Cc[z];if(A==="uninstall")await te.beforeUninstall?.(X);let ae=A==="install"?await te.install(X):await te.uninstall(X),le=A==="install"&&await te.afterInstall?.(X),ye=bt(z),he=!le&&(A==="install"&&ae.alreadyInstalled||A==="uninstall"&&!ae.alreadyInstalled);return[he?A==="install"?`${ye} plugin ${ee?"up to date":"already installed"} at ${ae.path}`:`${ye} plugin not installed at ${ae.path}`:`${A!=="install"?"Uninstalled":ee?"Updated":"Installed"} ${ye} plugin ${A==="install"?"at":"from"} ${ae.path}`,he?void 0:te.restartNote].filter(Boolean).join(`
248
+ `)}var Bm={"copilot-cli":{afterInstall:Im},"hermes-agent":{beforeInstall:(A,z)=>{if(!z)Or(A)}},openclaw:{afterInstall:async()=>{await qa();return},beforeUninstall:No},opencode:{afterInstall:async(A)=>{await nl(A);return}},pi:{afterInstall:Om}};function qm(A){return A in xc}function Vm(A){return A in Cc}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(`
249
+ `);function zm(A){if($n({environment:A,cwd:process.cwd()}).status!=="configured")return yc;return[yc,"",dt.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
252
250
  `))].join(`
253
- `)}function $c(j,K){return K.map((te)=>j==="install"&&te.target==="kimi-code"&&te.unavailableReason==="already installed"?{...te,available:!0,unavailableReason:void 0,label:`${te.label} (global hook installed)`}:te)}function dg(j,K){if(j.selectKimiInstallMethod)return j.selectKimiInstallMethod();if(!fi(j.input,j.output))return Promise.resolve("global-hook");return Jl({input:j.input,output:j.output,globalHookInstalled:Yn({environment:K,cwd:process.cwd()}).status==="configured"})}async function Hc(j,K,te,re=!1,oe){return lg[K][j](te,re,oe)}function ug(j){let K=At({label:"update"},j).errors[0];if(K)throw Error(K)}async function pg(j,K=xn){let te=await Mc(j,K),re=ki(Vn(j),"installed-plugins");return{targets:vi([...te.hooks.filter((ce)=>ce.platform!=="copilot-cli"&&ce.detected).map((ce)=>ce.platform),...[Er,fa,pa].flatMap((ce)=>Ci(ki(re,...ce))?["copilot-cli"]:[]),...Sr(j,xi)?["claude-code"]:[],...Si(te.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:te.codexPluginListOutput}}async function fg(j){let K=l(),te=j.output??process.stdout,re=(j.scriptPath??process.argv[1]??"").split(/[\\/]/),oe=re.find((at)=>/^bunx-\d+-/.test(at)),ce=oe!==void 0||re.includes("_npx")?null:(j.checkLatestVersion??tn)(),de=async()=>{let at=ce&&await ce;if(at?.updateAvailable)te.write(`
254
- Update available: cc-safety-net ${at.currentVersion} → ${at.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
255
- `)},we=pg(K,j.fetchVersion??xn).then(async(at)=>{let mt=new Set(at.targets);return{targets:at.targets,codexPluginListOutput:at.codexPluginListOutput,available:new Map(await Promise.all(Wt.filter((it)=>mt.has(it.target)&&Ac.has(it.target)).map(async(it)=>[it.target,await bi(it.probeCommand)])))}}),xe=await Bn(j.showBanner??!0,()=>({ready:we,finish:()=>we}),()=>Gn({input:j.input??process.stdin,output:te}),{loadingMessage:"Checking installed integrations…",output:te}),Ce=await Promise.resolve().then(()=>(pc(K.tmpdir,process.platform,oe),null)).catch((at)=>or(at));if(xe.targets.length===0){if(te.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),Ce!==null)console.error(Ce);return await de(),Ce===null?0:1}let Se=xe.targets.some((at)=>_c.has(at))?await Promise.resolve().then(()=>(Kr(K),null)).catch((at)=>or(at)):null,Ne=await kr(Promise.all(xe.targets.map((at)=>{if(Ac.has(at)&&!xe.available.get(at))return Promise.resolve({message:`${St(at)} not found; skipped`,failed:!1});if(Se!==null&&_c.has(at))return Promise.resolve({message:Se,failed:!0});return Hc("install",at,K,!0,xe.codexPluginListOutput).then((mt)=>({message:mt,failed:!1}),(mt)=>({message:or(mt),failed:!0}))})),{loadingMessage:`Updating ${xe.targets.length} integration${xe.targets.length===1?"":"s"}…`,output:te}),He=Ce===null?Ne:[...Ne,{message:Ce,failed:!0}];return He.forEach((at)=>{at.failed?console.error(at.message):te.write(`${at.message}
256
- `)}),await de(),He.some((at)=>at.failed)?1:0}function Ri(j,K={}){return Promise.resolve().then(()=>ug(j)).then(()=>fg(K)).catch((te)=>(console.error(or(te)),1))}async function ir(j,K,te={}){try{let re=l(),oe=await Bn(!0,()=>og(re,j,K,te),()=>Gn({input:te.input??process.stdin,output:te.output??process.stdout}),{loadingMessage:j==="install"?"Checking available integrations…":"Checking installed integrations…",output:te.output??process.stdout});if(!oe)return(te.output??process.stdout).write(`Cancelled: nothing was ${j}ed.
257
- `),0;if(oe==="update")return(te.runUpdate??(()=>Ri([],{fetchVersion:te.fetchVersion,input:te.input,output:te.output,showBanner:!1})))();let ce=te.output??process.stdout;return await fc(oe,async(de)=>{if(de==="kimi-code"&&j==="install"){let xe=await dg(te,re);if(xe===null){ce.write(`Cancelled: Kimi Code integration was not installed.
258
- `);return}if(xe==="plugin"){ce.write(`${cg(re)}
259
- `);return}}let we=await kr(Hc(j,de,re),{loadingMessage:`${j==="install"?"Installing":"Uninstalling"} ${St(de)} integration…`,output:ce});ce.write(`${we}
260
- `)}),0}catch(re){return console.error(or(re)),1}}function or(j){let K=j instanceof Error?j.message:String(j),te=typeof j==="object"&&j!==null&&"code"in j?j.code:null;if(te==="EACCES"||te==="EPERM")return`${K}
261
- Check file permissions for the target config file and parent directory.`;if(te==="ENOENT")return`${K}
262
- Check that the target config path and parent directory exist.`;if(te==="ENOTDIR")return`${K}
263
- Check that every parent path component is a directory.`;return K}import{mkdirSync as xg}from"node:fs";import{dirname as Cg}from"node:path";import{createInterface as Sg}from"node:readline";import{existsSync as Jc,readFileSync as vg}from"node:fs";var Bc=["version","safety","workflow","destructive_command_protection","secret_protection","audit"],mg=["standard","strict","paranoid"],qc="must be an object if provided",gg=`must be an integer between ${ye} and ${ve}`;function Ut(j,K){return se(nt(yg(j,K),Bc,(te)=>te.kind==="custom")," "," ")}function yg(j,K){if(!Ei(j))return[e([],"Config must be an object")];return[...j.version===1?[]:[e(["version"],"must be 1")],...jn(j.safety,["safety"],["level","overrides"],(te)=>[...te.level===void 0||typeof te.level==="string"&&mg.includes(te.level)?[]:[e(["safety","level"],'must be "standard", "strict", or "paranoid"')],...jn(te.overrides,["safety","overrides"],Uc,(re)=>Uc.flatMap((oe)=>Zr(re[oe],["safety","overrides",oe])))]),...jn(j.workflow,["workflow"],["worktree_mode"],(te)=>Zr(te.worktree_mode,["workflow","worktree_mode"])),...jn(j.destructive_command_protection,["destructive_command_protection"],["enabled","overrides","allow_paths"],(te)=>[...Zr(te.enabled,["destructive_command_protection","enabled"]),...Gc(te.overrides,["destructive_command_protection","overrides"],Pe,"destructive command"),...Pi(te.allow_paths,["destructive_command_protection","allow_paths"],Ae,K)]),...jn(j.secret_protection,["secret_protection"],["enabled","overrides","deny_paths","allow_paths"],(te)=>[...Zr(te.enabled,["secret_protection","enabled"]),...Gc(te.overrides,["secret_protection","overrides"],_e,"secret protection"),...Pi(te.deny_paths,["secret_protection","deny_paths"],Te,K),...Pi(te.allow_paths,["secret_protection","allow_paths"],Ie,K)]),...jn(j.audit,["audit"],["retention_days"],(te)=>hg(te.retention_days)?[]:[e(["audit","retention_days"],gg)]),...Object.keys(j).filter((te)=>!Bc.includes(te)).map((te)=>Vc([],te))]}var Uc=["fail_closed","paranoid_rm","paranoid_interpreters"];function jn(j,K,te,re){if(j===void 0)return[];if(!Ei(j))return[e(K,qc)];return[...re(j),...Object.keys(j).filter((oe)=>!te.includes(oe)).map((oe)=>Vc(K,oe))]}function Zr(j,K){return j===void 0||typeof j==="boolean"?[]:[e(K,"must be a boolean")]}function Gc(j,K,te,re){if(j===void 0)return[];if(!Ei(j))return[e(K,qc)];return[...Object.keys(j).filter((oe)=>!te.has(oe)).map((oe)=>({path:[...K,oe],message:`unknown ${re} rule id "${oe}"`,kind:"key"})),...Object.keys(j).filter((oe)=>j[oe]!=="on"&&j[oe]!=="off").map((oe)=>e([...K,oe],'must be "on" or "off"'))]}function Pi(j,K,te,re){if(j===void 0)return[];if(!Array.isArray(j))return[e(K,"must be an array of paths")];return j.flatMap((oe,ce)=>{if(typeof oe!=="string")return[e([...K,ce],"must be a non-empty path string")];let de=te(oe,re);return de===null?[]:[g([...K,ce],de)]})}function hg(j){if(j===void 0)return!0;if(typeof j!=="number"||!Number.isInteger(j))return!1;return j>=ye&&j<=ve}var Vc=(j,K)=>({path:j,message:K,kind:"unknownKeys"});function Ei(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}function zc(j,K){return{"safety.level":j.safety.level,...Di("safety.overrides",j.safety.overrides),"workflow.worktree_mode":String(j.workflow.worktree_mode),"destructive_command_protection.enabled":String(j.destructive_command_protection.enabled),...Di("destructive_command_protection.overrides",j.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Ai(j.destructive_command_protection.allow_paths),"secret_protection.enabled":String(j.secret_protection.enabled),...Di("secret_protection.overrides",j.secret_protection.overrides),"secret_protection.deny_paths":Ai(j.secret_protection.deny_paths),"secret_protection.allow_paths":Ai(j.secret_protection.allow_paths),...K?{"audit.retention_days":String(j.audit.retention_days)}:{}}}function Xr(j,K,te){let re=zc(j,te),oe=zc(K,te);return[...new Set([...Object.keys(re),...Object.keys(oe)])].flatMap((ce)=>re[ce]===oe[ce]?[]:[{field:ce,before:re[ce],after:oe[ce]}])}function sr(j,K){let te=d(j,K);if(!Jc(te))return{baseline:h(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,j.home),diagnostics:[]};let re=bn(te);return{baseline:h(re.value,j.home),diagnostics:re.errors.length>0?re.errors:Ut(re.value,j.home)}}function bn(j){if(!Jc(j))return{errors:[`${j}: file not found`]};try{return{value:JSON.parse(vg(j,"utf-8")),errors:[]}}catch(K){let te=K instanceof Error?K.message:String(K);return{errors:[`${j}: ${K instanceof SyntaxError?`Invalid JSON: ${te}`:te}`]}}}function Qr(j,K){let te=bg(j)?j:{};return{version:K.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((re)=>te[re]!==void 0).map((re)=>[re,te[re]]))}}function Di(j,K){return Object.fromEntries(Object.entries(K).flatMap(([te,re])=>re===void 0?[]:[[`${j}.${te}`,String(re)]]))}function Ai(j){return j.length===0?"(none)":j.join(", ")}function bg(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}import{chmodSync as Lg,existsSync as Wc,mkdirSync as wg,readFileSync as Kc}from"node:fs";import{dirname as kg}from"node:path";function Yc(j,K={}){let te=d(j,K);if(!Wc(te))return{path:te,exists:!1,raw:"",policy:z(),errors:[]};let re=Kc(te,"utf-8");if(!re.trim())return{path:te,exists:!0,raw:re,policy:z(),errors:["Config file is empty"]};try{let oe=JSON.parse(re),ce=Ut(oe,j.home);return{path:te,exists:!0,raw:re,policy:h(oe,j.home),errors:ce}}catch(oe){return{path:te,exists:!0,raw:re,policy:z(),errors:[`Invalid JSON: ${oe instanceof Error?oe.message:String(oe)}`]}}}function Xt(j,K,te={}){let re=d(j,te),oe=Ut(K,j.home),ce=oe.length>0?z():h(K,j.home);if(oe.length>0)return{path:re,policy:ce,errors:oe};return wg(kg(re),{recursive:!0,mode:448}),y(D(re),`${JSON.stringify(ce,null,2)}
264
- `,384),Lg(re,384),{path:re,policy:ce,errors:[]}}function Zc(j,K){let te=Ut(K,j.home);if(te.length>0)return{errors:te};return{preview:Ge(h(K,j.home),j.env),errors:[]}}function Xc(j,K={}){let te=d(j,K);if(!Wc(te))return Xt(j,Q,K);let re=Kc(te,"utf-8");if(!re.trim())return Xt(j,Q,K);try{return Xt(j,h(JSON.parse(re),j.home),K)}catch{return Xt(j,Q,K)}}var Qc=new Set(["check","apply"]),ed="(unset)";async function nd(j,K,te={}){let re=At({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},K),oe=re.positionals[0],ce=[...re.errors,...oe&&!Qc.has(oe)?[`Unknown policy subcommand: ${oe}`]:[],...oe&&Qc.has(oe)&&!re.positionals[1]?[`policy ${oe} requires a file`]:[],...re.positionals.slice(2).map((mt)=>`Unexpected policy argument: ${mt}`)];if(ce.length>0){for(let mt of ce)console.error(mt);return 1}let de=re.positionals[1];if(!oe||!de)return _n(pr,console.error),1;let we=re.flags.global?d(j):w(te.cwd??process.cwd()),xe=bn(de),Ce=[...xe.errors,...Ut(xe.value,j.home).map((mt)=>`${de}: ${mt}`),...!re.flags.global&&Eg(xe.value)&&xe.value.audit!==void 0?[`${de}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(Ce.length>0){for(let mt of Ce)console.error(mt);return 1}let Se=h(xe.value,j.home);if(console.log(`Scope: ${re.flags.global?"user":"project"} (${we})`),console.log(`Proposal: ${de}`),re.flags.global)td(h(bn(we).value,j.home),Se,!0);if(!re.flags.global){let mt=sr(j).baseline;console.log("Effective policy (user + project merged):"),td(X(mt,le(bn(we).value,j.home).policy).policy,X(mt,le(xe.value,j.home).policy).policy,!1)}if(oe==="check")return 0;let Ne=te.input??process.stdin,He=te.output??process.stdout;if(!Ne.isTTY||!He.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${de}${re.flags.global?" --global":""}`),1;if(!await Rg(`Apply this policy to ${we}? [y/N] `,Ne,He))return console.log("Cancelled; nothing was written."),0;return Pg(j,we,xe.value,Se,re.flags.global),console.log(`Policy applied: ${we}`),0}function Rg(j,K,te){let re=Sg({input:K,output:te,terminal:!1});return new Promise((oe)=>{re.once("close",()=>oe(!1)),re.question(j,(ce)=>{oe(/^y(es)?$/i.test(ce.trim())),re.close()})})}function Pg(j,K,te,re,oe){if(oe){Xt(j,re);return}xg(Cg(K),{recursive:!0}),It(K,Qr(te,re))}function td(j,K,te){let re=Xr(j,K,te);if(re.length===0){console.log("No changes.");return}console.log(`Changes (${re.length}):`);for(let oe of re)console.log(` ${oe.field}: ${oe.before??ed} -> ${oe.after??ed}`)}function Eg(j){return!!j&&typeof j==="object"&&!Array.isArray(j)}import{join as Gy}from"node:path";var rd="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Priority |\n|-------|-------------|---------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | Second |\n| GitHub source | Listed in a local `rule.json` | Vendored into the consumer's `<rulebook-name>/rulebook.json` by `rule add` | Source order |\n\nEvery rulebook is a live file: the runtime reads it on each tool call, so an edit applies to the next command with no publishing step.\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule verify` reports the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- Transparent wrappers have no built-in defaults. Configure only wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n\n## Rulebook Sources\n\n- Local sources are bare rulebook names such as `project-rules`; the rulebook file is `.cc-safety-net/rules/project-rules/rulebook.json`.\n- Run `cc-safety-net rule add owner/repo` to add every rulebook currently present on the repository's default branch.\n- Use `--only` to select one or more rulebooks while preserving their order: `cc-safety-net rule add owner/repo --only aws gcloud`.\n- Use `--ref` to select a branch, tag, or commit instead of the default branch: `cc-safety-net rule add owner/repo --ref v2 --only aws`.\n- GitHub sources are stored in canonical form as `owner/repo#ref/<rulebook-name>`. That form remains valid in `rule.json` and as direct CLI input.\n- GitHub refs may contain `/`-separated path segments, such as `feature/rulebook-v2`.\n- The GitHub source name, the repository directory name, and the rulebook `name` must match exactly.\n- Rulebook source strings must be unique in a config.\n\n## rulebook.json Schema\n\n```json\n{\n \"rulebook_version\": 1,\n \"name\": \"project-rules\",\n \"version\": \"1.0.0\",\n \"description\": \"Project-specific CC Safety Net rules.\",\n \"author\": \"project\",\n \"allowed_commands\": [\"docker\"],\n \"rules\": [\n {\n \"name\": \"block-docker-system-prune\",\n \"command\": \"docker\",\n \"subcommand\": \"system\",\n \"block_args\": [\"prune\"],\n \"reason\": \"Use targeted cleanup instead.\"\n }\n ],\n \"tests\": [\n {\n \"command\": \"docker system prune\",\n \"expect\": \"blocked\",\n \"rule\": \"block-docker-system-prune\"\n },\n {\n \"command\": \"docker ps\",\n \"expect\": \"allowed\"\n }\n ]\n}\n```\n\n### Rulebook Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `rulebook_version` | Yes | Must be `1` or `2` |\n| `name` | Yes | `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` |\n| `version` | Yes | Non-empty string |\n| `description` | No | Free text; not type-checked at runtime |\n| `author` | No | Free text; not type-checked at runtime |\n| `allowed_commands` | Yes | Unique command names matching `^[a-zA-Z][a-zA-Z0-9_-]*$` |\n| `rules` | Yes | Array of rule objects |\n| `tests` | No | Array of fixtures |\n\n### Rule Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Unique within the rulebook (case-insensitive); same pattern as rulebook `name` |\n| `command` | Yes | Must be listed in `allowed_commands`; basename only, not path |\n| `subcommand` | No | Same pattern as `command`; omit to match any subcommand |\n| `intent` | No | One of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain` |\n| `block_args` | Yes | Non-empty array of non-empty strings |\n| `reason` | Yes | Non-empty string, max 256 chars |\n\n### Rule Fields (`rulebook_version` 2)\n\nVersion 2 replaces `subcommand` and `block_args` with an exact-token `match` object. Version 1 rulebooks keep their fields and their behavior; a client that does not support version 2 rejects the rulebook instead of applying broader version 1 semantics.\n\n```json\n{\n \"name\": \"block-terraform-apply-destroy\",\n \"command\": \"terraform\",\n \"match\": {\n \"command_path\": [\"apply\"],\n \"any_args\": [\"-destroy\", \"--destroy\"]\n },\n \"reason\": \"Review a destroy plan first with 'terraform plan -destroy'.\",\n \"intent\": \"use_alternative\"\n}\n```\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Same as version 1 |\n| `command` | Yes | Same as version 1 |\n| `match.command_path` | Yes | Non-empty array of non-empty command words |\n| `match.any_args` | No | Non-empty array of unique non-empty argument tokens |\n| `match.exclude_args` | No | Non-empty array of unique non-empty argument tokens |\n| `intent` | No | Same as version 1 |\n| `reason` | Yes | Same as version 1 |\n\n### Matching Behavior (`rulebook_version` 2)\n\n- **Command**: Normalized to lowercase basename, as in version 1.\n- **Command path**: After recognized global options and their values are skipped, the next command words must equal `command_path` exactly. AWS, gcloud, and Azure CLI value-taking global options are built in; Terraform's `-chdir=dir` is `=`-joined and is skipped with its own token.\n- **Unrecognized options**: A token starting with `-` that is not a recognized global option is skipped without consuming a value, so an unlisted value-taking option with a separate value (`--newflag value`) makes the rule miss. This fails open deliberately; document such gaps in the rulebook.\n- **`any_args`**: At least one listed token must appear literally among the arguments.\n- **`exclude_args`**: Any listed token appearing literally among the arguments prevents the match, which is how a safe preview such as `aws s3 rm --dryrun` stays allowed.\n- **No short-option expansion**: Arguments compare as exact tokens, so list every accepted spelling (`\"-destroy\"` and `\"--destroy\"`).\n- **Literal and case-sensitive**: No regex, glob, or substring matching. The first matching rule wins.\n- Release channels are separate rules: `gcloud beta compute instances delete` needs its own `command_path`.\n\n### Test Fixture Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `command` | Yes | Non-empty shell command string |\n| `expect` | Yes | `\"blocked\"` or `\"allowed\"` |\n| `rule` | Required for blocked fixtures | Rule name expected to block the command |\n\nFixtures are optional documentation of intended behavior. Version 1 fixtures are shape-validated only. Version 2 fixtures are evaluated against the rulebook's own rules when a source is fetched by `rule add` or `rule update`, and by `rule verify`; a failing fixture rejects that source before it is written. Loading a rulebook does not re-evaluate fixtures. CC Safety Net never executes fixture commands; they are analyzer inputs only.\n\n## Matching Behavior\n\nThe subcommand, argument, and option rules below describe `rulebook_version` 1 rules; version 2 rules match as described in Matching Behavior (`rulebook_version` 2). Execution order and transparent wrappers apply to both.\n\n- **Command**: Normalized to lowercase basename with any trailing `.exe` removed (`/usr/bin/git` → `git`).\n- **Subcommand**: The first command token after recognized Git and Docker global options and their values; `--` ends option parsing. An unrecognized option without `=` may consume the following token as its value.\n- **Arguments**: Each `block_args` value is compared literally against every command token, including expanded short options. The command is blocked if **any** item matches.\n- **Short options**: Expanded (`-Ap` matches `-A`).\n- **Long options**: Exact match (`--all-files` does not match `--all`).\n- **Execution order**: Built-in rules first, then custom rulebooks. Custom rules only add restrictions.\n- **Transparent wrappers**: A configured wrapper such as `rtk` lets `rtk git commit` be analyzed as `git commit` only when `git` is protected by built-in analyzers or active custom rules. `rtk -- git commit` is also supported.\n\n## Workflow\n\n1. Run `cc-safety-net rule init` or create `rule.json` manually.\n2. Optionally run `cc-safety-net rule init --example` to create an inactive example rulebook.\n3. Use `cc-safety-net rule wrapper add rtk` for trusted transparent wrappers.\n4. Run `cc-safety-net rule add <source>` after creating or choosing a rulebook source; add `--only <rulebook...>` or `--ref <ref>` for repository selection. The command adds the selected sources and syncs them.\n5. Edit a local rulebook whenever you like: the edit is enforced on the next command, so there is nothing to run afterwards.\n6. Run `cc-safety-net rule update [source]` to re-fetch remote sources and rewrite the vendored copies; the command prints what changed. A source with an ordinary update failure keeps its vendored copy while the other selected sources still update. Resource-limit failures remain fatal for the whole update.\n7. Run `cc-safety-net rule verify` to validate config, local rulebooks, and shareable GitHub-source rulebook directories in the current repository (it does not fetch remote content).\n8. Run `cc-safety-net rule list` to inspect active rulebooks and transparent wrappers.\n\nA missing or invalid rulebook file makes that source inactive, and an unreadable or invalid `rule.json` makes every source in its scope inactive. Inactive sources stop applying their rules while other custom rules and all built-in protections stay active. Fix the file named in the diagnostic, or run `cc-safety-net rule update` when a remote source has not been vendored yet. Run `cc-safety-net status` to see degraded sources.\n";function eo(j,K){if(!j.ok){ld(j);return}sd(j,K)}function id(j,K,te){if(j.ok)console.log(te);if(!j.add){eo(j,`Added rulebook source: ${K}`);return}if(!j.ok){ld(j);return}if(j.add.added.length>0)console.log(`Added ${j.add.added.length} ${j.add.added.length===1?"rulebook":"rulebooks"} from ${j.add.source} at ${j.add.ref}:`),j.add.added.forEach((re)=>{console.log(` - ${re}`)});if(j.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${j.add.source} at ${j.add.ref}: ${j.add.alreadyConfigured.join(", ")}`);if(j.add.commits.length>0)console.log(`Vendored at ${j.add.commits.map((re)=>re.slice(0,7)).join(", ")}.`);sd(j,"Rule config updated.")}function sd(j,K){for(let te of j.changes??[])console.log(te);console.log(K),console.log(""),Dg(j.entries)}function Dg(j){if(j.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${j.length}):`);for(let K of j)console.log(` - ${K.name} ${K.version} (${Ag(K.ruleCount)})`),console.log(` Source: ${K.spec}`)}function Ag(j){return`${j} ${j===1?"rule":"rules"}`}function ad(j){Ln("Active sources",j.rulebooks,(K)=>[`[${K.source}] ${K.name} ${K.version}`,` Source: ${K.spec}`]),Ln("Active rules",j.rules,(K)=>[`[${Tg(j,K.name)}] ${K.name}`,..._g(K),` Reason: ${K.reason}`]),Ln("Disabled rules",od(j,"off"),(K)=>[K.key]),Ln("Reason overrides",od(j,"reason"),(K)=>[K.key,` Reason: ${K.value.reason}`]),Ln("Transparent wrappers",j.transparent_wrappers,(K)=>[K]),Ln("Issues",j.errors,(K)=>[K]),Ln("Warnings",j.warnings,(K)=>[K])}function Ln(j,K,te){if(K.length===0){console.log(`${j}: (none)`);return}console.log(`${j} (${K.length}):`);for(let re of K){let[oe,...ce]=te(re);console.log(` - ${oe}`);for(let de of ce)console.log(` ${de}`)}}function _g(j){if(!j.match)return[` Command: ${j.subcommand?`${j.command} ${j.subcommand}`:j.command}`,` Block args: ${j.block_args.join(", ")}`];return[` Command: ${[j.command,...j.match.command_path].join(" ")}`,...j.match.any_args?[` Any args: ${j.match.any_args.join(", ")}`]:[],...j.match.exclude_args?[` Exclude args: ${j.match.exclude_args.join(", ")}`]:[]]}function Tg(j,K){return j.rulebooks.find((te)=>te.rules.includes(K))?.source??"project"}function od(j,K){return Object.entries({...j.userConfig?.overrides??{},...j.projectConfig?.overrides??{}}).filter((te)=>{if(K==="off")return te[1]==="off";return!!te[1]&&typeof te[1]==="object"}).map(([te,re])=>({key:te,value:re}))}function ld(j){for(let K of j.errors)console.error(K)}import{dirname as _d,join as lo}from"node:path";import{join as ji,resolve as qg}from"node:path";function _i(j){let K=m(j);if(K.errors.length>0)return{ok:!1,result:{ok:!1,errors:K.errors,entries:[]}};return{ok:!0,config:K.config??pt}}function cd(j,K=[]){It(j,{version:1,rules:K,overrides:{},transparent_wrappers:[]})}function dd(j,K="project-rules"){It(j,{rulebook_version:1,name:K,version:"1.0.0",description:K==="project-rules"?"Project-specific CC Safety Net rules.":"User-specific CC Safety Net rules.",author:K==="project-rules"?"project":"user",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as oo}from"node:path";var Ig="custom.";function to(j){if(j.rulebook_version!==2)return[];let K=j.rules.map((te)=>({name:te.name,command:te.command,block_args:[],match:te.match,reason:te.reason,intent:te.intent}));return(j.tests??[]).flatMap((te,re)=>{let oe=Ti(v(te.command));if(oe.length===0)return[`tests[${re}]: could not parse fixture command: ${te.command}`];let ce=oe.reduce((de,we)=>de??E(we,K)?.id.slice(Ig.length),void 0);if(te.expect==="blocked"){if(ce===te.rule)return[];let de=ce?`"${ce}" matched first`:"no rule matched";return[`tests[${re}]: expected "${te.rule}" to block "${te.command}" but ${de}`]}return ce?[`tests[${re}]: expected "${te.command}" to be allowed but "${ce}" matched`]:[]})}function Ti(j){return j.nodes.flatMap((K)=>{if(K.kind==="group"||K.kind==="function")return Ti(K.body);if(K.kind!=="command")return[];let te=be(ee(K.dialect,K.words)).words.map(t);return[...te.length>0?[te]:[],...K.nested.flatMap((re)=>Ti(re))]})}var Ii="Rule synchronization exceeds CC Safety Net's safe resource limits.",no=Object.freeze({maxSources:J,concurrency:4,maxRequests:131,maxResponseBytes:67108864});function ro(j={}){return{requests:0,responseBytes:0,maxRequests:j.maxRequests??no.maxRequests,maxResponseBytes:j.maxResponseBytes??no.maxResponseBytes}}function Qt(j){return{controller:new AbortController,budget:ro(),resolveUrl:j}}function ud(j){return j instanceof Error&&j.message===Ii}function pd(j){if(j.requests>=j.maxRequests)throw Error(Ii);j.requests++}function fd(j,K){if(K>j.maxResponseBytes-j.responseBytes)throw j.responseBytes+=K,Error(Ii);j.responseBytes+=K}var yd=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function md(j,K,te=S(oo(oo(K)),"rules policy"),re=Qt()){if(x(j))return Fg(j,re);return jg(j,K,te)}async function hd(j,K,te,re,oe,ce){if(!x(j))return md(j,K,te,re);let de=oe?null:$g(j,K,te);if(de)return de;if(!oe&&!ce)throw Error(`${j} is not vendored; run rule update ${j} to vendor it`);return md(j,K,te,re)}function $g(j,K,te=S(oo(oo(K)),"rules policy")){let re=O(j),oe=N(K,re.name),ce=r(s(te,oe));if(ce===null)return null;let de=ae($i(ce,`Invalid rulebook ${oe}.`));if(de.name!==re.name)throw Error(`rulebook name "${de.name}" in ${oe} must match "${re.name}"`);return{spec:j,rulebook:de,content:ce}}async function vd(j,K={}){if(!Y(j))throw Error(`Invalid GitHub repository source: ${j}`);let[te,re]=j.split("/");if(!te||!re)throw Error(`Invalid GitHub repository source: ${j}`);if(K.ref!==void 0&&!ie(K.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${K.ref}`);let oe=K.operation??Qt(),ce=K.ref??await Og(te,re,j,oe),de=await Ld(te,re,ce,j,oe),we=await io(`https://api.github.com/repos/${te}/${re}/git/trees/${de}?recursive=1`,"tree",oe),xe=we.response;if(!xe.ok)throw Error(`Failed to inspect ${j}: GitHub tree returned ${xe.status}`);let Ce=JSON.parse(we.content);if(!Array.isArray(Ce?.tree))throw Error(`Failed to inspect ${j}: unexpected GitHub tree response`);let Se=Ce.tree,Ne=[...new Set(Se.flatMap((He)=>{if(!He||typeof He!=="object")return[];let at=He;if(at.type!=="blob"||typeof at.path!=="string")return[];let mt=at.path.match(dt);return mt?.[1]?[mt[1]]:[]}))].sort();if(Ne.length===0)throw Error(`No rulebooks found in ${j} under ${fe}/`);return{source:j,owner:te,repo:re,ref:ce,commit:de,names:Ne}}async function Og(j,K,te,re){let oe=await io(`https://api.github.com/repos/${j}/${K}`,"metadata",re),ce=oe.response;if(!ce.ok)throw Error(`Failed to inspect ${te}: GitHub returned ${ce.status}`);let we=JSON.parse(oe.content)?.default_branch;if(typeof we!=="string"||we==="")throw Error(`Failed to inspect ${te}: missing default branch`);if(!ie(we))throw Error(`GitHub returned an invalid default branch: ${we}`);return we}function jg(j,K,te){ut(j);let re=N(K,j),oe=r(s(te,re));if(oe===null)throw Error(`Rulebook source not found: ${j}`);let ce=bd($i(oe,"Invalid local rulebook source."));if(ce.name!==j)throw Error(`rulebook name "${ce.name}" must match local source "${j}"`);return{spec:j,rulebook:ce,content:oe}}async function Fg(j,K){let te=O(j),re=await Ld(te.owner,te.repo,te.ref,j,K),oe=await io(`https://raw.githubusercontent.com/${te.owner}/${te.repo}/${re}/${te.path}`,"raw",K),ce=oe.response;if(!ce.ok)throw Error(`Failed to fetch ${j}: GitHub raw returned ${ce.status}`);let de=oe.content,we=bd($i(de,"Invalid GitHub rulebook response."));if(we.name!==te.name)throw Error(`rulebook name "${we.name}" must match GitHub source "${te.name}"`);return{spec:j,rulebook:we,content:de}}function bd(j){let K=ae(j),te=to(K);if(te.length>0)throw Error(te.join("; "));return K}function $i(j,K){try{return JSON.parse(j)}catch{throw Error(K)}}async function Ld(j,K,te,re,oe){let ce=await io(`https://api.github.com/repos/${j}/${K}/commits/${encodeURIComponent(te)}`,"commit",oe),de=ce.response;if(!de.ok)throw Error(`Failed to resolve ${re}: GitHub returned ${de.status}`);let we=JSON.parse(ce.content);if(typeof we?.sha!=="string"||we.sha==="")throw Error(`Failed to resolve commit for ${re}`);return we.sha}async function Ng(j,K,te={}){if(te.signal?.aborted)throw te.signal.reason;let re=te.budget??ro(),oe=new AbortController,ce=()=>oe.abort(te.signal?.reason);te.signal?.addEventListener("abort",ce,{once:!0});let de=!1,we=setTimeout(()=>{if(oe.signal.aborted)return;de=!0,oe.abort()},te.timeoutMs??yd.timeoutMs);try{if(te.signal?.aborted)throw te.signal.reason;pd(re);let xe=await(te.fetch??fetch)(j,{signal:oe.signal,redirect:"error"});if(!xe.ok)return wd(xe),{response:xe,content:""};return{response:xe,content:await Mg(xe,K,re,()=>oe.abort())}}catch(xe){if(de)throw Error("GitHub request timed out",{cause:xe});if(te.signal?.aborted)throw te.signal.reason;throw xe}finally{clearTimeout(we),te.signal?.removeEventListener("abort",ce)}}function io(j,K,te){return Ng(te.resolveUrl?.(j)??j,K,{budget:te.budget,signal:te.controller.signal})}async function Mg(j,K,te=ro(),re){let oe=yd[`${K}Bytes`],ce=Number(j.headers.get("content-length"));if(Number.isFinite(ce)&&ce>oe)throw wd(j),Error(`GitHub ${K} response exceeds ${oe} bytes`);if(!j.body)return"";let de=j.body.getReader(),we=[],xe=0;while(!0){let Ce=await de.read();if(Ce.done)break;try{fd(te,Ce.value.byteLength)}catch(Se){throw re?.(),gd(de),Se}if(xe+=Ce.value.byteLength,xe>oe)throw re?.(),gd(de),Error(`GitHub ${K} response exceeds ${oe} bytes`);we.push(Buffer.from(Ce.value))}return Buffer.concat(we,xe).toString("utf-8")}function wd(j){if(!j.body)return;kd(()=>j.body?.cancel())}function gd(j){kd(()=>j.cancel())}function kd(j){try{Promise.resolve(j()).catch(()=>{})}catch{}}var Hg=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function xd(j,K){let te=Rd(j.rules,K);if(te.length>0)return{ok:!0,specs:te};return Sd(j.rules,K)}function Cd(j,K){let te=Rd(j,K);if(te.length>0)return{ok:!0,specs:te};let re=Gg(j,K);if(re.length>0)return{ok:!0,specs:re};let oe=Bg(j,K);if(!oe.ok)return oe;if(oe.specs.length>0)return{ok:!0,specs:oe.specs};return Sd(j,K)}function Sd(j,K){let te=j.filter((re)=>Oi(re)?.name===K);if(te.length===1)return{ok:!0,specs:te};return Ug(K,te)}function Ug(j,K){return{ok:!1,result:{ok:!1,errors:K.length===0?[`No configured rulebook matches ${j}`]:[`Ambiguous rulebook match ${j}: ${K.join(", ")}`],entries:[]}}}function Rd(j,K){return j.filter((te)=>te===K)}function Gg(j,K){let te=K.match(Hg),re=te?.[1],oe=te?.[2],ce=te?.[3];if(!re||!oe||!ce||!ie(ce))return[];return Pd(j,(de)=>de.owner===re&&de.repo===oe&&de.ref===ce)}function Bg(j,K){if(!Y(K))return{ok:!0,specs:[]};let[te,re]=K.split("/"),oe=Pd(j,(de)=>de.owner===te&&de.repo===re);if(new Set(oe.map((de)=>Oi(de)?.ref).filter((de)=>!!de)).size<2)return{ok:!0,specs:oe};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${K}. Use an explicit ref:`,` cc-safety-net rule remove ${K}#<ref>`],entries:[]}}}function Oi(j){try{return O(j)}catch{return null}}function Pd(j,K){return j.filter((te)=>{let re=Oi(te);return re?K(re):!1})}async function ao(j,K={}){let te=Fi(K);return Vg(j,te,await so(j,te,Qt()))}function Vg(j,K,te){if(!te.ok)return te;let re=$t(j,K),oe=[...new Set(W(re.configPath,re.filesystemScope))];if(oe.length===0)return te;return{ok:!1,errors:oe,entries:te.entries}}async function so(j,K,te,re={},oe=new Set,ce=new Set){try{let de=$t(j,K),we=_i(de.configTarget);if(!we.ok)return we.result;let xe=we.config;if(K.check)return ay(xe,de,K);let Ce=K.only?xd(xe,K.only):{ok:!0,specs:xe.rules};if(!Ce.ok)return Ce.result;let Se=new Set([...K.refresh?Ce.specs:[],...oe]),Ne=(Lt)=>hd(Lt,de.configDir,de.filesystemScope,te,Se.has(Lt),!K.refresh||Se.has(Lt)),He=await ny(xe.rules,K.refresh?(Lt)=>Ne(Lt).then((Ct)=>({ok:!0,item:Ct})).catch((Ct)=>{if(ud(Ct))throw Ct;return{ok:!1,spec:Lt,message:Ct instanceof Error?Ct.message:String(Ct)}}):async(Lt)=>({ok:!0,item:await Ne(Lt)}),te),at=He.filter((Lt)=>!Lt.ok),mt=He.filter((Lt)=>Lt.ok).map((Lt)=>Lt.item),it=mt.flatMap((Lt)=>zg(Lt,xe.rules)),gt=mt.flatMap((Lt)=>Jg(Lt,ce,de)),ht=new Set([...it,...gt].map((Lt)=>Lt.spec)),vt=[...at,...it,...gt],yt=[],kt=Kg(yt,()=>mt.flatMap((Lt)=>ht.has(Lt.spec)||vt.length>0&&ce.has(Lt.spec)?[]:Wg(Lt,de,re,yt)));return{ok:vt.length===0,errors:vt.map((Lt)=>`Failed to update ${Lt.spec}: ${Lt.message}`),entries:mt.map(Zg),changes:kt}}catch(de){return lr(de)}}function zg(j,K){if(!x(j.spec))return[];let te=je(j.spec),re=K.filter((oe)=>oe!==j.spec&&je(oe).toLowerCase()===te.toLowerCase());if(re.length===0)return[];return[{ok:!1,spec:j.spec,message:`rulebook name "${te}" is also claimed by ${re.join(", ")}; rename one of them`}]}function Jg(j,K,te){if(!K.has(j.spec)||!x(j.spec))return[];let re=N(te.configDir,j.rulebook.name),oe=r(s(te.filesystemScope,re));if(oe===null||oe===j.content)return[];return[{ok:!1,spec:j.spec,message:`${re} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Wg(j,K,te,re){if(!x(j.spec))return[];let oe=N(K.configDir,j.rulebook.name),ce=s(K.filesystemScope,oe),de=r(ce);if(de===j.content)return[];return re?.push({target:ce,previous:de}),y(ce,j.content,void 0,te._testAfterPolicyRename),Yg(j,de)}function Kg(j,K){try{return K()}catch(te){for(let re of[...j].reverse()){if(re.previous===null){G(re.target);continue}y(re.target,re.previous)}throw te}}function Yg(j,K){if(K===null)return[`Vendored ${j.spec} (${j.rulebook.version})`];let te=he(K),re="problem"in te?null:te.rulebook,oe=new Map(re?.rules.map((de)=>[de.name,JSON.stringify(de)])??[]),ce=new Set(j.rulebook.rules.map((de)=>de.name));return[`Updated ${j.spec} (${re?.version??"unreadable"} -> ${j.rulebook.version})`,...[...ce].filter((de)=>!oe.has(de)).map((de)=>` + ${de}`),...[...oe.keys()].filter((de)=>!ce.has(de)).map((de)=>` - ${de}`),...j.rulebook.rules.filter((de)=>{let we=oe.get(de.name);return we!==void 0&&we!==JSON.stringify(de)}).map((de)=>` ~ ${de.name}`)]}function Zg(j){return{spec:j.spec,name:j.rulebook.name,version:j.rulebook.version,ruleCount:j.rulebook.rules.length}}async function Ed(j,K,te={}){return Xg(j,K,oy(te),Qt())}async function Xg(j,K,te,re,oe={}){let ce=null,de=!1;try{let we=$t(j,te),xe=r(we.configTarget);ce={target:we.configTarget,content:xe};let Ce=_i(we.configTarget);if(!Ce.ok)return Ce.result;let Se=Ce.config,Ne=Y(K);Qg(K,te,Ne);let He=Ne?await vd(K,{ref:te.ref,operation:re}):null,at=He?ey(He,te.rulebooks):[],mt=He?at.map((yt)=>ty(Se.rules,He,yt)??`${K}#${He.ref}/${yt}`):[K],it=mt.filter((yt)=>!Se.rules.includes(yt)),gt=[...Se.rules,...it];if(gt.length>J)return ry();if(gt.length!==Se.rules.length)de=!0,It(we.configTarget,{version:1,rules:gt,overrides:Se.overrides??{},transparent_wrappers:Se.transparent_wrappers??[]},void 0,oe._testAfterPolicyRename);let ht=await so(j,te,re,oe,new Set(it),new Set(it));if(!ht.ok)ar(we.configTarget,xe);if(!ht.ok||!He)return ht;let vt=at.filter((yt,kt)=>it.includes(mt[kt]??""));return{...ht,add:{source:K,ref:He.ref,selected:at,added:vt,alreadyConfigured:at.filter((yt)=>!vt.includes(yt)),commits:it.length>0?[He.commit]:[]}}}catch(we){if(de&&ce)try{ar(ce.target,ce.content)}catch(xe){return lr(xe)}return lr(we)}}function Qg(j,K,te){if(!te&&K.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!te&&K.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${j}`);if(K.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let re=K.rulebooks?.filter((oe)=>!c.test(oe))??[];if(re.length>0)throw Error(`Invalid rulebook names: ${re.join(", ")}`)}function ey(j,K){let te=K?[...new Set(K)]:j.names,re=te.filter((oe)=>!j.names.includes(oe));if(re.length>0)throw Error(`Rulebooks not found in ${j.source} at ${j.ref}: ${re.join(", ")}
265
- Available rulebooks: ${j.names.join(", ")}`);return te}function ty(j,K,te){let re=`${K.source}#${K.ref}/${te}`;if(j.includes(re))return re;let oe=`${K.source}#${K.commit}/${te}`;return j.find((ce)=>ce===oe)}async function ny(j,K,te=Qt()){if(j.length>J)throw Error(ge);let re=Array(j.length),oe=0,ce,de=Array.from({length:Math.min(j.length,no.concurrency)},async()=>{while(!ce){let we=oe;if(we>=j.length)return;oe++;try{re[we]=await K(j[we],we,te.controller.signal)}catch(xe){if(!ce)ce={value:xe},oe=j.length,te.controller.abort(xe);return}}});if(await Promise.all(de),ce)throw ce.value;return re}function ry(){return{ok:!1,errors:[ge],entries:[]}}function Fi(j){return{cwd:j.cwd,userConfigDir:j.userConfigDir,userConfigPath:j.userConfigPath,projectConfigPath:j.projectConfigPath,global:j.global,check:j.check,only:j.only,refresh:j.refresh}}function oy(j){return{...Fi(j),ref:j.ref,rulebooks:j.rulebooks}}function iy(j){return{...Fi(j),deleteSource:j.deleteSource}}async function Dd(j,K,te={}){try{return await sy(j,K,iy(te),{})}catch(re){return lr(re)}}async function sy(j,K,te,re){let oe=$t(j,te),ce=m(oe.configTarget);if(ce.errors.length>0)return{ok:!1,errors:ce.errors,entries:[]};if(!ce.config)return{ok:!1,errors:[`No config found at ${oe.configPath}`],entries:[]};let de=Cd(ce.config.rules,K);if(!de.ok)return de.result;let we=te.deleteSource?ly(oe.configDir,de.specs,oe.filesystemScope):{ok:!0,dirs:[]};if(!we.ok)return we.result;let xe=r(oe.configTarget);if(xe===null)return lr(Error("Rules config is unavailable."));try{It(oe.configTarget,{version:1,rules:ce.config.rules.filter((Ne)=>!de.specs.includes(Ne)),overrides:ce.config.overrides??{},transparent_wrappers:ce.config.transparent_wrappers??[]},void 0,re._testAfterPolicyRename)}catch(Ne){throw ar(oe.configTarget,xe),Ne}let Ce=await so(j,te,Qt(),re);if(!Ce.ok)return ar(oe.configTarget,xe),Ce;let Se=cy(we.dirs,re,oe.filesystemScope);if(!Se.ok){ar(oe.configTarget,xe);let Ne=await so(j,te,Qt(),re);if(!Ne.ok)return{ok:!1,errors:[...Se.result.errors,...Ne.errors],entries:Ne.entries};return Se.result}return Ce}async function ay(j,K,te){let re=Re(j,K.configDir,te.global?"user":"project",K.filesystemScope);return{ok:re.errors.length===0&&re.warnings.length===0,errors:[...re.errors,...re.warnings],entries:re.entries}}function ly(j,K,te){let re=K.flatMap((we)=>c.test(we)?[]:["--delete-source can only delete local rulebook sources"]),oe=K.map((we)=>ji(j,we)),ce=re.length>0?[]:oe.flatMap((we)=>Ad(we,te)),de=[...re,...ce];return de.length>0?{ok:!1,result:{ok:!1,errors:de,entries:[]}}:{ok:!0,dirs:oe}}function Ad(j,K){let te=qg(j),re=s(K,te),oe=ue(re);if(!oe)return[`Local rulebook source directory not found: ${j}`];let ce=oe.find((de)=>de.name==="rulebook.json");if(!ce)return[`Local rulebook source directory is missing rulebook.json: ${j}`];if(ce.kind!=="file")throw new o(K.label);if(r(s(K,ji(te,"rulebook.json"))),oe.length>1)return[`Local rulebook source directory contains extra files: ${j}. delete manually if you really want to remove the directory.`];return[]}function cy(j,K,te){let re=j.flatMap((oe)=>{try{if(!ue(s(te,oe)))return[];let ce=Ad(oe,te);if(ce.length>0)return ce;return dy(oe,K,te),[]}catch(ce){return[`Failed to delete local rulebook source ${oe}: ${ce instanceof Error?ce.message:String(ce)}`]}});return re.length>0?{ok:!1,result:{ok:!1,errors:re,entries:[]}}:{ok:!0}}function dy(j,K,te){if(K._testDeleteLocalSourceDir){K._testDeleteLocalSourceDir(j);return}G(s(te,ji(j,pe))),ct(s(te,j))}function ar(j,K){if(K===null){G(j);return}y(j,K)}function lr(j){return{ok:!1,errors:[j instanceof Error?j.message:String(j)],entries:[]}}var uy=".safety-net.json",py="~/.cc-safety-net/config.json";async function $d(j,K){return[await Td(j,{legacyPath:zs({cwd:K.cwd}),configPath:A(K.cwd),defaultRulebookName:"project-rules",migratedFrom:uy,cleanup:K.cleanup,syncOptions:{cwd:K.cwd}}),await Td(j,{legacyPath:yr(j),configPath:T(j),defaultRulebookName:"user-rules",migratedFrom:py,cleanup:K.cleanup,syncOptions:{cwd:K.cwd,global:!0}})].every((re)=>re)?0:1}async function Td(j,K){let te=$t(j,K.syncOptions),re=s(te.filesystemScope,K.legacyPath),oe=r(re);if(oe===null)return console.log(`No legacy config found at ${K.legacyPath}`),!0;let ce=my(oe);if(!ce.ok){for(let at of ce.errors)console.error(at);return!1}let de=m(te.configTarget);if(de.errors.length>0){for(let at of de.errors)console.error(at);return!1}let we=de.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},xe=gy(_d(K.configPath),we.rules,K.defaultRulebookName,K.migratedFrom,te.filesystemScope),Ce=lo(_d(K.configPath),xe,"rulebook.json"),Se=s(te.filesystemScope,Ce),Ne=[Id(te.configTarget),Id(Se)],He=await fy(j,K,te.configTarget,Se,xe,ce.config.rules,we.rules.includes(xe)?we.rules:[...we.rules,xe],we.overrides??{},we.transparent_wrappers??[]);if(!He.ok){vy(Ne);for(let at of He.errors)console.error(at);return!1}if(!K.cleanup)return console.log(`Migrated legacy config at ${K.legacyPath}. Legacy file is no longer used.`),!0;if(!hy(te.configTarget,Se,xe,K.migratedFrom,ce.config.rules))return console.error(`Migration cleanup verification failed for ${K.legacyPath}`),!1;return G(re),console.log(`Deleted legacy config at ${K.legacyPath}`),!0}async function fy(j,K,te,re,oe,ce,de,we,xe){try{return It(te,{version:1,rules:de,overrides:we,transparent_wrappers:xe}),It(re,yy(oe,K.migratedFrom,ce)),await ao(j,K.syncOptions)}catch(Ce){return{ok:!1,errors:[Ce instanceof Error?Ce.message:String(Ce)]}}}function my(j){try{let K=JSON.parse(j),te=vo(K);if(te.errors.length>0)return{ok:!1,errors:te.errors};return{ok:!0,config:{version:1,rules:K.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function gy(j,K,te,re,oe){let ce=K.find((de)=>by(s(oe,lo(j,de,"rulebook.json")))===re);if(ce)return ce;if(r(s(oe,lo(j,te,"rulebook.json")))===null)return te;for(let de=2;;de++){let we=`${te}-${de}`;if(r(s(oe,lo(j,we,"rulebook.json")))===null)return we}}function yy(j,K,te){return{rulebook_version:1,name:j,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:K,allowed_commands:[...new Set(te.map((re)=>re.command))],rules:te,tests:te.map((re)=>({command:[re.command,re.subcommand,re.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:re.name}))}}function hy(j,K,te,re,oe){if(!m(j).config?.rules.includes(te))return!1;try{let de=r(K);if(de===null)return!1;let we=JSON.parse(de);return we.migrated_from===re&&JSON.stringify(we.rules)===JSON.stringify(oe)}catch{return!1}}function Id(j){return{target:j,content:r(j)}}function vy(j){for(let K of j){if(K.content===null){G(K.target);continue}y(K.target,K.content)}}function by(j){let K=r(j);if(K===null)return null;try{let te=JSON.parse(K);return typeof te.migrated_from==="string"?te.migrated_from:null}catch{return null}}import{mkdir as Ly,readFile as wy,writeFile as ky}from"node:fs/promises";import{dirname as xy,join as Cy}from"node:path";var Sy=86400000,Ry=604800000;async function jd(j,K=Date.now()){if(j.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let te=Ke(j);if(!te)return null;let re=Cy(te,".cc-safety-net","update-check.json"),oe=await Py(re,K);if(!oe.lastCheck||K-oe.lastCheck>Sy){let we=await tn();if(oe.lastCheck=K,we.latestVersion)oe.latestVersion=we.latestVersion;if(!await Od(re,oe))return null;if(we.error)return null}let ce=oe.latestVersion,de=Et();if(!ce||!Co(ce,de))return null;if(oe.notifiedVersion===ce&&oe.notifiedAt!==void 0&&K-oe.notifiedAt<Ry)return null;if(oe.notifiedVersion=ce,oe.notifiedAt=K,!await Od(re,oe))return null;return`UPDATE_AVAILABLE: cc-safety-net v${ce} is available (running v${de}). Ask the user once whether to run \`npx -y cc-safety-net@latest update\`; continue the current task either way and do not raise this again.`}async function Py(j,K){let te=await wy(j,"utf8").then((ce)=>JSON.parse(ce)).catch(()=>{return});if(!te||typeof te!=="object"||Array.isArray(te))return{};let re=te,oe=(ce)=>typeof ce==="number"&&Number.isFinite(ce)&&ce<=K?ce:void 0;return{lastCheck:oe(re.lastCheck),latestVersion:typeof re.latestVersion==="string"?re.latestVersion:void 0,notifiedVersion:typeof re.notifiedVersion==="string"?re.notifiedVersion:void 0,notifiedAt:oe(re.notifiedAt)}}async function Od(j,K){return Ly(xy(j),{recursive:!0,mode:448}).then(()=>ky(j,JSON.stringify(K),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as Ey,resolve as Ni}from"node:path";var Fd="CC Safety Net Config",Dy="═".repeat(Fd.length),Ay="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",_y=new Set(["rule.json","rule.lock","cache"]);function Nd(j,K={}){try{return Ty(j,K)}catch(te){if(te instanceof o)return console.error(te.message),1;throw te}}function Ty(j,K){let te=K.cwd??process.cwd(),re=K.userConfigPath??T(j),oe=K.projectConfigPath??A(te),ce=K.legacyUserConfigPath??yr(j),de=K.legacyProjectConfigPath??gs(te),we=Ni(te,fe),xe=H(j,{cwd:te,userConfigPath:re,projectConfigPath:oe}),Ce=H(j,{cwd:te}),Se=s(xe.userScope,re),Ne=s(xe.projectScope,oe),He=K.legacyUserConfigPath?D(K.legacyUserConfigPath,"user policy"):s(Ce.userScope,ce),at=K.legacyProjectConfigPath?D(K.legacyProjectConfigPath,"project policy"):s(Ce.projectScope,de),mt=!1,it=!1,gt=[],ht=[],vt=Iy(s(Ce.projectScope,we));if(Oy(),r(Se)!==null){let yt=en(Se);if(yt.errors.push(...W(re,xe.userScope)),gt.push({scope:"User",path:re,result:yt,schema:"rules",target:Se}),yt.errors.length>0)mt=!0}if(r(He)!==null)if(it=!0,r(Se)!==null)ht.push(co("user","cleanup"));else{let yt=bo(He);if(gt.push({scope:"User",path:ce,result:yt,schema:"legacy",inactive:!0,target:He}),ht.push(co("user",yt.errors.length>0?"fix-or-delete":"migrate")),yt.errors.length>0)mt=!0}if(r(Ne)!==null){let yt=en(Ne);if(yt.errors.push(...W(oe,xe.projectScope)),gt.push({scope:"Project",path:Ni(oe),result:yt,schema:"rules",target:Ne}),yt.errors.length>0)mt=!0;if(r(at)!==null)it=!0,ht.push(co("project","cleanup"))}else if(r(at)!==null){it=!0,mt=!0;let yt=bo(at);gt.push({scope:"Project",path:Ni(de),result:yt,schema:"legacy",inactive:!0,target:at}),ht.push(co("project",yt.errors.length>0?"fix-or-delete":"migrate"))}if(vt?.result.errors.length)mt=!0;if(gt.length===0&&!vt)return console.log(`
266
- No config files found. Using built-in rules only.`),0;for(let yt of gt)if(yt.inactive)Fy(yt.scope,yt.path,yt.result);else if(yt.result.errors.length>0)Ny(yt.scope,yt.path,yt.result.errors);else{if(yt.schema==="rules"&&Uy(yt.target))console.log(`
267
- Added $schema to ${yt.scope.toLowerCase()} config.`);jy(yt.scope,yt.path,yt.result,yt.schema)}for(let yt of ht)console.error(`
268
- ${bt.red(yt)}`);if(vt)if(vt.result.errors.length>0)Hy(vt.path,vt.result.errors);else My(vt.path,vt.result);if(mt)return console.error(`
269
- Config validation failed.`),1;return console.log(it?`
251
+ `)}function hc(A,z){return z.map((X)=>A==="install"&&X.target==="kimi-code"&&X.unavailableReason==="already installed"?{...X,available:!0,unavailableReason:void 0,label:`${X.label} (global hook installed)`}:X)}function Jm(A,z){if(A.selectKimiInstallMethod)return A.selectKimiInstallMethod();if(!Qo(A.input,A.output))return Promise.resolve("global-hook");return _l({input:A.input,output:A.output,globalHookInstalled:$n({environment:z,cwd:process.cwd()}).status==="configured"})}async function Sc(A,z,X,ee=!1,te){let ae=Bm[z];if(A==="install")ae?.beforeInstall?.(X,ee);if(A==="uninstall")ae?.beforeUninstall?.(X);if(qm(z))return Um(A,z,X,ee);if(Vm(z))return Gm(A,z,X,ee);if(A==="uninstall")return z==="opencode"?Hm(X):Mm(z);return[await Nm(z,X,ee,te),await ae?.afterInstall?.(X)].filter(Boolean).join(`
252
+ `)}function Wm(A){let z=xt({label:"update"},A).errors[0];if(z)throw Error(z)}async function Km(A,z=fn){let X=await kc(A,z),ee=ci(En(A),"installed-plugins");return{targets:ii([...X.hooks.filter((ae)=>ae.platform!=="copilot-cli"&&ae.detected).map((ae)=>ae.platform),...[mr,Zs,Ys].flatMap((ae)=>ui(ci(ee,...ae))?["copilot-cli"]:[]),...ur(A,di)?["claude-code"]:[],...pi(X.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:X.codexPluginListOutput}}async function Ym(A){let z=l(),X=A.output??process.stdout,ee=(A.scriptPath??process.argv[1]??"").split(/[\\/]/),te=ee.find((et)=>/^bunx-\d+-/.test(et)),ae=te!==void 0||ee.includes("_npx")?null:(A.checkLatestVersion??Wt)(),le=async()=>{let et=ae&&await ae;if(et?.updateAvailable)X.write(`
253
+ Update available: cc-safety-net ${et.currentVersion} → ${et.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
254
+ `)},ye=Km(z,A.fetchVersion??fn).then(async(et)=>{let Ee=new Set(et.targets);return{targets:et.targets,codexPluginListOutput:et.codexPluginListOutput,available:new Map(await Promise.all(Mt.filter((at)=>Ee.has(at.target)&&fc.has(at.target)).map(async(at)=>[at.target,await si(at.probeCommand)])))}}),he=await Rn(A.showBanner??!0,()=>({ready:ye,finish:()=>ye}),()=>Sn({input:A.input??process.stdin,output:X}),{loadingMessage:"Checking installed integrations…",output:X}),ve=await Promise.resolve().then(()=>(Kl(z.tmpdir,process.platform,te),null)).catch((et)=>Un(et));if(he.targets.length===0){if(X.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),ve!==null)console.error(ve);return await le(),ve===null?0:1}let be=he.targets.some((et)=>mc.has(et))?await Promise.resolve().then(()=>(Or(z),null)).catch((et)=>Un(et)):null,Ie=await lr(Promise.all(he.targets.map((et)=>{if(fc.has(et)&&!he.available.get(et))return Promise.resolve({message:`${bt(et)} not found; skipped`,failed:!1});if(be!==null&&mc.has(et))return Promise.resolve({message:be,failed:!0});return Sc("install",et,z,!0,he.codexPluginListOutput).then((Ee)=>({message:Ee,failed:!1}),(Ee)=>({message:Un(Ee),failed:!0}))})),{loadingMessage:`Updating ${he.targets.length} integration${he.targets.length===1?"":"s"}…`,output:X}),Xe=ve===null?Ie:[...Ie,{message:ve,failed:!0}];return Xe.forEach((et)=>{et.failed?console.error(et.message):X.write(`${et.message}
255
+ `)}),await le(),Xe.some((et)=>et.failed)?1:0}function fi(A,z={}){return Promise.resolve().then(()=>Wm(A)).then(()=>Ym(z)).catch((X)=>(console.error(Un(X)),1))}async function Gn(A,z,X={}){try{let ee=l(),te=await Rn(!0,()=>jm(ee,A,z,X),()=>Sn({input:X.input??process.stdin,output:X.output??process.stdout}),{loadingMessage:A==="install"?"Checking available integrations…":"Checking installed integrations…",output:X.output??process.stdout});if(!te)return(X.output??process.stdout).write(`Cancelled: nothing was ${A}ed.
256
+ `),0;if(te==="update")return(X.runUpdate??(()=>fi([],{fetchVersion:X.fetchVersion,input:X.input,output:X.output,showBanner:!1})))();let ae=X.output??process.stdout;return await Yl(te,async(le)=>{if(le==="kimi-code"&&A==="install"){let he=await Jm(X,ee);if(he===null){ae.write(`Cancelled: Kimi Code integration was not installed.
257
+ `);return}if(he==="plugin"){ae.write(`${zm(ee)}
258
+ `);return}}let ye=await lr(Sc(A,le,ee),{loadingMessage:`${A==="install"?"Installing":"Uninstalling"} ${bt(le)} integration…`,output:ae});ae.write(`${ye}
259
+ `)}),0}catch(ee){return console.error(Un(ee)),1}}function Un(A){let z=A instanceof Error?A.message:String(A),X=typeof A==="object"&&A!==null&&"code"in A?A.code:null;if(X==="EACCES"||X==="EPERM")return`${z}
260
+ Check file permissions for the target config file and parent directory.`;if(X==="ENOENT")return`${z}
261
+ Check that the target config path and parent directory exist.`;if(X==="ENOTDIR")return`${z}
262
+ Check that every parent path component is a directory.`;return z}import{mkdirSync as ng}from"node:fs";import{dirname as rg}from"node:path";import{createInterface as og}from"node:readline";import{existsSync as Pc,readFileSync as Zm}from"node:fs";function ln(A,z){let X=Je(A,z);return{policy:X.policy,errors:oe(qe(X.issues,Ye,(ee)=>ee.kind==="custom")," "," ")}}function Bn(A,z){return ln(A,z).errors}function Rc(A,z){return{"safety.level":A.safety.level,...mi("safety.overrides",A.safety.overrides),"workflow.worktree_mode":String(A.workflow.worktree_mode),"destructive_command_protection.enabled":String(A.destructive_command_protection.enabled),...mi("destructive_command_protection.overrides",A.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":gi(A.destructive_command_protection.allow_paths),"secret_protection.enabled":String(A.secret_protection.enabled),...mi("secret_protection.overrides",A.secret_protection.overrides),"secret_protection.deny_paths":gi(A.secret_protection.deny_paths),"secret_protection.allow_paths":gi(A.secret_protection.allow_paths),...z?{"audit.retention_days":String(A.audit.retention_days)}:{}}}function Fr(A,z,X){let ee=Rc(A,X),te=Rc(z,X);return[...new Set([...Object.keys(ee),...Object.keys(te)])].flatMap((ae)=>ee[ae]===te[ae]?[]:[{field:ae,before:ee[ae],after:te[ae]}])}function qn(A,z){let X=d(A,z);if(!Pc(X))return{baseline:x(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,A.home),diagnostics:[]};let ee=cn(X),te=ln(ee.value,A.home);return{baseline:te.policy,diagnostics:ee.errors.length>0?ee.errors:te.errors}}function cn(A){if(!Pc(A))return{errors:[`${A}: file not found`]};try{return{value:JSON.parse(Zm(A,"utf-8")),errors:[]}}catch(z){let X=z instanceof Error?z.message:String(z);return{errors:[`${A}: ${z instanceof SyntaxError?`Invalid JSON: ${X}`:X}`]}}}function jr(A,z){let X=Xm(A)?A:{};return{version:z.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((ee)=>X[ee]!==void 0).map((ee)=>[ee,X[ee]]))}}function mi(A,z){return Object.fromEntries(Object.entries(z).flatMap(([X,ee])=>ee===void 0?[]:[[`${A}.${X}`,String(ee)]]))}function gi(A){return A.length===0?"(none)":A.join(", ")}function Xm(A){return!!A&&typeof A==="object"&&!Array.isArray(A)}import{chmodSync as Qm,existsSync as Ec,mkdirSync as eg,readFileSync as Dc}from"node:fs";import{dirname as tg}from"node:path";function Ac(A,z={}){let X=d(A,z);if(!Ec(X))return{path:X,exists:!1,raw:"",policy:W(),errors:[]};let ee=Dc(X,"utf-8");if(!ee.trim())return{path:X,exists:!0,raw:ee,policy:W(),errors:["Config file is empty"]};try{let te=ln(JSON.parse(ee),A.home);return{path:X,exists:!0,raw:ee,policy:te.policy,errors:te.errors}}catch(te){return{path:X,exists:!0,raw:ee,policy:W(),errors:[`Invalid JSON: ${te instanceof Error?te.message:String(te)}`]}}}function Vt(A,z,X={}){let ee=d(A,X),te=ln(z,A.home);if(te.errors.length>0)return{path:ee,policy:W(),errors:te.errors};let ae=te.policy;return eg(tg(ee),{recursive:!0,mode:448}),g(ne(ee),`${JSON.stringify(ae,null,2)}
263
+ `,384),Qm(ee,384),{path:ee,policy:ae,errors:[]}}function _c(A,z){let X=ln(z,A.home);if(X.errors.length>0)return{errors:X.errors};return{preview:Te(X.policy,A.env),errors:[]}}function Tc(A,z={}){let X=d(A,z);if(!Ec(X))return Vt(A,J,z);let ee=Dc(X,"utf-8");if(!ee.trim())return Vt(A,J,z);try{return Vt(A,x(JSON.parse(ee),A.home),z)}catch{return Vt(A,J,z)}}var $c=new Set(["check","apply"]),Ic="(unset)";async function Fc(A,z,X={}){let ee=xt({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},z),te=ee.positionals[0],ae=[...ee.errors,...te&&!$c.has(te)?[`Unknown policy subcommand: ${te}`]:[],...te&&$c.has(te)&&!ee.positionals[1]?[`policy ${te} requires a file`]:[],...ee.positionals.slice(2).map((Ee)=>`Unexpected policy argument: ${Ee}`)];if(ae.length>0){for(let Ee of ae)console.error(Ee);return 1}let le=ee.positionals[1];if(!te||!le)return Ln(Zn,console.error),1;let ye=ee.flags.global?d(A):v(X.cwd??process.cwd()),he=cn(le),ve=[...he.errors,...Bn(he.value,A.home).map((Ee)=>`${le}: ${Ee}`),...!ee.flags.global&&ag(he.value)&&he.value.audit!==void 0?[`${le}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(ve.length>0){for(let Ee of ve)console.error(Ee);return 1}let be=x(he.value,A.home);if(console.log(`Scope: ${ee.flags.global?"user":"project"} (${ye})`),console.log(`Proposal: ${le}`),ee.flags.global)Oc(x(cn(ye).value,A.home),be,!0);if(!ee.flags.global){let Ee=qn(A).baseline;console.log("Effective policy (user + project merged):"),Oc(Y(Ee,se(cn(ye).value,A.home).policy).policy,Y(Ee,se(he.value,A.home).policy).policy,!1)}if(te==="check")return 0;let Ie=X.input??process.stdin,Xe=X.output??process.stdout;if(!Ie.isTTY||!Xe.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${le}${ee.flags.global?" --global":""}`),1;if(!await ig(`Apply this policy to ${ye}? [y/N] `,Ie,Xe))return console.log("Cancelled; nothing was written."),0;return sg(A,ye,he.value,be,ee.flags.global),console.log(`Policy applied: ${ye}`),0}function ig(A,z,X){let ee=og({input:z,output:X,terminal:!1});return new Promise((te)=>{ee.once("close",()=>te(!1)),ee.question(A,(ae)=>{te(/^y(es)?$/i.test(ae.trim())),ee.close()})})}function sg(A,z,X,ee,te){if(te){Vt(A,ee);return}ng(rg(z),{recursive:!0}),Rt(z,jr(X,ee))}function Oc(A,z,X){let ee=Fr(A,z,X);if(ee.length===0){console.log("No changes.");return}console.log(`Changes (${ee.length}):`);for(let te of ee)console.log(` ${te.field}: ${te.before??Ic} -> ${te.after??Ic}`)}function ag(A){return!!A&&typeof A==="object"&&!Array.isArray(A)}import{join as Ly}from"node:path";var jc="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Priority |\n|-------|-------------|---------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | Second |\n| GitHub source | Listed in a local `rule.json` | Vendored into the consumer's `<rulebook-name>/rulebook.json` by `rule add` | Source order |\n\nEvery rulebook is a live file: the runtime reads it on each tool call, so an edit applies to the next command with no publishing step.\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule verify` reports the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- Transparent wrappers have no built-in defaults. Configure only wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n\n## Rulebook Sources\n\n- Local sources are bare rulebook names such as `project-rules`; the rulebook file is `.cc-safety-net/rules/project-rules/rulebook.json`.\n- Run `cc-safety-net rule add owner/repo` to add every rulebook currently present on the repository's default branch.\n- Use `--only` to select one or more rulebooks while preserving their order: `cc-safety-net rule add owner/repo --only aws gcloud`.\n- Use `--ref` to select a branch, tag, or commit instead of the default branch: `cc-safety-net rule add owner/repo --ref v2 --only aws`.\n- GitHub sources are stored in canonical form as `owner/repo#ref/<rulebook-name>`. That form remains valid in `rule.json` and as direct CLI input.\n- GitHub refs may contain `/`-separated path segments, such as `feature/rulebook-v2`.\n- The GitHub source name, the repository directory name, and the rulebook `name` must match exactly.\n- Rulebook source strings must be unique in a config.\n\n## rulebook.json Schema\n\n```json\n{\n \"rulebook_version\": 1,\n \"name\": \"project-rules\",\n \"version\": \"1.0.0\",\n \"description\": \"Project-specific CC Safety Net rules.\",\n \"author\": \"project\",\n \"allowed_commands\": [\"docker\"],\n \"rules\": [\n {\n \"name\": \"block-docker-system-prune\",\n \"command\": \"docker\",\n \"subcommand\": \"system\",\n \"block_args\": [\"prune\"],\n \"reason\": \"Use targeted cleanup instead.\"\n }\n ],\n \"tests\": [\n {\n \"command\": \"docker system prune\",\n \"expect\": \"blocked\",\n \"rule\": \"block-docker-system-prune\"\n },\n {\n \"command\": \"docker ps\",\n \"expect\": \"allowed\"\n }\n ]\n}\n```\n\n### Rulebook Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `rulebook_version` | Yes | Must be `1` or `2` |\n| `name` | Yes | `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` |\n| `version` | Yes | Non-empty string |\n| `description` | No | Free text; not type-checked at runtime |\n| `author` | No | Free text; not type-checked at runtime |\n| `allowed_commands` | Yes | Unique command names matching `^[a-zA-Z][a-zA-Z0-9_-]*$` |\n| `rules` | Yes | Array of rule objects |\n| `tests` | No | Array of fixtures |\n\n### Rule Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Unique within the rulebook (case-insensitive); same pattern as rulebook `name` |\n| `command` | Yes | Must be listed in `allowed_commands`; basename only, not path |\n| `subcommand` | No | Same pattern as `command`; omit to match any subcommand |\n| `intent` | No | One of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain` |\n| `block_args` | Yes | Non-empty array of non-empty strings |\n| `reason` | Yes | Non-empty string, max 256 chars |\n\n### Rule Fields (`rulebook_version` 2)\n\nVersion 2 replaces `subcommand` and `block_args` with an exact-token `match` object. Version 1 rulebooks keep their fields and their behavior; a client that does not support version 2 rejects the rulebook instead of applying broader version 1 semantics.\n\n```json\n{\n \"name\": \"block-terraform-apply-destroy\",\n \"command\": \"terraform\",\n \"match\": {\n \"command_path\": [\"apply\"],\n \"any_args\": [\"-destroy\", \"--destroy\"]\n },\n \"reason\": \"Review a destroy plan first with 'terraform plan -destroy'.\",\n \"intent\": \"use_alternative\"\n}\n```\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Same as version 1 |\n| `command` | Yes | Same as version 1 |\n| `match.command_path` | Yes | Non-empty array of non-empty command words |\n| `match.any_args` | No | Non-empty array of unique non-empty argument tokens |\n| `match.exclude_args` | No | Non-empty array of unique non-empty argument tokens |\n| `intent` | No | Same as version 1 |\n| `reason` | Yes | Same as version 1 |\n\n### Matching Behavior (`rulebook_version` 2)\n\n- **Command**: Normalized to lowercase basename, as in version 1.\n- **Command path**: After recognized global options and their values are skipped, the next command words must equal `command_path` exactly. AWS, gcloud, and Azure CLI value-taking global options are built in; Terraform's `-chdir=dir` is `=`-joined and is skipped with its own token.\n- **Unrecognized options**: A token starting with `-` that is not a recognized global option is skipped without consuming a value, so an unlisted value-taking option with a separate value (`--newflag value`) makes the rule miss. This fails open deliberately; document such gaps in the rulebook.\n- **`any_args`**: At least one listed token must appear literally among the arguments.\n- **`exclude_args`**: Any listed token appearing literally among the arguments prevents the match, which is how a safe preview such as `aws s3 rm --dryrun` stays allowed.\n- **No short-option expansion**: Arguments compare as exact tokens, so list every accepted spelling (`\"-destroy\"` and `\"--destroy\"`).\n- **Literal and case-sensitive**: No regex, glob, or substring matching. The first matching rule wins.\n- Release channels are separate rules: `gcloud beta compute instances delete` needs its own `command_path`.\n\n### Test Fixture Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `command` | Yes | Non-empty shell command string |\n| `expect` | Yes | `\"blocked\"` or `\"allowed\"` |\n| `rule` | Required for blocked fixtures | Rule name expected to block the command |\n\nFixtures are optional documentation of intended behavior. Version 1 fixtures are shape-validated only. Version 2 fixtures are evaluated against the rulebook's own rules when a source is fetched by `rule add` or `rule update`, and by `rule verify`; a failing fixture rejects that source before it is written. Loading a rulebook does not re-evaluate fixtures. CC Safety Net never executes fixture commands; they are analyzer inputs only.\n\n## Matching Behavior\n\nThe subcommand, argument, and option rules below describe `rulebook_version` 1 rules; version 2 rules match as described in Matching Behavior (`rulebook_version` 2). Execution order and transparent wrappers apply to both.\n\n- **Command**: Normalized to lowercase basename with any trailing `.exe` removed (`/usr/bin/git` → `git`).\n- **Subcommand**: The first command token after recognized Git and Docker global options and their values; `--` ends option parsing. An unrecognized option without `=` may consume the following token as its value.\n- **Arguments**: Each `block_args` value is compared literally against every command token, including expanded short options. The command is blocked if **any** item matches.\n- **Short options**: Expanded (`-Ap` matches `-A`).\n- **Long options**: Exact match (`--all-files` does not match `--all`).\n- **Execution order**: Built-in rules first, then custom rulebooks. Custom rules only add restrictions.\n- **Transparent wrappers**: A configured wrapper such as `rtk` lets `rtk git commit` be analyzed as `git commit` only when `git` is protected by built-in analyzers or active custom rules. `rtk -- git commit` is also supported.\n\n## Workflow\n\n1. Run `cc-safety-net rule init` or create `rule.json` manually.\n2. Optionally run `cc-safety-net rule init --example` to create an inactive example rulebook.\n3. Use `cc-safety-net rule wrapper add rtk` for trusted transparent wrappers.\n4. Run `cc-safety-net rule add <source>` after creating or choosing a rulebook source; add `--only <rulebook...>` or `--ref <ref>` for repository selection. The command adds the selected sources and syncs them.\n5. Edit a local rulebook whenever you like: the edit is enforced on the next command, so there is nothing to run afterwards.\n6. Run `cc-safety-net rule update [source]` to re-fetch remote sources and rewrite the vendored copies; the command prints what changed. A source with an ordinary update failure keeps its vendored copy while the other selected sources still update. Resource-limit failures remain fatal for the whole update.\n7. Run `cc-safety-net rule verify` to validate config, local rulebooks, and shareable GitHub-source rulebook directories in the current repository (it does not fetch remote content).\n8. Run `cc-safety-net rule list` to inspect active rulebooks and transparent wrappers.\n\nA missing or invalid rulebook file makes that source inactive, and an unreadable or invalid `rule.json` makes every source in its scope inactive. Inactive sources stop applying their rules while other custom rules and all built-in protections stay active. Fix the file named in the diagnostic, or run `cc-safety-net rule update` when a remote source has not been vendored yet. Run `cc-safety-net status` to see degraded sources.\n";function Nr(A,z){if(!A.ok){Gc(A);return}Hc(A,z)}function Mc(A,z,X){if(A.ok)console.log(X);if(!A.add){Nr(A,`Added rulebook source: ${z}`);return}if(!A.ok){Gc(A);return}if(A.add.added.length>0)console.log(`Added ${A.add.added.length} ${A.add.added.length===1?"rulebook":"rulebooks"} from ${A.add.source} at ${A.add.ref}:`),A.add.added.forEach((ee)=>{console.log(` - ${ee}`)});if(A.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${A.add.source} at ${A.add.ref}: ${A.add.alreadyConfigured.join(", ")}`);if(A.add.commits.length>0)console.log(`Vendored at ${A.add.commits.map((ee)=>ee.slice(0,7)).join(", ")}.`);Hc(A,"Rule config updated.")}function Hc(A,z){for(let X of A.changes??[])console.log(X);console.log(z),console.log(""),lg(A.entries)}function lg(A){if(A.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${A.length}):`);for(let z of A)console.log(` - ${z.name} ${z.version} (${cg(z.ruleCount)})`),console.log(` Source: ${z.spec}`)}function cg(A){return`${A} ${A===1?"rule":"rules"}`}function Uc(A){dn("Active sources",A.rulebooks,(z)=>[`[${z.source}] ${z.name} ${z.version}`,` Source: ${z.spec}`]),dn("Active rules",A.rules,(z)=>[`[${ug(A,z.name)}] ${z.name}`,...dg(z),` Reason: ${z.reason}`]),dn("Disabled rules",Nc(A,"off"),(z)=>[z.key]),dn("Reason overrides",Nc(A,"reason"),(z)=>[z.key,` Reason: ${z.value.reason}`]),dn("Transparent wrappers",A.transparent_wrappers,(z)=>[z]),dn("Issues",A.errors,(z)=>[z]),dn("Warnings",A.warnings,(z)=>[z])}function dn(A,z,X){if(z.length===0){console.log(`${A}: (none)`);return}console.log(`${A} (${z.length}):`);for(let ee of z){let[te,...ae]=X(ee);console.log(` - ${te}`);for(let le of ae)console.log(` ${le}`)}}function dg(A){if(!A.match)return[` Command: ${A.subcommand?`${A.command} ${A.subcommand}`:A.command}`,` Block args: ${A.block_args.join(", ")}`];return[` Command: ${[A.command,...A.match.command_path].join(" ")}`,...A.match.any_args?[` Any args: ${A.match.any_args.join(", ")}`]:[],...A.match.exclude_args?[` Exclude args: ${A.match.exclude_args.join(", ")}`]:[]]}function ug(A,z){return A.rulebooks.find((X)=>X.rules.includes(z))?.source??"project"}function Nc(A,z){return Object.entries({...A.userConfig?.overrides??{},...A.projectConfig?.overrides??{}}).filter((X)=>{if(z==="off")return X[1]==="off";return!!X[1]&&typeof X[1]==="object"}).map(([X,ee])=>({key:X,value:ee}))}function Gc(A){for(let z of A.errors)console.error(z)}import{dirname as ud,join as zr}from"node:path";import{join as Li,resolve as xg}from"node:path";function yi(A){let z=m(A);if(z.errors.length>0)return{ok:!1,result:{ok:!1,errors:z.errors,entries:[]}};return{ok:!0,config:z.config??it}}function Bc(A){Rt(A,{version:1,rules:[],overrides:{},transparent_wrappers:[]})}function qc(A){Rt(A,{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 Gr}from"node:path";var pg="custom.";function Mr(A){if(A.rulebook_version!==2)return[];let z=A.rules.map((X)=>({name:X.name,command:X.command,block_args:[],match:X.match,reason:X.reason,intent:X.intent}));return(A.tests??[]).flatMap((X,ee)=>{let te=hi(h(X.command));if(te.length===0)return[`tests[${ee}]: could not parse fixture command: ${X.command}`];let ae=te.reduce((le,ye)=>le??_(ye,z)?.id.slice(pg.length),void 0);if(X.expect==="blocked"){if(ae===X.rule)return[];let le=ae?`"${ae}" matched first`:"no rule matched";return[`tests[${ee}]: expected "${X.rule}" to block "${X.command}" but ${le}`]}return ae?[`tests[${ee}]: expected "${X.command}" to be allowed but "${ae}" matched`]:[]})}function hi(A){return A.nodes.flatMap((z)=>{if(z.kind==="group"||z.kind==="function")return hi(z.body);if(z.kind!=="command")return[];let X=ge(Z(z.dialect,z.words)).words.map(t);return[...X.length>0?[X]:[],...z.nested.flatMap((ee)=>hi(ee))]})}var Hr=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function Ur(A={}){return{requests:0,responseBytes:0,maxRequests:A.maxRequests??Hr.maxRequests,maxResponseBytes:A.maxResponseBytes??Hr.maxResponseBytes}}function zt(A){return{controller:new AbortController,budget:Ur(),resolveUrl:A}}function Vc(A){return A instanceof Error&&A.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function zc(A){if(A.requests>=A.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");A.requests++}function Jc(A,z){if(z>A.maxResponseBytes-A.responseBytes)throw A.responseBytes+=z,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");A.responseBytes+=z}var Yc=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function Wc(A,z,X=w(Gr(Gr(z)),"rules policy"),ee=zt()){if(C(A))return yg(A,ee);return gg(A,z,X)}async function Zc(A,z,X,ee,te,ae){if(!C(A))return Wc(A,z,X,ee);let le=te?null:fg(A,z,X);if(le)return le;if(!te&&!ae)throw Error(`${A} is not vendored; run rule update ${A} to vendor it`);return Wc(A,z,X,ee)}function fg(A,z,X=w(Gr(Gr(z)),"rules policy")){let ee=T(A),te=I(z,ee.name),ae=n(i(X,te));if(ae===null)return null;let le=ie(vi(ae,`Invalid rulebook ${te}.`));if(le.name!==ee.name)throw Error(`rulebook name "${le.name}" in ${te} must match "${ee.name}"`);return{spec:A,rulebook:le,content:ae}}async function Xc(A,z={}){if(!V(A))throw Error(`Invalid GitHub repository source: ${A}`);let[X,ee]=A.split("/");if(!X||!ee)throw Error(`Invalid GitHub repository source: ${A}`);if(z.ref!==void 0&&!re(z.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${z.ref}`);let te=z.operation??zt(),ae=z.ref??await mg(X,ee,A,te),le=await ed(X,ee,ae,A,te),ye=await Br(`https://api.github.com/repos/${X}/${ee}/git/trees/${le}?recursive=1`,"tree",te),he=ye.response;if(!he.ok)throw Error(`Failed to inspect ${A}: GitHub tree returned ${he.status}`);let ve=JSON.parse(ye.content);if(!Array.isArray(ve?.tree))throw Error(`Failed to inspect ${A}: unexpected GitHub tree response`);let be=ve.tree,Ie=[...new Set(be.flatMap((Xe)=>{if(!Xe||typeof Xe!=="object")return[];let et=Xe;if(et.type!=="blob"||typeof et.path!=="string")return[];let Ee=et.path.match(rt);return Ee?.[1]?[Ee[1]]:[]}))].sort();if(Ie.length===0)throw Error(`No rulebooks found in ${A} under ${ue}/`);return{source:A,owner:X,repo:ee,ref:ae,commit:le,names:Ie}}async function mg(A,z,X,ee){let te=await Br(`https://api.github.com/repos/${A}/${z}`,"metadata",ee),ae=te.response;if(!ae.ok)throw Error(`Failed to inspect ${X}: GitHub returned ${ae.status}`);let ye=JSON.parse(te.content)?.default_branch;if(typeof ye!=="string"||ye==="")throw Error(`Failed to inspect ${X}: missing default branch`);if(!re(ye))throw Error(`GitHub returned an invalid default branch: ${ye}`);return ye}function gg(A,z,X){ot(A);let ee=I(z,A),te=n(i(X,ee));if(te===null)throw Error(`Rulebook source not found: ${A}`);let ae=Qc(vi(te,"Invalid local rulebook source."));if(ae.name!==A)throw Error(`rulebook name "${ae.name}" must match local source "${A}"`);return{spec:A,rulebook:ae,content:te}}async function yg(A,z){let X=T(A),ee=await ed(X.owner,X.repo,X.ref,A,z),te=await Br(`https://raw.githubusercontent.com/${X.owner}/${X.repo}/${ee}/${X.path}`,"raw",z),ae=te.response;if(!ae.ok)throw Error(`Failed to fetch ${A}: GitHub raw returned ${ae.status}`);let le=te.content,ye=Qc(vi(le,"Invalid GitHub rulebook response."));if(ye.name!==X.name)throw Error(`rulebook name "${ye.name}" must match GitHub source "${X.name}"`);return{spec:A,rulebook:ye,content:le}}function Qc(A){let z=ie(A),X=Mr(z);if(X.length>0)throw Error(X.join("; "));return z}function vi(A,z){try{return JSON.parse(A)}catch{throw Error(z)}}async function ed(A,z,X,ee,te){let ae=await Br(`https://api.github.com/repos/${A}/${z}/commits/${encodeURIComponent(X)}`,"commit",te),le=ae.response;if(!le.ok)throw Error(`Failed to resolve ${ee}: GitHub returned ${le.status}`);let ye=JSON.parse(ae.content);if(typeof ye?.sha!=="string"||ye.sha==="")throw Error(`Failed to resolve commit for ${ee}`);return ye.sha}async function hg(A,z,X={}){if(X.signal?.aborted)throw X.signal.reason;let ee=X.budget??Ur(),te=new AbortController,ae=()=>te.abort(X.signal?.reason);X.signal?.addEventListener("abort",ae,{once:!0});let le=!1,ye=setTimeout(()=>{if(te.signal.aborted)return;le=!0,te.abort()},X.timeoutMs??Yc.timeoutMs);try{if(X.signal?.aborted)throw X.signal.reason;zc(ee);let he=await fetch(A,{signal:te.signal,redirect:"error"});if(!he.ok)return td(he),{response:he,content:""};return{response:he,content:await vg(he,z,ee,()=>te.abort())}}catch(he){if(le)throw Error("GitHub request timed out",{cause:he});if(X.signal?.aborted)throw X.signal.reason;throw he}finally{clearTimeout(ye),X.signal?.removeEventListener("abort",ae)}}function Br(A,z,X){return hg(X.resolveUrl?.(A)??A,z,{budget:X.budget,signal:X.controller.signal})}async function vg(A,z,X=Ur(),ee){let te=Yc[`${z}Bytes`],ae=Number(A.headers.get("content-length"));if(Number.isFinite(ae)&&ae>te)throw td(A),Error(`GitHub ${z} response exceeds ${te} bytes`);if(!A.body)return"";let le=A.body.getReader(),ye=[],he=0;while(!0){let ve=await le.read();if(ve.done)break;try{Jc(X,ve.value.byteLength)}catch(be){throw ee?.(),Kc(le),be}if(he+=ve.value.byteLength,he>te)throw ee?.(),Kc(le),Error(`GitHub ${z} response exceeds ${te} bytes`);ye.push(Buffer.from(ve.value))}return Buffer.concat(ye,he).toString("utf-8")}function td(A){if(!A.body)return;nd(()=>A.body?.cancel())}function Kc(A){nd(()=>A.cancel())}function nd(A){try{Promise.resolve(A()).catch(()=>{})}catch{}}var bg=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function rd(A,z){let X=sd(A.rules,z);if(X.length>0)return{ok:!0,specs:X};return id(A.rules,z)}function od(A,z){let X=sd(A,z);if(X.length>0)return{ok:!0,specs:X};let ee=wg(A,z);if(ee.length>0)return{ok:!0,specs:ee};let te=kg(A,z);if(!te.ok)return te;if(te.specs.length>0)return{ok:!0,specs:te.specs};return id(A,z)}function id(A,z){let X=A.filter((ee)=>bi(ee)?.name===z);if(X.length===1)return{ok:!0,specs:X};return Lg(z,X)}function Lg(A,z){return{ok:!1,result:{ok:!1,errors:z.length===0?[`No configured rulebook matches ${A}`]:[`Ambiguous rulebook match ${A}: ${z.join(", ")}`],entries:[]}}}function sd(A,z){return A.filter((X)=>X===z)}function wg(A,z){let X=z.match(bg),ee=X?.[1],te=X?.[2],ae=X?.[3];if(!ee||!te||!ae||!re(ae))return[];return ad(A,(le)=>le.owner===ee&&le.repo===te&&le.ref===ae)}function kg(A,z){if(!V(z))return{ok:!0,specs:[]};let[X,ee]=z.split("/"),te=ad(A,(le)=>le.owner===X&&le.repo===ee);if(new Set(te.map((le)=>bi(le)?.ref).filter((le)=>!!le)).size<2)return{ok:!0,specs:te};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${z}. Use an explicit ref:`,` cc-safety-net rule remove ${z}#<ref>`],entries:[]}}}function bi(A){try{return T(A)}catch{return null}}function ad(A,z){return A.filter((X)=>{let ee=bi(X);return ee?z(ee):!1})}async function Vr(A,z={}){let X=wi(z);return Cg(A,X,await qr(A,X,zt()))}function Cg(A,z,X){if(!X.ok)return X;let ee=Pt(A,z),te=[...new Set(j(ee.configPath,ee.filesystemScope))];if(te.length===0)return X;return{ok:!1,errors:te,entries:X.entries}}async function qr(A,z,X,ee={},te=new Set,ae=new Set){try{let le=Pt(A,z),ye=yi(le.configTarget);if(!ye.ok)return ye.result;let he=ye.config,ve=z.only?rd(he,z.only):{ok:!0,specs:he.rules};if(!ve.ok)return ve.result;let be=new Set([...z.refresh?ve.specs:[],...te]),Ie=(ut)=>Zc(ut,le.configDir,le.filesystemScope,X,be.has(ut),!z.refresh||be.has(ut)),Xe=await Og(he.rules,z.refresh?(ut)=>Ie(ut).then((vt)=>({ok:!0,item:vt})).catch((vt)=>{if(Vc(vt))throw vt;return{ok:!1,spec:ut,message:vt instanceof Error?vt.message:String(vt)}}):async(ut)=>({ok:!0,item:await Ie(ut)}),X),et=Xe.filter((ut)=>!ut.ok),Ee=Xe.filter((ut)=>ut.ok).map((ut)=>ut.item),at=Ee.flatMap((ut)=>Sg(ut,he.rules)),ct=Ee.flatMap((ut)=>Rg(ut,ae,le)),lt=new Set([...at,...ct].map((ut)=>ut.spec)),pt=[...et,...at,...ct],mt=[],gt=Eg(mt,()=>Ee.flatMap((ut)=>lt.has(ut.spec)||pt.length>0&&ae.has(ut.spec)?[]:Pg(ut,le,ee,mt)));return{ok:pt.length===0,errors:pt.map((ut)=>`Failed to update ${ut.spec}: ${ut.message}`),entries:Ee.map(Ag),changes:gt}}catch(le){return zn(le)}}function Sg(A,z){if(!C(A.spec))return[];let X=Ae(A.spec),ee=z.filter((te)=>te!==A.spec&&Ae(te).toLowerCase()===X.toLowerCase());if(ee.length===0)return[];return[{ok:!1,spec:A.spec,message:`rulebook name "${X}" is also claimed by ${ee.join(", ")}; rename one of them`}]}function Rg(A,z,X){if(!z.has(A.spec)||!C(A.spec))return[];let ee=I(X.configDir,A.rulebook.name),te=n(i(X.filesystemScope,ee));if(te===null||te===A.content)return[];return[{ok:!1,spec:A.spec,message:`${ee} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Pg(A,z,X,ee){if(!C(A.spec))return[];let te=I(z.configDir,A.rulebook.name),ae=i(z.filesystemScope,te),le=n(ae);if(le===A.content)return[];return ee?.push({target:ae,previous:le}),g(ae,A.content,void 0,X._testAfterPolicyRename),Dg(A,le)}function Eg(A,z){try{return z()}catch(X){for(let ee of[...A].reverse()){if(ee.previous===null){N(ee.target);continue}g(ee.target,ee.previous)}throw X}}function Dg(A,z){if(z===null)return[`Vendored ${A.spec} (${A.rulebook.version})`];let X=me(z),ee="problem"in X?null:X.rulebook,te=new Map(ee?.rules.map((le)=>[le.name,JSON.stringify(le)])??[]),ae=new Set(A.rulebook.rules.map((le)=>le.name));return[`Updated ${A.spec} (${ee?.version??"unreadable"} -> ${A.rulebook.version})`,...[...ae].filter((le)=>!te.has(le)).map((le)=>` + ${le}`),...[...te.keys()].filter((le)=>!ae.has(le)).map((le)=>` - ${le}`),...A.rulebook.rules.filter((le)=>{let ye=te.get(le.name);return ye!==void 0&&ye!==JSON.stringify(le)}).map((le)=>` ~ ${le.name}`)]}function Ag(A){return{spec:A.spec,name:A.rulebook.name,version:A.rulebook.version,ruleCount:A.rulebook.rules.length}}async function ld(A,z,X={}){return _g(A,z,jg(X),zt())}async function _g(A,z,X,ee,te={}){let ae=null,le=!1;try{let ye=Pt(A,X),he=n(ye.configTarget);ae={target:ye.configTarget,content:he};let ve=yi(ye.configTarget);if(!ve.ok)return ve.result;let be=ve.config,Ie=V(z);Tg(z,X,Ie);let Xe=Ie?await Xc(z,{ref:X.ref,operation:ee}):null,et=Xe?$g(Xe,X.rulebooks):[],Ee=Xe?et.map((mt)=>Ig(be.rules,Xe,mt)??`${z}#${Xe.ref}/${mt}`):[z],at=Ee.filter((mt)=>!be.rules.includes(mt)),ct=[...be.rules,...at];if(ct.length>pe)return Fg();if(ct.length!==be.rules.length)le=!0,Rt(ye.configTarget,{version:1,rules:ct,overrides:be.overrides??{},transparent_wrappers:be.transparent_wrappers??[]},void 0,te._testAfterPolicyRename);let lt=await qr(A,X,ee,te,new Set(at),new Set(at));if(!lt.ok)Vn(ye.configTarget,he);if(!lt.ok||!Xe)return lt;let pt=et.filter((mt,gt)=>at.includes(Ee[gt]??""));return{...lt,add:{source:z,ref:Xe.ref,selected:et,added:pt,alreadyConfigured:et.filter((mt)=>!pt.includes(mt)),commits:at.length>0?[Xe.commit]:[]}}}catch(ye){if(le&&ae)try{Vn(ae.target,ae.content)}catch(he){return zn(he)}return zn(ye)}}function Tg(A,z,X){if(!X&&z.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!X&&z.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${A}`);if(z.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let ee=z.rulebooks?.filter((te)=>!c.test(te))??[];if(ee.length>0)throw Error(`Invalid rulebook names: ${ee.join(", ")}`)}function $g(A,z){let X=z?[...new Set(z)]:A.names,ee=X.filter((te)=>!A.names.includes(te));if(ee.length>0)throw Error(`Rulebooks not found in ${A.source} at ${A.ref}: ${ee.join(", ")}
264
+ Available rulebooks: ${A.names.join(", ")}`);return X}function Ig(A,z,X){let ee=`${z.source}#${z.ref}/${X}`;if(A.includes(ee))return ee;let te=`${z.source}#${z.commit}/${X}`;return A.find((ae)=>ae===te)}async function Og(A,z,X=zt()){if(A.length>pe)throw Error(fe);let ee=Array(A.length),te=0,ae,le=Array.from({length:Math.min(A.length,Hr.concurrency)},async()=>{while(!ae){let ye=te;if(ye>=A.length)return;te++;try{ee[ye]=await z(A[ye],ye,X.controller.signal)}catch(he){if(!ae)ae={value:he},te=A.length,X.controller.abort(he);return}}});if(await Promise.all(le),ae)throw ae.value;return ee}function Fg(){return{ok:!1,errors:[fe],entries:[]}}function wi(A){return{cwd:A.cwd,userConfigDir:A.userConfigDir,userConfigPath:A.userConfigPath,projectConfigPath:A.projectConfigPath,global:A.global,only:A.only,refresh:A.refresh}}function jg(A){return{...wi(A),ref:A.ref,rulebooks:A.rulebooks}}function Ng(A){return{...wi(A),deleteSource:A.deleteSource}}async function cd(A,z,X={}){try{return await Mg(A,z,Ng(X),{})}catch(ee){return zn(ee)}}async function Mg(A,z,X,ee){let te=Pt(A,X),ae=m(te.configTarget);if(ae.errors.length>0)return{ok:!1,errors:ae.errors,entries:[]};if(!ae.config)return{ok:!1,errors:[`No config found at ${te.configPath}`],entries:[]};let le=od(ae.config.rules,z);if(!le.ok)return le.result;let ye=X.deleteSource?Hg(te.configDir,le.specs,te.filesystemScope):{ok:!0,dirs:[]};if(!ye.ok)return ye.result;let he=n(te.configTarget);if(he===null)return zn(Error("Rules config is unavailable."));try{Rt(te.configTarget,{version:1,rules:ae.config.rules.filter((Ie)=>!le.specs.includes(Ie)),overrides:ae.config.overrides??{},transparent_wrappers:ae.config.transparent_wrappers??[]},void 0,ee._testAfterPolicyRename)}catch(Ie){throw Vn(te.configTarget,he),Ie}let ve=await qr(A,X,zt(),ee);if(!ve.ok)return Vn(te.configTarget,he),ve;let be=Ug(ye.dirs,ee,te.filesystemScope);if(!be.ok){Vn(te.configTarget,he);let Ie=await qr(A,X,zt(),ee);if(!Ie.ok)return{ok:!1,errors:[...be.result.errors,...Ie.errors],entries:Ie.entries};return be.result}return ve}function Hg(A,z,X){let ee=z.flatMap((ye)=>c.test(ye)?[]:["--delete-source can only delete local rulebook sources"]),te=z.map((ye)=>Li(A,ye)),ae=ee.length>0?[]:te.flatMap((ye)=>dd(ye,X)),le=[...ee,...ae];return le.length>0?{ok:!1,result:{ok:!1,errors:le,entries:[]}}:{ok:!0,dirs:te}}function dd(A,z){let X=xg(A),ee=i(z,X),te=ce(ee);if(!te)return[`Local rulebook source directory not found: ${A}`];let ae=te.find((le)=>le.name==="rulebook.json");if(!ae)return[`Local rulebook source directory is missing rulebook.json: ${A}`];if(ae.kind!=="file")throw new r(z.label);if(n(i(z,Li(X,"rulebook.json"))),te.length>1)return[`Local rulebook source directory contains extra files: ${A}. delete manually if you really want to remove the directory.`];return[]}function Ug(A,z,X){let ee=A.flatMap((te)=>{try{if(!ce(i(X,te)))return[];let ae=dd(te,X);if(ae.length>0)return ae;return Gg(te,z,X),[]}catch(ae){return[`Failed to delete local rulebook source ${te}: ${ae instanceof Error?ae.message:String(ae)}`]}});return ee.length>0?{ok:!1,result:{ok:!1,errors:ee,entries:[]}}:{ok:!0}}function Gg(A,z,X){if(z._testDeleteLocalSourceDir){z._testDeleteLocalSourceDir(A);return}N(i(X,Li(A,de))),nt(i(X,A))}function Vn(A,z){if(z===null){N(A);return}g(A,z)}function zn(A){return{ok:!1,errors:[A instanceof Error?A.message:String(A)],entries:[]}}var Bg=".safety-net.json",qg="~/.cc-safety-net/config.json";async function md(A,z){return[await pd(A,{legacyPath:As({cwd:z.cwd}),configPath:M(z.cwd),defaultRulebookName:"project-rules",migratedFrom:Bg,cleanup:z.cleanup,syncOptions:{cwd:z.cwd}}),await pd(A,{legacyPath:tr(A),configPath:F(A),defaultRulebookName:"user-rules",migratedFrom:qg,cleanup:z.cleanup,syncOptions:{cwd:z.cwd,global:!0}})].every((ee)=>ee)?0:1}async function pd(A,z){let X=Pt(A,z.syncOptions),ee=i(X.filesystemScope,z.legacyPath),te=n(ee);if(te===null)return console.log(`No legacy config found at ${z.legacyPath}`),!0;let ae=zg(te);if(!ae.ok){for(let et of ae.errors)console.error(et);return!1}let le=m(X.configTarget);if(le.errors.length>0){for(let et of le.errors)console.error(et);return!1}let ye=le.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},he=Jg(ud(z.configPath),ye.rules,z.defaultRulebookName,z.migratedFrom,X.filesystemScope),ve=zr(ud(z.configPath),he,"rulebook.json"),be=i(X.filesystemScope,ve),Ie=[fd(X.configTarget),fd(be)],Xe=await Vg(A,z,X.configTarget,be,he,ae.config.rules,ye.rules.includes(he)?ye.rules:[...ye.rules,he],ye.overrides??{},ye.transparent_wrappers??[]);if(!Xe.ok){Yg(Ie);for(let et of Xe.errors)console.error(et);return!1}if(!z.cleanup)return console.log(`Migrated legacy config at ${z.legacyPath}. Legacy file is no longer used.`),!0;if(!Kg(X.configTarget,be,he,z.migratedFrom,ae.config.rules))return console.error(`Migration cleanup verification failed for ${z.legacyPath}`),!1;return N(ee),console.log(`Deleted legacy config at ${z.legacyPath}`),!0}async function Vg(A,z,X,ee,te,ae,le,ye,he){try{return Rt(X,{version:1,rules:le,overrides:ye,transparent_wrappers:he}),Rt(ee,Wg(te,z.migratedFrom,ae)),await Vr(A,z.syncOptions)}catch(ve){return{ok:!1,errors:[ve instanceof Error?ve.message:String(ve)]}}}function zg(A){try{let z=JSON.parse(A),X=no(z);if(X.errors.length>0)return{ok:!1,errors:X.errors};return{ok:!0,config:{version:1,rules:z.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function Jg(A,z,X,ee,te){let ae=z.find((le)=>Zg(i(te,zr(A,le,"rulebook.json")))===ee);if(ae)return ae;if(n(i(te,zr(A,X,"rulebook.json")))===null)return X;for(let le=2;;le++){let ye=`${X}-${le}`;if(n(i(te,zr(A,ye,"rulebook.json")))===null)return ye}}function Wg(A,z,X){return{rulebook_version:1,name:A,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:z,allowed_commands:[...new Set(X.map((ee)=>ee.command))],rules:X,tests:X.map((ee)=>({command:[ee.command,ee.subcommand,ee.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:ee.name}))}}function Kg(A,z,X,ee,te){if(!m(A).config?.rules.includes(X))return!1;try{let le=n(z);if(le===null)return!1;let ye=JSON.parse(le);return ye.migrated_from===ee&&JSON.stringify(ye.rules)===JSON.stringify(te)}catch{return!1}}function fd(A){return{target:A,content:n(A)}}function Yg(A){for(let z of A){if(z.content===null){N(z.target);continue}g(z.target,z.content)}}function Zg(A){let z=n(A);if(z===null)return null;try{let X=JSON.parse(z);return typeof X.migrated_from==="string"?X.migrated_from:null}catch{return null}}import{mkdir as Xg,readFile as Qg,writeFile as ey}from"node:fs/promises";import{dirname as ty,join as ny}from"node:path";var ry=86400000,oy=604800000;async function yd(A,z=Date.now()){if(A.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let X=je(A);if(!X)return null;let ee=ny(X,".cc-safety-net","update-check.json"),te=await iy(ee,z);if(!te.lastCheck||z-te.lastCheck>ry){let ye=await Wt();if(te.lastCheck=z,ye.latestVersion)te.latestVersion=ye.latestVersion;if(!await gd(ee,te))return null;if(ye.error)return null}let ae=te.latestVersion,le=wt();if(!ae||!lo(ae,le))return null;if(te.notifiedVersion===ae&&te.notifiedAt!==void 0&&z-te.notifiedAt<oy)return null;if(te.notifiedVersion=ae,te.notifiedAt=z,!await gd(ee,te))return null;return`UPDATE_AVAILABLE: cc-safety-net v${ae} is available (running v${le}). 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 iy(A,z){let X=await Qg(A,"utf8").then((ae)=>JSON.parse(ae)).catch(()=>{return});if(!X||typeof X!=="object"||Array.isArray(X))return{};let ee=X,te=(ae)=>typeof ae==="number"&&Number.isFinite(ae)&&ae<=z?ae:void 0;return{lastCheck:te(ee.lastCheck),latestVersion:typeof ee.latestVersion==="string"?ee.latestVersion:void 0,notifiedVersion:typeof ee.notifiedVersion==="string"?ee.notifiedVersion:void 0,notifiedAt:te(ee.notifiedAt)}}async function gd(A,z){return Xg(ty(A),{recursive:!0,mode:448}).then(()=>ey(A,JSON.stringify(z),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as sy,resolve as ki}from"node:path";var hd="CC Safety Net Config",ay="═".repeat(hd.length),ly="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",cy=new Set(["rule.json","rule.lock","cache"]);function vd(A,z={}){try{return dy(A,z)}catch(X){if(X instanceof r)return console.error(X.message),1;throw X}}function dy(A,z){let X=z.cwd??process.cwd(),ee=q(A,{cwd:X}),te=tr(A),ae=Qi(X),le=ki(X,ue),ye=i(ee.userScope,te),he=i(ee.projectScope,ae),ve=!1,be=!1,Ie=[],Xe=[],et=uy(i(ee.projectScope,le));if(fy(),n(ee.userConfigTarget)!==null){let Ee=Jt(ee.userConfigTarget);if(Ee.errors.push(...j(ee.userConfigPath,ee.userScope)),Ie.push({scope:"User",path:ee.userConfigPath,result:Ee,schema:"rules",target:ee.userConfigTarget}),Ee.errors.length>0)ve=!0}if(n(ye)!==null)if(be=!0,n(ee.userConfigTarget)!==null)Xe.push(Jr("user","cleanup"));else{let Ee=ro(ye);if(Ie.push({scope:"User",path:te,result:Ee,schema:"legacy",inactive:!0,target:ye}),Xe.push(Jr("user",Ee.errors.length>0?"fix-or-delete":"migrate")),Ee.errors.length>0)ve=!0}if(n(ee.projectConfigTarget)!==null){let Ee=Jt(ee.projectConfigTarget);if(Ee.errors.push(...j(ee.projectConfigPath,ee.projectScope)),Ie.push({scope:"Project",path:ki(ee.projectConfigPath),result:Ee,schema:"rules",target:ee.projectConfigTarget}),Ee.errors.length>0)ve=!0;if(n(he)!==null)be=!0,Xe.push(Jr("project","cleanup"))}else if(n(he)!==null){be=!0,ve=!0;let Ee=ro(he);Ie.push({scope:"Project",path:ki(ae),result:Ee,schema:"legacy",inactive:!0,target:he}),Xe.push(Jr("project",Ee.errors.length>0?"fix-or-delete":"migrate"))}if(et?.result.errors.length)ve=!0;if(Ie.length===0&&!et)return console.log(`
265
+ No config files found. Using built-in rules only.`),0;for(let Ee of Ie)if(Ee.inactive)gy(Ee.scope,Ee.path,Ee.result);else if(Ee.result.errors.length>0)yy(Ee.scope,Ee.path,Ee.result.errors);else{if(Ee.schema==="rules"&&by(Ee.target))console.log(`
266
+ Added $schema to ${Ee.scope.toLowerCase()} config.`);my(Ee.scope,Ee.path,Ee.result,Ee.schema)}for(let Ee of Xe)console.error(`
267
+ ${dt.red(Ee)}`);if(et)if(et.result.errors.length>0)vy(et.path,et.result.errors);else hy(et.path,et.result);if(ve)return console.error(`
268
+ Config validation failed.`),1;return console.log(be?`
270
269
  Configs valid with warnings.`:`
271
- All configs valid.`),0}function co(j,K){let te=`legacy ${j} config`;if(K==="cleanup")return`Warning: Legacy ${j} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(K==="migrate")return`Warning: Legacy ${j} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${j} config is no longer supported. Fix or delete the ${te}, then run \`npx -y cc-safety-net rule migrate\`.`}function Iy(j){if(ue(j)===null)return null;let K=$y(j);if(K.ruleNames.size===0&&K.errors.length===0)return null;return{path:j.path,result:K}}function $y(j){let K=[],te=new Set,re=(ue(j)??[]).filter((oe)=>!_y.has(oe.name)).sort((oe,ce)=>oe.name.localeCompare(ce.name));if(re.length===0)return{errors:K,ruleNames:te};for(let oe of re){if(!c.test(oe.name)){K.push(`rulebook directory names must match ${c}: ${oe.name}`);continue}if(oe.kind!=="directory"){K.push(`${oe.name} must be a rulebook directory`);continue}let ce=s(j.scope,Ey(j.path,oe.name,"rulebook.json")),de=r(ce);if(de===null){K.push(`${oe.name}/rulebook.json is required`);continue}try{let we;try{we=JSON.parse(de)}catch{K.push(`${oe.name}/rulebook.json: invalid JSON`);continue}let xe=ae(we);if(xe.name!==oe.name){K.push(`rulebook name "${xe.name}" must match folder "${oe.name}"`);continue}let Ce=to(xe);if(Ce.length>0){K.push(...Ce.map((Se)=>`${oe.name}/rulebook.json: ${Se}`));continue}te.add(oe.name)}catch(we){K.push(we instanceof Error?`${oe.name}/rulebook.json: ${we.message}`:`${oe.name}/rulebook.json: ${String(we)}`)}}return{errors:K,ruleNames:te}}function Oy(){console.log(Fd),console.log(Dy)}function jy(j,K,te,re){if(console.log(`
272
- ✓ ${j} config: ${K}`),console.log(` Schema: ${re==="rules"?"rulebook sources":"legacy inline rules"}`),te.ruleNames.size>0){console.log(` ${re==="rules"?"Sources":"Rules"}:`);let oe=1;for(let ce of te.ruleNames)console.log(` ${oe}. ${ce}`),oe++}else console.log(` ${re==="rules"?"Sources":"Rules"}: (none)`)}function Fy(j,K,te){if(console.error(`
273
- ✗ Legacy ${j.toLowerCase()} config: ${K}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),te.errors.length>0){console.error(" Errors:");let re=1;for(let oe of te.errors)for(let ce of oe.split("; "))console.error(` ${re}. ${ce}`),re++;return}if(te.ruleNames.size>0){console.error(" Rules:");let re=1;for(let oe of te.ruleNames)console.error(` ${re}. ${oe}`),re++;return}console.error(" Rules: (none)")}function Ny(j,K,te){Md(`${j} config`,K,te)}function My(j,K){console.log(`
274
- ✓ GitHub source rules: ${j}`),console.log(" Rulebooks:");let te=1;for(let re of K.ruleNames)console.log(` ${te}. ${re}`),te++}function Hy(j,K){Md("GitHub source rules",j,K)}function Md(j,K,te){console.error(`
275
- ✗ ${j}: ${K}`),console.error(" Errors:");let re=1;for(let oe of te)for(let ce of oe.split("; "))console.error(` ${re}. ${ce}`),re++}function Uy(j){try{let K=r(j);if(K===null)return!1;let te=JSON.parse(K);if(te.$schema)return!1;return y(j,JSON.stringify({$schema:Ay,...te},null,2)),!0}catch(K){if(K instanceof o)throw K;return!1}}var Hd=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),By=new Set(["add","remove","list"]),qy="cc-safety-net/rulebooks";async function Ud(j,K){try{return await Vy(j,K)}catch(te){if(te instanceof o)return console.error(te.message),1;throw te}}async function Vy(j,K){let te=Jy(K),re=te.help?zy(te.positionals):null;if(re)return _n(re),0;if(te.errors.length>0){for(let we of te.errors)console.error(we);return 1}let oe=te.positionals[0];if(!oe)return _n(kn,console.error),1;let ce=te.positionals[1],de={global:te.global};if(oe==="init"){let we=$t(j,de);Zy(we.configTarget);let xe=Gy(we.configDir,"example-rules","rulebook.json"),Ce=s(we.filesystemScope,xe);if(te.example&&r(Ce)===null)dd(Ce,"example-rules");let Se=W(we.configPath,we.filesystemScope);for(let Ne of Se)console.error(Ne);if(Se.length>0)return 1;return console.log("Rule config initialized."),0}if(oe==="add"){let we=Gd(te);if(!we)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let xe=$t(j,de),Ce=await Ed(j,we,{...de,ref:te.ref,rulebooks:te.only.length>0?te.only:void 0});return id(Ce,we,`Scope: ${te.global?"user":"project"} (${xe.configDir})`),Ce.ok?0:1}if(oe==="remove"){if(!ce)return console.error("rule remove requires a source"),1;let we=await Dd(j,ce,{...de,deleteSource:te.deleteSource});return eo(we,`Removed rulebook source: ${ce}`),we.ok?0:1}if(oe==="update"){let we=await ao(j,{...de,only:ce,refresh:!0});return eo(we,"Rule config updated."),we.ok?0:1}if(oe==="sync")return Ks(j,{global:te.global});if(oe==="list"){let we=Z(j,{cwd:process.cwd()});return ad(we),we.errors.length>0?1:0}if(oe==="wrapper")return Xy(j,te);if(oe==="migrate")return $d(j,{cleanup:te.cleanup,cwd:process.cwd()});if(oe==="doc"){console.log(rd);let we=await jd(j);if(we)console.error(we);return 0}if(oe==="verify")return Nd(j);return 1}function zy(j){if(j.length===0)return kn;let K=kn.subcommands.filter((re)=>re.usage.split(" ")[0]===j[0]);if(K.length===0)return null;if(j.length===1&&K.length>1)return{name:`rule ${j[0]}`,description:`Subcommands of rule ${j[0]}`,usage:`rule ${j[0]} <subcommand>`,subcommands:K,options:[]};let te=j.length===1?K[0]:K.find((re)=>re.usage.split(" ")[1]===j[1]);if(!te)return null;return{name:`rule ${j[0]}`,description:te.description,usage:`rule ${te.usage}`,options:j[0]==="add"?go:[],examples:j[0]==="add"?yo:void 0}}function Jy(j){let K=At({label:"rule",booleans:{global:["-g","--global"],check:["--check"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},j),te={...K.flags,ref:K.values.ref,only:K.lists.only??[],help:K.help,positionals:K.positionals,errors:K.errors};return Wy(te),te}function Wy(j){let[K]=j.positionals;if(K&&!Hd.has(K))j.errors.push(`Unknown rule subcommand: ${K}`);if(j.deleteSource&&K!=="remove")if(K&&Hd.has(K))j.errors.push(`Unknown option for rule ${K}: --delete-source`);else j.errors.push("--delete-source is only valid with 'rule remove'");if(j.check&&K)j.errors.push(Fn(K,"--check"));if(j.cleanup&&K!=="migrate")j.errors.push(Fn(K,"--cleanup"));if(j.example&&K!=="init")j.errors.push(Fn(K,"--example"));if(j.ref&&K!=="add")j.errors.push(Fn(K,"--ref"));if(j.only.length>0&&K!=="add")j.errors.push(Fn(K,"--only"));if(K==="add")Ky(j);if(K==="migrate"){if(j.global)j.errors.push(Fn(K,"--global"));if(j.positionals.length>1)j.errors.push(`Unexpected rule migrate argument: ${j.positionals[1]}`)}else if(K==="wrapper")Yy(j);else if(j.positionals.length>2)j.errors.push(`Unexpected rule argument: ${j.positionals[2]}`);if(K==="list"&&j.global)j.errors.push("Unknown option for rule list: --global")}function Gd(j){if(j.positionals[1])return j.positionals[1];if(j.ref||j.only.length>0)return qy;return}function Ky(j){let K=Gd(j);if(!K)return;if((j.ref||j.only.length>0)&&!Y(K)){if(j.ref)j.errors.push(`--ref can only select a ref for an owner/repo source: ${K}`);if(j.only.length>0)j.errors.push("--only can only select rulebooks from an owner/repo source");return}if(j.ref&&!ie(j.ref))j.errors.push(`--ref must use valid path segments: ${j.ref}`);let te=j.only.filter((re)=>!c.test(re));if(te.length>0)j.errors.push(`Invalid rulebook names: ${te.join(", ")}`)}function Fn(j,K){return j?`Unknown option for rule ${j}: ${K}`:`Unknown option for rule: ${K}`}function Yy(j){let K=j.positionals[1],te=j.positionals[2];if(!K){j.errors.push("rule wrapper requires add, remove, or list");return}if(!By.has(K)){j.errors.push(`Unknown rule wrapper action: ${K}`);return}if(K==="list"){if(te)j.errors.push(`Unexpected rule wrapper argument: ${te}`);return}if(!te){j.errors.push(`rule wrapper ${K} requires a command`);return}if(j.positionals.length>3)j.errors.push(`Unexpected rule wrapper argument: ${j.positionals[3]}`)}function Zy(j){if(r(j)===null){cd(j);return}let K=m(j);if(!K.config)return;It(j,{version:1,rules:K.config.rules,overrides:K.config.overrides??{},transparent_wrappers:K.config.transparent_wrappers??[]})}async function Xy(j,K){let te=K.positionals[1],re=K.positionals[2],oe=$t(j,{global:K.global}).configTarget;if(te==="list"){let xe=m(oe);if(xe.errors.length>0){for(let Ce of xe.errors)console.error(Ce);return 1}return Qy(xe.config?.transparent_wrappers??[]),0}if(!re||!L.test(re))return console.error("transparent wrapper must match command pattern"),1;if(Me(re))return console.error(`reserved command "${re}" cannot be a wrapper`),1;let ce=m(oe);if(ce.errors.length>0){for(let xe of ce.errors)console.error(xe);return 1}let de=ce.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},we=te==="add"?[...new Set([...de.transparent_wrappers??[],re])]:(de.transparent_wrappers??[]).filter((xe)=>xe!==re);return It(oe,{version:1,rules:de.rules,overrides:de.overrides??{},transparent_wrappers:we}),console.log(te==="add"?`Added transparent wrapper: ${re}`:`Removed transparent wrapper: ${re}`),0}function Qy(j){if(j.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${j.length}):`);for(let K of j)console.log(` - ${K}`)}import{sep as ih}from"node:path";import{existsSync as eh,readFileSync as th}from"node:fs";import{join as nh}from"node:path";async function rh(j){if(j.isTTY)return null;return(await Xe(j).catch(()=>null))?.trim()||null}function oh(j){let K=j.env.get("CLAUDE_SETTINGS_PATH");if(K)return K;return nh(j.home,".claude","settings.json")}function Mi(j){let K=oh(j);if(!eh(K))return!1;try{let te=th(K,"utf-8"),re=JSON.parse(te);if(!re.enabledPlugins)return!1;let oe="cc-safety-net@cc-marketplace";if(!(oe in re.enabledPlugins))return!1;return re.enabledPlugins[oe]===!0}catch(te){if(_(i.debug,j.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${K}: ${te instanceof Error?te.message:String(te)}`);return!1}}async function Hi(j,K=process.stdin){let te=Mi(j),re;if(!te)re="\uD83D\uDEE1️ CC Safety Net ❌";else{let ce=k(j,{cwd:process.cwd()}),de=ce.policy,we=P(de,j.env),xe=Object.values(B(de,we.capabilities)).some((Ne)=>Ne.changesInherited),Ce={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[xe?"custom":we.effectiveLevel],Se=(ce.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";re=`\uD83D\uDEE1️ CC Safety Net ${Ce}${we.worktreeMode?"\uD83C\uDF33":""}${Se}${ce.state==="degraded"?"⚠️":""}`}let oe=await rh(K);if(oe&&!oe.startsWith("{"))console.log(`${oe} | ${re}`);else console.log(re)}function Bd(j){let K=k(j,{cwd:process.cwd()}),te=K.policy,re=P(te,j.env),oe=!!process.env.NO_COLOR||!process.stdout.isTTY,ce=Math.min(process.stdout.columns||80,100),de=oe?"ok":"✔",we=oe?"OFF":"✘",xe=(it,gt)=>{let ht=` ${it.padEnd(13)}${gt}`;return(ht.length>ce?`${ht.slice(0,ce-1)}…`:ht).replaceAll(we,bt.red(we))},Ce=Object.values(B(te,re.capabilities)).some((it)=>it.changesInherited),Se=(it)=>it===j.home||it.startsWith(`${j.home}${ih}`)?`~${it.slice(j.home.length)}`:it,Ne={ready:bt.green,degraded:bt.yellow}[K.state],He=K.policyScopes?.weakenings??[],at=[...Mi(j)?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...K.diagnostics],mt=oe?"-":"·";console.log([`${oe?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ne(K.state)}`,"",xe("Protection",`destructive ${te.destructiveCommandProtectionEnabled?de:we} secrets ${te.secretProtection.enabled?de:we}`),xe("Level",Ce?`${re.effectiveLevel} (customised)`:re.effectiveLevel),xe("Rules",te.rules.length===0?"none active":`${te.rules.length} active`),xe("Policy",Se(d(j))),...K.policyScopes?[xe("Project",Se(w(process.cwd())))]:[],...re.worktreeMode?[xe("Worktree","relaxations active")]:[],"",...He.length===0?[]:[" Project policy",...He.flatMap((it)=>Qn(it," ",ce-6).map((gt,ht)=>ht===0?` ${gt}`:gt)),""],...at.length===0?[" Everything configured is active."]:[" Not active",...at.flatMap((it)=>Qn(it," ",ce-6).map((gt,ht)=>ht===0?` ${mt} ${gt}`:gt)),""," Full report: cc-safety-net doctor"]].join(`
276
- `))}import{spawn as eu}from"node:child_process";import{randomBytes as gh}from"node:crypto";import{existsSync as yh}from"node:fs";import{createServer as hh}from"node:http";import{Writable as vh}from"node:stream";var uo=500;function sh(j){let K=j.filter((oe)=>oe.decision!=="allow"),te=j.filter((oe)=>oe.decision==="allow"),re=Math.min(K.length,Math.max(uo-te.length,Math.ceil(uo/2)));return[...K.slice(0,re),...te.slice(0,uo-re)]}function qd(j,K,te=M(j)){if(te)q(j,te);let re=(gt)=>new Date(gt.getFullYear(),gt.getMonth(),gt.getDate()).getTime(),oe=re(new Date),ce=new Date(oe);ce.setDate(ce.getDate()-(K-1));let de=ce.getTime(),we=[],xe={count:0};for(let gt of te?an(te,xe):[])for(let ht of wn(gt,xe)){if(!ht||typeof ht.ts!=="string"||typeof ht.command!=="string")continue;let vt=new Date(ht.ts).getTime();if(!Number.isFinite(vt))continue;if(vt>=de)we.push(ht)}we.sort((gt,ht)=>new Date(ht.ts).getTime()-new Date(gt.ts).getTime());let Ce=Array.from({length:K},()=>0),Se=Array.from({length:K},()=>0),Ne={},He={},at={},mt=0,it=0;for(let gt of we){let ht=gt.agent||"unknown";Ne[ht]=(Ne[ht]??0)+1;let vt=Math.round((oe-re(new Date(gt.ts)))/86400000),yt=K-1-vt,kt=vt>=0&&vt<K;if(kt)Se[yt]=(Se[yt]??0)+1;if(gt.decision!=="allow"){if(mt++,gt.ruleId)He[gt.ruleId]=(He[gt.ruleId]??0)+1;let Lt=dr(gt.segment||gt.command);if(Lt)at[Lt]=(at[Lt]??0)+1;if(gt.failureStage)it++;if(kt)Ce[yt]=(Ce[yt]??0)+1}}return{days:K,logsDir:te,homeDir:j.home,totalInWindow:we.length,truncated:we.length>uo,unreadable:xe.count,counts:{blocked:mt,allowed:we.length-mt,agents:Ne,blockedByDay:Ce,analyzedByDay:Se,rules:He,commands:at,errors:it},entries:sh(we).sort((gt,ht)=>new Date(ht.ts).getTime()-new Date(gt.ts).getTime())}}import{spawn as ah}from"node:child_process";import{existsSync as lh,statSync as Vd}from"node:fs";import{delimiter as ch,join as dh}from"node:path";var uh=120000,po="Choose the project folder",ph=`try
277
- return POSIX path of (choose folder with prompt "${po}")
270
+ All configs valid.`),0}function Jr(A,z){let X=`legacy ${A} config`;if(z==="cleanup")return`Warning: Legacy ${A} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(z==="migrate")return`Warning: Legacy ${A} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${A} config is no longer supported. Fix or delete the ${X}, then run \`npx -y cc-safety-net rule migrate\`.`}function uy(A){if(ce(A)===null)return null;let z=py(A);if(z.ruleNames.size===0&&z.errors.length===0)return null;return{path:A.path,result:z}}function py(A){let z=[],X=new Set,ee=(ce(A)??[]).filter((te)=>!cy.has(te.name)).sort((te,ae)=>te.name.localeCompare(ae.name));if(ee.length===0)return{errors:z,ruleNames:X};for(let te of ee){if(!c.test(te.name)){z.push(`rulebook directory names must match ${c}: ${te.name}`);continue}if(te.kind!=="directory"){z.push(`${te.name} must be a rulebook directory`);continue}let ae=i(A.scope,sy(A.path,te.name,"rulebook.json")),le=n(ae);if(le===null){z.push(`${te.name}/rulebook.json is required`);continue}try{let ye;try{ye=JSON.parse(le)}catch{z.push(`${te.name}/rulebook.json: invalid JSON`);continue}let he=ie(ye);if(he.name!==te.name){z.push(`rulebook name "${he.name}" must match folder "${te.name}"`);continue}let ve=Mr(he);if(ve.length>0){z.push(...ve.map((be)=>`${te.name}/rulebook.json: ${be}`));continue}X.add(te.name)}catch(ye){z.push(ye instanceof Error?`${te.name}/rulebook.json: ${ye.message}`:`${te.name}/rulebook.json: ${String(ye)}`)}}return{errors:z,ruleNames:X}}function fy(){console.log(hd),console.log(ay)}function my(A,z,X,ee){if(console.log(`
271
+ ✓ ${A} config: ${z}`),console.log(` Schema: ${ee==="rules"?"rulebook sources":"legacy inline rules"}`),X.ruleNames.size>0){console.log(` ${ee==="rules"?"Sources":"Rules"}:`);let te=1;for(let ae of X.ruleNames)console.log(` ${te}. ${ae}`),te++}else console.log(` ${ee==="rules"?"Sources":"Rules"}: (none)`)}function gy(A,z,X){if(console.error(`
272
+ ✗ Legacy ${A.toLowerCase()} config: ${z}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),X.errors.length>0){console.error(" Errors:");let ee=1;for(let te of X.errors)for(let ae of te.split("; "))console.error(` ${ee}. ${ae}`),ee++;return}if(X.ruleNames.size>0){console.error(" Rules:");let ee=1;for(let te of X.ruleNames)console.error(` ${ee}. ${te}`),ee++;return}console.error(" Rules: (none)")}function yy(A,z,X){bd(`${A} config`,z,X)}function hy(A,z){console.log(`
273
+ ✓ GitHub source rules: ${A}`),console.log(" Rulebooks:");let X=1;for(let ee of z.ruleNames)console.log(` ${X}. ${ee}`),X++}function vy(A,z){bd("GitHub source rules",A,z)}function bd(A,z,X){console.error(`
274
+ ✗ ${A}: ${z}`),console.error(" Errors:");let ee=1;for(let te of X)for(let ae of te.split("; "))console.error(` ${ee}. ${ae}`),ee++}function by(A){try{let z=n(A);if(z===null)return!1;let X=JSON.parse(z);if(X.$schema)return!1;return g(A,JSON.stringify({$schema:ly,...X},null,2)),!0}catch(z){if(z instanceof r)throw z;return!1}}var Ld=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),wy=new Set(["add","remove","list"]),ky="cc-safety-net/rulebooks";async function wd(A,z){try{return await xy(A,z)}catch(X){if(X instanceof r)return console.error(X.message),1;throw X}}async function xy(A,z){let X=Sy(z),ee=X.help?Cy(X.positionals):null;if(ee)return Ln(ee),0;if(X.errors.length>0){for(let ye of X.errors)console.error(ye);return 1}let te=X.positionals[0];if(!te)return Ln(pn,console.error),1;let ae=X.positionals[1],le={global:X.global};if(te==="init"){let ye=Pt(A,le);Dy(ye.configTarget);let he=Ly(ye.configDir,"example-rules","rulebook.json"),ve=i(ye.filesystemScope,he);if(X.example&&n(ve)===null)qc(ve);let be=j(ye.configPath,ye.filesystemScope);for(let Ie of be)console.error(Ie);if(be.length>0)return 1;return console.log("Rule config initialized."),0}if(te==="add"){let ye=kd(X);if(!ye)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let he=Pt(A,le),ve=await ld(A,ye,{...le,ref:X.ref,rulebooks:X.only.length>0?X.only:void 0});return Mc(ve,ye,`Scope: ${X.global?"user":"project"} (${he.configDir})`),ve.ok?0:1}if(te==="remove"){if(!ae)return console.error("rule remove requires a source"),1;let ye=await cd(A,ae,{...le,deleteSource:X.deleteSource});return Nr(ye,`Removed rulebook source: ${ae}`),ye.ok?0:1}if(te==="update"){let ye=await Vr(A,{...le,only:ae,refresh:!0});return Nr(ye,"Rule config updated."),ye.ok?0:1}if(te==="sync")return $s(A,{global:X.global});if(te==="list"){let ye=K(A,{cwd:process.cwd()});return Uc(ye),ye.errors.length>0?1:0}if(te==="wrapper")return Ay(A,X);if(te==="migrate")return md(A,{cleanup:X.cleanup,cwd:process.cwd()});if(te==="doc"){console.log(jc);let ye=await yd(A);if(ye)console.error(ye);return 0}if(te==="verify")return vd(A);return 1}function Cy(A){if(A.length===0)return pn;let z=pn.subcommands.filter((ee)=>ee.usage.split(" ")[0]===A[0]);if(z.length===0)return null;if(A.length===1&&z.length>1)return{name:`rule ${A[0]}`,description:`Subcommands of rule ${A[0]}`,usage:`rule ${A[0]} <subcommand>`,subcommands:z,options:[]};let X=A.length===1?z[0]:z.find((ee)=>ee.usage.split(" ")[1]===A[1]);if(!X)return null;return{name:`rule ${A[0]}`,description:X.description,usage:`rule ${X.usage}`,options:A[0]==="add"?Qr:[],examples:A[0]==="add"?eo:void 0}}function Sy(A){let z=xt({label:"rule",booleans:{global:["-g","--global"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},A),X={...z.flags,ref:z.values.ref,only:z.lists.only??[],help:z.help,positionals:z.positionals,errors:z.errors};return Ry(X),X}function Ry(A){let[z]=A.positionals;if(z&&!Ld.has(z))A.errors.push(`Unknown rule subcommand: ${z}`);if(A.deleteSource&&z!=="remove")if(z&&Ld.has(z))A.errors.push(`Unknown option for rule ${z}: --delete-source`);else A.errors.push("--delete-source is only valid with 'rule remove'");if(A.cleanup&&z!=="migrate")A.errors.push(Jn(z,"--cleanup"));if(A.example&&z!=="init")A.errors.push(Jn(z,"--example"));if(A.ref&&z!=="add")A.errors.push(Jn(z,"--ref"));if(A.only.length>0&&z!=="add")A.errors.push(Jn(z,"--only"));if(z==="add")Py(A);if(z==="migrate"){if(A.global)A.errors.push(Jn(z,"--global"));if(A.positionals.length>1)A.errors.push(`Unexpected rule migrate argument: ${A.positionals[1]}`)}else if(z==="wrapper")Ey(A);else if(A.positionals.length>2)A.errors.push(`Unexpected rule argument: ${A.positionals[2]}`);if(z==="list"&&A.global)A.errors.push("Unknown option for rule list: --global")}function kd(A){if(A.positionals[1])return A.positionals[1];if(A.ref||A.only.length>0)return ky;return}function Py(A){let z=kd(A);if(!z)return;if((A.ref||A.only.length>0)&&!V(z)){if(A.ref)A.errors.push(`--ref can only select a ref for an owner/repo source: ${z}`);if(A.only.length>0)A.errors.push("--only can only select rulebooks from an owner/repo source");return}if(A.ref&&!re(A.ref))A.errors.push(`--ref must use valid path segments: ${A.ref}`);let X=A.only.filter((ee)=>!c.test(ee));if(X.length>0)A.errors.push(`Invalid rulebook names: ${X.join(", ")}`)}function Jn(A,z){return A?`Unknown option for rule ${A}: ${z}`:`Unknown option for rule: ${z}`}function Ey(A){let z=A.positionals[1],X=A.positionals[2];if(!z){A.errors.push("rule wrapper requires add, remove, or list");return}if(!wy.has(z)){A.errors.push(`Unknown rule wrapper action: ${z}`);return}if(z==="list"){if(X)A.errors.push(`Unexpected rule wrapper argument: ${X}`);return}if(!X){A.errors.push(`rule wrapper ${z} requires a command`);return}if(A.positionals.length>3)A.errors.push(`Unexpected rule wrapper argument: ${A.positionals[3]}`)}function Dy(A){if(n(A)===null){Bc(A);return}let z=m(A);if(!z.config)return;Rt(A,{version:1,rules:z.config.rules,overrides:z.config.overrides??{},transparent_wrappers:z.config.transparent_wrappers??[]})}async function Ay(A,z){let X=z.positionals[1],ee=z.positionals[2],te=Pt(A,{global:z.global}).configTarget;if(X==="list"){let he=m(te);if(he.errors.length>0){for(let ve of he.errors)console.error(ve);return 1}return _y(he.config?.transparent_wrappers??[]),0}if(!ee||!S.test(ee))return console.error("transparent wrapper must match command pattern"),1;if(Re(ee))return console.error(`reserved command "${ee}" cannot be a wrapper`),1;let ae=m(te);if(ae.errors.length>0){for(let he of ae.errors)console.error(he);return 1}let le=ae.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},ye=X==="add"?[...new Set([...le.transparent_wrappers??[],ee])]:(le.transparent_wrappers??[]).filter((he)=>he!==ee);return Rt(te,{version:1,rules:le.rules,overrides:le.overrides??{},transparent_wrappers:ye}),console.log(X==="add"?`Added transparent wrapper: ${ee}`:`Removed transparent wrapper: ${ee}`),0}function _y(A){if(A.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${A.length}):`);for(let z of A)console.log(` - ${z}`)}import{sep as jy}from"node:path";import{existsSync as Ty,readFileSync as $y}from"node:fs";import{join as Iy}from"node:path";async function Oy(A){if(A.isTTY)return null;return(await Ue(A).catch(()=>null))?.trim()||null}function Fy(A){let z=A.env.get("CLAUDE_SETTINGS_PATH");if(z)return z;return Iy(A.home,".claude","settings.json")}function xi(A){let z=Fy(A);if(!Ty(z))return!1;try{let X=$y(z,"utf-8"),ee=JSON.parse(X);if(!ee.enabledPlugins)return!1;let te="cc-safety-net@cc-marketplace";if(!(te in ee.enabledPlugins))return!1;return ee.enabledPlugins[te]===!0}catch(X){if(R(o.debug,A.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${z}: ${X instanceof Error?X.message:String(X)}`);return!1}}async function Ci(A,z=process.stdin){let X=xi(A),ee;if(!X)ee="\uD83D\uDEE1️ CC Safety Net ❌";else{let ae=L(A,{cwd:process.cwd()}),le=ae.policy,ye=E(le,A.env),he=Object.values(H(le,ye.capabilities)).some((Ie)=>Ie.changesInherited),ve={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[he?"custom":ye.effectiveLevel],be=(ae.policyScopes?.weakenings.length??0)>0?"\uD83D\uDD3B":"";ee=`\uD83D\uDEE1️ CC Safety Net ${ve}${ye.worktreeMode?"\uD83C\uDF33":""}${be}${ae.state==="degraded"?"⚠️":""}`}let te=await Oy(z);if(te&&!te.startsWith("{"))console.log(`${te} | ${ee}`);else console.log(ee)}function xd(A){let z=L(A,{cwd:process.cwd()}),X=z.policy,ee=E(X,A.env),te=!!process.env.NO_COLOR||!process.stdout.isTTY,ae=Math.min(process.stdout.columns||80,100),le=te?"ok":"✔",ye=te?"OFF":"✘",he=(at,ct)=>{let lt=` ${at.padEnd(13)}${ct}`;return(lt.length>ae?`${lt.slice(0,ae-1)}…`:lt).replaceAll(ye,dt.red(ye))},ve=Object.values(H(X,ee.capabilities)).some((at)=>at.changesInherited),be=(at)=>at===A.home||at.startsWith(`${A.home}${jy}`)?`~${at.slice(A.home.length)}`:at,Ie={ready:dt.green,degraded:dt.yellow}[z.state],Xe=z.policyScopes?.weakenings??[],et=[...xi(A)?[]:["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."],...z.diagnostics],Ee=te?"-":"·";console.log([`${te?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ie(z.state)}`,"",he("Protection",`destructive ${X.destructiveCommandProtectionEnabled?le:ye} secrets ${X.secretProtection.enabled?le:ye}`),he("Level",ve?`${ee.effectiveLevel} (customised)`:ee.effectiveLevel),he("Rules",X.rules.length===0?"none active":`${X.rules.length} active`),he("Policy",be(d(A))),...z.policyScopes?[he("Project",be(v(process.cwd())))]:[],...ee.worktreeMode?[he("Worktree","relaxations active")]:[],"",...Xe.length===0?[]:[" Project policy",...Xe.flatMap((at)=>Fn(at," ",ae-6).map((ct,lt)=>lt===0?` ${ct}`:ct)),""],...et.length===0?[" Everything configured is active."]:[" Not active",...et.flatMap((at)=>Fn(at," ",ae-6).map((ct,lt)=>lt===0?` ${Ee} ${ct}`:ct)),""," Full report: cc-safety-net doctor"]].join(`
275
+ `))}import{spawn as Id}from"node:child_process";import{randomBytes as Jy}from"node:crypto";import{existsSync as Wy}from"node:fs";import{createServer as Ky}from"node:http";import{Writable as Yy}from"node:stream";var Wr=500;function Ny(A){let z=A.filter((te)=>te.decision!=="allow"),X=A.filter((te)=>te.decision==="allow"),ee=Math.min(z.length,Math.max(Wr-X.length,Math.ceil(Wr/2)));return[...z.slice(0,ee),...X.slice(0,Wr-ee)]}function Cd(A,z,X=D(A)){if(X)B(A,X);let ee=(ct)=>new Date(ct.getFullYear(),ct.getMonth(),ct.getDate()).getTime(),te=ee(new Date),ae=new Date(te);ae.setDate(ae.getDate()-(z-1));let le=ae.getTime(),ye=[],he={count:0};for(let ct of X?Yt(X,he):[])for(let lt of un(ct,he)){let pt=new Date(lt.ts).getTime();if(!Number.isFinite(pt))continue;if(pt>=le)ye.push(lt)}ye.sort((ct,lt)=>new Date(lt.ts).getTime()-new Date(ct.ts).getTime());let ve=Array.from({length:z},()=>0),be=Array.from({length:z},()=>0),Ie={},Xe={},et={},Ee=0,at=0;for(let ct of ye){let lt=ct.agent||"unknown";Ie[lt]=(Ie[lt]??0)+1;let pt=Math.round((te-ee(new Date(ct.ts)))/86400000),mt=z-1-pt,gt=pt>=0&&pt<z;if(gt)be[mt]=(be[mt]??0)+1;if(ct.decision!=="allow"){if(Ee++,ct.ruleId)Xe[ct.ruleId]=(Xe[ct.ruleId]??0)+1;let ut=Xr(ct.segment||ct.command);if(ut)et[ut]=(et[ut]??0)+1;if(ct.failureStage)at++;if(gt)ve[mt]=(ve[mt]??0)+1}}return{days:z,logsDir:X,homeDir:A.home,totalInWindow:ye.length,truncated:ye.length>Wr,unreadable:he.count,counts:{blocked:Ee,allowed:ye.length-Ee,agents:Ie,blockedByDay:ve,analyzedByDay:be,rules:Xe,commands:et,errors:at},entries:Ny(ye).sort((ct,lt)=>new Date(lt.ts).getTime()-new Date(ct.ts).getTime())}}import{spawn as My}from"node:child_process";import{existsSync as Hy,statSync as Sd}from"node:fs";import{delimiter as Uy,join as Gy}from"node:path";var By=120000,Kr="Choose the project folder",qy=`try
276
+ return POSIX path of (choose folder with prompt "${Kr}")
278
277
  on error number -128
279
278
  return ""
280
- end try`,fh=`Add-Type -AssemblyName System.Windows.Forms
279
+ end try`,Vy=`Add-Type -AssemblyName System.Windows.Forms
281
280
  $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
282
- $dialog.Description = '${po}'
283
- if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,zd=[{binary:"zenity",args:["--file-selection","--directory",`--title=${po}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",po]}],Jd=(j,K)=>(K.PATH??"").split(ch).some((te)=>{if(te.length===0)return!1;try{let re=Vd(dh(te,j));return re.isFile()&&(re.mode&73)!==0}catch{return!1}});function Ui(j,K){if(j==="darwin"||j==="win32")return!0;if(j!=="linux")return!1;if(!K.DISPLAY&&!K.WAYLAND_DISPLAY)return!1;return zd.some((te)=>Jd(te.binary,K))}function mh(j,K){if(j==="darwin")return{cmd:"osascript",args:["-e",ph]};if(j==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",fh]};let te=zd.find((re)=>Jd(re.binary,K));return te?{cmd:te.binary,args:te.args}:null}function Gi(j=process.platform,K=process.env){let te=mh(j,K);if(!te)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((re)=>{let oe=ah(te.cmd,te.args,{env:K,stdio:["ignore","pipe","pipe"]}),ce="",de=!1,we=(Ce)=>{if(de)return;de=!0,clearTimeout(xe),re(Ce)},xe=setTimeout(()=>{oe.kill(),we({error:"The folder dialog timed out"})},uh);oe.stdout.on("data",(Ce)=>{ce+=Ce.toString()}),oe.on("error",()=>we({error:`Could not open the folder dialog (${te.cmd})`})),oe.on("close",()=>{let Ce=ce.trim().replace(/\/+$/,"");if(!Ce)return we({cancelled:!0});if(!lh(Ce)||!Vd(Ce).isDirectory())return we({error:"That selection is not a folder on disk"});we({path:Ce})})})}var Wd=`<!doctype html>
281
+ $dialog.Description = '${Kr}'
282
+ if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,Rd=[{binary:"zenity",args:["--file-selection","--directory",`--title=${Kr}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",Kr]}],Pd=(A,z)=>(z.PATH??"").split(Uy).some((X)=>{if(X.length===0)return!1;try{let ee=Sd(Gy(X,A));return ee.isFile()&&(ee.mode&73)!==0}catch{return!1}});function Si(A,z){if(A==="darwin"||A==="win32")return!0;if(A!=="linux")return!1;if(!z.DISPLAY&&!z.WAYLAND_DISPLAY)return!1;return Rd.some((X)=>Pd(X.binary,z))}function zy(A,z){if(A==="darwin")return{cmd:"osascript",args:["-e",qy]};if(A==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",Vy]};let X=Rd.find((ee)=>Pd(ee.binary,z));return X?{cmd:X.binary,args:X.args}:null}function Ri(A=process.platform,z=process.env){let X=zy(A,z);if(!X)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((ee)=>{let te=My(X.cmd,X.args,{env:z,stdio:["ignore","pipe","pipe"]}),ae="",le=!1,ye=(ve)=>{if(le)return;le=!0,clearTimeout(he),ee(ve)},he=setTimeout(()=>{te.kill(),ye({error:"The folder dialog timed out"})},By);te.stdout.on("data",(ve)=>{ae+=ve.toString()}),te.on("error",()=>ye({error:`Could not open the folder dialog (${X.cmd})`})),te.on("close",()=>{let ve=ae.trim().replace(/\/+$/,"");if(!ve)return ye({cancelled:!0});if(!Hy(ve)||!Sd(ve).isDirectory())return ye({error:"That selection is not a folder on disk"});ye({path:ve})})})}var Ed=`<!doctype html>
284
283
  <html lang="en">
285
284
  <head>
286
285
  <meta charset="utf-8">
@@ -3188,6 +3187,18 @@ var commandSignature = (source) => {
3188
3187
  const next = tokens[1];
3189
3188
  return next && /^[a-z][a-z0-9-]*$/.test(next) ? \`\${binary} \${next}\` : binary;
3190
3189
  };
3190
+ function findSuspectEntries(entries) {
3191
+ const signatureKey = (entry) => \`\${entry.sessionId}
3192
+ \${commandSignature(entry.segment || entry.command)}\`;
3193
+ const denials = entries.filter((entry) => entry.decision !== "allow");
3194
+ const repeats = denials.filter((entry) => entry.sessionId).reduce((counts, entry) => counts.set(signatureKey(entry), (counts.get(signatureKey(entry)) ?? 0) + 1), new Map);
3195
+ return new Set(denials.filter((entry) => entry.failureStage || (repeats.get(signatureKey(entry)) ?? 0) >= 2));
3196
+ }
3197
+
3198
+ // src/core/policy/audit-retention-days.ts
3199
+ var DEFAULT_AUDIT_RETENTION_DAYS = 30;
3200
+ var MIN_AUDIT_RETENTION_DAYS = 1;
3201
+ var MAX_AUDIT_RETENTION_DAYS = 365;
3191
3202
 
3192
3203
  // src/core/policy/safety-level.ts
3193
3204
  var SAFETY_LEVEL_CAPABILITIES = {
@@ -3454,8 +3465,6 @@ var previewRequestId = 0;
3454
3465
  var dirty = false;
3455
3466
  var searchActive = false;
3456
3467
  var OVERVIEW_DAYS = 7;
3457
- var DEFAULT_RETENTION_DAYS = 30;
3458
- var MAX_RETENTION_DAYS = 365;
3459
3468
  var overview = null;
3460
3469
  var activity = null;
3461
3470
  var knownRuleIds = new Set;
@@ -3476,7 +3485,6 @@ var renderedFeedEntries = [];
3476
3485
  var suspects = new Set;
3477
3486
  var activeStarContext = { starred: null, starCount: null, blockedTotal: 0 };
3478
3487
  var integrations = null;
3479
- var integrationsRequested = false;
3480
3488
  var integrationBusy = new Set;
3481
3489
  var rulesData = null;
3482
3490
  var rulesRequested = false;
@@ -3764,10 +3772,6 @@ var applyView = () => {
3764
3772
  qs("dirty-chip").hidden = !dirty || view === "policy";
3765
3773
  if (view === "activity")
3766
3774
  applyFeedClamps(qs("activity-feed"));
3767
- if (view === "integrations" && !integrationsRequested) {
3768
- integrationsRequested = true;
3769
- loadIntegrations();
3770
- }
3771
3775
  if (view === "rules" && !rulesRequested) {
3772
3776
  rulesRequested = true;
3773
3777
  loadRules();
@@ -3830,7 +3834,7 @@ var renderOverviewActivity = () => {
3830
3834
  tile(overview.totalInWindow, "Analyzed", sparkline(overview.counts.analyzedByDay, "analyzed"))
3831
3835
  ].join("");
3832
3836
  };
3833
- var retentionDays = () => state?.policy?.audit?.retention_days ?? DEFAULT_RETENTION_DAYS;
3837
+ var retentionDays = () => state?.policy?.audit?.retention_days ?? DEFAULT_AUDIT_RETENTION_DAYS;
3834
3838
  var overviewDays = () => Math.min(OVERVIEW_DAYS, retentionDays());
3835
3839
  var renderRetention = (loaded) => {
3836
3840
  qs("retention-days").value = String(loaded.policy.audit.retention_days);
@@ -3886,15 +3890,6 @@ var renderTopLists = () => {
3886
3890
  renderTopList("top-commands", overview.counts.commands, "top-command", "data-command");
3887
3891
  renderTopList("top-rules", overview.counts.rules, "top-rule", "data-rule-id");
3888
3892
  };
3889
- var findSuspects = (entries) => {
3890
- const signatureKey = (entry) => \`\${entry.sessionId}
3891
- \${commandSignature(entry.segment || entry.command)}\`;
3892
- const repeats = entries.filter((entry) => entry.decision !== "allow" && entry.sessionId).reduce((counts, entry) => {
3893
- const key = signatureKey(entry);
3894
- return counts.set(key, (counts.get(key) ?? 0) + 1);
3895
- }, new Map);
3896
- return new Set(entries.filter((entry) => entry.decision !== "allow" && (entry.failureStage || (repeats.get(signatureKey(entry)) ?? 0) >= 2)));
3897
- };
3898
3893
  var clearCommandFilter = () => {
3899
3894
  if (!activityFilters.command)
3900
3895
  return false;
@@ -4001,7 +3996,7 @@ var loadActivity = async () => {
4001
3996
  }
4002
3997
  const feed = result.data;
4003
3998
  activity = feed;
4004
- suspects = findSuspects(activity.entries);
3999
+ suspects = findSuspectEntries(activity.entries);
4005
4000
  if (activityFilters.agent !== "all" && !(activityFilters.agent in activity.counts.agents)) {
4006
4001
  activityFilters.agent = "all";
4007
4002
  }
@@ -4047,23 +4042,24 @@ var renderIntegrations = () => {
4047
4042
  </div>\`;
4048
4043
  }).join("");
4049
4044
  };
4050
- var loadHealth = async () => {
4051
- const result = await requestJson("/api/health");
4052
- if (!result.ok || !Array.isArray(result.data?.hooks))
4045
+ var renderHealthStrip = (health) => {
4046
+ const loaded = integrations;
4047
+ if (!loaded || !health.ok)
4053
4048
  return;
4054
- const active = result.data.hooks.filter((hook) => hook.configured);
4055
- const inactive = result.data.hooks.filter((hook) => !hook.configured);
4049
+ const detected = loaded.targets.filter((row) => row.status === "active" || row.status === "disabled");
4050
+ const active = detected.filter((row) => row.status === "active");
4051
+ const inactive = detected.filter((row) => row.status === "disabled");
4056
4052
  const attention = inactive.length > 0 || active.length === 0;
4057
4053
  const parts = [];
4058
- const labelHtml = (hook) => \`<strong>\${escapeHtml(hook.label)}</strong>\`;
4054
+ const labelHtml = (row) => \`<strong>\${escapeHtml(row.label)}</strong>\`;
4059
4055
  if (active.length)
4060
4056
  parts.push(\`Hook active in \${active.map(labelHtml).join(", ")}\`);
4061
4057
  if (inactive.length)
4062
4058
  parts.push(\`\${inactive.map(labelHtml).join(", ")} detected without an active hook\`);
4063
4059
  if (!parts.length)
4064
4060
  parts.push("No agent hooks detected");
4065
- if (result.data.update?.updateAvailable)
4066
- parts.push(\`v\${escapeHtml(result.data.update.latestVersion)} available\`);
4061
+ if (health.data?.update?.updateAvailable)
4062
+ parts.push(\`v\${escapeHtml(health.data.update.latestVersion)} available\`);
4067
4063
  const link = attention ? ' <a class="view-all-link" href="#integrations">Fix in Integrations</a>' : "";
4068
4064
  const el = qs("health-strip");
4069
4065
  el.className = attention ? "status health-strip error" : "status health-strip ok";
@@ -4074,7 +4070,6 @@ var loadIntegrations = async () => {
4074
4070
  const result = await requestJson("/api/integrations");
4075
4071
  if (!result.ok || !Array.isArray(result.data?.targets)) {
4076
4072
  qs("integrations-list").innerHTML = \`<p class="empty">Could not load integrations: \${escapeHtml(errorText(result))}</p>\`;
4077
- integrationsRequested = false;
4078
4073
  return;
4079
4074
  }
4080
4075
  integrations = result.data;
@@ -4084,10 +4079,7 @@ var loadIntegrations = async () => {
4084
4079
  qs("integrations-platform").textContent = result.data.system.platform;
4085
4080
  qs("integrations-system").hidden = false;
4086
4081
  };
4087
- var refreshIntegrations = () => runRefresh("integrations-refresh", () => {
4088
- integrationsRequested = true;
4089
- return loadIntegrations();
4090
- });
4082
+ var refreshIntegrations = () => runRefresh("integrations-refresh", loadIntegrations);
4091
4083
  var renderRules = () => {
4092
4084
  const loaded = rulesData;
4093
4085
  if (!loaded)
@@ -4541,7 +4533,7 @@ var createPathList = (prefix, config) => {
4541
4533
  claimForProject();
4542
4534
  const submitted = qs(\`\${prefix}-input\`).value;
4543
4535
  const additions = entries.filter((entry) => !config.getPaths().includes(entry));
4544
- if (config.validateAdditions && additions.length) {
4536
+ if (additions.length) {
4545
4537
  adding = true;
4546
4538
  try {
4547
4539
  const error = await config.validateAdditions([...config.getPaths(), ...additions]);
@@ -5153,7 +5145,6 @@ var ingestProjectState = async (okStatus) => {
5153
5145
  return false;
5154
5146
  }
5155
5147
  projectDraft = {
5156
- dir: result.data.dir,
5157
5148
  path: result.data.path,
5158
5149
  revision: result.data.revision,
5159
5150
  canPickDirectory: result.data.canPickDirectory === true,
@@ -5312,10 +5303,10 @@ var saveRetentionDays = async (days) => {
5312
5303
  if (!saved)
5313
5304
  return;
5314
5305
  const current = saved.policy.audit.retention_days;
5315
- if (!Number.isInteger(days) || days < 1 || days > MAX_RETENTION_DAYS) {
5306
+ if (!Number.isInteger(days) || days < MIN_AUDIT_RETENTION_DAYS || days > MAX_AUDIT_RETENTION_DAYS) {
5316
5307
  qs("retention-days").value = String(current);
5317
5308
  setAppStatus("Retention unchanged", "error");
5318
- setDetailStatus(\`Error: retention must be a whole number of days from 1 to \${MAX_RETENTION_DAYS}.\`, "error");
5309
+ setDetailStatus(\`Error: retention must be a whole number of days from \${MIN_AUDIT_RETENTION_DAYS} to \${MAX_AUDIT_RETENTION_DAYS}.\`, "error");
5319
5310
  return;
5320
5311
  }
5321
5312
  if (days === current)
@@ -5899,7 +5890,7 @@ window.addEventListener("beforeunload", (event) => {
5899
5890
  });
5900
5891
  window.addEventListener("hashchange", applyView);
5901
5892
  applyView();
5902
- loadHealth();
5893
+ Promise.all([loadIntegrations(), requestJson("/api/health")]).then(([, health]) => renderHealthStrip(health));
5903
5894
  load().then((loaded) => {
5904
5895
  if (loaded)
5905
5896
  loadStarContext();
@@ -5914,6 +5905,6 @@ load().then((loaded) => {
5914
5905
  </script>
5915
5906
  </body>
5916
5907
  </html>
5917
- `;var Kd='<script id="ccsn-data" type="application/json">';function Yd(j){return Wd.replace(Kd,()=>Kd+JSON.stringify({token:j}).replaceAll("<","\\u003c"))}var fo="kenryu42/cc-safety-net",bh=`https://github.com/${fo}`,Vi=1e4,Lh=7,wh="The project draft directory changed; reload the draft before applying.",kh="audit settings are user scope only; remove the audit section from a project proposal";async function tu(j,K={}){let te=At({label:"gui",booleans:{noOpen:["--no-open"]}},j),re=K.log??console.log,oe=K.error??console.error;if(te.errors.length>0){for(let de of te.errors)oe(de);return oe("Usage: cc-safety-net gui [--no-open]"),1}let ce=await xh(l,K);if(re(`CC Safety Net policy GUI: ${ce.url}`),!te.flags.noOpen)try{await(K.openBrowser??$h)(ce.url)}catch(de){oe(`Failed to open browser: ${de instanceof Error?de.message:String(de)}`),oe(`Open this URL manually: ${ce.url}`)}if(K.keepAlive===!1)return await ce.close(),0;return await Ih(ce),0}async function xh(j,K={}){let te=gh(24).toString("base64url"),re={dir:null,revision:0},oe=hh((we,xe)=>{Ch(j,we,xe,te,K,re)});await new Promise((we,xe)=>{oe.once("error",xe),oe.listen(0,"127.0.0.1",()=>{oe.off("error",xe),we()})});let de=`http://127.0.0.1:${oe.address().port}`;return{origin:de,token:te,url:`${de}/?token=${encodeURIComponent(te)}`,close:()=>Th(oe)}}async function Ch(j,K,te,re,oe,ce){let de=j(),we=new URL(K.url??"/","http://127.0.0.1");if(K.method==="GET"&&we.pathname==="/favicon.ico"){te.writeHead(204,{"cache-control":"no-store"}),te.end();return}if(!Dh(K,we,re)){xt(te,403,{error:"Forbidden"});return}if(K.method==="GET"&&we.pathname==="/"){_h(te,Yd(re));return}if(K.method==="GET"&&we.pathname==="/api/policy"){let xe=Yc(de,oe),Ce=k(de,Bi(oe));xt(te,200,{...xe,configState:Be(Ce),...Ce.policyScopes?{projectPolicy:{path:w(oe.cwd??process.cwd()),weakenings:Ce.policyScopes.weakenings}}:{},destructiveCommandRules:U,secretPatterns:rt,version:Et(),preview:xe.errors.length>0?null:Ge(xe.policy,de.env)});return}if(K.method==="POST"&&we.pathname==="/api/policy/preview"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=Zc(de,xe.value);xt(te,Ce.errors.length>0?400:200,Ce);return}if(K.method==="POST"&&we.pathname==="/api/policy/explain"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=xe.value;if(Ce===null||typeof Ce.command!=="string"){xt(te,400,{errors:["command must be a string"]});return}let Se=Ut(Ce.policy,de.home);if(Se.length>0){xt(te,400,{errors:Se});return}xt(te,200,Ph(de,Ce.command,Ce.policy,oe));return}if(K.method==="POST"&&we.pathname==="/api/policy"){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=Xt(de,xe.value,oe);xt(te,Ce.errors.length>0?400:200,Ce);return}if(K.method==="POST"&&we.pathname==="/api/reset"){xt(te,200,Xt(de,Q,oe));return}if(K.method==="POST"&&we.pathname==="/api/repair"){xt(te,200,Xc(de,oe));return}if(K.method==="POST"&&we.pathname==="/api/policy/project/choose-directory"){let xe=await(oe.chooseDirectory??Gi)();if("path"in xe)ce.dir=xe.path,ce.revision+=1;xt(te,200,{cancelled:"cancelled"in xe,..."error"in xe?{error:xe.error}:{}});return}if(K.method==="GET"&&we.pathname==="/api/policy/project"){let xe=nu(ce,oe),Ce=Zd(xe,de.home),Se=sr(de,oe);xt(te,200,{dir:xe,path:w(xe),revision:ce.revision,baseline:Se.baseline,userPolicyDiagnostics:Se.diagnostics,projection:Ce.projection,projectionDiagnostics:Ce.diagnostics,canPickDirectory:Ui(process.platform,process.env)});return}if(K.method==="POST"&&we.pathname==="/api/policy/project/diff"){let xe=await Xd(de,K,te,ce,oe);if(!xe)return;let Ce=Zd(xe.dir,de.home),Se=sr(de,oe).baseline,Ne=X(Se,le(xe.proposal,de.home).policy);xt(te,200,{rows:Xr(X(Se,Ce.projection).policy,Ne.policy,!1),weakenings:Ne.weakenings,existingFileDiagnostics:Ce.diagnostics,errors:[]});return}if(K.method==="POST"&&we.pathname==="/api/policy/project/apply"){let xe=await Xd(de,K,te,ce,oe);if(!xe)return;let Ce=Rh(xe.dir,xe.proposal,de.home);xt(te,Ce.errors.length>0?500:200,Ce);return}if(K.method==="GET"&&we.pathname==="/api/activity"){let xe=ne(de,oe),Ce=Eh(we.searchParams.get("days"),xe);if(Ce===null){xt(te,400,{error:`days must be an integer between 1 and ${xe}`});return}xt(te,200,qd(de,Ce,oe.activityLogsDir));return}if(K.method==="POST"&&we.pathname==="/api/rules/choose-directory"){xt(te,200,await Gi());return}if(K.method==="GET"&&we.pathname==="/api/rules"){let xe=Z(de,Bi(oe)),Ce=new Map(xe.rules.map((Se)=>[Se.name,Se]));xt(te,200,{projectPath:oe.cwd??process.cwd(),canPickDirectory:Ui(process.platform,process.env),rulebooks:xe.rulebooks.map((Se)=>({source:Se.source,spec:Se.spec,name:Se.name,version:Se.version,rules:Se.rules.flatMap((Ne)=>{let He=Ce.get(Ne);if(!He)return[];return[{name:He.name,command:He.command,subcommand:He.subcommand,block_args:He.block_args,reason:He.reason}]})})),errors:xe.errors,warnings:xe.warnings});return}if(K.method==="GET"&&we.pathname==="/api/star/context"){xt(te,200,await(oe.fetchStarContext??(()=>Mh(de,{logsDir:oe.activityLogsDir})))());return}if(K.method==="POST"&&we.pathname==="/api/star"){let xe=await(oe.starRepo??Oh)();xt(te,200,xe.ok?{ok:!0}:{ok:!1,fallbackUrl:bh});return}if(K.method==="GET"&&we.pathname==="/api/integrations"){xt(te,200,await(oe.fetchIntegrations??(()=>jh(de)))());return}if(K.method==="GET"&&we.pathname==="/api/health"){xt(te,200,await(oe.fetchHealth??(()=>Fh(de)))());return}if(K.method==="POST"&&(we.pathname==="/api/install"||we.pathname==="/api/uninstall")){let xe=await cr(K);if(!xe.ok){xt(te,xe.status,{errors:[xe.error]});return}let Ce=xe.value?.target;if(typeof Ce!=="string"||!Wt.some((Ne)=>Ne.target===Ce)){xt(te,400,{error:"unknown target"});return}let Se=we.pathname==="/api/install"?"install":"uninstall";xt(te,200,await(oe.runIntegration??Nh)(Se,Ce));return}xt(te,404,{error:"Not found"})}function Bi(j){return{...j,cwd:j.cwd??process.cwd()}}function nu(j,K){return j.dir??K.cwd??process.cwd()}function Zd(j,K){let te=w(j),re=yh(te)?bn(te):{value:void 0,errors:[]},oe=le(re.value,K);return{projection:oe.policy,diagnostics:[...re.errors,...oe.diagnostics]}}async function Xd(j,K,te,re,oe){let ce=nu(re,oe),de=re.revision,we=await cr(K);if(!we.ok)return xt(te,we.status,{errors:[we.error]}),null;let xe=we.value;if(typeof xe?.revision!=="number")return xt(te,400,{errors:["revision must be a number"]}),null;if(xe.revision!==de)return xt(te,409,{errors:[wh]}),null;let Ce=Sh(xe.proposal,j.home);if(Ce.length>0)return xt(te,400,{errors:Ce}),null;return{dir:ce,proposal:xe.proposal}}function Sh(j,K){let te=Ut(j,K);if(te.length>0)return te;return j?.audit===void 0?[]:[kh]}function Rh(j,K,te){let re=w(j),oe=Qr(K,h(K,te));try{return y(s(S(j,"project policy"),re),`${JSON.stringify(oe,null,2)}
5918
- `),{path:re,errors:[]}}catch(ce){return{path:re,errors:[ce instanceof Error?ce.message:String(ce)]}}}function Ph(j,K,te,re){let oe=h(te,j.home),ce=k(j,Bi(re)),de=De({rules:ce.policy.rules,transparentWrappers:ce.policy.transparentWrappers,safety:Ue(oe.safety),worktreeMode:oe.workflow.worktree_mode,destructiveCommandProtectionEnabled:oe.destructive_command_protection.enabled,destructiveCommandRuleOverrides:oe.destructive_command_protection.overrides,destructiveCommandAllowPaths:oe.destructive_command_protection.allow_paths,secretProtection:{enabled:oe.secret_protection.enabled,disabledRules:We(oe.secret_protection.overrides),denyPaths:oe.secret_protection.deny_paths,allowPaths:oe.secret_protection.allow_paths}});return er(K,{policySnapshot:de,cwd:re.cwd,userConfigDir:re.userConfigDir},j)}function Eh(j,K){if(j===null)return Math.min(Lh,K);let te=Number(j);if(!Number.isInteger(te)||te<1||te>K)return null;return te}function Dh(j,K,te){if(K.searchParams.get("token")!==te)return!1;if(j.method!=="POST")return!0;return j.headers["x-cc-safety-net-token"]===te}var Ah=1048576;async function cr(j){let K=[],te=0;for await(let re of j){let oe=re;if(te+=oe.byteLength,te>Ah)return{ok:!1,status:413,error:"Request body is too large"};K.push(oe)}try{return{ok:!0,value:JSON.parse(Buffer.concat(K).toString("utf-8")||"{}")}}catch(re){return{ok:!1,status:400,error:`Invalid JSON: ${re instanceof Error?re.message:String(re)}`}}}function _h(j,K){j.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),j.end(K)}function xt(j,K,te){j.writeHead(K,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),j.end(JSON.stringify(te))}function Th(j){return new Promise((K,te)=>{j.close((re)=>re?te(re):K())})}function Ih(j){return new Promise((K)=>{let te=()=>{process.off("SIGINT",re),process.off("SIGTERM",re)},re=()=>{te(),j.close().then(K)};process.once("SIGINT",re),process.once("SIGTERM",re)})}function $h(j){let K=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",te=process.platform==="win32"?["/c","start","",j]:[j];return new Promise((re,oe)=>{let ce=eu(K,te,{detached:!0,stdio:"ignore"}),de=(xe)=>{ce.off("spawn",we),oe(xe)},we=()=>{ce.off("error",de),ce.unref(),re()};ce.once("error",de),ce.once("spawn",we)})}async function Oh(j="gh",K=Vi){return{ok:await qi(j,["api","-X","PUT",`/user/starred/${fo}`],K)===0}}async function jh(j,K={}){let te=await Hn(K.fetcher),re=ru(j,te);return{targets:Nt.map((oe)=>{let ce=re.find((de)=>de.platform===oe.id);return{target:oe.id,label:St(oe.id),version:te.versions[oe.id]??null,status:ce?.configured?"active":ce?.detected?"disabled":ce?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:te.version,nodeVersion:te.nodeVersion,platform:te.platform}}}function ru(j,K){return Dn(j,process.cwd(),{ampPluginListOutput:K.ampPluginListOutput,codexPluginListOutput:K.codexPluginListOutput,copilotCliVersion:K.versions["copilot-cli"]})}async function Fh(j,K={}){let[te,re]=await Promise.all([Hn(K.fetcher),(K.checkUpdates??tn)()]);return{hooks:ru(j,te).filter((oe)=>oe.detected).map((oe)=>({platform:oe.platform,label:St(oe.platform),configured:oe.configured})),update:{currentVersion:re.currentVersion,latestVersion:re.latestVersion??null,updateAvailable:re.updateAvailable}}}var Qd=Promise.resolve();function Nh(j,K,te={}){let re=async()=>{let ce=[],{log:de,error:we}=console;console.log=(...xe)=>ce.push(xe.map(String).join(" ")),console.error=console.log;try{return{ok:await ir(j,[],{selectTargets:async()=>[K],output:new vh({write(Ce,Se,Ne){ce.push(String(Ce).replace(/\n$/,"")),Ne()}}),...te})===0,output:ce.join(`
5919
- `)}}finally{console.log=de,console.error=we}},oe=Qd.then(re);return Qd=oe.then(()=>{return},()=>{return}),oe}async function Mh(j,K={}){let[te,re,oe]=await Promise.all([Hh(K.command),Uh(K.fetchRepo),Promise.resolve(gr(j,ne(j),K.logsDir).totalBlocked)]);return{starred:te,starCount:re,blockedTotal:oe}}async function Hh(j="gh",K=Vi){if(await qi(j,["auth","status"],K)!==0)return null;let te=await qi(j,["api",`/user/starred/${fo}`],K);if(te===0)return!0;if(te===null)return null;return!1}function qi(j,K,te){return new Promise((re)=>{let oe=eu(j,K,{stdio:"ignore",windowsHide:!0}),ce=!1,de,we=(xe)=>{if(ce)return;if(ce=!0,de)clearTimeout(de);re(xe)};oe.once("error",()=>we(null)),oe.once("close",we),de=setTimeout(()=>{oe.kill(),we(null)},te)})}async function Uh(j=fetch){try{let K=await j(`https://api.github.com/repos/${fo}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(Vi)});if(!K.ok)return null;let te=await K.json();return typeof te.stargazers_count==="number"?te.stargazers_count:null}catch{return null}}function Gh(j){if(j[0]!=="help")return!1;let K=j[1];if(!K)pi(),process.exit(0);if(tr(K))process.exit(0);console.error(`Unknown command: ${K}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var Bh={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),tr("hook",console.error),process.exit(1)},install:async(j)=>{process.exit(await ir("install",j))},update:async(j)=>{process.exit(await Ri(j))},uninstall:async(j)=>{process.exit(await ir("uninstall",j))},rule:async(j)=>{process.exit(await Ud(l(),j))},policy:async(j)=>{process.exit(await nd(l(),j))},status:async(j)=>{if(Kt(At({label:"status"},j).errors))process.exit(1);Bd(l())},statusline:async(j)=>{let K=At({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},j);if(K.errors.length===0&&K.flags.claudeCode){await Hi(l());return}if(Kt(K.errors),!K.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");tr("statusline",console.error),process.exit(1)},doctor:async(j)=>{let K=oi(j);if(!K)process.exit(1);let te=await Sl(l(),{json:K.json,skipUpdateCheck:K.skipUpdateCheck});process.exit(te)},logs:async(j)=>{process.exit(await Qi(l(),j))},gui:async(j)=>{process.exit(await tu(j))},explain:async(j)=>{process.exit(await Ol(l(),j))}};async function qh(j){let K=At({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},j);if(Gh(j))return;let te=j[0],re=te?mr(te):void 0;if(K.help&&re&&re.name!=="rule")tr(re.name),process.exit(0);if(!te||K.help&&!re)pi(),process.exit(0);if(K.flags.version)Nl(),process.exit(0);if(re){await Bh[re.name](j.slice(1));return}if(te==="--statusline"){await Hi(l());return}console.error(te.startsWith("-")?`Unknown option: ${te}`:`Unknown command: ${te}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{qh as runCli};
5908
+ `;var Dd='<script id="ccsn-data" type="application/json">';function Ad(A){return Ed.replace(Dd,()=>Dd+JSON.stringify({token:A}).replaceAll("<","\\u003c"))}var Yr="kenryu42/cc-safety-net",Zy=`https://github.com/${Yr}`,Di=1e4,Xy=7,Qy="The project draft directory changed; reload the draft before applying.",eh="audit settings are user scope only; remove the audit section from a project proposal";async function Od(A,z={}){let X=xt({label:"gui",booleans:{noOpen:["--no-open"]}},A),ee=z.log??console.log,te=z.error??console.error;if(X.errors.length>0){for(let le of X.errors)te(le);return te("Usage: cc-safety-net gui [--no-open]"),1}let ae=await th(l,z);if(ee(`CC Safety Net policy GUI: ${ae.url}`),!X.flags.noOpen)try{await(z.openBrowser??ph)(ae.url)}catch(le){te(`Failed to open browser: ${le instanceof Error?le.message:String(le)}`),te(`Open this URL manually: ${ae.url}`)}if(z.keepAlive===!1)return await ae.close(),0;return await uh(ae),0}async function th(A,z={}){let X=Jy(24).toString("base64url"),ee={dir:null,revision:0},te=Ky((ye,he)=>{nh(A,ye,he,X,z,ee)});await new Promise((ye,he)=>{te.once("error",he),te.listen(0,"127.0.0.1",()=>{te.off("error",he),ye()})});let le=`http://127.0.0.1:${te.address().port}`;return{origin:le,token:X,url:`${le}/?token=${encodeURIComponent(X)}`,close:()=>dh(te)}}async function nh(A,z,X,ee,te,ae){let le=A(),ye=new URL(z.url??"/","http://127.0.0.1");if(z.method==="GET"&&ye.pathname==="/favicon.ico"){X.writeHead(204,{"cache-control":"no-store"}),X.end();return}if(!ah(z,ye,ee)){yt(X,403,{error:"Forbidden"});return}if(z.method==="GET"&&ye.pathname==="/"){ch(X,Ad(ee));return}if(z.method==="GET"&&ye.pathname==="/api/policy"){let he=Ac(le,te),ve=L(le,Pi(te));yt(X,200,{...he,configState:Ne(ve),...ve.policyScopes?{projectPolicy:{path:v(te.cwd??process.cwd()),weakenings:ve.policyScopes.weakenings}}:{},destructiveCommandRules:G,secretPatterns:Ke,version:wt(),preview:he.errors.length>0?null:Te(he.policy,le.env)});return}if(z.method==="POST"&&ye.pathname==="/api/policy/preview"){let he=await Wn(z);if(!he.ok){yt(X,he.status,{errors:[he.error]});return}let ve=_c(le,he.value);yt(X,ve.errors.length>0?400:200,ve);return}if(z.method==="POST"&&ye.pathname==="/api/policy/explain"){let he=await Wn(z);if(!he.ok){yt(X,he.status,{errors:[he.error]});return}let ve=he.value;if(ve===null||typeof ve.command!=="string"){yt(X,400,{errors:["command must be a string"]});return}let be=Bn(ve.policy,le.home);if(be.length>0){yt(X,400,{errors:be});return}yt(X,200,ih(le,ve.command,ve.policy,te));return}if(z.method==="POST"&&ye.pathname==="/api/policy"){let he=await Wn(z);if(!he.ok){yt(X,he.status,{errors:[he.error]});return}let ve=Vt(le,he.value,te);yt(X,ve.errors.length>0?400:200,ve);return}if(z.method==="POST"&&ye.pathname==="/api/reset"){yt(X,200,Vt(le,J,te));return}if(z.method==="POST"&&ye.pathname==="/api/repair"){yt(X,200,Tc(le,te));return}if(z.method==="POST"&&ye.pathname==="/api/policy/project/choose-directory"){let he=await(te.chooseDirectory??Ri)();if("path"in he)ae.dir=he.path,ae.revision+=1;yt(X,200,{cancelled:"cancelled"in he,..."error"in he?{error:he.error}:{}});return}if(z.method==="GET"&&ye.pathname==="/api/policy/project"){let he=Fd(ae,te),ve=_d(he,le.home),be=qn(le,te);yt(X,200,{path:v(he),revision:ae.revision,baseline:be.baseline,userPolicyDiagnostics:be.diagnostics,projection:ve.projection,projectionDiagnostics:ve.diagnostics,canPickDirectory:Si(process.platform,process.env)});return}if(z.method==="POST"&&ye.pathname==="/api/policy/project/diff"){let he=await Td(le,z,X,ae,te);if(!he)return;let ve=_d(he.dir,le.home),be=qn(le,te).baseline,Ie=Y(be,se(he.proposal,le.home).policy);yt(X,200,{rows:Fr(Y(be,ve.projection).policy,Ie.policy,!1),weakenings:Ie.weakenings,existingFileDiagnostics:ve.diagnostics});return}if(z.method==="POST"&&ye.pathname==="/api/policy/project/apply"){let he=await Td(le,z,X,ae,te);if(!he)return;let ve=oh(he.dir,he.proposal,le.home);yt(X,ve.errors.length>0?500:200,ve);return}if(z.method==="GET"&&ye.pathname==="/api/activity"){let he=Q(le,te),ve=sh(ye.searchParams.get("days"),he);if(ve===null){yt(X,400,{error:`days must be an integer between 1 and ${he}`});return}yt(X,200,Cd(le,ve,te.activityLogsDir));return}if(z.method==="POST"&&ye.pathname==="/api/rules/choose-directory"){yt(X,200,await Ri());return}if(z.method==="GET"&&ye.pathname==="/api/rules"){let he=K(le,Pi(te)),ve=new Map(he.rules.map((be)=>[be.name,be]));yt(X,200,{projectPath:te.cwd??process.cwd(),canPickDirectory:Si(process.platform,process.env),rulebooks:he.rulebooks.map((be)=>({source:be.source,spec:be.spec,name:be.name,version:be.version,rules:be.rules.flatMap((Ie)=>{let Xe=ve.get(Ie);if(!Xe)return[];return[{name:Xe.name,command:Xe.command,subcommand:Xe.subcommand,block_args:Xe.block_args,reason:Xe.reason}]})})),errors:he.errors,warnings:he.warnings});return}if(z.method==="GET"&&ye.pathname==="/api/star/context"){yt(X,200,await(te.fetchStarContext??(()=>vh(le,{logsDir:te.activityLogsDir})))());return}if(z.method==="POST"&&ye.pathname==="/api/star"){let he=await(te.starRepo??fh)();yt(X,200,he.ok?{ok:!0}:{ok:!1,fallbackUrl:Zy});return}if(z.method==="GET"&&ye.pathname==="/api/integrations"){yt(X,200,await(te.fetchIntegrations??(()=>mh(le)))());return}if(z.method==="GET"&&ye.pathname==="/api/health"){yt(X,200,await(te.fetchHealth??yh)());return}if(z.method==="POST"&&(ye.pathname==="/api/install"||ye.pathname==="/api/uninstall")){let he=await Wn(z);if(!he.ok){yt(X,he.status,{errors:[he.error]});return}let ve=he.value?.target;if(typeof ve!=="string"||!Mt.some((Ie)=>Ie.target===ve)){yt(X,400,{error:"unknown target"});return}let be=ye.pathname==="/api/install"?"install":"uninstall";yt(X,200,await(te.runIntegration??hh)(be,ve));return}yt(X,404,{error:"Not found"})}function Pi(A){return{...A,cwd:A.cwd??process.cwd()}}function Fd(A,z){return A.dir??z.cwd??process.cwd()}function _d(A,z){let X=v(A),ee=Wy(X)?cn(X):{value:void 0,errors:[]},te=se(ee.value,z);return{projection:te.policy,diagnostics:[...ee.errors,...te.diagnostics]}}async function Td(A,z,X,ee,te){let ae=Fd(ee,te),le=ee.revision,ye=await Wn(z);if(!ye.ok)return yt(X,ye.status,{errors:[ye.error]}),null;let he=ye.value;if(typeof he?.revision!=="number")return yt(X,400,{errors:["revision must be a number"]}),null;if(he.revision!==le)return yt(X,409,{errors:[Qy]}),null;let ve=rh(he.proposal,A.home);if(ve.length>0)return yt(X,400,{errors:ve}),null;return{dir:ae,proposal:he.proposal}}function rh(A,z){let X=Bn(A,z);if(X.length>0)return X;return A?.audit===void 0?[]:[eh]}function oh(A,z,X){let ee=v(A),te=jr(z,x(z,X));try{return g(i(w(A,"project policy"),ee),`${JSON.stringify(te,null,2)}
5909
+ `),{path:ee,errors:[]}}catch(ae){return{path:ee,errors:[ae instanceof Error?ae.message:String(ae)]}}}function ih(A,z,X,ee){let te=x(X,A.home),ae=L(A,Pi(ee)),le=Le({rules:ae.policy.rules,transparentWrappers:ae.policy.transparentWrappers,safety:Oe(te.safety),worktreeMode:te.workflow.worktree_mode,destructiveCommandProtectionEnabled:te.destructive_command_protection.enabled,destructiveCommandRuleOverrides:te.destructive_command_protection.overrides,destructiveCommandAllowPaths:te.destructive_command_protection.allow_paths,secretProtection:{enabled:te.secret_protection.enabled,disabledRules:De(te.secret_protection.overrides),denyPaths:te.secret_protection.deny_paths,allowPaths:te.secret_protection.allow_paths}});return jn(z,{policySnapshot:le,cwd:ee.cwd,userConfigDir:ee.userConfigDir},A)}function sh(A,z){if(A===null)return Math.min(Xy,z);let X=Number(A);if(!Number.isInteger(X)||X<1||X>z)return null;return X}function ah(A,z,X){if(z.searchParams.get("token")!==X)return!1;if(A.method!=="POST")return!0;return A.headers["x-cc-safety-net-token"]===X}var lh=1048576;async function Wn(A){let z=[],X=0;for await(let ee of A){let te=ee;if(X+=te.byteLength,X>lh)return{ok:!1,status:413,error:"Request body is too large"};z.push(te)}try{return{ok:!0,value:JSON.parse(Buffer.concat(z).toString("utf-8")||"{}")}}catch(ee){return{ok:!1,status:400,error:`Invalid JSON: ${ee instanceof Error?ee.message:String(ee)}`}}}function ch(A,z){A.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),A.end(z)}function yt(A,z,X){A.writeHead(z,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),A.end(JSON.stringify(X))}function dh(A){return new Promise((z,X)=>{A.close((ee)=>ee?X(ee):z())})}function uh(A){return new Promise((z)=>{let X=()=>{process.off("SIGINT",ee),process.off("SIGTERM",ee)},ee=()=>{X(),A.close().then(z)};process.once("SIGINT",ee),process.once("SIGTERM",ee)})}function ph(A){let z=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",X=process.platform==="win32"?["/c","start","",A]:[A];return new Promise((ee,te)=>{let ae=Id(z,X,{detached:!0,stdio:"ignore"}),le=(he)=>{ae.off("spawn",ye),te(he)},ye=()=>{ae.off("error",le),ae.unref(),ee()};ae.once("error",le),ae.once("spawn",ye)})}async function fh(A="gh",z=Di){return{ok:await Ei(A,["api","-X","PUT",`/user/starred/${Yr}`],z)===0}}async function mh(A,z={}){let X=await ir(z.fetcher),ee=gh(A,X);return{targets:Tt.map((te)=>{let ae=ee.find((le)=>le.platform===te.id);return{target:te.id,label:bt(te.id),version:X.versions[te.id]??null,status:ae?.configured?"active":ae?.detected?"disabled":ae?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:X.version,nodeVersion:X.nodeVersion,platform:X.platform}}}function gh(A,z){return bn(A,process.cwd(),{ampPluginListOutput:z.ampPluginListOutput,codexPluginListOutput:z.codexPluginListOutput,copilotCliVersion:z.versions["copilot-cli"]})}async function yh(A={}){let z=await(A.checkUpdates??Wt)();return{update:{latestVersion:z.latestVersion??null,updateAvailable:z.updateAvailable}}}var $d=Promise.resolve();function hh(A,z,X={}){let ee=async()=>{let ae=[],{log:le,error:ye}=console;console.log=(...he)=>ae.push(he.map(String).join(" ")),console.error=console.log;try{return{ok:await Gn(A,[],{selectTargets:async()=>[z],output:new Yy({write(ve,be,Ie){ae.push(String(ve).replace(/\n$/,"")),Ie()}}),...X})===0,output:ae.join(`
5910
+ `)}}finally{console.log=le,console.error=ye}},te=$d.then(ee);return $d=te.then(()=>{return},()=>{return}),te}async function vh(A,z={}){let[X,ee,te]=await Promise.all([bh(z.command),Lh(z.fetchRepo),Promise.resolve(er(A,Q(A),z.logsDir).totalBlocked)]);return{starred:X,starCount:ee,blockedTotal:te}}async function bh(A="gh",z=Di){if(await Ei(A,["auth","status"],z)!==0)return null;let X=await Ei(A,["api",`/user/starred/${Yr}`],z);if(X===0)return!0;if(X===null)return null;return!1}function Ei(A,z,X){return new Promise((ee)=>{let te=Id(A,z,{stdio:"ignore",windowsHide:!0}),ae=!1,le,ye=(he)=>{if(ae)return;if(ae=!0,le)clearTimeout(le);ee(he)};te.once("error",()=>ye(null)),te.once("close",ye),le=setTimeout(()=>{te.kill(),ye(null)},X)})}async function Lh(A=fetch){try{let z=await A(`https://api.github.com/repos/${Yr}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(Di)});if(!z.ok)return null;let X=await z.json();return typeof X.stargazers_count==="number"?X.stargazers_count:null}catch{return null}}function wh(A){if(A[0]!=="help")return!1;let z=A[1];if(!z)Xo(),process.exit(0);if(Nn(z))process.exit(0);console.error(`Unknown command: ${z}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var kh={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),Nn("hook",console.error),process.exit(1)},install:async(A)=>{process.exit(await Gn("install",A))},update:async(A)=>{process.exit(await fi(A))},uninstall:async(A)=>{process.exit(await Gn("uninstall",A))},rule:async(A)=>{process.exit(await wd(l(),A))},policy:async(A)=>{process.exit(await Fc(l(),A))},status:async(A)=>{if(Ht(xt({label:"status"},A).errors))process.exit(1);xd(l())},statusline:async(A)=>{let z=xt({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},A);if(z.errors.length===0&&z.flags.claudeCode){await Ci(l());return}if(Ht(z.errors),!z.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");Nn("statusline",console.error),process.exit(1)},doctor:async(A)=>{let z=qo(A);if(!z)process.exit(1);let X=await ll(l(),{json:z.json,skipUpdateCheck:z.skipUpdateCheck});process.exit(X)},logs:async(A)=>{process.exit(await ji(l(),A))},gui:async(A)=>{process.exit(await Od(A))},explain:async(A)=>{process.exit(await bl(l(),A))}};async function xh(A){let z=xt({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},A);if(wh(A))return;let X=A[0],ee=X?Qn(X):void 0;if(z.help&&ee&&ee.name!=="rule")Nn(ee.name),process.exit(0);if(!X||z.help&&!ee)Xo(),process.exit(0);if(z.flags.version)kl(),process.exit(0);if(ee){await kh[ee.name](A.slice(1));return}if(X==="--statusline"){await Ci(l());return}console.error(X.startsWith("-")?`Unknown option: ${X}`:`Unknown command: ${X}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{xh as runCli};