cc-safety-net 2.6.16 → 2.6.18

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,55 +1,55 @@
1
- import{a,s,Me,nt,T,vt,rt,c,n,ot,_,S,ge,xt,m,Ie,x,st,l,o,w,i,ae,r,h,ye,W,wt,Ct,p,ve,be,Et,M,X,ce,C,kt,A,y,le,z,u,O,Q,at,ct,F,E,D,xe,Se,$e,ue,d,e,je,Oe,Ue,we,lt,ut,de,De,pe,He,ee,V,Ge,Ce,q,dt,K,te,ne,fe,pt,ft,k,I,Be,mt,ze,R,Ve,Ne,qe,v,t,re,Ee,b,j,g,N,Rt,Ke,Je,f,U}from"./chunks/index-pzctbrv3.js";import{Qe}from"./chunks/index-3s2q5wht.js";import{Ye,Re}from"./chunks/index-wshq0mgp.js";import{et}from"./chunks/index-2r2nzahr.js";import"./chunks/index-90bkfxht.js";import{ie,J,tt,G,B}from"./chunks/index-gkf3ty4y.js";var wf=["-h","--help"];function mn(P,L){let H=Object.entries(P.booleans??{}),Y=Object.entries(P.values??{}),Z=Object.entries(P.lists??{}),oe=Object.fromEntries(H.map(([_e])=>[_e,!1])),se={},me=Object.fromEntries(Z.map(([_e])=>[_e,[]])),he=[],ke=[],Pe=!1,Te=-1;for(let[_e,Ae]of L.entries()){if(_e<=Te)continue;if(Ae==="--"){he.push(...L.slice(_e+1));break}if(wf.includes(Ae)){Pe=!0;continue}let Le=H.find(([,Ze])=>Ze.includes(Ae));if(Le){oe[Le[0]]=!0;continue}let We=Y.find(([,Ze])=>Ze.includes(Ae));if(We){let Ze=L[_e+1];if(Ze===void 0||Ze.startsWith("-")){ke.push(`${Ae} requires a value`);continue}se[We[0]]=Ze,Te=_e+1;continue}let Fe=Z.find(([,Ze])=>Ze.includes(Ae));if(Fe){let Ze=L.slice(_e+1),tn=Ze.findIndex((ln)=>ln.startsWith("-")),on=Ze.slice(0,tn===-1?Ze.length:tn);if(on.length===0){ke.push(`${Ae} requires at least one value`);continue}me[Fe[0]]=[...me[Fe[0]]??[],...on],Te=_e+on.length;continue}if(Ae.startsWith("-")){ke.push(`Unknown option for ${P.label}: ${Ae}`);continue}if(P.positionals==="tail"){he.push(...L.slice(_e));break}he.push(Ae)}if(P.positionals!=="list"&&P.positionals!=="tail")ke.push(...he.map((_e)=>`Unexpected argument for ${P.label}: ${_e}`));return{flags:oe,values:se,lists:me,positionals:he,help:Pe,errors:ke}}function $n(P){for(let L of P)console.error(L);return P.length>0}import{readdirSync as Ef,statSync as Zs,unlinkSync as Tf}from"node:fs";import{basename as Xs,dirname as Af,isAbsolute as _f,join as If,relative as Of,resolve as $f,sep as Df}from"node:path";var zs=(P)=>{let L=Date.now()-new Date(P).getTime();if(!Number.isFinite(L))return"";let H=Math.floor(L/60000),Y=Math.floor(H/60),Z=Math.floor(Y/24);if(Z>0)return`${Z}d ago`;if(Y>0)return`${Y}h ago`;if(H>0)return`${H}m ago`;return"just now"},Go=(P)=>{let L=(P??"").trim().split(/\s+/).filter((Z)=>Z&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(Z)),H=L[0]?.split("/").pop();if(!H)return null;let Y=L[1];return Y&&/^[a-z][a-z0-9-]*$/.test(Y)?`${H} ${Y}`:H};function Ws(P){let L=(Z)=>`${Z.sessionId}
2
- ${Go(Z.segment||Z.command)}`,H=P.filter((Z)=>Z.decision!=="allow"),Y=H.filter((Z)=>Z.sessionId).reduce((Z,oe)=>Z.set(L(oe),(Z.get(L(oe))??0)+1),new Map);return new Set(H.filter((Z)=>Z.failureStage||(Y.get(L(Z))??0)>=2))}import{existsSync as kf,readdirSync as Cf,readFileSync as xf}from"node:fs";import{join as Pf}from"node:path";function Yn(P,L){try{return Cf(P,{withFileTypes:!0,encoding:"utf8"}).flatMap((H)=>{let Y=Pf(P,H.name);if(H.isDirectory())return Yn(Y,L);if(H.name.endsWith(".jsonl"))return[Y];return[]})}catch{if(L&&kf(P))L.count++;return[]}}var Sf=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function Rf(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let L=P;if(typeof L.ts!=="string"||typeof L.command!=="string")return!1;return Sf.every((H)=>L[H]===void 0||typeof L[H]==="string")}function Dt(P,L){try{return xf(P,"utf-8").split(`
3
- `).filter(Boolean).flatMap((H)=>{try{let Y=JSON.parse(H);if(!Rf(Y)){if(L)L.count++;return[]}return[Y]}catch{if(L)L.count++;return[]}})}catch{if(L)L.count++;return[]}}function gn(P){return Array.from(P,(L)=>{let H=L.charCodeAt(0);if(H<=31||H>=127&&H<=159)return`\\x${H.toString(16).padStart(2,"0")}`;return L}).join("")}function Nf(P,L){let H=ie(P),Y=mn({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"]}},L);if($n(Y.errors))return null;if(Y.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(Y.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let Z=Y.values.limit===void 0?20:Ys(Y.values.limit);if(Z===null)return console.error("--limit must be a positive number"),null;let oe=Y.values.since===void 0?Math.min(30,H):Ys(Y.values.since);if(oe===null||oe>H)return console.error(`--since must be a positive number of days no greater than ${H}`),null;let se={limit:Z,limitExplicit:Y.values.limit!==void 0,since:oe,sinceExplicit:Y.values.since!==void 0,all:Y.flags.all,json:Y.flags.json,suspect:Y.flags.suspect,pruneLegacy:Y.flags.pruneLegacy,dryRun:Y.flags.dryRun,id:Y.values.id,agent:Y.values.agent,rule:Y.values.rule,session:Y.values.session,project:Y.values.project===void 0?void 0:$f(Y.values.project)};if(se.id&&(se.agent!==void 0||se.rule!==void 0||se.session!==void 0||se.project!==void 0||se.suspect||se.sinceExplicit||se.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(se.pruneLegacy&&(se.id!==void 0||se.agent!==void 0||se.rule!==void 0||se.session!==void 0||se.project!==void 0||se.suspect||se.all||se.sinceExplicit||se.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(se.dryRun&&!se.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return se}async function Qs(P,L,H={}){let Y=Nf(P,L);if(!Y)return 1;let Z=H.logsDir??G(P);if(Y.pruneLegacy)return Lf(Z,Y.json,Y.dryRun);if(!Z)return console.log(Y.json?"[]":Y.id?`No retained audit log entry found for id ${gn(Y.id)}.`:"No audit log entries found."),0;J(P,Z);let oe={count:0},se=Yn(Z,oe).flatMap((Te)=>Dt(Te,oe).map((_e)=>({entry:_e,file:Te})));if(oe.count>0)console.error(`warning: ${oe.count} audit log ${oe.count===1?"source":"sources"} could not be read; these results are incomplete`);if(Y.id)return Mf(se,Y,H.timeZone);let me=Date.now()-Y.since*24*60*60*1000,he=se.filter((Te)=>Uf(Te,Y,Z,me)),ke=Y.suspect?Ws(he.map((Te)=>Te.entry)):null,Pe=(ke?he.filter((Te)=>ke.has(Te.entry)):he).sort((Te,_e)=>Date.parse(_e.entry.ts)-Date.parse(Te.entry.ts)).slice(0,Y.limit);if(Y.json)return console.log(JSON.stringify(Pe.map((Te)=>Te.entry),null,2)),0;if(Pe.length===0)return console.log("No audit log entries found."),0;for(let Te of Pe)console.log(qf(Te.entry,H.timeZone));return 0}function Lf(P,L,H){let Y=P?Ff(P).map((me)=>If(P,me)):[];if(H)return jf(Y,L);let Z=[],oe=0,se=0;for(let me of Y){let he=Zs(me,{throwIfNoEntry:!1})?.size??0,ke=Hf(me);if(ke){Z.push(`${Xs(me)}: ${ke}`);continue}oe++,se+=he}if(L)return console.log(JSON.stringify({removedFiles:oe,removedBytes:se,failedFiles:Z.length})),Z.length===0?0:1;console.log(oe===0&&Z.length===0?"No legacy audit log files found.":`Removed ${oe} legacy audit log ${oe===1?"file":"files"} (${ea(se)}).`);for(let me of Z)console.error(`Could not remove ${gn(me)}`);if(console.log("Nested v2 audit logs were not changed."),oe>0)console.log("This deletion cannot be undone.");return Z.length===0?0:1}function jf(P,L){let H=P.reduce((Y,Z)=>Y+(Zs(Z,{throwIfNoEntry:!1})?.size??0),0);if(L)return console.log(JSON.stringify({dryRun:!0,files:P.length,bytes:H})),0;if(console.log(P.length===0?"No legacy audit log files found.":`Would remove ${P.length} legacy audit log ${P.length===1?"file":"files"} (${ea(H)}).`),console.log("Nested v2 audit logs are not included."),P.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Ff(P){try{return Ef(P,{withFileTypes:!0}).filter((L)=>L.isFile()&&L.name.endsWith(".jsonl")).map((L)=>L.name)}catch{return[]}}function Hf(P){try{return Tf(P),null}catch(L){return L instanceof Error?L.message:String(L)}}function ea(P){let L=["B","KiB","MiB","GiB"],H=Math.min(Math.floor(Math.log2(Math.max(P,1))/10),L.length-1);return`${Math.round(P/1024**H*10)/10} ${L[H]}`}function Mf(P,L,H){let Y=P.filter((oe)=>oe.entry.id===L.id);if(Y.length>1)return console.error(`Multiple audit log entries found for id ${gn(L.id??"")}.`),1;if(L.json)return console.log(JSON.stringify(Y.map((oe)=>oe.entry),null,2)),0;let Z=Y[0];if(!Z)return console.log(`No retained audit log entry found for id ${gn(L.id??"")}.`),0;return console.log(Vf(Z.entry,H)),0}function Uf(P,L,H,Y){if(!L.all&&P.entry.decision==="allow")return!1;if(Date.parse(P.entry.ts)<Y)return!1;if(L.agent!==void 0&&P.entry.agent!==L.agent)return!1;if(L.rule!==void 0&&P.entry.ruleId!==L.rule)return!1;if(L.session!==void 0&&!Bf(P,H,L.session))return!1;if(L.project!==void 0&&!Gf(P.entry.cwd,L.project))return!1;return!0}function Bf(P,L,H){if(P.entry.sessionId===H)return!0;return Af(P.file)===L&&Xs(P.file,".jsonl")===H}function Gf(P,L){if(!P)return!1;let H=Of(L,P);return H!==".."&&!H.startsWith(`..${Df}`)&&!_f(H)}function qf(P,L){let H=gn(P.id??"-"),Y=gn(P.decision??"deny"),Z=P.cwd?` [${gn(P.cwd)}]`:"",oe=P.segment||P.command,se=oe===P.command?"":"↳ ",me=oe.length>50?`${oe.slice(0,50)}…`:oe;return`${H.padEnd(16)} ${gn(na(P.ts,L))} ${Y.padEnd(5)} ${gn(P.agent??"-").padEnd(15)} ${gn(P.ruleId??"-").padEnd(20)} ${se}${gn(me)}${Z}`}function Vf(P,L){let H=(Z)=>gn(Z===void 0||Z===null||Z===""?"-":Z),Y=P.shape?`${P.agent??"-"} (shape: ${P.shape})`:P.agent??"-";return[`id: ${H(P.id)}`,`ts: ${H(na(P.ts,L))}`,`decision: ${H(P.decision)}`,`agent: ${H(Y)}`,`level: ${H(P.level)}`,`tool: ${H(P.toolName)}`,`rule: ${H(P.ruleId)}`,`intent: ${H(P.intent)}`,`stage: ${H(P.failureStage)}`,`error: ${H(P.errorCode)}`,`session: ${H(P.sessionId)}`,`cwd: ${H(P.cwd)}`,`version: ${H(P.v)}`,`truncated: ${H(P.truncated===!0?"yes":void 0)}`,`reason: ${H(P.reason)}`,`command: ${H(P.command)}`,`segment: ${H(P.segment)}`].join(`
4
- `)}function na(P,L){let H=new Date(P);if(Number.isNaN(H.getTime()))return P;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:L}).format(H)}function Ys(P){let L=Number(P);return Number.isFinite(L)&&L>0?L:null}var ta={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 ra={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 oa={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 qo=["npx","--offline","--no-install","@deepseek-ai/dsh","--version"],ia=["cursor-agent","--version"],sa=[{id:"antigravity-cli",displayName:"Antigravity CLI",runtime:{flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",runtime:{displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",runtime:{flags:["-cx","--codex"],description:"Run as a Codex PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",runtime:{flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",runtime:{flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",runtime:{flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",runtime:{flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",runtime:{flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",install:{flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",install:{flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",install:{flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",runtime:{flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"deepseek-harness",displayName:"DeepSeek Harness",install:{flag:"--deepseek-harness",artifactKind:"package",probeCommand:qo}},{id:"devin",displayName:"Devin CLI",runtime:{flags:["-dv","--devin"],description:"Run as Devin CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--devin",artifactKind:"hook config",probeCommand:["devin","--version"]}},{id:"droid",displayName:"Factory Droid",runtime:{flags:["-fd","--droid"],description:"Run as Factory Droid PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--droid",artifactKind:"hook config",probeCommand:["droid","--version"]}},{id:"amp",displayName:"Amp Code",install:{flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],Vo=sa.slice().sort((P,L)=>P.displayName.localeCompare(L.displayName,"en")),Er=Vo.map((P)=>P.id).sort((P,L)=>Number(L==="claude-code")-Number(P==="claude-code")),er=Vo.filter((P)=>("runtime"in P)).map((P)=>({id:P.id,displayName:"displayName"in P.runtime?P.runtime.displayName:P.displayName,flags:P.runtime.flags,legacyFlags:"legacyFlags"in P.runtime?P.runtime.legacyFlags:[],description:P.runtime.description,legacyTopLevelFlags:P.runtime.legacyTopLevelFlags})),Rn=Vo.map((P)=>({id:P.id,...P.install})),Kf=Object.fromEntries(sa.map((P)=>[P.id,P.displayName]));function cn(P){return Kf[P]}var Jf=er.map((P)=>({flags:P.flags.join(", "),description:P.description})),zf=er.flatMap((P)=>P.flags.map((L)=>`cc-safety-net hook ${L}`)),aa={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Jf,{flags:"-h, --help",description:"Show this help"}],examples:zf};var la={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...Rn.map((P)=>({flags:P.flag,description:`Install ${cn(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...Rn.map((P)=>`cc-safety-net install ${P.flag}`)]},ca={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...Rn.map((P)=>({flags:P.flag,description:`Uninstall ${cn(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...Rn.map((P)=>`cc-safety-net uninstall ${P.flag}`)]},da={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 ua={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 Tr={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 Ko=[{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"}],Jo=["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"],Nt={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:"tool add <name...> [--cwd-arg <name>] [--project]",description:"Analyze community shell tools (user scope by default)"},{usage:"tool remove <name...> [--project]",description:"Stop analyzing declared tools"},{usage:"tool list",description:"List declared command tools in both scopes"},{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"},{flags:"--project",description:"Use project-scope rule config with rule tool"},{flags:"--cwd-arg",argument:"<name>",description:"Name the working-directory argument with rule tool add"},...Ko.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","cc-safety-net rule tool add ops_bash","cc-safety-net rule tool add ops_run_background --cwd-arg cwd --project",...Jo,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var pa={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 fa={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 Ar=[pa,ta,ua,ra,Nt,Tr,la,da,ca,aa,oa,fa];function Wf(P){return P.aliases??[]}function _r(P){let L=P.toLowerCase();return Ar.find((H)=>H.name.toLowerCase()===L||Wf(H).some((Y)=>Y.toLowerCase()===L))}import{existsSync as Bh}from"node:fs";import{basename as Yf}from"node:path";function Ir(P,L=7,H=G(P)){let Y=Date.now()-L*24*60*60*1000,Z=[],oe=new Set,se=0,me,he,ke,Pe;if(H)J(P,H);let Te={count:0},_e=H?Yn(H,Te):[];for(let Le of _e)for(let We of Dt(Le,Te)){if(We.decision==="allow")continue;let Fe=new Date(We.ts).getTime();if(Fe>=Y){if(se++,oe.add(We.sessionId??Yf(Le,".jsonl")),he===void 0||Fe<=he)me=We.ts,he=Fe;if(Pe===void 0||Fe>Pe)ke=We.ts,Pe=Fe;Zf(Z,We,Fe)}}let Ae=Z.map((Le)=>({timestamp:Le.ts,command:Le.command,reason:Le.reason,relativeTime:zs(new Date(Le.ts))}));return{totalBlocked:se,sessionCount:oe.size,recentEntries:Ae,oldestEntry:me,newestEntry:ke,unreadable:Te.count}}function Zf(P,L,H){let Y=P.findIndex((Z)=>H>new Date(Z.ts).getTime());if(Y===-1){if(P.length<3)P.push(L);return}if(P.splice(Y,0,L),P.length>3)P.pop()}import{dirname as cm}from"node:path";import{dirname as Xf,join as Qf,resolve as em}from"node:path";var nm="config.json";function bn(P,L,H,Y){h(tm(P),`${JSON.stringify(L,null,2)}
5
- `,H,Y)}function tm(P){return typeof P==="string"?ae(P):P}function Wo(P){return{errors:de(om(P),": "," "),ruleNames:new Set(He(P).map((L)=>L.toLowerCase()))}}var rm="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",ma="must match pattern (letters, numbers, hyphens, underscores)";function om(P){if(!ga(P))return[e([],"Config must be an object")];return[...P.version===1?[]:[e(["version"],"must be 1")],...im(P.rules)]}function im(P){if(P===void 0)return[];if(!Array.isArray(P))return[e(["rules"],"must be an array")];return[...P.flatMap((L,H)=>ga(L)?sm(L,["rules",H]):[e(["rules",H],"must be an object")]),...je(P)]}function sm(P,L){return[...zo(P.name,[...L,"name"],"required string",p,rm),...zo(P.command,[...L,"command"],"required string",E,ma),...P.subcommand===void 0?[]:zo(P.subcommand,[...L,"subcommand"],"must be a string if provided",E,ma),...am(P.block_args,[...L,"block_args"]),...lm(P.reason,[...L,"reason"]),...P.intent===void 0||De(P.intent)?[]:[e([...L,"intent"],Oe)]]}function zo(P,L,H,Y,Z){if(typeof P!=="string")return[e(L,H)];return Y.test(P)?[]:[e(L,Z)]}function am(P,L){if(!Array.isArray(P))return[e(L,"required array")];if(P.length===0)return[e(L,"must have at least one element")];return P.flatMap((H,Y)=>{if(typeof H!=="string")return[e([...L,Y],"must be a string")];return H===""?[e([...L,Y],"must not be empty")]:[]})}function lm(P,L){if(typeof P!=="string")return[e(L,"required string")];if(P==="")return[e(L,"must not be empty")];return P.length>D?[e(L,`must be at most ${D} characters`)]:[]}function ga(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function Yo(P){let L=ya(P);if(!L.ok)return L.result;return Wo(L.parsed)}function ya(P){let L=[],H=new Set;try{let Y=typeof P==="string"?ae(P):P,Z=r(Y);if(Z===null)return L.push(`File not found: ${Y.path}`),{ok:!1,result:{errors:L,ruleNames:H}};if(!Z.trim())return L.push("Config file is empty"),{ok:!1,result:{errors:L,ruleNames:H}};return{ok:!0,parsed:JSON.parse(Z)}}catch(Y){if(Y instanceof o)return L.push(Y.message),{ok:!1,result:{errors:L,ruleNames:H}};let Z=Y instanceof Error?Y.message:String(Y);return L.push(Y instanceof SyntaxError?"Invalid JSON":Z),{ok:!1,result:{errors:L,ruleNames:H}}}}function Lt(P){return em(P,".safety-net.json")}function Un(P){let L=ya(P);if(!L.ok)return L.result;let H=lt(L.parsed);return{errors:H.errors,ruleNames:H.sources}}function jt(P,L={}){return Qf(Xf(le(P,L)),nm)}function ha(P,L,H){let Y;try{if(r(L)===null)return{path:P,exists:!1,valid:!1,ruleCount:0};Y=Un(L),Y.errors.push(...V(P,H))}catch(Z){if(!(Z instanceof o))throw Z;Y={errors:[Z.message],ruleNames:new Set}}return{path:P,exists:!0,valid:Y.errors.length===0,ruleCount:Y.ruleNames.size,...Y.errors.length>0?{errors:Y.errors}:{}}}function dm(P,L){return{source:L,name:P.name,command:P.command,subcommand:P.subcommand,blockArgs:[...P.block_args],reason:P.reason}}function va(P,L){let H=z(P),Y=A(L),Z=cm(H),oe=ee(P,{cwd:L,userConfigPath:H,projectConfigPath:Y,userConfigDir:Z}),se=Q(P,{cwd:L,userConfigPath:H,projectConfigPath:Y,userConfigDir:Z}),me=new Map(oe.rulebooks.flatMap((he)=>he.rules.map((ke)=>[ke,he.source])));return{userConfig:ha(H,se.userConfigTarget,se.userScope),projectConfig:ha(Y,se.projectConfigTarget,se.projectScope),effectiveRules:oe.rules.map((he)=>dm(he,me.get(he.name)??"project"))}}var um=[{flag:n.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:n.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:n.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:n.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:n.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:n.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:n.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:n.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"},{flag:n.projectTightenOnly,description:"Ignore project policy settings that weaken the user policy",defaultBehavior:"off"}];function ba(P){return[...um.map((L)=>({name:L.flag.name,value:ge(L.flag,P.env),isSet:xt(L.flag,P.env),legacyName:L.flag.legacyName,legacyValue:L.flag.legacyName?P.env.get(L.flag.legacyName):void 0,legacyIsSet:L.flag.legacyName?P.env.get(L.flag.legacyName)!==void 0:void 0,description:L.description,defaultBehavior:L.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:P.env.get("CC_SAFETY_NET_HOME"),isSet:P.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var wa={error:0,warning:1,info:2},pm=["policy","config","audit"];function fm(P){return P.map((L)=>{if(L==="ownership")return"is not owned by the current user";if(L==="permissions")return"has unsafe permissions";if(L==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var mm=[{derive:(P)=>P.hooks.length>0&&P.hooks.every((L)=>!L.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(P)=>P.hooks.filter((L)=>L.inspectionStatus==="failed").map((L)=>{let H=cn(L.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${H} inspection failed`,detail:`Doctor could not verify the ${H} integration configuration.`,fixHint:`Correct the reported ${H} configuration error, then run \`cc-safety-net doctor\` again.`,integration:L.platform}})},{derive:(P)=>P.userConfig.exists&&!P.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.userConfig.path}]:[]},{derive:(P)=>P.projectConfig.exists&&!P.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.projectConfig.path}]:[]},{derive:(P)=>P.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${P.configState.reason}`,fixHint:"Fix the file named in the reason, or run `cc-safety-net rule update` to vendor a remote source, then rerun doctor."}]:[]},{derive:(P)=>P.v2Leftovers&&P.v2Leftovers.length>0?[{checkId:"config.v2-leftovers",severity:"info",title:"Rulebook lock and cache leftovers detected",detail:`Files an earlier version left behind are no longer read: ${P.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(P)=>P.legacyConfigs&&P.legacyConfigs.length>0?[{checkId:"config.legacy-ignored",severity:"warning",title:"Legacy inline rule configs are ignored",detail:`CC Safety Net no longer loads these files, so their rules enforce nothing: ${P.legacyConfigs.join(", ")}.`,fixHint:"Run `cc-safety-net rule migrate` to convert them (add `--cleanup` to delete each file once it is converted), then rerun doctor."}]:[]},{derive:(P)=>{let L=P.environment.find((H)=>H.name==="CC_SAFETY_NET_AUDIT_SCOPE");return ot(L?.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."}]:[]}},...pm.map((P)=>({derive:(L)=>L.posture.directories.filter((H)=>H.kind===P&&H.status==="unsafe").map((H)=>({checkId:`posture.${P}-directory-unsafe`,severity:"error",title:`${P[0]?.toUpperCase()}${P.slice(1)} directory is unsafe`,detail:`The ${P} directory ${fm(H.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...H.path?{path:H.path}:{}}))})),{derive:(P)=>{let L=[...P.effectiveSafety.weakenedRuleOverrides].sort();return L.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: ${L.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${L.join(", ")}.`}]:[]}}];function ka(P){return mm.flatMap((L,H)=>L.derive(P).map((Y,Z)=>({finding:Y,catalogOrder:H,occurrence:Z}))).sort((L,H)=>wa[L.finding.severity]-wa[H.finding.severity]||L.catalogOrder-H.catalogOrder||L.occurrence-H.occurrence).map((L)=>L.finding)}function Dn(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var gm=(P)=>Dn()?`\x1B[32m${P}\x1B[0m`:P,ym=(P)=>Dn()?`\x1B[33m${P}\x1B[0m`:P,hm=(P)=>Dn()?`\x1B[34m${P}\x1B[0m`:P,vm=(P)=>Dn()?`\x1B[36m${P}\x1B[0m`:P,bm=(P)=>Dn()?`\x1B[31m${P}\x1B[0m`:P,wm=(P)=>Dn()?`\x1B[2m${P}\x1B[0m`:P,km=(P)=>Dn()?`\x1B[1m${P}\x1B[0m`:P,en={green:gm,yellow:ym,blue:hm,cyan:vm,red:bm,dim:wm,bold:km},Cm="\x1B[0m",xm=[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 Pm(P){let L=P;return()=>(L=(L*1664525+1013904223)%4294967296,L/4294967296)}function Sm(P){let L=[...xm],H=Pm(P);for(let Y=L.length-1;Y>0;Y--){let Z=Math.floor(H()*(Y+1)),oe=L[Y];L[Y]=L[Z],L[Z]=oe}return L}function Rm(P,L=0){if(!Dn())return"";let H=Sm(L);return`\x1B[38;5;${H[P%H.length]}m`}function Ca(P,L,H=0){if(!Dn())return`"${P}"`;return`${Rm(L,H)}"${P}"${Cm}`}function Or(P){return P==="default"?"built-in default":`${P} policy`}var Em=new RegExp("\x1B\\[[0-9;]*m","g"),Zo=(P)=>P.replace(Em,"").length;function Zn(P){let L=(P.headers??P.rows[0]??[]).map((se,me)=>{let he=Math.max(...P.rows.map((ke)=>Zo(ke[me]??"")));return Math.max(Zo(se),he)}),H=(se,me)=>se+" ".repeat(Math.max(0,me-Zo(se))),Y=(se,me)=>me[0]+L.map((he)=>se.repeat(he+2)).join(me[1])+me[2],Z=(se)=>`│ ${se.map((me,he)=>H(me,L[he]??0)).join(" │ ")} │`,oe=P.headers?[` ${Z(P.headers)}`,` ${Y("─",["├","┼","┤"])}`]:[];return[` ${Y("─",["┌","┬","┐"])}`,...oe,...P.rows.map((se)=>` ${Z(se)}`),` ${Y("─",["└","┴","┘"])}`].join(`
6
- `)}function xa(P){let L=[];L.push("Hook Integration"),L.push(Tm(P));let H=[],Y=[];for(let Z of P){let oe=cn(Z.platform);if(Z.errors&&Z.errors.length>0)for(let se of Z.errors)if(Z.configured)H.push({platform:oe,message:se});else Y.push({platform:oe,message:se})}for(let Z of H)L.push(` Warning (${Z.platform}): ${Z.message}`);for(let Z of Y)L.push(en.red(` Error (${Z.platform}): ${Z.message}`));return L.join(`
7
- `)}function Tm(P){let L=["Platform","Discovery","Configuration","Inspection"],H=P.map((Y)=>{let Z=cn(Y.platform);if(Y.inspectionStatus==="not-inspected"){let he=en.dim("Not inspected");return[Z,he,he,he]}let oe=Y.detected?en.green("Detected"):Y.inspectionStatus==="failed"?en.red("Unknown"):en.dim("Not detected"),se=Y.configured?en.green("Configured"):Y.detected?en.yellow("Not configured"):Y.inspectionStatus==="failed"?en.red("Unknown"):en.dim("Not applicable"),me=Y.inspectionStatus==="verified"?en.green("Verified"):Y.inspectionStatus==="failed"?en.red("Failed"):en.dim("Not applicable");return[Z,oe,se,me]});return Zn({headers:L,rows:H})}function Pa(P){let H=["Guard Engine Verification",` Synthetic self-test: ${P.failed>0?en.red(`${P.passed}/${P.total} FAIL`):en.green(`${P.passed}/${P.total} passed`)}`],Y=P.results.filter((Z)=>!Z.passed);if(Y.length>0){H.push(""),H.push(en.red(" Failures:"));for(let Z of Y)H.push(en.red(` • ${Z.description}`)),H.push(en.red(` expected ${Z.expected}, got ${Z.actual}`))}return H.join(`
8
- `)}function Am(P){if(P.length===0)return" (no custom rules)";let L=["Source","Name","Command","Block Args"],H=P.map((Y)=>[Y.source,Y.name,Y.subcommand?`${Y.command} ${Y.subcommand}`:Y.command,Y.blockArgs.join(", ")]);return Zn({headers:L,rows:H})}function Sa(P){let L=[];if(L.push("Configuration"),L.push(_m(P.userConfig,P.projectConfig)),L.push(""),P.effectiveRules.length>0)L.push(` Effective rules (${P.effectiveRules.length} total):`),L.push(Am(P.effectiveRules));else L.push(" Effective rules: (none - using built-in rules only)");return L.join(`
9
- `)}function _m(P,L){let H=["Scope","Status"],Y=(oe)=>{if(!oe.exists)return en.dim("N/A");if(!oe.valid)return en.red(`Invalid (${oe.errors?.[0]??"unknown error"})`);return en.green("Configured")},Z=[["User",Y(P)],["Project",Y(L)]];return Zn({headers:H,rows:Z})}function Ra(P){let L=[];return L.push("Environment"),L.push(Im(P)),L.join(`
10
- `)}function Ea(P){let L=P.effectiveSafety.policyScopes,H=["Effective Safety",` Selected preset: ${P.effectiveSafety.selectedPreset}${L?` (${Or(L.levelScope)})`:""}`,` Effective: ${P.effectiveSafety.level}`],Y=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[Z,oe]of Y){let se=P.effectiveSafety.capabilities[Z],me=se.enabled?en.green("ON"):en.dim("OFF"),he=se.sources.length>0?` (${se.sources.join(", ")})`:"";H.push(` ${oe}: ${me} via ${se.source}${he}`)}if(L&&L.weakenings.length>0){H.push(` Project policy deltas${L.weakeningsIgnored?" (ignored)":""}:`);for(let Z of L.weakenings)H.push(` ${Z}`)}H.push(` Stored rule customizations: ${P.effectiveSafety.ruleCounts.stored}`),H.push(` Effective rule customizations: ${P.effectiveSafety.ruleCounts.effective}`);for(let[Z,oe]of Object.entries(P.effectiveSafety.ruleOverrides))H.push(` ${Z}: ${oe}`);return H.join(`
11
- `)}function Ta(P){let L=["Findings"];if(P.length===0)return L.push(" No findings from inspected doctor facts."),L.join(`
12
- `);for(let H of P){let Y=`[${H.severity.toUpperCase()}] ${H.checkId}: ${gn(H.title)}`,Z=H.severity==="error"?en.red:H.severity==="warning"?en.yellow:en.blue;if(L.push(` ${Z(Y)}`),L.push(` ${gn(H.detail)}`),H.path)L.push(` Path: ${gn(H.path)}`);if(H.fixHint)L.push(` Fix: ${gn(H.fixHint)}`)}return L.join(`
13
- `)}function Im(P){let L=["Variable","Status","Legacy"],H=P.map((Y)=>{let Z=Y.isSet?en.green("✓"):en.dim("✗"),oe=Y.legacyName&&Y.legacyIsSet?`${Y.legacyName} ${en.green("✓")}`:Y.legacyName??"";return[Y.name,Z,oe]});return Zn({headers:L,rows:H})}function Aa(P){let L=[];if(P.totalBlocked===0)L.push("Recent Activity"),L.push(" No blocked commands in the last 7 days"),L.push(" Tip: This is normal for new installations");else L.push(`Recent Activity · last 7 days (${P.totalBlocked} blocked / ${P.sessionCount} sessions)`),L.push(Om(P.recentEntries));if(P.unreadable>0)L.push(` Warning: ${P.unreadable} audit log ${P.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return L.join(`
14
- `)}function Om(P){let L=["Time","Command"],H=P.map((Y)=>{let Z=gn(Y.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),oe=Z.length>40?`${Z.slice(0,37)}...`:Z;return[Y.relativeTime,oe]});return Zn({headers:L,rows:H})}function _a(P){let L=[];if(L.push("Update Check"),P.latestVersion===null&&!P.error)return L.push($r([["Status",en.dim("Skipped")],["Installed",P.currentVersion]])),L.join(`
15
- `);if(P.error)return L.push($r([["Status",`${en.yellow("⚠")} Error`],["Installed",P.currentVersion],["Error",en.dim(P.error)]])),L.join(`
16
- `);if(P.updateAvailable)return L.push($r([["Status",`${en.yellow("⚠")} Update Available`],["Current",P.currentVersion],["Latest",en.green(P.latestVersion??"")]])),L.push(""),L.push(" Run: bunx cc-safety-net@latest doctor"),L.push(" Or: npx cc-safety-net@latest doctor"),L.join(`
17
- `);return L.push($r([["Status",`${en.green("✓")} Up to date`],["Version",P.currentVersion]])),L.join(`
18
- `)}function $r(P){return Zn({rows:P})}function Ia(P){let L=[];return L.push("System Info"),L.push($m(P)),L.join(`
19
- `)}function $m(P){let L=["Component","Version"],H=(oe)=>{if(oe===null)return en.dim("not found");return oe},Z=[{label:"cc-safety-net",value:P.version},...Er.map((oe)=>({label:cn(oe),value:P.versions[oe]??null})),{label:"Node.js",value:P.nodeVersion},{label:"npm",value:P.npmVersion},{label:"Bun",value:P.bunVersion},{label:"Platform",value:P.platform}].map((oe)=>[oe.label,H(oe.value)]);return Zn({headers:L,rows:Z})}function Oa(P){if(P.findings.length===0)return en.green(`
20
- No findings from inspected doctor facts.`);let L={error:P.findings.filter((oe)=>oe.severity==="error").length,warning:P.findings.filter((oe)=>oe.severity==="warning").length,info:P.findings.filter((oe)=>oe.severity==="info").length},H=["error","warning","info"].filter((oe)=>L[oe]>0).map((oe)=>`${L[oe]} ${oe}`),Y=P.findings.length===1?"finding":"findings",Z=`
21
- ${P.findings.length} ${Y}: ${H.join(", ")}.`;if(L.error>0)return en.red(Z);if(L.warning>0)return en.yellow(Z);return en.blue(Z)}import{lstatSync as Dm}from"node:fs";import{dirname as Xo}from"node:path";function Qo(P,L){try{let H=Dm(L);if(H.isSymbolicLink())return{kind:P,path:L,status:"unsafe",issues:["symlink"]};if(!H.isDirectory())return{kind:P,path:L,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:P,path:L,status:"unknown",issues:[]};let Y=[...H.uid!==process.getuid()?["ownership"]:[],...(H.mode&18)!==0?["permissions"]:[]];return{kind:P,path:L,status:Y.length>0?"unsafe":"safe",issues:Y}}catch(H){if(typeof H==="object"&&H!==null&&"code"in H&&H.code==="ENOENT")return{kind:P,path:L,status:"not-applicable",issues:[]};return{kind:P,path:L,status:"unknown",issues:[]}}}function $a(P,L){let H=G(P);return{directories:[Qo("policy",Xo(Xo(L))),Qo("config",Xo(L)),...H?[Qo("audit",H)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as Nm}from"node:child_process";import{existsSync as Da}from"node:fs";import{delimiter as Lm,extname as jm,join as Fm}from"node:path";import{stripVTControlCharacters as Na}from"node:util";var ja="2.6.16",Hm=5000,Mm="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function pn(){return ja}function ei(P,L){let H=P[L];if(H)return H;let Y=Object.keys(P).find((Z)=>Z.toLowerCase()===L.toLowerCase()&&!!P[Z]);return Y?P[Y]:H}function Um(P){return(ei(P,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((L)=>L.length>0)}function Bm(P,L){let H=jm(P)?[P]:[...Um(L).map((Y)=>`${P}${Y}`),P];if(P.includes("/")||P.includes("\\"))return H.find((Y)=>Da(Y))??P;return(ei(L,"PATH")??"").split(Lm).flatMap((Y)=>H.map((Z)=>Fm(Y,Z))).find((Y)=>Da(Y))??P}function La(P){if(!/[\s"&|<>^]/.test(P))return P;return`"${P.replace(/"/g,'""')}"`}function Xn(P,L){let[H,...Y]=P,Z=L[Mm]==="win32"?"win32":process.platform;if(!H||Z!=="win32")return{cmd:H??"",args:Y};let oe=Bm(H,L);if(!/\.(?:bat|cmd)$/i.test(oe))return{cmd:oe,args:Y};return{cmd:ei(L,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",La(oe),...Y.map(La)].join(" ")]}}var Ft=async(P,L=Hm)=>{let H=await Gm(P,{timeoutMs:L});if(H.code!==0)return null;return Na(H.stdout).trim()||Na(H.stderr).trim()||null};function Gm(P,L){let[H,...Y]=P;if(!H)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((Z)=>{try{let oe=Xn([H,...Y],process.env),se=Nm(oe.cmd,oe.args,{stdio:["ignore","pipe","pipe"]}),me=!1,he="",ke="";se.stdout.on("data",(_e)=>{he+=_e.toString()}),se.stderr.on("data",(_e)=>{ke+=_e.toString()});let Pe=(_e)=>{if(me)return;me=!0,clearTimeout(Te),Z(_e)},Te=setTimeout(()=>{se.kill(),Pe({code:null,stdout:he,stderr:ke})},L.timeoutMs);se.on("close",(_e)=>{Pe({code:_e,stdout:he,stderr:ke})}),se.on("error",()=>{Pe({code:null,stdout:he,stderr:ke})})}catch{Z({code:null,stdout:"",stderr:""})}})}function Dr(P){if(!P)return null;let L=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(P);if(L)return L[1]??null;let H=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(P);if(H)return H[1]??null;return P.split(`
22
- `)[0]?.trim()||null}async function Nr(P,L=Ft,H=process.cwd()){let Y=Promise.all(Rn.map(async(Te)=>[Te.id,Dr(await L([...Te.probeCommand]))])),[Z,oe,se,me,he,ke,Pe]=await Promise.all([Y,Y.then(async(Te)=>{let _e=Te.find(([We])=>We==="opencode")?.[1];if(!_e?.startsWith("2.")||!P(_e))return null;let Ae=["--param",`location[directory]=${H}`],Le=["opencode","api","integration.list",...Ae];return await L(Le,30000),L(["opencode","api","plugin.list",...Ae],30000)}),L(["codex","plugin","list"],30000),L(["amp","plugins","list"],30000),L(["node","--version"]),L(["npm","--version"]),L(["bun","--version"])]);return{version:ja,versions:Object.fromEntries(Z),codexPluginListOutput:se,ampPluginListOutput:me,openCodePluginListOutput:oe,nodeVersion:Dr(he),npmVersion:Dr(ke),bunVersion:Dr(Pe),platform:`${process.platform} ${process.arch}`}}function ni(P,L){if(L==="dev")return!1;let H=P.split(".").map(Number),Y=L.split(".").map(Number),[Z=0,oe=0,se=0]=H,[me=0,he=0,ke=0]=Y;if(Z!==me)return Z>me;if(oe!==he)return oe>he;return se>ke}async function Bn(){let P=pn(),L=new AbortController,H=setTimeout(()=>L.abort(),3000);try{let Y=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:L.signal});if(!Y.ok)return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${Y.status}`};let Z=await Y.json(),oe=ni(Z.version,P);return{currentVersion:P,latestVersion:Z.version,updateAvailable:oe}}catch(Y){return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:Y instanceof Error?Y.message:"Network error"}}finally{clearTimeout(H)}}import*as Va from"node:readline";var Ua=(P)=>`\x1B[${P}B`,qm=(P)=>`\x1B[${P}A`;var Fa=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function Vm(P){return new Promise((L)=>setTimeout(L,P))}function Km(P,L,H){if(!H)return L(P);if(H.aborted)return Promise.resolve();return new Promise((Y,Z)=>{let oe=()=>H.removeEventListener("abort",se),se=()=>{oe(),Y()};H.addEventListener("abort",se,{once:!0}),L(P).then(()=>{oe(),Y()},(me)=>{oe(),Z(me)})})}function Lr(P){return Math.max(0,Math.min(1,P))}function Ht(P){return Math.max(0,Math.min(255,Math.round(P)))}function ti(P){return P<=0.0031308?12.92*P:1.055*P**0.4166666666666667-0.055}function Jm(P,L,H){let Y=H*Math.PI/180,Z=L*Math.cos(Y),oe=L*Math.sin(Y),se=(P+0.3963377774*Z+0.2158037573*oe)**3,me=(P-0.1055613458*Z-0.0638541728*oe)**3,he=(P-0.0894841775*Z-1.291485548*oe)**3;return{blue:Ht(ti(Lr(-0.0041960863*se-0.7034186147*me+1.707614701*he))*255),green:Ht(ti(Lr(-1.2684380046*se+2.6097574011*me-0.3413193965*he))*255),red:Ht(ti(Lr(4.0767416621*se-3.3077115913*me+0.2309699292*he))*255)}}function ri(P,L){let H=(L*P*180/Math.PI%360+360)%360;return Jm(0.72,0.15,H)}function Ba(P,L=0.1){let H=ri(L,P);return`\x1B[38;2;${H.red};${H.green};${H.blue}m`}function zm(P,L){return{blue:Ht(P.blue+(255-P.blue)*L),green:Ht(P.green+(255-P.green)*L),red:Ht(P.red+(255-P.red)*L)}}function Ga(P,L,H){let Y=Math.imul(P+2654435769,2246822507)^Math.imul(L+3266489909,668265263)^Math.imul(H+374761393,2654435761),Z=Y^Y>>>15,oe=Math.imul(Z,739982445),se=oe^oe>>>12,me=Math.imul(se,695872825);return((me^me>>>15)>>>0)/4294967296}function Wm(P,L,H){let Y=Math.floor(Ga(P,L,H)*Fa.length);return Fa[Y]??"░"}function Ha(P){let L=Lr(P);return L*L*L*(L*(L*6-15)+10)}function Ym(P){if(P.length===0)return"";let L=[],H=!1,Y="";for(let Z of P){let oe=`${Z.red};${Z.green};${Z.blue}`;if(Z.bold!==H)L.push(Z.bold?"\x1B[1m":"\x1B[22m"),H=Z.bold;if(oe!==Y)L.push(`\x1B[38;2;${oe}m`),Y=oe;L.push(Z.character)}return`${L.join("")}\x1B[22m\x1B[39m`}function Zm(P,L,H,Y,Z){return P.map((oe,se)=>({...ri(H,Y+L+se/Z),bold:!1,character:oe}))}function Xm(P,L,H,Y,Z,oe,se,me){let he=Math.max(1,Y*0.75),ke=Math.min(1,H/he),Pe=Z*Ha(ke),Te=Math.max(0,(H-he)/Math.max(1,Y-he)),_e=(1-Ha(H/Y))*me*2,Ae=0.35*Math.max(0,1-Te*2),Le=ke>=1,We=Math.min(P.length,Math.ceil(Pe+2+1));return P.slice(0,We).map((Fe,Ze)=>{let tn=ri(oe,se+L+Ze/me+_e),on=Ze+Ga(L,Ze,7919)*2-1;if(on>Pe+2)return{...tn,bold:!1,character:" "};let ln=Pe-on,nn=0.8*Math.exp(-(ln*ln)/12.5),sn=Math.min(0.9,nn+Ae),Pn=!Le&&on>Pe-4;return{...zm(tn,sn),bold:sn>0.3,character:Pn?Wm(L,Ze,H):Fe}})}function Ma(P){return`\x1B[?2026h${P.map((L,H)=>`\x1B8${H>0?Ua(H):""}${Ym(L)}`).join("")}\x1B[?2026l`}async function oi(P,L={}){if(!P)return;let H=L.output??process.stdout,Y=L.sleep??Vm,Z=L.seed??0,oe=P.split(`
23
- `).map((Pe)=>Array.from(Pe)),se=Math.max(...oe.map((Pe)=>Pe.length)),me=12000*oe.filter((Pe)=>Pe.length>0).length/40,he=se>0?Math.max(1,Math.ceil(me/16.666666666666668)):0,ke=he>0?me/he:0;H.write(`\x1B[?25l${oe.length>1?`${`
24
- `.repeat(oe.length-1)}${qm(oe.length-1)}`:""}\x1B7`);try{for(let Pe=1;Pe<=he;Pe+=1){if(L.signal?.aborted)break;H.write(Ma(oe.map((Te,_e)=>Xm(Te,_e,Pe,he,se,0.1,Z,3)))),await Km(ke,Y,L.signal)}}finally{if(H.write(Ma(oe.map((Pe,Te)=>Zm(Pe,Te,0.1,Z,3)))),H.write("\x1B8"),oe.length>1)H.write(Ua(oe.length-1));H.write(`
25
- \x1B[0m\x1B[?25h`)}}var qa=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
- `);function Qm(P){return Boolean(P.isTTY)}async function nr(P={}){let L=P.output??process.stdout;if(!Qm(L))return;let H=P.input??process.stdin,Y={output:L,seed:P.seed??Math.random()*8192,sleep:P.sleep};if(!H.isTTY||typeof H.setRawMode!=="function"){await oi(qa,Y);return}let Z=new AbortController,oe=H.readableFlowing===!0,se=H.isRaw===!0,me=!1,he=(ke,Pe)=>{if(Pe.ctrl&&Pe.name==="c")me=!0;if(me||Pe.name==="return"||Pe.name==="enter")Z.abort()};Va.emitKeypressEvents(H),H.on("keypress",he),H.setRawMode(!0),H.resume();try{await oi(qa,{...Y,signal:Z.signal})}finally{if(H.off("keypress",he),H.setRawMode(se),!oe)H.pause()}if(!me)return;if(P.onInterrupt){P.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as rg}from"node:crypto";import{existsSync as Ja}from"node:fs";import{dirname as jr,join as za}from"node:path";import{dirname as Ka,join as eg}from"node:path";var ng="rule.lock";function tg(P){return eg(Ka(P),ng)}function hn(P,L){let H=L.global?L.userConfigPath??z(P,L):L.projectConfigPath??A(L.cwd??process.cwd()),Y=L.global?at(P,L):ct(H,L.cwd??process.cwd()),Z=tg(H);return{configDir:Ka(H),configPath:H,lockPath:Z,filesystemScope:Y,configTarget:i(Y,H),lockTarget:i(Y,Z)}}var og="`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.",ig="cache",sg="rulebooks";function Wa(P,L={}){let H=hn(P,L),Y=i(H.filesystemScope,Za(H.configDir)),Z=r(H.lockTarget);if(console.log(og),Z===null&&!Ja(Y.path))return console.log(`No v2 lock or cache leftovers found in ${jr(H.configDir)}; nothing to migrate.`),0;let oe=ug(Z),se=d(H.configTarget);if(!se.config&&(r(H.configTarget)!==null||oe.size>0))return console.error(`Cannot migrate: the rules config in ${jr(H.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let me=se.config?.rules??[];for(let he of me.flatMap((ke)=>ag(ke,oe,H,Y,L.global===!0)))console.log(he);return W(H.lockTarget),wt(Y),console.log(`Removed the v2 lock and cache under ${jr(H.configDir)}.`),0}function Ya(P,L){return[...new Set([{cwd:L},{cwd:L,global:!0}].flatMap((H)=>{let Y=hn(P,H);return[Y.lockPath,Za(Y.configDir)]}))].filter((H)=>Ja(H))}function ag(P,L,H,Y,Z){if(!C(P))return[];let oe=M(P).name,se=i(H.filesystemScope,F(H.configDir,oe)),me=r(se);if(me!==null&&lg(me,oe))return[];let he=L.get(P),ke=he?cg(he,oe,Y.path,H.filesystemScope):null;if(ke===null)return[`Could not migrate ${P} from the v2 cache. Run \`cc-safety-net rule update ${P}${Z?" --global":""}\` to vendor it.`];if(h(se,ke),me!==null)return[`Restored ${P} from the v2 cache over an invalid file.`];return[`Vendored ${P} from the v2 cache.`]}function lg(P,L){let H=Ce(P);return!("problem"in H)&&H.rulebook.name===L}function cg(P,L,H,Y){let Z=za(H,sg,`${dg(P)}--${P.digest.replace("sha256:","").slice(0,12)}`,ve),oe=r(i(Y,Z));if(oe===null||mg(oe)!==P.digest)return null;let se=Ce(oe);if("problem"in se||se.rulebook.name!==L)return null;return oe}function Za(P){return za(jr(P),ig)}function dg(P){return([P.owner,P.repo,P.display_ref,P.name].every((Y)=>typeof Y==="string"&&Y!=="")?`${P.owner}/${P.repo}#${P.display_ref}/${P.name}`:P.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function ug(P){let L=P===null?null:fg(P),H=Xa(L)&&Array.isArray(L.rulebooks)?L.rulebooks:[];return new Map(H.filter(pg).map((Y)=>[Y.spec,Y]))}function pg(P){return Xa(P)&&typeof P.spec==="string"&&typeof P.digest==="string"}function Xa(P){return!!P&&typeof P==="object"}function fg(P){try{return JSON.parse(P)}catch{return null}}function mg(P){return`sha256:${rg("sha256").update(P).digest("hex")}`}var Qa="\r\x1B[2K",gg="\x1B[?25l",yg="\x1B[39m",hg="\x1B[?25h",vg=100,bg=0.55,wg=80,el=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function kg(P){return new Promise((L)=>setTimeout(L,P))}async function Fr(P,L={}){let H=L.output??process.stdout;if(!H.isTTY)return P;let Y=L.sleep??kg,Z=!1,oe=P.then((me)=>(Z=!0,me),(me)=>{throw Z=!0,me});if(await Promise.race([oe.then(()=>!0),Y(vg).then(()=>!1)]))return oe;H.write(gg);try{for(let me=0;!Z;me+=1)H.write(`${Qa}${Ba(me*bg)}${el[me%el.length]}${yg} ${L.loadingMessage??"Loading…"}`),await Promise.race([oe,Y(wg)]);return await oe}finally{H.write(`${Qa}${hg}`)}}async function tr(P,L,H,Y={}){let Z=L();if(P)await H();if(P&&Z.ready)await Fr(Z.ready,Y);return Z.finish()}import{stripVTControlCharacters as Cg}from"node:util";var Hr="amp plugins list",xg=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function nl(P){if(!P.ampPluginListOutput)return{platform:"amp",status:"n/a"};let L=Cg(P.ampPluginListOutput).split(`
27
- `).map((H)=>xg.exec(H)?.[1]).find((H)=>H!==void 0);if(!L)return{platform:"amp",status:"n/a"};if(L!=="active")return{platform:"amp",status:"disabled",method:Hr,configPath:Hr,errors:[`Amp personal plugin cc-safety-net is ${L}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:Hr,configPath:Hr}}import{existsSync as _g,readFileSync as Ig}from"node:fs";import{isAbsolute as yP,join as Ag}from"node:path";function rr(P){return Ag(P,".gemini","config","hooks.json")}var rl=new Map([["run_command","auto"]]),ol="manage_task";var Og=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function $g(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];return Object.values(P).flatMap((L)=>{if(!L||typeof L!=="object"||Array.isArray(L))return[];let H=L,Y=H.PreToolUse;if(!Array.isArray(Y))return[];return Y.flatMap((Z)=>{if(!Z||typeof Z!=="object"||Array.isArray(Z))return[];let oe=Z.hooks;if(!Array.isArray(oe))return[];return oe.flatMap((se)=>{if(!se||typeof se!=="object"||Array.isArray(se))return[];let me=se.command;if(typeof me!=="string"||!Og.test(me))return[];return[{command:me,enabled:H.enabled!==!1}]})})})}function il(P){let L=rr(P.environment.home);if(!_g(L))return{platform:"antigravity-cli",status:"n/a",configPath:L};let H;try{H=$g(JSON.parse(Ig(L,"utf-8")))}catch(Y){return{platform:"antigravity-cli",status:"n/a",configPath:L,errors:[`Failed to parse Antigravity hooks config ${L}: ${Y instanceof Error?Y.message:String(Y)}`]}}if(H.some((Y)=>Y.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:L};if(H.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:L};return{platform:"antigravity-cli",status:"n/a",configPath:L}}import{existsSync as Fg}from"node:fs";import{join as Ln}from"node:path";import{existsSync as Dg,lstatSync as Ng,readFileSync as Lg}from"node:fs";import{join as jg}from"node:path";function vn(P,L=(H)=>H){if(!Dg(P))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(L(Lg(P,"utf-8")))}}catch{return{kind:"unreadable"}}}function Nn(P,L){if(P==="~")return L;if(P.startsWith("~/")||P.startsWith("~\\"))return jg(L,P.slice(2));return P}function dn(P){try{return Ng(P)}catch{return}}function Gr(P,L){let H=dn(L);if(!H)return{platform:P,status:"n/a",configPath:L};if(!H.isSymbolicLink()&&H.isDirectory())return;return{platform:P,status:"n/a",configPath:L,errors:[`${L} is a symlink or not a directory; move or remove it before installing`]}}function Xe(P,L){return typeof P==="object"&&P!==null?P[L]:void 0}var qr="cc-safety-net@cc-marketplace";function Vr(P){return P.env.get("CLAUDE_CONFIG_DIR")||Ln(P.home,".claude")}function sl(P){return Ln(P.env.get("CLAUDE_CODE_PLUGIN_CACHE_DIR")||Ln(Vr(P),"plugins"),"installed_plugins.json")}function al(P,L){let H=Xe(Xe(P,"plugins"),L);return Array.isArray(H)&&H.length>0}function Kr(P,L){let H=vn(sl(P));return H.kind==="ok"&&al(H.value,L)}function si(P){return ll(sl(P),Ln(Vr(P),"settings.json"))}function ll(P,L){let H=vn(P);if(H.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(H.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!al(H.value,qr))return{platform:"claude-code",status:"n/a"};let Y=vn(L);if(Y.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(Y.kind==="ok"&&Xe(Xe(Y.value,"enabledPlugins"),qr)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:L,errors:[`${qr} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:P}}function cl(P){let L=Ln(P.home,".claude"),H=Ln(L,"plugins","installed_plugins.json");if(ll(H,Ln(L,"settings.json")).status!=="configured")return;let Y=vn(H),Z=Y.kind==="ok"?Xe(Xe(Y.value,"plugins"),qr):void 0,oe=(Array.isArray(Z)?Z:[]).filter((ke)=>Xe(ke,"scope")==="user").map((ke)=>Xe(ke,"installPath")).find((ke)=>typeof ke==="string");if(!oe)return;let se=Ln(oe,".cursor-plugin","plugin.json"),me=vn(se),he=me.kind==="ok"?Xe(me.value,"hooks"):void 0;return typeof he==="string"&&Fg(Ln(oe,he))?se:void 0}function dl(P){return si(P.environment)}var ul="Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it.";function pl(P){if(!P.codexPluginListOutput)return{platform:"codex",status:"n/a"};let L=P.codexPluginListOutput.split(`
28
- `).find((H)=>H.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!L)return{platform:"codex",status:"n/a"};if(!L.includes("installed,"))return{platform:"codex",status:"n/a"};if(!L.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex runs only trusted hooks, and doctor cannot check trust. Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."]}}import{existsSync as Yr,readdirSync as Hg,readFileSync as Mg}from"node:fs";import{join as wn}from"node:path";function yn(P){let L="",H=0,Y=!1,Z=!1,oe=-1;while(H<P.length){let se=P[H],me=P[H+1];if(Z){L+=se,Z=!1,H++;continue}if(se==='"'&&!Y){Y=!0,oe=-1,L+=se,H++;continue}if(se==='"'&&Y){Y=!1,L+=se,H++;continue}if(se==="\\"&&Y){Z=!0,L+=se,H++;continue}if(Y){L+=se,H++;continue}if(se==="/"&&me==="/"){while(H<P.length&&P[H]!==`
29
- `)H++;continue}if(se==="/"&&me==="*"){H+=2;while(H<P.length-1){if(P[H]==="*"&&P[H+1]==="/"){H+=2;break}H++}continue}if(se===","){oe=L.length,L+=se,H++;continue}if(se==="}"||se==="]"){if(oe!==-1){let he=L.slice(oe+1);if(/^\s*$/.test(he))L=L.slice(0,oe)+he}oe=-1,L+=se,H++;continue}if(!/\s/.test(se))oe=-1;L+=se,H++}return L}function ml(P,L,H){let Y=L+1,Z=!1;while(Y<P.length){if(Z){Z=!1,Y++;continue}if(P[Y]==="\\"){Z=!0,Y++;continue}if(P[Y]==='"')return Y+1;Y++}throw Error(H)}function li(P,L,H){let Y=P[L],Z=Y==="["?"]":"}",oe=0,se=L;while(se<P.length){let me=H.skipComment?.(P,se)??se;if(me!==se){se=me;continue}if(P[se]==='"'){se=ml(P,se,H.stringError);continue}if(P[se]===Y)oe++;if(P[se]===Z){if(oe--,oe===0)return se}se++}throw Error(H.bracketError)}function gl(P,L){let H=P.lastIndexOf(`
30
- `,L)+1;return/^[ \t]*/.exec(P.slice(H))?.[0]??""}function yl(P,L){let H=L.end+(/^\s*/.exec(P.slice(L.end))?.[0].length??0);if(P[H]===","){let se=P[H+1]===`
31
- `?H+2:H+1;return`${P.slice(0,L.start)}${P.slice(se)}`}let Y=P.slice(0,L.start).search(/\s*$/)-1;if(P[Y]!==",")return`${P.slice(0,L.start)}${P.slice(L.end)}`;let Z=P.lastIndexOf(`
32
- `,Y-1),oe=Z!==-1&&/^\s*$/.test(P.slice(Z+1,Y))?Z:Y;return`${P.slice(0,oe)}${P.slice(L.end)}`}function ai(P,L){if(P.startsWith("//",L)){let H=P.indexOf(`
33
- `,L+2);return H===-1?P.length:H+1}if(P.startsWith("/*",L)){let H=P.indexOf("*/",L+2);return H===-1?P.length:H+2}return L}function fl(P,L){let H=L;while(H<P.length){if(/\s/.test(P[H]??"")){H++;continue}let Y=ai(P,H);if(Y===H)return H;H=Y}return H}function hl(P,L,H){let Y=0,Z=0;while(Z<P.length){let oe=ai(P,Z);if(oe!==Z){Z=oe;continue}if(P[Z]==='"'){let se=ml(P,Z,H.stringError);if(Y===1&&JSON.parse(P.slice(Z,se))===L){let me=fl(P,se),he=fl(P,me+1);if(P[me]===":"&&P[he]==="[")return{start:he,end:li(P,he,{skipComment:ai,...H})}}Z=se;continue}if(P[Z]==="{"||P[Z]==="[")Y++;if(P[Z]==="}"||P[Z]==="]")Y--;Z++}return}var An="cc-safety-net@cc-marketplace",Jr=["cc-marketplace","cc-safety-net"],vl=["_direct","copilot-safety-net"],bl=["cc-marketplace","safety-net"],wl="safety-net@cc-marketplace";function zr(P,L){let H=L.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${H}([^a-z0-9-]|$)`,"m").test(P??"")}function kl(P){return zr(P,"cc-safety-net@cc-marketplace")}function Cl(P){return zr(P,"cc-marketplace")}function xl(P){return zr(P,"copilot-safety-net")}function Pl(P){return zr(P,"safety-net@cc-marketplace")}function Wr(P){if(!P?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(P)}function Rl(P,L){if(!P)return null;let H=P.match(/(\d+)\.(\d+)\.(\d+)/);if(!H)return null;let Y=[Number(H[1]),Number(H[2]),Number(H[3])];for(let Z=0;Z<L.length;Z++){let oe=Y[Z]??0,se=L[Z]??0;if(oe!==se)return oe>se}return!0}function Ug(P){return Rl(P,[0,0,422])}function Bg(P){return Rl(P,[1,0,8])}function sr(P){return P.env.get("COPILOT_HOME")||wn(P.home,".copilot")}function El(P){return P.disableAllHooks!==!0&&Tl(P)}function Tl(P){return(P.hooks?.preToolUse??[]).some((H)=>{if(H.type!==void 0&&H.type!=="command")return!1;return Wr(H.command)||Wr(H.bash)||Wr(H.powershell)||Wr(H.exec&&[H.exec,...H.args??[]].join(" "))})}function or(P){return P===void 0||typeof P==="string"}function Gg(P){return P===void 0||Array.isArray(P)&&P.every((L)=>typeof L==="string")}function qg(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let L=P;if(L.disableAllHooks!==void 0&&typeof L.disableAllHooks!=="boolean")return!1;if(L.hooks===void 0)return!0;if(!L.hooks||typeof L.hooks!=="object"||Array.isArray(L.hooks))return!1;let H=L.hooks.preToolUse;if(H===void 0)return!0;return Array.isArray(H)&&H.every((Y)=>Y!==null&&typeof Y==="object"&&!Array.isArray(Y)&&or(Y.type)&&or(Y.command)&&or(Y.bash)&&or(Y.powershell)&&or(Y.exec)&&Gg(Y.args))}function ci(P,L){try{let H=JSON.parse(yn(Mg(P,"utf-8")));if(!qg(H)){L?.push(`Invalid hook config ${P}: hooks.preToolUse must be an array of hook objects`);return}return H}catch(H){L?.push(`Failed to parse ${P}: ${H instanceof Error?H.message:String(H)}`);return}}function Al(P,L){try{return Hg(P).filter((H)=>H.endsWith(".json")).sort((H,Y)=>H.localeCompare(Y))}catch(H){return L?.push(`Failed to read ${P}: ${H instanceof Error?H.message:String(H)}`),[]}}function Vg(P,L){if(!Yr(P))return[];let H=[];for(let Y of Al(P,L)){let Z=wn(P,Y),oe=ci(Z,L);if(oe&&El(oe))H.push(Z)}return H}function ir(P,L){if(!Yr(P))return;let H=ci(P,L);if(!H)return;return{path:P,config:H}}function Sl(P,L,H,Y){if(L){P.push(`GitHub Copilot CLI ${L} does not support ${H}; requires ${Y}+`);return}P.push(`GitHub Copilot CLI version unavailable; skipping ${H} because it requires ${Y}+`)}function Kg(P){for(let L of P){if(L?.config.disableAllHooks===!0)return L.path;if(L?.config.disableAllHooks===!1)return}return}function Jg(P,L,H,Y){let Z=sr(P),oe=wn(L,".github","hooks"),se=wn(Z,"hooks"),me=wn(L,".github","copilot"),he=wn(L,".claude"),ke=Bg(H),Pe=ke===!0?Y:void 0,Te=[ir(wn(me,"settings.local.json"),Pe),ir(wn(me,"settings.json"),Pe),ir(wn(he,"settings.local.json"),Pe),ir(wn(he,"settings.json"),Pe)],_e=ir(wn(Z,"settings.json"),Pe),Ae=[_e?.config.disableAllHooks===!0?void 0:_e];if(ke!==!1){let nn=Kg(Te);if(nn){if(ke===null)Y.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${nn} as active`);return{activeConfigPaths:[],repoInlineSources:Te,disabledBy:nn}}}let Le=Vg(oe,Y),We=Ug(H),Fe=We===!0?Y:void 0,Ze=Yr(se)?Al(se,Fe):[],tn=[];for(let nn of Ze){let sn=wn(se,nn),Pn=ci(sn,Fe);if(Pn&&El(Pn))tn.push(sn)}if(We!==!0&&tn.length>0)Sl(Y,H,`user hook files in ${se}`,"0.0.422"),tn.length=0;let on=[];for(let nn of[...Te,...Ae]){if(!nn)continue;if(!Tl(nn.config))continue;if(ke===!0){on.push(nn);continue}Sl(Y,H,"inline hook definitions in Copilot config files","1.0.8");break}let ln=(nn)=>nn.filter((sn)=>!!sn&&on.includes(sn)).map((sn)=>sn.path);return{activeConfigPaths:[...ln(Te),...Le,...ln(Ae),...tn],repoInlineSources:Te}}function _l(P){let L=[],H=Jg(P.environment,P.cwd,P.copilotCliVersion,L);if(H.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:H.disabledBy,configPaths:[H.disabledBy],errors:L.length>0?L:void 0};let Y=sr(P.environment),Z=wn(Y,"installed-plugins",...Jr),oe=Yr(Z),se=wn(Y,"settings.json"),me=vn(se,yn),he=(Ae)=>Xe(Xe(Ae,"enabledPlugins"),An),ke=H.repoInlineSources.find((Ae)=>typeof he(Ae?.config)==="boolean"),Pe=ke??(me.kind==="ok"?{path:se,config:me.value}:void 0);if(oe&&!ke&&me.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};let Te=oe&&Pe!==void 0&&he(Pe.config)===!1;if(Te&&H.activeConfigPaths.length===0)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:Pe.path,errors:[`${An} is installed but not enabled in Copilot CLI`]};let _e=oe&&!Te;if(_e||H.activeConfigPaths.length>0){let Ae=H.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:_e?"plugin config":"hook config",configPath:Ae??(_e?Z:void 0),configPaths:H.activeConfigPaths.length>0?H.activeConfigPaths:void 0,errors:L.length>0?L:void 0}}return{platform:"copilot-cli",status:"n/a",errors:L.length>0?L:void 0}}import{existsSync as hi,readdirSync as ay,readFileSync as ly}from"node:fs";import{join as yi}from"node:path";import{existsSync as mi,mkdirSync as ey,readFileSync as ny,rmSync as ty}from"node:fs";import{dirname as ry,join as Zr}from"node:path";import{existsSync as zg,renameSync as Wg,statSync as Yg,writeFileSync as Zg}from"node:fs";function an(P,L){let H=`${P}.${process.pid}.tmp`;Zg(H,L,zg(P)?{mode:Yg(P).mode&511}:{}),Wg(H,P)}import{spawn as Xg}from"node:child_process";function Qg(P){return P.join(" ")}function di(P,L,H){return[`Failed to run ${Qg(P)}${L===null?"":` (exit ${L})`}.`,H.trim()].filter(Boolean).join(`
34
- `)}function ui(P){let L={stdout:"",stderr:""};return P.stdout.setEncoding("utf-8"),P.stderr.setEncoding("utf-8"),P.stdout.on("data",(H)=>{L.stdout+=H}),P.stderr.on("data",(H)=>{L.stderr+=H}),L}function fn(P,L){return new Promise((H,Y)=>{let Z=Xn([...P],process.env),oe=Xg(Z.cmd,Z.args,{stdio:["ignore","pipe","pipe"]}),se=ui(oe),me=()=>[se.stdout,se.stderr].filter(Boolean).join(`
35
- `),he=L?.timeoutMs??120000,ke=setTimeout(()=>{oe.kill(),Y(Error(di(P,null,`Timed out after ${he}ms.
36
- ${me()}`.trim())))},he);oe.on("error",(Pe)=>{clearTimeout(ke),Y(Error(di(P,null,`${Pe.message}
37
- ${me()}`.trim())))}),oe.on("close",(Pe)=>{if(clearTimeout(ke),Pe!==0){Y(Error(di(P,Pe,me())));return}H(L?.stdoutOnly?se.stdout:me())})})}async function pi(P){for(let L of P)await fn(L)}async function Il(P){for(let L of P)try{await fn(L)}catch(H){console.warn(H instanceof Error?H.message:String(H))}}var kn=Object.fromEntries(er.map((P)=>[P.id,`npx -y cc-safety-net hook ${P.flags[1]}`]));var lr=kn.cursor,Ol=30;function Qr(P){return Zr(P.home,".cursor","hooks.json")}var ar="cc-safety-net";function gi(P){let L=Zr(P.home,".cursor","plugins");return{cache:Zr(L,"cache",ar),marketplaceClone:Zr(L,"marketplaces","github.com","kenryu42","cc-safety-net")}}async function $l(P){let L=Object.values(gi(P));if(!L.some((Y)=>mi(Y)))return;let H="No marketplace matches";return await fn(["cursor-agent","plugin","marketplace","remove",ar]).catch((Y)=>{if(!(Y instanceof Error&&Y.message.includes(H)))throw Y}),L.forEach((Y)=>ty(Y,{recursive:!0,force:!0})),[`Removed the ${ar} marketplace from your Cursor account.`,"If /plugins in cursor-agent still lists CC Safety Net as installed, uninstall it there."].join(`
38
- `)}function it(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function fi(){return{command:lr,timeout:Ol,failClosed:!0}}function Xr(P){return it(P)&&P.command===lr}function oy(P){return Object.keys(P).length===3&&P.command===lr&&P.timeout===Ol&&P.failClosed===!0}function iy(P){try{return JSON.parse(ny(P,"utf-8"))}catch(L){if(L instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${P}: ${L.message}`);throw L}}function Dl(P){let L=iy(P);if(!it(L))throw Error(`Cursor hooks config ${P} must be a JSON object`);if(L.version!==1)throw Error(`Cursor hooks config ${P} must set "version": 1`);if(L.hooks!==void 0&&!it(L.hooks))throw Error(`Cursor hooks config ${P} "hooks" must be an object`);let H=it(L.hooks)?L.hooks.preToolUse:void 0;if(H!==void 0&&!Array.isArray(H))throw Error(`Cursor hooks config ${P} "hooks.preToolUse" must be an array`);return L}function Nl(P){let L=it(P.hooks)?P.hooks.preToolUse:void 0;return Array.isArray(L)?L:[]}function sy(P){if(!P.some(Xr))return[...P,fi()];return P.reduce((L,H)=>{if(!Xr(H))return L.result.push(H),L;if(!L.inserted)L.result.push(fi()),L.inserted=!0;return L},{result:[],inserted:!1}).result}function Ll(P,L,H){let Y=it(L.hooks)?L.hooks:{},Z={...L,hooks:{...Y,preToolUse:H}};an(P,`${JSON.stringify(Z,null,2)}
39
- `)}function jl(P){let L=Qr(P);if(!mi(L))return ey(ry(L),{recursive:!0}),an(L,`${JSON.stringify({version:1,hooks:{preToolUse:[fi()]}},null,2)}
40
- `),{path:L,alreadyInstalled:!1};let H=Dl(L),Y=Nl(H),Z=Y.filter(Xr);if(it(H.hooks)&&Array.isArray(H.hooks.preToolUse)&&Z.length===1&&Z[0]!==void 0&&oy(Z[0]))return{path:L,alreadyInstalled:!0};return Ll(L,H,sy(Y)),{path:L,alreadyInstalled:!1}}function Fl(P){let L=Qr(P);if(!mi(L))return{path:L,alreadyInstalled:!1};let H=Dl(L),Y=Nl(H),Z=Y.filter((oe)=>!Xr(oe));if(Z.length===Y.length)return{path:L,alreadyInstalled:!1};return Ll(L,H,Z),{path:L,alreadyInstalled:!0}}function cy(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];let L=P.hooks;if(!L||typeof L!=="object"||Array.isArray(L))return[];let H=L.preToolUse;if(!Array.isArray(H))return[];return H.filter((Y)=>!!Y&&typeof Y==="object"&&!Array.isArray(Y)&&Y.command===lr)}function dy(P){let L=[];if(P.length>1)L.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let H=P[0];if(H&&H.failClosed!==!0)L.push('Managed hook is missing "failClosed": true; reinstall to repair');if(H&&H.timeout!==30)L.push('Managed hook "timeout" is not 30; reinstall to repair');return L}var eo="Claude Code plugin",vi="Cursor plugin";function uy(P){let L=yi(gi(P).cache,ar);if(!hi(L))return{};try{return{version:ay(L).map((H)=>yi(L,H)).find((H)=>hi(yi(H,".cache-complete")))}}catch{return{unreadable:L}}}function py(P,L){if(L){let Z=["Cursor records enabled plugins on your Cursor account, which doctor cannot check, and keeps a plugin's files after it is uninstalled.","Cursor pins marketplace plugins to the commit they were added at, so `cc-safety-net update` cannot update this plugin, while the npx hook (`cc-safety-net install --cursor`) stays current."].join(" ");return{method:vi,configPath:L,duplicate:`The Cursor plugin also runs this check, so every tool call is checked twice. ${Z} If the plugin is installed, run \`cc-safety-net uninstall --cursor\`, uninstall CC Safety Net from /plugins in cursor-agent, then run \`cc-safety-net install --cursor\`.`,alone:`${Z} If /plugins in cursor-agent does not list CC Safety Net as installed, run \`cc-safety-net install --cursor\`.`}}let H=cl(P);if(!H)return;let Y="Cursor runs the Claude Code plugin only while it imports Claude Code plugins, which doctor cannot check.";return{method:eo,configPath:H,duplicate:`The Claude Code plugin also runs this check in Cursor, so every tool call is checked twice. ${Y} If Cursor runs it, run \`cc-safety-net uninstall --cursor\` to remove this hook.`,alone:`${Y} If it stops, run \`cc-safety-net install --cursor\`.`}}function Hl(P){let L=fy(P),H=uy(P.environment);if(H.unreadable)return L.status==="configured"?{...L,errors:[...L.errors??[],`Cannot read ${H.unreadable}, so doctor cannot tell whether the Cursor plugin also runs this check.`]}:{platform:"cursor",status:"not-inspected"};let Y=py(P.environment,H.version);if(!Y)return L;if(L.status==="configured")return{...L,errors:[...L.errors??[],Y.duplicate]};return{platform:"cursor",status:"configured",method:Y.method,configPath:Y.configPath,errors:[...L.errors??[],Y.alone]}}function fy(P){let L=Qr(P.environment);if(!hi(L))return{platform:"cursor",status:"n/a",configPath:L};let H;try{H=JSON.parse(ly(L,"utf-8"))}catch(oe){return{platform:"cursor",status:"n/a",configPath:L,errors:[`Failed to parse Cursor hooks config ${L}: ${oe instanceof Error?oe.message:String(oe)}`]}}let Y=cy(H);if(Y.length===0)return{platform:"cursor",status:"n/a",configPath:L};let Z=dy(Y);return{platform:"cursor",status:"configured",method:"hook config",configPath:L,errors:Z.length>0?Z:void 0}}import{readdirSync as my}from"node:fs";import{join as bi,resolve as gy}from"node:path";var wi="cc-safety-net";function ki(P){let L=P.env.get("DSH_HOME");return bi(L?.trim()?gy(Nn(L,P.home)):bi(P.home,".dsh"),"profiles")}function Ml(P){let L=ki(P),H=dn(L)?.isDirectory()?my(L,{withFileTypes:!0}).filter((Z)=>Z.isDirectory()&&Z.name!=="node_modules").map((Z)=>{let oe=bi(L,Z.name,"package.json");return{name:Z.name,configPath:oe,manifest:vn(oe)}}):[];return{installed:H.flatMap((Z)=>{if(Z.manifest.kind!=="ok")return[];let oe=Z.manifest.value;if(Xe(Xe(oe,"dependencies"),wi)===void 0)return[];let se=Xe(Xe(Xe(oe,"dsh"),"profile"),"bundles");return[{name:Z.name,configPath:Z.configPath,enabled:Array.isArray(se)&&se.includes(wi)}]}),unreadable:H.some((Z)=>Z.manifest.kind==="unreadable")}}function Ci(P){return Ml(P).installed}function Ul(P){let L=Ml(P.environment),H=L.installed.filter((oe)=>oe.enabled),Y=L.installed.filter((oe)=>!oe.enabled),Z=Y.map((oe)=>`${wi} is installed in the ${oe.name} profile but its bundle is disabled`);if(H.length>0)return{platform:"deepseek-harness",status:"configured",method:"dsh bundle",configPaths:H.map((oe)=>oe.configPath),...Z.length>0?{errors:Z}:{}};if(Y.length>0)return{platform:"deepseek-harness",status:"disabled",method:"dsh bundle",configPaths:Y.map((oe)=>oe.configPath),errors:Z};return L.unreadable?{platform:"deepseek-harness",status:"not-inspected"}:{platform:"deepseek-harness",status:"n/a"}}import{existsSync as ky}from"node:fs";import{existsSync as ql,mkdirSync as yy,readFileSync as hy}from"node:fs";import{dirname as vy,join as Si}from"node:path";function xi(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Pi(P,L){return xi(P)&&P.command===L}function Bl(P,L){return xi(P)&&Array.isArray(P.hooks)&&P.hooks.some((H)=>Pi(H,L))}function gt(P,L){return{hooks:[{type:"command",command:P,timeout:L}]}}function jn(P,L){return P.flatMap((H)=>{if(!xi(H)||!Array.isArray(H.hooks))return[H];let Y=H.hooks.filter((Z)=>!Pi(Z,L));if(Y.length===H.hooks.length)return[H];return Y.length===0?[]:[{...H,hooks:Y}]})}function Mt(P,L,H){let Y=P.filter((Z)=>Bl(Z,L));return Y.length===1&&JSON.stringify(Y[0])===JSON.stringify(gt(L,H))}function Ut(P,L){return P.find((H)=>Bl(H,L))}function Bt(P,L,H){let Y=Array.isArray(P.hooks)?P.hooks.find((Z)=>Pi(Z,L)):void 0;return[...P.matcher===void 0||P.matcher===""||P.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...Y?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...Y?.timeout===H?[]:[`Managed hook "timeout" is not ${H}; reinstall to repair`]]}var yt=kn.devin,no=30,by={config:{},hooks:{},preToolUse:[]};function to(P,L=process.platform){let H=L==="win32"?P.env.get("APPDATA")||Si(P.home,"AppData","Roaming"):P.env.get("XDG_CONFIG_HOME")||Si(P.home,".config");return Si(H,"devin","config.json")}function Gl(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function wy(P){try{return{ok:!0,value:JSON.parse(yn(hy(P,"utf-8")))}}catch(L){return{ok:!1,message:L instanceof Error?L.message:String(L)}}}function Ri(P){let L=wy(P);if(!L.ok)return`Failed to parse Devin CLI config ${P}: ${L.message}`;let H=L.value;if(!Gl(H))return`Devin CLI config ${P} must be a JSON object`;let Y=H.hooks===void 0?{}:H.hooks;if(!Gl(Y))return`Devin CLI config ${P} "hooks" must be an object`;let Z=Y.PreToolUse===void 0?[]:Y.PreToolUse;if(!Array.isArray(Z))return`Devin CLI config ${P} "hooks.PreToolUse" must be an array`;return{config:H,hooks:Y,preToolUse:Z}}function Vl(P){let L=Ri(P);if(typeof L==="string")throw Error(L);return L}function Kl(P,L,H){let Y={...L.config,hooks:{...L.hooks,PreToolUse:H}};an(P,`${JSON.stringify(Y,null,2)}
41
- `)}function Jl(P){let L=to(P),H=ql(L)?Vl(L):by;if(Mt(H.preToolUse,yt,no))return{path:L,alreadyInstalled:!0};return yy(vy(L),{recursive:!0}),Kl(L,H,[...jn(H.preToolUse,yt),gt(yt,no)]),{path:L,alreadyInstalled:!1}}function zl(P){let L=to(P);if(!ql(L))return{path:L,alreadyInstalled:!1};let H=Vl(L),Y=jn(H.preToolUse,yt);if(JSON.stringify(Y)===JSON.stringify(H.preToolUse))return{path:L,alreadyInstalled:!1};return Kl(L,H,Y),{path:L,alreadyInstalled:!0}}function Wl(P){let L=to(P.environment);if(!ky(L))return{platform:"devin",status:"n/a",configPath:L};let H=Ri(L);if(typeof H==="string")return{platform:"devin",status:"n/a",configPath:L,errors:[H]};let Y=Ut(H.preToolUse,yt);if(!Y)return{platform:"devin",status:"n/a",configPath:L};let Z=Bt(Y,yt,no);return{platform:"devin",status:"configured",method:"hook config",configPath:L,errors:Z.length>0?Z:void 0}}import{existsSync as Ty,readFileSync as Ay}from"node:fs";import{existsSync as Gt,mkdirSync as Cy,readFileSync as xy,rmSync as Py}from"node:fs";import{dirname as Sy,join as Ti}from"node:path";var ht=kn.droid,ro=30;function oo(P){return Ti(P.home,".factory","hooks.json")}function Yl(P){return Ti(P.home,".factory","settings.json")}function Zl(P){return Ti(P.home,".factory","hooks","hooks.json")}function Ei(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Xl(P){try{return JSON.parse(yn(xy(P,"utf-8")))}catch(L){if(L instanceof SyntaxError)throw Error(`Failed to parse Factory Droid hooks config ${P}: ${L.message}`);throw L}}function Ai(P){let L=Xl(P);if(!Ei(L))throw Error(`Factory Droid hooks config ${P} must be a JSON object`);if(L.PreToolUse===void 0||Array.isArray(L.PreToolUse))return L;throw Error(`Factory Droid hooks config ${P} "PreToolUse" must be an array`)}function Ry(P){if(!Gt(P))return{};let L=Xl(P);return Ei(L)&&Ei(L.hooks)&&L.hooks.PreToolUse!==void 0?{PreToolUse:L.hooks.PreToolUse}:{}}function Ey(P){let L=Zl(P);return{...Ry(Yl(P)),...Gt(L)?Ai(L):{}}}function Ql(P){return Array.isArray(P.PreToolUse)?P.PreToolUse:[]}function ec(P,L,H){an(P,`${JSON.stringify({...L,PreToolUse:H},null,2)}
42
- `)}function nc(P){let L=oo(P),H=Gt(L),Y=H?Ai(L):Ey(P),Z=Ql(Y);if(H&&Mt(Z,ht,ro))return{path:L,alreadyInstalled:!0};return Cy(Sy(L),{recursive:!0}),ec(L,Y,[...jn(Z,ht),gt(ht,ro)]),{path:L,alreadyInstalled:!1}}function tc(P){let L=oo(P);if(!Gt(L))return{path:L,alreadyInstalled:!1};let H=Ai(L),Y=Ql(H),Z=jn(Y,ht);if(JSON.stringify(Z)===JSON.stringify(Y))return{path:L,alreadyInstalled:!1};let oe=Gt(Yl(P))||Gt(Zl(P));if(Z.length===0&&Object.keys(H).length===1&&!oe)return Py(L),{path:L,alreadyInstalled:!0};return ec(L,H,Z),{path:L,alreadyInstalled:!0}}function rc(P){let L=oo(P.environment);if(!Ty(L))return{platform:"droid",status:"n/a",configPath:L};let H;try{H=JSON.parse(yn(Ay(L,"utf-8")))}catch(se){return{platform:"droid",status:"n/a",configPath:L,errors:[`Failed to parse Factory Droid hooks config ${L}: ${se instanceof Error?se.message:String(se)}`]}}let Y=typeof H==="object"&&H!==null&&"PreToolUse"in H?H.PreToolUse:void 0,Z=Ut(Array.isArray(Y)?Y:[],ht);if(!Z)return{platform:"droid",status:"n/a",configPath:L};let oe=[...Z.commandRegex===void 0||Z.commandRegex===""?[]:['Managed hook has a "commandRegex" that narrows coverage; reinstall to repair'],...Bt(Z,ht,ro)];return{platform:"droid",status:"configured",method:"hook config",configPath:L,errors:oe.length>0?oe:void 0}}import{existsSync as _y}from"node:fs";import{join as _i}from"node:path";var Ii="gemini-safety-net";function Oi(P){let L=_i(P.home,".gemini","extensions"),H=_i(L,Ii);if(!_y(H))return{platform:"gemini-cli",status:"n/a"};let Y=_i(L,"extension-enablement.json"),Z=vn(Y);if(Z.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let oe=Z.kind==="ok"?Xe(Xe(Z.value,Ii),"overrides"):void 0;if(Array.isArray(oe)&&oe.some((me)=>typeof me==="string"&&me.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:Y,errors:[`${Ii} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:H}}function oc(P){return Oi(P.environment)}import{existsSync as Dy,readFileSync as fc,statSync as Ny}from"node:fs";import{dirname as pc,join as Ly}from"node:path";import{existsSync as sc,mkdirSync as Iy,readFileSync as ac,rmSync as Oy}from"node:fs";import{dirname as $y,join as ic}from"node:path";var Gn=kn["grok-build"],so=30,$i=gt(Gn,so);function ao(P){return ic(P.env.get("GROK_HOME")??ic(P.home,".grok"),"hooks","cc-safety-net.json")}function lo(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function lc(P){try{let L=JSON.parse(P);return lo(L)?L:null}catch{return null}}function cc(P){let L=lo(P.hooks)?P.hooks.PreToolUse:void 0;return Array.isArray(L)?L:[]}function io(P,L,H){let Y=lo(L.hooks)?L.hooks:{};an(P,`${JSON.stringify({...L,hooks:{...Y,PreToolUse:H}},null,2)}
43
- `)}function dc(P){let L=ao(P);if(!sc(L))return Iy($y(L),{recursive:!0}),io(L,{},[$i]),{path:L,alreadyInstalled:!1};let H=lc(ac(L,"utf-8"));if(!H)return io(L,{},[$i]),{path:L,alreadyInstalled:!1};let Y=cc(H);if(Mt(Y,Gn,so))return{path:L,alreadyInstalled:!0};return io(L,H,[...jn(Y,Gn),$i]),{path:L,alreadyInstalled:!1}}function uc(P){let L=ao(P);if(!sc(L))return{path:L,alreadyInstalled:!1};let H=lc(ac(L,"utf-8"));if(!H)return{path:L,alreadyInstalled:!1};let Y=cc(H),Z=jn(Y,Gn);if(JSON.stringify(Z)===JSON.stringify(Y))return{path:L,alreadyInstalled:!1};let oe=lo(H.hooks)?H.hooks:{};if(Z.length===0&&Object.keys(H).length===1&&Object.keys(oe).length===1)return Oy(L),{path:L,alreadyInstalled:!0};return io(L,H,Z),{path:L,alreadyInstalled:!0}}function Di(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function jy(P){try{return Ny(P,{throwIfNoEntry:!1})?.isFile()===!0?fc(P,"utf-8"):""}catch{return}}function mc(P){let L=ao(P.environment);if(!Dy(L))return{platform:"grok-build",status:"n/a",configPath:L};let H;try{H=JSON.parse(fc(L,"utf-8"))}catch(Te){return{platform:"grok-build",status:"n/a",configPath:L,errors:[`Failed to parse Grok Build hooks config ${L}: ${Te instanceof Error?Te.message:String(Te)}`]}}let Y=Di(H)&&Di(H.hooks)&&Array.isArray(H.hooks.PreToolUse)?H.hooks.PreToolUse:[],Z=Ut(Y,Gn);if(!Z)return{platform:"grok-build",status:"n/a",configPath:L};let oe=Array.isArray(Z.hooks)?Z.hooks.findIndex((Te)=>Di(Te)&&Te.command===Gn):-1,se=`global/cc-safety-net:pre_tool_use[${Y.indexOf(Z)}].hooks[${oe}]`,me=Ly(pc(pc(L)),"disabled-hooks"),he=jy(me),ke=he?.split(`
44
- `).some((Te)=>Te.trim()===se)===!0,Pe=[...he===void 0?[`Cannot read ${me}, so doctor cannot tell whether Grok Build skips the hook`]:[],...ke?[`Grok Build skips the hook: ${se} is listed in ${me}; enable it in /hooks`]:[],...Bt(Z,Gn,so)];return{platform:"grok-build",status:ke?"disabled":"configured",method:"hook config",configPath:L,errors:Pe.length>0?Pe:void 0}}import{readFileSync as xc}from"node:fs";import{join as Pc}from"node:path";var Sn="cc-safety-net",Ni="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",Fy=30;function gc(P){return`${Ni}
1
+ import{a,s,$e,ot,T,xt,it,c,n,st,_,S,he,wt,m,De,x,ct,l,o,w,i,ce,r,h,ve,B,Et,kt,p,be,xe,Rt,L,Q,le,C,Tt,A,y,ue,W,u,O,ee,lt,ut,M,E,D,Se,we,Ue,de,d,e,He,Ne,Ge,Ce,dt,pt,pe,Le,fe,Be,te,z,We,Ee,V,ft,q,ne,re,me,mt,gt,k,I,ze,ht,qe,R,Ke,Me,Je,v,t,oe,ke,b,F,g,N,Pt,Ye,Ze,f,j}from"./chunks/index-1p1q38x4.js";import{tt}from"./chunks/index-8c31a7e4.js";import{Xe,Te}from"./chunks/index-03hfs9tb.js";import{nt}from"./chunks/index-7nndhfn3.js";import"./chunks/index-tz7650sh.js";import{se,J,rt,U,H}from"./chunks/index-8m4sxbp8.js";var Cf=["-h","--help"];function fn(P,G){let K=Object.entries(P.booleans??{}),Y=Object.entries(P.values??{}),Z=Object.entries(P.lists??{}),X=Object.fromEntries(K.map(([_e])=>[_e,!1])),ie={},ae=Object.fromEntries(Z.map(([_e])=>[_e,[]])),ge=[],ye=[],Pe=!1,Re=-1;for(let[_e,Ae]of G.entries()){if(_e<=Re)continue;if(Ae==="--"){ge.push(...G.slice(_e+1));break}if(Cf.includes(Ae)){Pe=!0;continue}let Ie=K.find(([,Ve])=>Ve.includes(Ae));if(Ie){X[Ie[0]]=!0;continue}let je=Y.find(([,Ve])=>Ve.includes(Ae));if(je){let Ve=G[_e+1];if(Ve===void 0||Ve.startsWith("-")){ye.push(`${Ae} requires a value`);continue}ie[je[0]]=Ve,Re=_e+1;continue}let Oe=Z.find(([,Ve])=>Ve.includes(Ae));if(Oe){let Ve=G.slice(_e+1),nn=Ve.findIndex((an)=>an.startsWith("-")),rn=Ve.slice(0,nn===-1?Ve.length:nn);if(rn.length===0){ye.push(`${Ae} requires at least one value`);continue}ae[Oe[0]]=[...ae[Oe[0]]??[],...rn],Re=_e+rn.length;continue}if(Ae.startsWith("-")){ye.push(`Unknown option for ${P.label}: ${Ae}`);continue}if(P.positionals==="tail"){ge.push(...G.slice(_e));break}ge.push(Ae)}if(P.positionals!=="list"&&P.positionals!=="tail")ye.push(...ge.map((_e)=>`Unexpected argument for ${P.label}: ${_e}`));return{flags:X,values:ie,lists:ae,positionals:ge,help:Pe,errors:ye}}function $n(P){for(let G of P)console.error(G);return P.length>0}import{readdirSync as Af,statSync as Xs,unlinkSync as _f}from"node:fs";import{basename as Qs,dirname as If,isAbsolute as Of,join as $f,relative as Df,resolve as Nf,sep as Lf}from"node:path";var Ws=(P)=>{let G=Date.now()-new Date(P).getTime();if(!Number.isFinite(G))return"";let K=Math.floor(G/60000),Y=Math.floor(K/60),Z=Math.floor(Y/24);if(Z>0)return`${Z}d ago`;if(Y>0)return`${Y}h ago`;if(K>0)return`${K}m ago`;return"just now"},Go=(P)=>{let G=(P??"").trim().split(/\s+/).filter((Z)=>Z&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(Z)),K=G[0]?.split("/").pop();if(!K)return null;let Y=G[1];return Y&&/^[a-z][a-z0-9-]*$/.test(Y)?`${K} ${Y}`:K};function Ys(P){let G=(Z)=>`${Z.sessionId}
2
+ ${Go(Z.segment||Z.command)}`,K=P.filter((Z)=>Z.decision!=="allow"),Y=K.filter((Z)=>Z.sessionId).reduce((Z,X)=>Z.set(G(X),(Z.get(G(X))??0)+1),new Map);return new Set(K.filter((Z)=>Z.failureStage||(Y.get(G(Z))??0)>=2))}import{existsSync as xf,readdirSync as Pf,readFileSync as Sf}from"node:fs";import{join as Rf}from"node:path";function Wn(P,G){try{return Pf(P,{withFileTypes:!0,encoding:"utf8"}).flatMap((K)=>{let Y=Rf(P,K.name);if(K.isDirectory())return Wn(Y,G);if(K.name.endsWith(".jsonl"))return[Y];return[]})}catch{if(G&&xf(P))G.count++;return[]}}var Ef=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function Tf(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let G=P;if(typeof G.ts!=="string"||typeof G.command!=="string")return!1;return Ef.every((K)=>G[K]===void 0||typeof G[K]==="string")}function Dt(P,G){try{return Sf(P,"utf-8").split(`
3
+ `).filter(Boolean).flatMap((K)=>{try{let Y=JSON.parse(K);if(!Tf(Y)){if(G)G.count++;return[]}return[Y]}catch{if(G)G.count++;return[]}})}catch{if(G)G.count++;return[]}}function mn(P){return Array.from(P,(G)=>{let K=G.charCodeAt(0);if(K<=31||K>=127&&K<=159)return`\\x${K.toString(16).padStart(2,"0")}`;return G}).join("")}function jf(P,G){let K=se(P),Y=fn({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"]}},G);if($n(Y.errors))return null;if(Y.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(Y.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let Z=Y.values.limit===void 0?20:Zs(Y.values.limit);if(Z===null)return console.error("--limit must be a positive number"),null;let X=Y.values.since===void 0?Math.min(30,K):Zs(Y.values.since);if(X===null||X>K)return console.error(`--since must be a positive number of days no greater than ${K}`),null;let ie={limit:Z,limitExplicit:Y.values.limit!==void 0,since:X,sinceExplicit:Y.values.since!==void 0,all:Y.flags.all,json:Y.flags.json,suspect:Y.flags.suspect,pruneLegacy:Y.flags.pruneLegacy,dryRun:Y.flags.dryRun,id:Y.values.id,agent:Y.values.agent,rule:Y.values.rule,session:Y.values.session,project:Y.values.project===void 0?void 0:Nf(Y.values.project)};if(ie.id&&(ie.agent!==void 0||ie.rule!==void 0||ie.session!==void 0||ie.project!==void 0||ie.suspect||ie.sinceExplicit||ie.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(ie.pruneLegacy&&(ie.id!==void 0||ie.agent!==void 0||ie.rule!==void 0||ie.session!==void 0||ie.project!==void 0||ie.suspect||ie.all||ie.sinceExplicit||ie.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(ie.dryRun&&!ie.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return ie}async function ea(P,G,K={}){let Y=jf(P,G);if(!Y)return 1;let Z=K.logsDir??U(P);if(Y.pruneLegacy)return Ff(Z,Y.json,Y.dryRun);if(!Z)return console.log(Y.json?"[]":Y.id?`No retained audit log entry found for id ${mn(Y.id)}.`:"No audit log entries found."),0;J(P,Z);let X={count:0},ie=Wn(Z,X).flatMap((Re)=>Dt(Re,X).map((_e)=>({entry:_e,file:Re})));if(X.count>0)console.error(`warning: ${X.count} audit log ${X.count===1?"source":"sources"} could not be read; these results are incomplete`);if(Y.id)return Bf(ie,Y,K.timeZone);let ae=Date.now()-Y.since*24*60*60*1000,ge=ie.filter((Re)=>Gf(Re,Y,Z,ae)),ye=Y.suspect?Ys(ge.map((Re)=>Re.entry)):null,Pe=(ye?ge.filter((Re)=>ye.has(Re.entry)):ge).sort((Re,_e)=>Date.parse(_e.entry.ts)-Date.parse(Re.entry.ts)).slice(0,Y.limit);if(Y.json)return console.log(JSON.stringify(Pe.map((Re)=>Re.entry),null,2)),0;if(Pe.length===0)return console.log("No audit log entries found."),0;for(let Re of Pe)console.log(Kf(Re.entry,K.timeZone));return 0}function Ff(P,G,K){let Y=P?Mf(P).map((ae)=>$f(P,ae)):[];if(K)return Hf(Y,G);let Z=[],X=0,ie=0;for(let ae of Y){let ge=Xs(ae,{throwIfNoEntry:!1})?.size??0,ye=Uf(ae);if(ye){Z.push(`${Qs(ae)}: ${ye}`);continue}X++,ie+=ge}if(G)return console.log(JSON.stringify({removedFiles:X,removedBytes:ie,failedFiles:Z.length})),Z.length===0?0:1;console.log(X===0&&Z.length===0?"No legacy audit log files found.":`Removed ${X} legacy audit log ${X===1?"file":"files"} (${na(ie)}).`);for(let ae of Z)console.error(`Could not remove ${mn(ae)}`);if(console.log("Nested v2 audit logs were not changed."),X>0)console.log("This deletion cannot be undone.");return Z.length===0?0:1}function Hf(P,G){let K=P.reduce((Y,Z)=>Y+(Xs(Z,{throwIfNoEntry:!1})?.size??0),0);if(G)return console.log(JSON.stringify({dryRun:!0,files:P.length,bytes:K})),0;if(console.log(P.length===0?"No legacy audit log files found.":`Would remove ${P.length} legacy audit log ${P.length===1?"file":"files"} (${na(K)}).`),console.log("Nested v2 audit logs are not included."),P.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Mf(P){try{return Af(P,{withFileTypes:!0}).filter((G)=>G.isFile()&&G.name.endsWith(".jsonl")).map((G)=>G.name)}catch{return[]}}function Uf(P){try{return _f(P),null}catch(G){return G instanceof Error?G.message:String(G)}}function na(P){let G=["B","KiB","MiB","GiB"],K=Math.min(Math.floor(Math.log2(Math.max(P,1))/10),G.length-1);return`${Math.round(P/1024**K*10)/10} ${G[K]}`}function Bf(P,G,K){let Y=P.filter((X)=>X.entry.id===G.id);if(Y.length>1)return console.error(`Multiple audit log entries found for id ${mn(G.id??"")}.`),1;if(G.json)return console.log(JSON.stringify(Y.map((X)=>X.entry),null,2)),0;let Z=Y[0];if(!Z)return console.log(`No retained audit log entry found for id ${mn(G.id??"")}.`),0;return console.log(Jf(Z.entry,K)),0}function Gf(P,G,K,Y){if(!G.all&&P.entry.decision==="allow")return!1;if(Date.parse(P.entry.ts)<Y)return!1;if(G.agent!==void 0&&P.entry.agent!==G.agent)return!1;if(G.rule!==void 0&&P.entry.ruleId!==G.rule)return!1;if(G.session!==void 0&&!qf(P,K,G.session))return!1;if(G.project!==void 0&&!Vf(P.entry.cwd,G.project))return!1;return!0}function qf(P,G,K){if(P.entry.sessionId===K)return!0;return If(P.file)===G&&Qs(P.file,".jsonl")===K}function Vf(P,G){if(!P)return!1;let K=Df(G,P);return K!==".."&&!K.startsWith(`..${Lf}`)&&!Of(K)}function Kf(P,G){let K=mn(P.id??"-"),Y=mn(P.decision??"deny"),Z=P.cwd?` [${mn(P.cwd)}]`:"",X=P.segment||P.command,ie=X===P.command?"":"↳ ",ae=X.length>50?`${X.slice(0,50)}…`:X;return`${K.padEnd(16)} ${mn(ta(P.ts,G))} ${Y.padEnd(5)} ${mn(P.agent??"-").padEnd(15)} ${mn(P.ruleId??"-").padEnd(20)} ${ie}${mn(ae)}${Z}`}function Jf(P,G){let K=(Z)=>mn(Z===void 0||Z===null||Z===""?"-":Z),Y=P.shape?`${P.agent??"-"} (shape: ${P.shape})`:P.agent??"-";return[`id: ${K(P.id)}`,`ts: ${K(ta(P.ts,G))}`,`decision: ${K(P.decision)}`,`agent: ${K(Y)}`,`level: ${K(P.level)}`,`tool: ${K(P.toolName)}`,`rule: ${K(P.ruleId)}`,`intent: ${K(P.intent)}`,`stage: ${K(P.failureStage)}`,`error: ${K(P.errorCode)}`,`session: ${K(P.sessionId)}`,`cwd: ${K(P.cwd)}`,`version: ${K(P.v)}`,`truncated: ${K(P.truncated===!0?"yes":void 0)}`,`reason: ${K(P.reason)}`,`command: ${K(P.command)}`,`segment: ${K(P.segment)}`].join(`
4
+ `)}function ta(P,G){let K=new Date(P);if(Number.isNaN(K.getTime()))return P;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:G}).format(K)}function Zs(P){let G=Number(P);return Number.isFinite(G)&&G>0?G:null}var ra={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 oa={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 ia={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 qo=["npx","--offline","--no-install","@deepseek-ai/dsh","--version"],sa=["cursor-agent","--version"],aa=[{id:"antigravity-cli",displayName:"Antigravity CLI",runtime:{flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",runtime:{displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",runtime:{flags:["-cx","--codex"],description:"Run as a Codex PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",runtime:{flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",runtime:{flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",runtime:{flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",runtime:{flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",runtime:{flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",install:{flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",install:{flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",install:{flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",runtime:{flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"deepseek-harness",displayName:"DeepSeek Harness",install:{flag:"--deepseek-harness",artifactKind:"package",probeCommand:qo}},{id:"devin",displayName:"Devin CLI",runtime:{flags:["-dv","--devin"],description:"Run as Devin CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--devin",artifactKind:"hook config",probeCommand:["devin","--version"]}},{id:"droid",displayName:"Factory Droid",runtime:{flags:["-fd","--droid"],description:"Run as Factory Droid PreToolUse hook",legacyTopLevelFlags:[]},install:{flag:"--droid",artifactKind:"hook config",probeCommand:["droid","--version"]}},{id:"amp",displayName:"Amp Code",install:{flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],Vo=aa.slice().sort((P,G)=>P.displayName.localeCompare(G.displayName,"en")),Er=Vo.map((P)=>P.id).sort((P,G)=>Number(G==="claude-code")-Number(P==="claude-code")),er=Vo.filter((P)=>("runtime"in P)).map((P)=>({id:P.id,displayName:"displayName"in P.runtime?P.runtime.displayName:P.displayName,flags:P.runtime.flags,legacyFlags:"legacyFlags"in P.runtime?P.runtime.legacyFlags:[],description:P.runtime.description,legacyTopLevelFlags:P.runtime.legacyTopLevelFlags})),Sn=Vo.map((P)=>({id:P.id,...P.install})),zf=Object.fromEntries(aa.map((P)=>[P.id,P.displayName]));function ln(P){return zf[P]}var Wf=er.map((P)=>({flags:P.flags.join(", "),description:P.description})),Yf=er.flatMap((P)=>P.flags.map((G)=>`cc-safety-net hook ${G}`)),la={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Wf,{flags:"-h, --help",description:"Show this help"}],examples:Yf};var ca={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...Sn.map((P)=>({flags:P.flag,description:`Install ${ln(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...Sn.map((P)=>`cc-safety-net install ${P.flag}`)]},da={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...Sn.map((P)=>({flags:P.flag,description:`Uninstall ${ln(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...Sn.map((P)=>`cc-safety-net uninstall ${P.flag}`)]},ua={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 pa={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 Tr={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 Ko=[{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"}],Jo=["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"],Nt={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:"tool add <name...> [--cwd-arg <name>] [--project]",description:"Analyze community shell tools (user scope by default)"},{usage:"tool remove <name...> [--project]",description:"Stop analyzing declared tools"},{usage:"tool list",description:"List declared command tools in both scopes"},{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"},{flags:"--project",description:"Use project-scope rule config with rule tool"},{flags:"--cwd-arg",argument:"<name>",description:"Name the working-directory argument with rule tool add"},...Ko.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","cc-safety-net rule tool add ops_bash","cc-safety-net rule tool add ops_run_background --cwd-arg cwd --project",...Jo,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var fa={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 ma={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 Ar=[fa,ra,pa,oa,Nt,Tr,ca,ua,da,la,ia,ma];function Zf(P){return P.aliases??[]}function _r(P){let G=P.toLowerCase();return Ar.find((K)=>K.name.toLowerCase()===G||Zf(K).some((Y)=>Y.toLowerCase()===G))}import{existsSync as qh}from"node:fs";import{basename as Xf}from"node:path";function Ir(P,G=7,K=U(P)){let Y=Date.now()-G*24*60*60*1000,Z=[],X=new Set,ie=0,ae,ge,ye,Pe;if(K)J(P,K);let Re={count:0},_e=K?Wn(K,Re):[];for(let Ie of _e)for(let je of Dt(Ie,Re)){if(je.decision==="allow")continue;let Oe=new Date(je.ts).getTime();if(Oe>=Y){if(ie++,X.add(je.sessionId??Xf(Ie,".jsonl")),ge===void 0||Oe<=ge)ae=je.ts,ge=Oe;if(Pe===void 0||Oe>Pe)ye=je.ts,Pe=Oe;Qf(Z,je,Oe)}}let Ae=Z.map((Ie)=>({timestamp:Ie.ts,command:Ie.command,reason:Ie.reason,relativeTime:Ws(new Date(Ie.ts))}));return{totalBlocked:ie,sessionCount:X.size,recentEntries:Ae,oldestEntry:ae,newestEntry:ye,unreadable:Re.count}}function Qf(P,G,K){let Y=P.findIndex((Z)=>K>new Date(Z.ts).getTime());if(Y===-1){if(P.length<3)P.push(G);return}if(P.splice(Y,0,G),P.length>3)P.pop()}import{dirname as um}from"node:path";import{dirname as em,join as nm,resolve as tm}from"node:path";var rm="config.json";function vn(P,G,K,Y){h(om(P),`${JSON.stringify(G,null,2)}
5
+ `,K,Y)}function om(P){return typeof P==="string"?ce(P):P}function Wo(P){return{errors:pe(sm(P),": "," "),ruleNames:new Set(Be(P).map((G)=>G.toLowerCase()))}}var im="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",ga="must match pattern (letters, numbers, hyphens, underscores)";function sm(P){if(!ya(P))return[e([],"Config must be an object")];return[...P.version===1?[]:[e(["version"],"must be 1")],...am(P.rules)]}function am(P){if(P===void 0)return[];if(!Array.isArray(P))return[e(["rules"],"must be an array")];return[...P.flatMap((G,K)=>ya(G)?lm(G,["rules",K]):[e(["rules",K],"must be an object")]),...He(P)]}function lm(P,G){return[...zo(P.name,[...G,"name"],"required string",p,im),...zo(P.command,[...G,"command"],"required string",E,ga),...P.subcommand===void 0?[]:zo(P.subcommand,[...G,"subcommand"],"must be a string if provided",E,ga),...cm(P.block_args,[...G,"block_args"]),...dm(P.reason,[...G,"reason"]),...P.intent===void 0||Le(P.intent)?[]:[e([...G,"intent"],Ne)]]}function zo(P,G,K,Y,Z){if(typeof P!=="string")return[e(G,K)];return Y.test(P)?[]:[e(G,Z)]}function cm(P,G){if(!Array.isArray(P))return[e(G,"required array")];if(P.length===0)return[e(G,"must have at least one element")];return P.flatMap((K,Y)=>{if(typeof K!=="string")return[e([...G,Y],"must be a string")];return K===""?[e([...G,Y],"must not be empty")]:[]})}function dm(P,G){if(typeof P!=="string")return[e(G,"required string")];if(P==="")return[e(G,"must not be empty")];return P.length>D?[e(G,`must be at most ${D} characters`)]:[]}function ya(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function Yo(P){let G=ha(P);if(!G.ok)return G.result;return Wo(G.parsed)}function ha(P){let G=[],K=new Set;try{let Y=typeof P==="string"?ce(P):P,Z=r(Y);if(Z===null)return G.push(`File not found: ${Y.path}`),{ok:!1,result:{errors:G,ruleNames:K}};if(!Z.trim())return G.push("Config file is empty"),{ok:!1,result:{errors:G,ruleNames:K}};return{ok:!0,parsed:JSON.parse(Z)}}catch(Y){if(Y instanceof o)return G.push(Y.message),{ok:!1,result:{errors:G,ruleNames:K}};let Z=Y instanceof Error?Y.message:String(Y);return G.push(Y instanceof SyntaxError?"Invalid JSON":Z),{ok:!1,result:{errors:G,ruleNames:K}}}}function Lt(P){return tm(P,".safety-net.json")}function Un(P){let G=ha(P);if(!G.ok)return G.result;let K=dt(G.parsed);return{errors:K.errors,ruleNames:K.sources}}function jt(P,G={}){return nm(em(ue(P,G)),rm)}function va(P,G,K){let Y;try{if(r(G)===null)return{path:P,exists:!1,valid:!1,ruleCount:0};Y=Un(G),Y.errors.push(...z(P,K))}catch(Z){if(!(Z instanceof o))throw Z;Y={errors:[Z.message],ruleNames:new Set}}return{path:P,exists:!0,valid:Y.errors.length===0,ruleCount:Y.ruleNames.size,...Y.errors.length>0?{errors:Y.errors}:{}}}function pm(P,G){return{source:G,name:P.name,command:P.command,subcommand:P.subcommand,blockArgs:[...P.block_args],reason:P.reason}}function ba(P,G){let K=W(P),Y=A(G),Z=um(K),X=te(P,{cwd:G,userConfigPath:K,projectConfigPath:Y,userConfigDir:Z}),ie=ee(P,{cwd:G,userConfigPath:K,projectConfigPath:Y,userConfigDir:Z}),ae=new Map(X.rulebooks.flatMap((ge)=>ge.rules.map((ye)=>[ye,ge.source])));return{userConfig:va(K,ie.userConfigTarget,ie.userScope),projectConfig:va(Y,ie.projectConfigTarget,ie.projectScope),effectiveRules:X.rules.map((ge)=>pm(ge,ae.get(ge.name)??"project"))}}var fm=[{flag:n.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:n.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:n.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:n.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:n.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:n.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:n.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:n.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"},{flag:n.projectTightenOnly,description:"Ignore project policy settings that weaken the user policy",defaultBehavior:"off"}];function wa(P){return[...fm.map((G)=>({name:G.flag.name,value:he(G.flag,P.env),isSet:wt(G.flag,P.env),legacyName:G.flag.legacyName,legacyValue:G.flag.legacyName?P.env.get(G.flag.legacyName):void 0,legacyIsSet:G.flag.legacyName?P.env.get(G.flag.legacyName)!==void 0:void 0,description:G.description,defaultBehavior:G.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:P.env.get("CC_SAFETY_NET_HOME"),isSet:P.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var ka={error:0,warning:1,info:2},mm=["policy","config","audit"];function gm(P){return P.map((G)=>{if(G==="ownership")return"is not owned by the current user";if(G==="permissions")return"has unsafe permissions";if(G==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var ym=[{derive:(P)=>P.hooks.length>0&&P.hooks.every((G)=>!G.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(P)=>P.hooks.filter((G)=>G.inspectionStatus==="failed").map((G)=>{let K=ln(G.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${K} inspection failed`,detail:`Doctor could not verify the ${K} integration configuration.`,fixHint:`Correct the reported ${K} configuration error, then run \`cc-safety-net doctor\` again.`,integration:G.platform}})},{derive:(P)=>P.userConfig.exists&&!P.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.userConfig.path}]:[]},{derive:(P)=>P.projectConfig.exists&&!P.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.projectConfig.path}]:[]},{derive:(P)=>P.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${P.configState.reason}`,fixHint:"Fix the file named in the reason, or run `cc-safety-net rule update` to vendor a remote source, then rerun doctor."}]:[]},{derive:(P)=>P.v2Leftovers&&P.v2Leftovers.length>0?[{checkId:"config.v2-leftovers",severity:"info",title:"Rulebook lock and cache leftovers detected",detail:`Files an earlier version left behind are no longer read: ${P.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(P)=>P.legacyConfigs&&P.legacyConfigs.length>0?[{checkId:"config.legacy-ignored",severity:"warning",title:"Legacy inline rule configs are ignored",detail:`CC Safety Net no longer loads these files, so their rules enforce nothing: ${P.legacyConfigs.join(", ")}.`,fixHint:"Run `cc-safety-net rule migrate` to convert them (add `--cleanup` to delete each file once it is converted), then rerun doctor."}]:[]},{derive:(P)=>{let G=P.environment.find((K)=>K.name==="CC_SAFETY_NET_AUDIT_SCOPE");return st(G?.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."}]:[]}},...mm.map((P)=>({derive:(G)=>G.posture.directories.filter((K)=>K.kind===P&&K.status==="unsafe").map((K)=>({checkId:`posture.${P}-directory-unsafe`,severity:"error",title:`${P[0]?.toUpperCase()}${P.slice(1)} directory is unsafe`,detail:`The ${P} directory ${gm(K.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...K.path?{path:K.path}:{}}))})),{derive:(P)=>{let G=[...P.effectiveSafety.weakenedRuleOverrides].sort();return G.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: ${G.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${G.join(", ")}.`}]:[]}}];function Ca(P){return ym.flatMap((G,K)=>G.derive(P).map((Y,Z)=>({finding:Y,catalogOrder:K,occurrence:Z}))).sort((G,K)=>ka[G.finding.severity]-ka[K.finding.severity]||G.catalogOrder-K.catalogOrder||G.occurrence-K.occurrence).map((G)=>G.finding)}function Dn(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var hm=(P)=>Dn()?`\x1B[32m${P}\x1B[0m`:P,vm=(P)=>Dn()?`\x1B[33m${P}\x1B[0m`:P,bm=(P)=>Dn()?`\x1B[34m${P}\x1B[0m`:P,wm=(P)=>Dn()?`\x1B[36m${P}\x1B[0m`:P,km=(P)=>Dn()?`\x1B[31m${P}\x1B[0m`:P,Cm=(P)=>Dn()?`\x1B[2m${P}\x1B[0m`:P,xm=(P)=>Dn()?`\x1B[1m${P}\x1B[0m`:P,Qe={green:hm,yellow:vm,blue:bm,cyan:wm,red:km,dim:Cm,bold:xm},Pm="\x1B[0m",Sm=[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 Rm(P){let G=P;return()=>(G=(G*1664525+1013904223)%4294967296,G/4294967296)}function Em(P){let G=[...Sm],K=Rm(P);for(let Y=G.length-1;Y>0;Y--){let Z=Math.floor(K()*(Y+1)),X=G[Y];G[Y]=G[Z],G[Z]=X}return G}function Tm(P,G=0){if(!Dn())return"";let K=Em(G);return`\x1B[38;5;${K[P%K.length]}m`}function xa(P,G,K=0){if(!Dn())return`"${P}"`;return`${Tm(G,K)}"${P}"${Pm}`}function Or(P){return P==="default"?"built-in default":`${P} policy`}var Am=new RegExp("\x1B\\[[0-9;]*m","g"),Zo=(P)=>P.replace(Am,"").length;function Yn(P){let G=(P.headers??P.rows[0]??[]).map((ie,ae)=>{let ge=Math.max(...P.rows.map((ye)=>Zo(ye[ae]??"")));return Math.max(Zo(ie),ge)}),K=(ie,ae)=>ie+" ".repeat(Math.max(0,ae-Zo(ie))),Y=(ie,ae)=>ae[0]+G.map((ge)=>ie.repeat(ge+2)).join(ae[1])+ae[2],Z=(ie)=>`│ ${ie.map((ae,ge)=>K(ae,G[ge]??0)).join(" │ ")} │`,X=P.headers?[` ${Z(P.headers)}`,` ${Y("─",["├","┼","┤"])}`]:[];return[` ${Y("─",["┌","┬","┐"])}`,...X,...P.rows.map((ie)=>` ${Z(ie)}`),` ${Y("─",["└","┴","┘"])}`].join(`
6
+ `)}function Pa(P){let G=[];G.push("Hook Integration"),G.push(_m(P));let K=[],Y=[];for(let Z of P){let X=ln(Z.platform);if(Z.errors&&Z.errors.length>0)for(let ie of Z.errors)if(Z.configured)K.push({platform:X,message:ie});else Y.push({platform:X,message:ie})}for(let Z of K)G.push(` Warning (${Z.platform}): ${Z.message}`);for(let Z of Y)G.push(Qe.red(` Error (${Z.platform}): ${Z.message}`));return G.join(`
7
+ `)}function _m(P){let G=["Platform","Discovery","Configuration","Inspection"],K=P.map((Y)=>{let Z=ln(Y.platform);if(Y.inspectionStatus==="not-inspected"){let ge=Qe.dim("Not inspected");return[Z,ge,ge,ge]}let X=Y.detected?Qe.green("Detected"):Y.inspectionStatus==="failed"?Qe.red("Unknown"):Qe.dim("Not detected"),ie=Y.configured?Qe.green("Configured"):Y.detected?Qe.yellow("Not configured"):Y.inspectionStatus==="failed"?Qe.red("Unknown"):Qe.dim("Not applicable"),ae=Y.inspectionStatus==="verified"?Qe.green("Verified"):Y.inspectionStatus==="failed"?Qe.red("Failed"):Qe.dim("Not applicable");return[Z,X,ie,ae]});return Yn({headers:G,rows:K})}function Sa(P){let K=["Guard Engine Verification",` Synthetic self-test: ${P.failed>0?Qe.red(`${P.passed}/${P.total} FAIL`):Qe.green(`${P.passed}/${P.total} passed`)}`],Y=P.results.filter((Z)=>!Z.passed);if(Y.length>0){K.push(""),K.push(Qe.red(" Failures:"));for(let Z of Y)K.push(Qe.red(` • ${Z.description}`)),K.push(Qe.red(` expected ${Z.expected}, got ${Z.actual}`))}return K.join(`
8
+ `)}function Im(P){if(P.length===0)return" (no custom rules)";let G=["Source","Name","Command","Block Args"],K=P.map((Y)=>[Y.source,Y.name,Y.subcommand?`${Y.command} ${Y.subcommand}`:Y.command,Y.blockArgs.join(", ")]);return Yn({headers:G,rows:K})}function Ra(P){let G=[];if(G.push("Configuration"),G.push(Om(P.userConfig,P.projectConfig)),G.push(""),P.effectiveRules.length>0)G.push(` Effective rules (${P.effectiveRules.length} total):`),G.push(Im(P.effectiveRules));else G.push(" Effective rules: (none - using built-in rules only)");return G.join(`
9
+ `)}function Om(P,G){let K=["Scope","Status"],Y=(X)=>{if(!X.exists)return Qe.dim("N/A");if(!X.valid)return Qe.red(`Invalid (${X.errors?.[0]??"unknown error"})`);return Qe.green("Configured")},Z=[["User",Y(P)],["Project",Y(G)]];return Yn({headers:K,rows:Z})}function Ea(P){let G=[];return G.push("Environment"),G.push($m(P)),G.join(`
10
+ `)}function Ta(P){let G=P.effectiveSafety.policyScopes,K=["Effective Safety",` Selected preset: ${P.effectiveSafety.selectedPreset}${G?` (${Or(G.levelScope)})`:""}`,` Effective: ${P.effectiveSafety.level}`],Y=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[Z,X]of Y){let ie=P.effectiveSafety.capabilities[Z],ae=ie.enabled?Qe.green("ON"):Qe.dim("OFF"),ge=ie.sources.length>0?` (${ie.sources.join(", ")})`:"";K.push(` ${X}: ${ae} via ${ie.source}${ge}`)}if(G&&G.weakenings.length>0){K.push(` Project policy deltas${G.weakeningsIgnored?" (ignored)":""}:`);for(let Z of G.weakenings)K.push(` ${Z}`)}K.push(` Stored rule customizations: ${P.effectiveSafety.ruleCounts.stored}`),K.push(` Effective rule customizations: ${P.effectiveSafety.ruleCounts.effective}`);for(let[Z,X]of Object.entries(P.effectiveSafety.ruleOverrides))K.push(` ${Z}: ${X}`);return K.join(`
11
+ `)}function Aa(P){let G=["Findings"];if(P.length===0)return G.push(" No findings from inspected doctor facts."),G.join(`
12
+ `);for(let K of P){let Y=`[${K.severity.toUpperCase()}] ${K.checkId}: ${mn(K.title)}`,Z=K.severity==="error"?Qe.red:K.severity==="warning"?Qe.yellow:Qe.blue;if(G.push(` ${Z(Y)}`),G.push(` ${mn(K.detail)}`),K.path)G.push(` Path: ${mn(K.path)}`);if(K.fixHint)G.push(` Fix: ${mn(K.fixHint)}`)}return G.join(`
13
+ `)}function $m(P){let G=["Variable","Status","Legacy"],K=P.map((Y)=>{let Z=Y.isSet?Qe.green("✓"):Qe.dim("✗"),X=Y.legacyName&&Y.legacyIsSet?`${Y.legacyName} ${Qe.green("✓")}`:Y.legacyName??"";return[Y.name,Z,X]});return Yn({headers:G,rows:K})}function _a(P){let G=[];if(P.totalBlocked===0)G.push("Recent Activity"),G.push(" No blocked commands in the last 7 days"),G.push(" Tip: This is normal for new installations");else G.push(`Recent Activity · last 7 days (${P.totalBlocked} blocked / ${P.sessionCount} sessions)`),G.push(Dm(P.recentEntries));if(P.unreadable>0)G.push(` Warning: ${P.unreadable} audit log ${P.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return G.join(`
14
+ `)}function Dm(P){let G=["Time","Command"],K=P.map((Y)=>{let Z=mn(Y.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),X=Z.length>40?`${Z.slice(0,37)}...`:Z;return[Y.relativeTime,X]});return Yn({headers:G,rows:K})}function Ia(P){let G=[];if(G.push("Update Check"),P.latestVersion===null&&!P.error)return G.push($r([["Status",Qe.dim("Skipped")],["Installed",P.currentVersion]])),G.join(`
15
+ `);if(P.error)return G.push($r([["Status",`${Qe.yellow("⚠")} Error`],["Installed",P.currentVersion],["Error",Qe.dim(P.error)]])),G.join(`
16
+ `);if(P.updateAvailable)return G.push($r([["Status",`${Qe.yellow("⚠")} Update Available`],["Current",P.currentVersion],["Latest",Qe.green(P.latestVersion??"")]])),G.push(""),G.push(" Run: bunx cc-safety-net@latest doctor"),G.push(" Or: npx cc-safety-net@latest doctor"),G.join(`
17
+ `);return G.push($r([["Status",`${Qe.green("✓")} Up to date`],["Version",P.currentVersion]])),G.join(`
18
+ `)}function $r(P){return Yn({rows:P})}function Oa(P){let G=[];return G.push("System Info"),G.push(Nm(P)),G.join(`
19
+ `)}function Nm(P){let G=["Component","Version"],K=(X)=>{if(X===null)return Qe.dim("not found");return X},Z=[{label:"cc-safety-net",value:P.version},...Er.map((X)=>({label:ln(X),value:P.versions[X]??null})),{label:"Node.js",value:P.nodeVersion},{label:"npm",value:P.npmVersion},{label:"Bun",value:P.bunVersion},{label:"Platform",value:P.platform}].map((X)=>[X.label,K(X.value)]);return Yn({headers:G,rows:Z})}function $a(P){if(P.findings.length===0)return Qe.green(`
20
+ No findings from inspected doctor facts.`);let G={error:P.findings.filter((X)=>X.severity==="error").length,warning:P.findings.filter((X)=>X.severity==="warning").length,info:P.findings.filter((X)=>X.severity==="info").length},K=["error","warning","info"].filter((X)=>G[X]>0).map((X)=>`${G[X]} ${X}`),Y=P.findings.length===1?"finding":"findings",Z=`
21
+ ${P.findings.length} ${Y}: ${K.join(", ")}.`;if(G.error>0)return Qe.red(Z);if(G.warning>0)return Qe.yellow(Z);return Qe.blue(Z)}import{lstatSync as Lm}from"node:fs";import{dirname as Xo}from"node:path";function Qo(P,G){try{let K=Lm(G);if(K.isSymbolicLink())return{kind:P,path:G,status:"unsafe",issues:["symlink"]};if(!K.isDirectory())return{kind:P,path:G,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:P,path:G,status:"unknown",issues:[]};let Y=[...K.uid!==process.getuid()?["ownership"]:[],...(K.mode&18)!==0?["permissions"]:[]];return{kind:P,path:G,status:Y.length>0?"unsafe":"safe",issues:Y}}catch(K){if(typeof K==="object"&&K!==null&&"code"in K&&K.code==="ENOENT")return{kind:P,path:G,status:"not-applicable",issues:[]};return{kind:P,path:G,status:"unknown",issues:[]}}}function Da(P,G){let K=U(P);return{directories:[Qo("policy",Xo(Xo(G))),Qo("config",Xo(G)),...K?[Qo("audit",K)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as jm}from"node:child_process";import{existsSync as Na}from"node:fs";import{delimiter as Fm,extname as Hm,join as Mm}from"node:path";import{stripVTControlCharacters as La}from"node:util";var Fa="2.6.18",Um=5000,Bm="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function un(){return Fa}function ei(P,G){let K=P[G];if(K)return K;let Y=Object.keys(P).find((Z)=>Z.toLowerCase()===G.toLowerCase()&&!!P[Z]);return Y?P[Y]:K}function Gm(P){return(ei(P,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((G)=>G.length>0)}function qm(P,G){let K=Hm(P)?[P]:[...Gm(G).map((Y)=>`${P}${Y}`),P];if(P.includes("/")||P.includes("\\"))return K.find((Y)=>Na(Y))??P;return(ei(G,"PATH")??"").split(Fm).flatMap((Y)=>K.map((Z)=>Mm(Y,Z))).find((Y)=>Na(Y))??P}function ja(P){if(!/[\s"&|<>^]/.test(P))return P;return`"${P.replace(/"/g,'""')}"`}function Zn(P,G){let[K,...Y]=P,Z=G[Bm]==="win32"?"win32":process.platform;if(!K||Z!=="win32")return{cmd:K??"",args:Y};let X=qm(K,G);if(!/\.(?:bat|cmd)$/i.test(X))return{cmd:X,args:Y};return{cmd:ei(G,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",ja(X),...Y.map(ja)].join(" ")]}}var Ft=async(P,G=Um)=>{let K=await Vm(P,{timeoutMs:G});if(K.code!==0)return null;return La(K.stdout).trim()||La(K.stderr).trim()||null};function Vm(P,G){let[K,...Y]=P;if(!K)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((Z)=>{try{let X=Zn([K,...Y],process.env),ie=jm(X.cmd,X.args,{stdio:["ignore","pipe","pipe"]}),ae=!1,ge="",ye="";ie.stdout.on("data",(_e)=>{ge+=_e.toString()}),ie.stderr.on("data",(_e)=>{ye+=_e.toString()});let Pe=(_e)=>{if(ae)return;ae=!0,clearTimeout(Re),Z(_e)},Re=setTimeout(()=>{ie.kill(),Pe({code:null,stdout:ge,stderr:ye})},G.timeoutMs);ie.on("close",(_e)=>{Pe({code:_e,stdout:ge,stderr:ye})}),ie.on("error",()=>{Pe({code:null,stdout:ge,stderr:ye})})}catch{Z({code:null,stdout:"",stderr:""})}})}function Dr(P){if(!P)return null;let G=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(P);if(G)return G[1]??null;let K=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(P);if(K)return K[1]??null;return P.split(`
22
+ `)[0]?.trim()||null}async function Nr(P,G=Ft,K=process.cwd()){let Y=Promise.all(Sn.map(async(Re)=>[Re.id,Dr(await G([...Re.probeCommand]))])),[Z,X,ie,ae,ge,ye,Pe]=await Promise.all([Y,Y.then(async(Re)=>{let _e=Re.find(([je])=>je==="opencode")?.[1];if(!_e?.startsWith("2.")||!P(_e))return null;let Ae=["--param",`location[directory]=${K}`],Ie=["opencode","api","integration.list",...Ae];return await G(Ie,30000),G(["opencode","api","plugin.list",...Ae],30000)}),G(["codex","plugin","list"],30000),G(["amp","plugins","list"],30000),G(["node","--version"]),G(["npm","--version"]),G(["bun","--version"])]);return{version:Fa,versions:Object.fromEntries(Z),codexPluginListOutput:ie,ampPluginListOutput:ae,openCodePluginListOutput:X,nodeVersion:Dr(ge),npmVersion:Dr(ye),bunVersion:Dr(Pe),platform:`${process.platform} ${process.arch}`}}function ni(P,G){if(G==="dev")return!1;let K=P.split(".").map(Number),Y=G.split(".").map(Number),[Z=0,X=0,ie=0]=K,[ae=0,ge=0,ye=0]=Y;if(Z!==ae)return Z>ae;if(X!==ge)return X>ge;return ie>ye}async function Bn(){let P=un(),G=new AbortController,K=setTimeout(()=>G.abort(),3000);try{let Y=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:G.signal});if(!Y.ok)return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${Y.status}`};let Z=await Y.json(),X=ni(Z.version,P);return{currentVersion:P,latestVersion:Z.version,updateAvailable:X}}catch(Y){return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:Y instanceof Error?Y.message:"Network error"}}finally{clearTimeout(K)}}import*as Ka from"node:readline";var Ba=(P)=>`\x1B[${P}B`,Km=(P)=>`\x1B[${P}A`;var Ha=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function Jm(P){return new Promise((G)=>setTimeout(G,P))}function zm(P,G,K){if(!K)return G(P);if(K.aborted)return Promise.resolve();return new Promise((Y,Z)=>{let X=()=>K.removeEventListener("abort",ie),ie=()=>{X(),Y()};K.addEventListener("abort",ie,{once:!0}),G(P).then(()=>{X(),Y()},(ae)=>{X(),Z(ae)})})}function Lr(P){return Math.max(0,Math.min(1,P))}function Ht(P){return Math.max(0,Math.min(255,Math.round(P)))}function ti(P){return P<=0.0031308?12.92*P:1.055*P**0.4166666666666667-0.055}function Wm(P,G,K){let Y=K*Math.PI/180,Z=G*Math.cos(Y),X=G*Math.sin(Y),ie=(P+0.3963377774*Z+0.2158037573*X)**3,ae=(P-0.1055613458*Z-0.0638541728*X)**3,ge=(P-0.0894841775*Z-1.291485548*X)**3;return{blue:Ht(ti(Lr(-0.0041960863*ie-0.7034186147*ae+1.707614701*ge))*255),green:Ht(ti(Lr(-1.2684380046*ie+2.6097574011*ae-0.3413193965*ge))*255),red:Ht(ti(Lr(4.0767416621*ie-3.3077115913*ae+0.2309699292*ge))*255)}}function ri(P,G){let K=(G*P*180/Math.PI%360+360)%360;return Wm(0.72,0.15,K)}function Ga(P,G=0.1){let K=ri(G,P);return`\x1B[38;2;${K.red};${K.green};${K.blue}m`}function Ym(P,G){return{blue:Ht(P.blue+(255-P.blue)*G),green:Ht(P.green+(255-P.green)*G),red:Ht(P.red+(255-P.red)*G)}}function qa(P,G,K){let Y=Math.imul(P+2654435769,2246822507)^Math.imul(G+3266489909,668265263)^Math.imul(K+374761393,2654435761),Z=Y^Y>>>15,X=Math.imul(Z,739982445),ie=X^X>>>12,ae=Math.imul(ie,695872825);return((ae^ae>>>15)>>>0)/4294967296}function Zm(P,G,K){let Y=Math.floor(qa(P,G,K)*Ha.length);return Ha[Y]??"░"}function Ma(P){let G=Lr(P);return G*G*G*(G*(G*6-15)+10)}function Xm(P){if(P.length===0)return"";let G=[],K=!1,Y="";for(let Z of P){let X=`${Z.red};${Z.green};${Z.blue}`;if(Z.bold!==K)G.push(Z.bold?"\x1B[1m":"\x1B[22m"),K=Z.bold;if(X!==Y)G.push(`\x1B[38;2;${X}m`),Y=X;G.push(Z.character)}return`${G.join("")}\x1B[22m\x1B[39m`}function Qm(P,G,K,Y,Z){return P.map((X,ie)=>({...ri(K,Y+G+ie/Z),bold:!1,character:X}))}function eg(P,G,K,Y,Z,X,ie,ae){let ge=Math.max(1,Y*0.75),ye=Math.min(1,K/ge),Pe=Z*Ma(ye),Re=Math.max(0,(K-ge)/Math.max(1,Y-ge)),_e=(1-Ma(K/Y))*ae*2,Ae=0.35*Math.max(0,1-Re*2),Ie=ye>=1,je=Math.min(P.length,Math.ceil(Pe+2+1));return P.slice(0,je).map((Oe,Ve)=>{let nn=ri(X,ie+G+Ve/ae+_e),rn=Ve+qa(G,Ve,7919)*2-1;if(rn>Pe+2)return{...nn,bold:!1,character:" "};let an=Pe-rn,en=0.8*Math.exp(-(an*an)/12.5),on=Math.min(0.9,en+Ae),xn=!Ie&&rn>Pe-4;return{...Ym(nn,on),bold:on>0.3,character:xn?Zm(G,Ve,K):Oe}})}function Ua(P){return`\x1B[?2026h${P.map((G,K)=>`\x1B8${K>0?Ba(K):""}${Xm(G)}`).join("")}\x1B[?2026l`}async function oi(P,G={}){if(!P)return;let K=G.output??process.stdout,Y=G.sleep??Jm,Z=G.seed??0,X=P.split(`
23
+ `).map((Pe)=>Array.from(Pe)),ie=Math.max(...X.map((Pe)=>Pe.length)),ae=12000*X.filter((Pe)=>Pe.length>0).length/40,ge=ie>0?Math.max(1,Math.ceil(ae/16.666666666666668)):0,ye=ge>0?ae/ge:0;K.write(`\x1B[?25l${X.length>1?`${`
24
+ `.repeat(X.length-1)}${Km(X.length-1)}`:""}\x1B7`);try{for(let Pe=1;Pe<=ge;Pe+=1){if(G.signal?.aborted)break;K.write(Ua(X.map((Re,_e)=>eg(Re,_e,Pe,ge,ie,0.1,Z,3)))),await zm(ye,Y,G.signal)}}finally{if(K.write(Ua(X.map((Pe,Re)=>Qm(Pe,Re,0.1,Z,3)))),K.write("\x1B8"),X.length>1)K.write(Ba(X.length-1));K.write(`
25
+ \x1B[0m\x1B[?25h`)}}var Va=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
+ `);function ng(P){return Boolean(P.isTTY)}async function nr(P={}){let G=P.output??process.stdout;if(!ng(G))return;let K=P.input??process.stdin,Y={output:G,seed:P.seed??Math.random()*8192,sleep:P.sleep};if(!K.isTTY||typeof K.setRawMode!=="function"){await oi(Va,Y);return}let Z=new AbortController,X=K.readableFlowing===!0,ie=K.isRaw===!0,ae=!1,ge=(ye,Pe)=>{if(Pe.ctrl&&Pe.name==="c")ae=!0;if(ae||Pe.name==="return"||Pe.name==="enter")Z.abort()};Ka.emitKeypressEvents(K),K.on("keypress",ge),K.setRawMode(!0),K.resume();try{await oi(Va,{...Y,signal:Z.signal})}finally{if(K.off("keypress",ge),K.setRawMode(ie),!X)K.pause()}if(!ae)return;if(P.onInterrupt){P.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as ig}from"node:crypto";import{existsSync as za}from"node:fs";import{dirname as jr,join as Wa}from"node:path";import{dirname as Ja,join as tg}from"node:path";var rg="rule.lock";function og(P){return tg(Ja(P),rg)}function hn(P,G){let K=G.global?G.userConfigPath??W(P,G):G.projectConfigPath??A(G.cwd??process.cwd()),Y=G.global?lt(P,G):ut(K,G.cwd??process.cwd()),Z=og(K);return{configDir:Ja(K),configPath:K,lockPath:Z,filesystemScope:Y,configTarget:i(Y,K),lockTarget:i(Y,Z)}}var sg="`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.",ag="cache",lg="rulebooks";function Ya(P,G={}){let K=hn(P,G),Y=i(K.filesystemScope,Xa(K.configDir)),Z=r(K.lockTarget);if(console.log(sg),Z===null&&!za(Y.path))return console.log(`No v2 lock or cache leftovers found in ${jr(K.configDir)}; nothing to migrate.`),0;let X=fg(Z),ie=d(K.configTarget);if(!ie.config&&(r(K.configTarget)!==null||X.size>0))return console.error(`Cannot migrate: the rules config in ${jr(K.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let ae=ie.config?.rules??[];for(let ge of ae.flatMap((ye)=>cg(ye,X,K,Y,G.global===!0)))console.log(ge);return B(K.lockTarget),Et(Y),console.log(`Removed the v2 lock and cache under ${jr(K.configDir)}.`),0}function Za(P,G){return[...new Set([{cwd:G},{cwd:G,global:!0}].flatMap((K)=>{let Y=hn(P,K);return[Y.lockPath,Xa(Y.configDir)]}))].filter((K)=>za(K))}function cg(P,G,K,Y,Z){if(!C(P))return[];let X=L(P).name,ie=i(K.filesystemScope,M(K.configDir,X)),ae=r(ie);if(ae!==null&&dg(ae,X))return[];let ge=G.get(P),ye=ge?ug(ge,X,Y.path,K.filesystemScope):null;if(ye===null)return[`Could not migrate ${P} from the v2 cache. Run \`cc-safety-net rule update ${P}${Z?" --global":""}\` to vendor it.`];if(h(ie,ye),ae!==null)return[`Restored ${P} from the v2 cache over an invalid file.`];return[`Vendored ${P} from the v2 cache.`]}function dg(P,G){let K=Ee(P);return!("problem"in K)&&K.rulebook.name===G}function ug(P,G,K,Y){let Z=Wa(K,lg,`${pg(P)}--${P.digest.replace("sha256:","").slice(0,12)}`,be),X=r(i(Y,Z));if(X===null||yg(X)!==P.digest)return null;let ie=Ee(X);if("problem"in ie||ie.rulebook.name!==G)return null;return X}function Xa(P){return Wa(jr(P),ag)}function pg(P){return([P.owner,P.repo,P.display_ref,P.name].every((Y)=>typeof Y==="string"&&Y!=="")?`${P.owner}/${P.repo}#${P.display_ref}/${P.name}`:P.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function fg(P){let G=P===null?null:gg(P),K=Qa(G)&&Array.isArray(G.rulebooks)?G.rulebooks:[];return new Map(K.filter(mg).map((Y)=>[Y.spec,Y]))}function mg(P){return Qa(P)&&typeof P.spec==="string"&&typeof P.digest==="string"}function Qa(P){return!!P&&typeof P==="object"}function gg(P){try{return JSON.parse(P)}catch{return null}}function yg(P){return`sha256:${ig("sha256").update(P).digest("hex")}`}var el="\r\x1B[2K",hg="\x1B[?25l",vg="\x1B[39m",bg="\x1B[?25h",wg=100,kg=0.55,Cg=80,nl=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function xg(P){return new Promise((G)=>setTimeout(G,P))}async function Fr(P,G={}){let K=G.output??process.stdout;if(!K.isTTY)return P;let Y=G.sleep??xg,Z=!1,X=P.then((ae)=>(Z=!0,ae),(ae)=>{throw Z=!0,ae});if(await Promise.race([X.then(()=>!0),Y(wg).then(()=>!1)]))return X;K.write(hg);try{for(let ae=0;!Z;ae+=1)K.write(`${el}${Ga(ae*kg)}${nl[ae%nl.length]}${vg} ${G.loadingMessage??"Loading…"}`),await Promise.race([X,Y(Cg)]);return await X}finally{K.write(`${el}${bg}`)}}async function tr(P,G,K,Y={}){let Z=G();if(P)await K();if(P&&Z.ready)await Fr(Z.ready,Y);return Z.finish()}import{stripVTControlCharacters as Pg}from"node:util";var Hr="amp plugins list",Sg=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function tl(P){if(!P.ampPluginListOutput)return{platform:"amp",status:"n/a"};let G=Pg(P.ampPluginListOutput).split(`
27
+ `).map((K)=>Sg.exec(K)?.[1]).find((K)=>K!==void 0);if(!G)return{platform:"amp",status:"n/a"};if(G!=="active")return{platform:"amp",status:"disabled",method:Hr,configPath:Hr,errors:[`Amp personal plugin cc-safety-net is ${G}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:Hr,configPath:Hr}}import{existsSync as Og,readFileSync as $g}from"node:fs";import{isAbsolute as bP,join as Ig}from"node:path";function rr(P){return Ig(P,".gemini","config","hooks.json")}var ol=new Map([["run_command","auto"]]),il="manage_task";var Dg=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Ng(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];return Object.values(P).flatMap((G)=>{if(!G||typeof G!=="object"||Array.isArray(G))return[];let K=G,Y=K.PreToolUse;if(!Array.isArray(Y))return[];return Y.flatMap((Z)=>{if(!Z||typeof Z!=="object"||Array.isArray(Z))return[];let X=Z.hooks;if(!Array.isArray(X))return[];return X.flatMap((ie)=>{if(!ie||typeof ie!=="object"||Array.isArray(ie))return[];let ae=ie.command;if(typeof ae!=="string"||!Dg.test(ae))return[];return[{command:ae,enabled:K.enabled!==!1}]})})})}function sl(P){let G=rr(P.environment.home);if(!Og(G))return{platform:"antigravity-cli",status:"n/a",configPath:G};let K;try{K=Ng(JSON.parse($g(G,"utf-8")))}catch(Y){return{platform:"antigravity-cli",status:"n/a",configPath:G,errors:[`Failed to parse Antigravity hooks config ${G}: ${Y instanceof Error?Y.message:String(Y)}`]}}if(K.some((Y)=>Y.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:G};if(K.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:G};return{platform:"antigravity-cli",status:"n/a",configPath:G}}import{existsSync as Mg}from"node:fs";import{join as Ln}from"node:path";import{existsSync as Lg,lstatSync as jg,readFileSync as Fg}from"node:fs";import{join as Hg}from"node:path";function yn(P,G=(K)=>K){if(!Lg(P))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(G(Fg(P,"utf-8")))}}catch{return{kind:"unreadable"}}}function Nn(P,G){if(P==="~")return G;if(P.startsWith("~/")||P.startsWith("~\\"))return Hg(G,P.slice(2));return P}function cn(P){try{return jg(P)}catch{return}}function Gr(P,G){let K=cn(G);if(!K)return{platform:P,status:"n/a",configPath:G};if(!K.isSymbolicLink()&&K.isDirectory())return;return{platform:P,status:"n/a",configPath:G,errors:[`${G} is a symlink or not a directory; move or remove it before installing`]}}function Fe(P,G){return typeof P==="object"&&P!==null?P[G]:void 0}var qr="cc-safety-net@cc-marketplace";function Vr(P){return P.env.get("CLAUDE_CONFIG_DIR")||Ln(P.home,".claude")}function al(P){return Ln(P.env.get("CLAUDE_CODE_PLUGIN_CACHE_DIR")||Ln(Vr(P),"plugins"),"installed_plugins.json")}function ll(P,G){let K=Fe(Fe(P,"plugins"),G);return Array.isArray(K)&&K.length>0}function Kr(P,G){let K=yn(al(P));return K.kind==="ok"&&ll(K.value,G)}function ai(P){return cl(al(P),Ln(Vr(P),"settings.json"))}function cl(P,G){let K=yn(P);if(K.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(K.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!ll(K.value,qr))return{platform:"claude-code",status:"n/a"};let Y=yn(G);if(Y.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(Y.kind==="ok"&&Fe(Fe(Y.value,"enabledPlugins"),qr)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:G,errors:[`${qr} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:P}}function dl(P){let G=Ln(P.home,".claude"),K=Ln(G,"plugins","installed_plugins.json");if(cl(K,Ln(G,"settings.json")).status!=="configured")return;let Y=yn(K),Z=Y.kind==="ok"?Fe(Fe(Y.value,"plugins"),qr):void 0,X=(Array.isArray(Z)?Z:[]).filter((ye)=>Fe(ye,"scope")==="user").map((ye)=>Fe(ye,"installPath")).find((ye)=>typeof ye==="string");if(!X)return;let ie=Ln(X,".cursor-plugin","plugin.json"),ae=yn(ie),ge=ae.kind==="ok"?Fe(ae.value,"hooks"):void 0;return typeof ge==="string"&&Mg(Ln(X,ge))?ie:void 0}function ul(P){return ai(P.environment)}var pl="Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it.";function fl(P){if(!P.codexPluginListOutput)return{platform:"codex",status:"n/a"};let G=P.codexPluginListOutput.split(`
28
+ `).find((K)=>K.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!G)return{platform:"codex",status:"n/a"};if(!G.includes("installed,"))return{platform:"codex",status:"n/a"};if(!G.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex runs only trusted hooks, and doctor cannot check trust. Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."]}}import{existsSync as Yr,readdirSync as Ug,readFileSync as Bg}from"node:fs";import{join as bn}from"node:path";function gn(P){let G="",K=0,Y=!1,Z=!1,X=-1;while(K<P.length){let ie=P[K],ae=P[K+1];if(Z){G+=ie,Z=!1,K++;continue}if(ie==='"'&&!Y){Y=!0,X=-1,G+=ie,K++;continue}if(ie==='"'&&Y){Y=!1,G+=ie,K++;continue}if(ie==="\\"&&Y){Z=!0,G+=ie,K++;continue}if(Y){G+=ie,K++;continue}if(ie==="/"&&ae==="/"){while(K<P.length&&P[K]!==`
29
+ `)K++;continue}if(ie==="/"&&ae==="*"){K+=2;while(K<P.length-1){if(P[K]==="*"&&P[K+1]==="/"){K+=2;break}K++}continue}if(ie===","){X=G.length,G+=ie,K++;continue}if(ie==="}"||ie==="]"){if(X!==-1){let ge=G.slice(X+1);if(/^\s*$/.test(ge))G=G.slice(0,X)+ge}X=-1,G+=ie,K++;continue}if(!/\s/.test(ie))X=-1;G+=ie,K++}return G}function gl(P,G,K){let Y=G+1,Z=!1;while(Y<P.length){if(Z){Z=!1,Y++;continue}if(P[Y]==="\\"){Z=!0,Y++;continue}if(P[Y]==='"')return Y+1;Y++}throw Error(K)}function ci(P,G,K){let Y=P[G],Z=Y==="["?"]":"}",X=0,ie=G;while(ie<P.length){let ae=K.skipComment?.(P,ie)??ie;if(ae!==ie){ie=ae;continue}if(P[ie]==='"'){ie=gl(P,ie,K.stringError);continue}if(P[ie]===Y)X++;if(P[ie]===Z){if(X--,X===0)return ie}ie++}throw Error(K.bracketError)}function yl(P,G){let K=P.lastIndexOf(`
30
+ `,G)+1;return/^[ \t]*/.exec(P.slice(K))?.[0]??""}function hl(P,G){let K=G.end+(/^\s*/.exec(P.slice(G.end))?.[0].length??0);if(P[K]===","){let ie=P[K+1]===`
31
+ `?K+2:K+1;return`${P.slice(0,G.start)}${P.slice(ie)}`}let Y=P.slice(0,G.start).search(/\s*$/)-1;if(P[Y]!==",")return`${P.slice(0,G.start)}${P.slice(G.end)}`;let Z=P.lastIndexOf(`
32
+ `,Y-1),X=Z!==-1&&/^\s*$/.test(P.slice(Z+1,Y))?Z:Y;return`${P.slice(0,X)}${P.slice(G.end)}`}function li(P,G){if(P.startsWith("//",G)){let K=P.indexOf(`
33
+ `,G+2);return K===-1?P.length:K+1}if(P.startsWith("/*",G)){let K=P.indexOf("*/",G+2);return K===-1?P.length:K+2}return G}function ml(P,G){let K=G;while(K<P.length){if(/\s/.test(P[K]??"")){K++;continue}let Y=li(P,K);if(Y===K)return K;K=Y}return K}function vl(P,G,K){let Y=0,Z=0;while(Z<P.length){let X=li(P,Z);if(X!==Z){Z=X;continue}if(P[Z]==='"'){let ie=gl(P,Z,K.stringError);if(Y===1&&JSON.parse(P.slice(Z,ie))===G){let ae=ml(P,ie),ge=ml(P,ae+1);if(P[ae]===":"&&P[ge]==="[")return{start:ge,end:ci(P,ge,{skipComment:li,...K})}}Z=ie;continue}if(P[Z]==="{"||P[Z]==="[")Y++;if(P[Z]==="}"||P[Z]==="]")Y--;Z++}return}var An="cc-safety-net@cc-marketplace",Jr=["cc-marketplace","cc-safety-net"],bl=["_direct","copilot-safety-net"],wl=["cc-marketplace","safety-net"],kl="safety-net@cc-marketplace";function zr(P,G){let K=G.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${K}([^a-z0-9-]|$)`,"m").test(P??"")}function Cl(P){return zr(P,"cc-safety-net@cc-marketplace")}function xl(P){return zr(P,"cc-marketplace")}function Pl(P){return zr(P,"copilot-safety-net")}function Sl(P){return zr(P,"safety-net@cc-marketplace")}function Wr(P){if(!P?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(P)}function El(P,G){if(!P)return null;let K=P.match(/(\d+)\.(\d+)\.(\d+)/);if(!K)return null;let Y=[Number(K[1]),Number(K[2]),Number(K[3])];for(let Z=0;Z<G.length;Z++){let X=Y[Z]??0,ie=G[Z]??0;if(X!==ie)return X>ie}return!0}function Gg(P){return El(P,[0,0,422])}function qg(P){return El(P,[1,0,8])}function sr(P){return P.env.get("COPILOT_HOME")||bn(P.home,".copilot")}function Tl(P){return P.disableAllHooks!==!0&&Al(P)}function Al(P){return(P.hooks?.preToolUse??[]).some((K)=>{if(K.type!==void 0&&K.type!=="command")return!1;return Wr(K.command)||Wr(K.bash)||Wr(K.powershell)||Wr(K.exec&&[K.exec,...K.args??[]].join(" "))})}function or(P){return P===void 0||typeof P==="string"}function Vg(P){return P===void 0||Array.isArray(P)&&P.every((G)=>typeof G==="string")}function Kg(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let G=P;if(G.disableAllHooks!==void 0&&typeof G.disableAllHooks!=="boolean")return!1;if(G.hooks===void 0)return!0;if(!G.hooks||typeof G.hooks!=="object"||Array.isArray(G.hooks))return!1;let K=G.hooks.preToolUse;if(K===void 0)return!0;return Array.isArray(K)&&K.every((Y)=>Y!==null&&typeof Y==="object"&&!Array.isArray(Y)&&or(Y.type)&&or(Y.command)&&or(Y.bash)&&or(Y.powershell)&&or(Y.exec)&&Vg(Y.args))}function di(P,G){try{let K=JSON.parse(gn(Bg(P,"utf-8")));if(!Kg(K)){G?.push(`Invalid hook config ${P}: hooks.preToolUse must be an array of hook objects`);return}return K}catch(K){G?.push(`Failed to parse ${P}: ${K instanceof Error?K.message:String(K)}`);return}}function _l(P,G){try{return Ug(P).filter((K)=>K.endsWith(".json")).sort((K,Y)=>K.localeCompare(Y))}catch(K){return G?.push(`Failed to read ${P}: ${K instanceof Error?K.message:String(K)}`),[]}}function Jg(P,G){if(!Yr(P))return[];let K=[];for(let Y of _l(P,G)){let Z=bn(P,Y),X=di(Z,G);if(X&&Tl(X))K.push(Z)}return K}function ir(P,G){if(!Yr(P))return;let K=di(P,G);if(!K)return;return{path:P,config:K}}function Rl(P,G,K,Y){if(G){P.push(`GitHub Copilot CLI ${G} does not support ${K}; requires ${Y}+`);return}P.push(`GitHub Copilot CLI version unavailable; skipping ${K} because it requires ${Y}+`)}function zg(P){for(let G of P){if(G?.config.disableAllHooks===!0)return G.path;if(G?.config.disableAllHooks===!1)return}return}function Wg(P,G,K,Y){let Z=sr(P),X=bn(G,".github","hooks"),ie=bn(Z,"hooks"),ae=bn(G,".github","copilot"),ge=bn(G,".claude"),ye=qg(K),Pe=ye===!0?Y:void 0,Re=[ir(bn(ae,"settings.local.json"),Pe),ir(bn(ae,"settings.json"),Pe),ir(bn(ge,"settings.local.json"),Pe),ir(bn(ge,"settings.json"),Pe)],_e=ir(bn(Z,"settings.json"),Pe),Ae=[_e?.config.disableAllHooks===!0?void 0:_e];if(ye!==!1){let en=zg(Re);if(en){if(ye===null)Y.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${en} as active`);return{activeConfigPaths:[],repoInlineSources:Re,disabledBy:en}}}let Ie=Jg(X,Y),je=Gg(K),Oe=je===!0?Y:void 0,Ve=Yr(ie)?_l(ie,Oe):[],nn=[];for(let en of Ve){let on=bn(ie,en),xn=di(on,Oe);if(xn&&Tl(xn))nn.push(on)}if(je!==!0&&nn.length>0)Rl(Y,K,`user hook files in ${ie}`,"0.0.422"),nn.length=0;let rn=[];for(let en of[...Re,...Ae]){if(!en)continue;if(!Al(en.config))continue;if(ye===!0){rn.push(en);continue}Rl(Y,K,"inline hook definitions in Copilot config files","1.0.8");break}let an=(en)=>en.filter((on)=>!!on&&rn.includes(on)).map((on)=>on.path);return{activeConfigPaths:[...an(Re),...Ie,...an(Ae),...nn],repoInlineSources:Re}}function Il(P){let G=[],K=Wg(P.environment,P.cwd,P.copilotCliVersion,G);if(K.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:K.disabledBy,configPaths:[K.disabledBy],errors:G.length>0?G:void 0};let Y=sr(P.environment),Z=bn(Y,"installed-plugins",...Jr),X=Yr(Z),ie=bn(Y,"settings.json"),ae=yn(ie,gn),ge=(Ae)=>Fe(Fe(Ae,"enabledPlugins"),An),ye=K.repoInlineSources.find((Ae)=>typeof ge(Ae?.config)==="boolean"),Pe=ye??(ae.kind==="ok"?{path:ie,config:ae.value}:void 0);if(X&&!ye&&ae.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};let Re=X&&Pe!==void 0&&ge(Pe.config)===!1;if(Re&&K.activeConfigPaths.length===0)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:Pe.path,errors:[`${An} is installed but not enabled in Copilot CLI`]};let _e=X&&!Re;if(_e||K.activeConfigPaths.length>0){let Ae=K.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:_e?"plugin config":"hook config",configPath:Ae??(_e?Z:void 0),configPaths:K.activeConfigPaths.length>0?K.activeConfigPaths:void 0,errors:G.length>0?G:void 0}}return{platform:"copilot-cli",status:"n/a",errors:G.length>0?G:void 0}}import{existsSync as vi,readdirSync as cy,readFileSync as dy}from"node:fs";import{join as hi}from"node:path";import{existsSync as gi,mkdirSync as ty,readFileSync as ry,rmSync as oy}from"node:fs";import{dirname as iy,join as Zr}from"node:path";import{existsSync as Yg,renameSync as Zg,statSync as Xg,writeFileSync as Qg}from"node:fs";function sn(P,G){let K=`${P}.${process.pid}.tmp`;Qg(K,G,Yg(P)?{mode:Xg(P).mode&511}:{}),Zg(K,P)}import{spawn as ey}from"node:child_process";function ny(P){return P.join(" ")}function ui(P,G,K){return[`Failed to run ${ny(P)}${G===null?"":` (exit ${G})`}.`,K.trim()].filter(Boolean).join(`
34
+ `)}function pi(P){let G={stdout:"",stderr:""};return P.stdout.setEncoding("utf-8"),P.stderr.setEncoding("utf-8"),P.stdout.on("data",(K)=>{G.stdout+=K}),P.stderr.on("data",(K)=>{G.stderr+=K}),G}function pn(P,G){return new Promise((K,Y)=>{let Z=Zn([...P],process.env),X=ey(Z.cmd,Z.args,{stdio:["ignore","pipe","pipe"]}),ie=pi(X),ae=()=>[ie.stdout,ie.stderr].filter(Boolean).join(`
35
+ `),ge=G?.timeoutMs??120000,ye=setTimeout(()=>{X.kill(),Y(Error(ui(P,null,`Timed out after ${ge}ms.
36
+ ${ae()}`.trim())))},ge);X.on("error",(Pe)=>{clearTimeout(ye),Y(Error(ui(P,null,`${Pe.message}
37
+ ${ae()}`.trim())))}),X.on("close",(Pe)=>{if(clearTimeout(ye),Pe!==0){Y(Error(ui(P,Pe,ae())));return}K(G?.stdoutOnly?ie.stdout:ae())})})}async function fi(P){for(let G of P)await pn(G)}async function Ol(P){for(let G of P)try{await pn(G)}catch(K){console.warn(K instanceof Error?K.message:String(K))}}var wn=Object.fromEntries(er.map((P)=>[P.id,`npx -y cc-safety-net hook ${P.flags[1]}`]));var lr=wn.cursor,$l=30;function Qr(P){return Zr(P.home,".cursor","hooks.json")}var ar="cc-safety-net";function yi(P){let G=Zr(P.home,".cursor","plugins");return{cache:Zr(G,"cache",ar),marketplaceClone:Zr(G,"marketplaces","github.com","kenryu42","cc-safety-net")}}async function Dl(P){let G=Object.values(yi(P));if(!G.some((Y)=>gi(Y)))return;let K="No marketplace matches";return await pn(["cursor-agent","plugin","marketplace","remove",ar]).catch((Y)=>{if(!(Y instanceof Error&&Y.message.includes(K)))throw Y}),G.forEach((Y)=>oy(Y,{recursive:!0,force:!0})),[`Removed the ${ar} marketplace from your Cursor account.`,"If /plugins in cursor-agent still lists CC Safety Net as installed, uninstall it there."].join(`
38
+ `)}function Qn(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function mi(){return{command:lr,timeout:$l,failClosed:!0}}function Xr(P){return Qn(P)&&P.command===lr}function sy(P){return Object.keys(P).length===3&&P.command===lr&&P.timeout===$l&&P.failClosed===!0}function ay(P){try{return JSON.parse(ry(P,"utf-8"))}catch(G){if(G instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${P}: ${G.message}`);throw G}}function Nl(P){let G=ay(P);if(!Qn(G))throw Error(`Cursor hooks config ${P} must be a JSON object`);if(G.version!==1)throw Error(`Cursor hooks config ${P} must set "version": 1`);if(G.hooks!==void 0&&!Qn(G.hooks))throw Error(`Cursor hooks config ${P} "hooks" must be an object`);let K=Qn(G.hooks)?G.hooks.preToolUse:void 0;if(K!==void 0&&!Array.isArray(K))throw Error(`Cursor hooks config ${P} "hooks.preToolUse" must be an array`);return G}function Ll(P){let G=Qn(P.hooks)?P.hooks.preToolUse:void 0;return Array.isArray(G)?G:[]}function ly(P){if(!P.some(Xr))return[...P,mi()];return P.reduce((G,K)=>{if(!Xr(K))return G.result.push(K),G;if(!G.inserted)G.result.push(mi()),G.inserted=!0;return G},{result:[],inserted:!1}).result}function jl(P,G,K){let Y=Qn(G.hooks)?G.hooks:{},Z={...G,hooks:{...Y,preToolUse:K}};sn(P,`${JSON.stringify(Z,null,2)}
39
+ `)}function Fl(P){let G=Qr(P);if(!gi(G))return ty(iy(G),{recursive:!0}),sn(G,`${JSON.stringify({version:1,hooks:{preToolUse:[mi()]}},null,2)}
40
+ `),{path:G,alreadyInstalled:!1};let K=Nl(G),Y=Ll(K),Z=Y.filter(Xr);if(Qn(K.hooks)&&Array.isArray(K.hooks.preToolUse)&&Z.length===1&&Z[0]!==void 0&&sy(Z[0]))return{path:G,alreadyInstalled:!0};return jl(G,K,ly(Y)),{path:G,alreadyInstalled:!1}}function Hl(P){let G=Qr(P);if(!gi(G))return{path:G,alreadyInstalled:!1};let K=Nl(G),Y=Ll(K),Z=Y.filter((X)=>!Xr(X));if(Z.length===Y.length)return{path:G,alreadyInstalled:!1};return jl(G,K,Z),{path:G,alreadyInstalled:!0}}function uy(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];let G=P.hooks;if(!G||typeof G!=="object"||Array.isArray(G))return[];let K=G.preToolUse;if(!Array.isArray(K))return[];return K.filter((Y)=>!!Y&&typeof Y==="object"&&!Array.isArray(Y)&&Y.command===lr)}function py(P){let G=[];if(P.length>1)G.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let K=P[0];if(K&&K.failClosed!==!0)G.push('Managed hook is missing "failClosed": true; reinstall to repair');if(K&&K.timeout!==30)G.push('Managed hook "timeout" is not 30; reinstall to repair');return G}var eo="Claude Code plugin",bi="Cursor plugin";function fy(P){let G=hi(yi(P).cache,ar);if(!vi(G))return{};try{return{version:cy(G).map((K)=>hi(G,K)).find((K)=>vi(hi(K,".cache-complete")))}}catch{return{unreadable:G}}}function my(P,G){if(G){let Z=["Cursor records enabled plugins on your Cursor account, which doctor cannot check, and keeps a plugin's files after it is uninstalled.","Cursor pins marketplace plugins to the commit they were added at, so `cc-safety-net update` cannot update this plugin, while the npx hook (`cc-safety-net install --cursor`) stays current."].join(" ");return{method:bi,configPath:G,duplicate:`The Cursor plugin also runs this check, so every tool call is checked twice. ${Z} If the plugin is installed, run \`cc-safety-net uninstall --cursor\`, uninstall CC Safety Net from /plugins in cursor-agent, then run \`cc-safety-net install --cursor\`.`,alone:`${Z} If /plugins in cursor-agent does not list CC Safety Net as installed, run \`cc-safety-net install --cursor\`.`}}let K=dl(P);if(!K)return;let Y="Cursor runs the Claude Code plugin only while it imports Claude Code plugins, which doctor cannot check.";return{method:eo,configPath:K,duplicate:`The Claude Code plugin also runs this check in Cursor, so every tool call is checked twice. ${Y} If Cursor runs it, run \`cc-safety-net uninstall --cursor\` to remove this hook.`,alone:`${Y} If it stops, run \`cc-safety-net install --cursor\`.`}}function Ml(P){let G=gy(P),K=fy(P.environment);if(K.unreadable)return G.status==="configured"?{...G,errors:[...G.errors??[],`Cannot read ${K.unreadable}, so doctor cannot tell whether the Cursor plugin also runs this check.`]}:{platform:"cursor",status:"not-inspected"};let Y=my(P.environment,K.version);if(!Y)return G;if(G.status==="configured")return{...G,errors:[...G.errors??[],Y.duplicate]};return{platform:"cursor",status:"configured",method:Y.method,configPath:Y.configPath,errors:[...G.errors??[],Y.alone]}}function gy(P){let G=Qr(P.environment);if(!vi(G))return{platform:"cursor",status:"n/a",configPath:G};let K;try{K=JSON.parse(dy(G,"utf-8"))}catch(X){return{platform:"cursor",status:"n/a",configPath:G,errors:[`Failed to parse Cursor hooks config ${G}: ${X instanceof Error?X.message:String(X)}`]}}let Y=uy(K);if(Y.length===0)return{platform:"cursor",status:"n/a",configPath:G};let Z=py(Y);return{platform:"cursor",status:"configured",method:"hook config",configPath:G,errors:Z.length>0?Z:void 0}}import{readdirSync as yy}from"node:fs";import{join as wi,resolve as hy}from"node:path";var ki="cc-safety-net";function Ci(P){let G=P.env.get("DSH_HOME");return wi(G?.trim()?hy(Nn(G,P.home)):wi(P.home,".dsh"),"profiles")}function Ul(P){let G=Ci(P),K=cn(G)?.isDirectory()?yy(G,{withFileTypes:!0}).filter((Z)=>Z.isDirectory()&&Z.name!=="node_modules").map((Z)=>{let X=wi(G,Z.name,"package.json");return{name:Z.name,configPath:X,manifest:yn(X)}}):[];return{installed:K.flatMap((Z)=>{if(Z.manifest.kind!=="ok")return[];let X=Z.manifest.value;if(Fe(Fe(X,"dependencies"),ki)===void 0)return[];let ie=Fe(Fe(Fe(X,"dsh"),"profile"),"bundles");return[{name:Z.name,configPath:Z.configPath,enabled:Array.isArray(ie)&&ie.includes(ki)}]}),unreadable:K.some((Z)=>Z.manifest.kind==="unreadable")}}function xi(P){return Ul(P).installed}function Bl(P){let G=Ul(P.environment),K=G.installed.filter((X)=>X.enabled),Y=G.installed.filter((X)=>!X.enabled),Z=Y.map((X)=>`${ki} is installed in the ${X.name} profile but its bundle is disabled`);if(K.length>0)return{platform:"deepseek-harness",status:"configured",method:"dsh bundle",configPaths:K.map((X)=>X.configPath),...Z.length>0?{errors:Z}:{}};if(Y.length>0)return{platform:"deepseek-harness",status:"disabled",method:"dsh bundle",configPaths:Y.map((X)=>X.configPath),errors:Z};return G.unreadable?{platform:"deepseek-harness",status:"not-inspected"}:{platform:"deepseek-harness",status:"n/a"}}import{existsSync as xy}from"node:fs";import{existsSync as Vl,mkdirSync as vy,readFileSync as by}from"node:fs";import{dirname as wy,join as Ri}from"node:path";function Pi(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Si(P,G){return Pi(P)&&P.command===G}function Gl(P,G){return Pi(P)&&Array.isArray(P.hooks)&&P.hooks.some((K)=>Si(K,G))}function et(P,G){return{hooks:[{type:"command",command:P,timeout:G}]}}function jn(P,G){return P.flatMap((K)=>{if(!Pi(K)||!Array.isArray(K.hooks))return[K];let Y=K.hooks.filter((Z)=>!Si(Z,G));if(Y.length===K.hooks.length)return[K];return Y.length===0?[]:[{...K,hooks:Y}]})}function Mt(P,G,K){let Y=P.filter((Z)=>Gl(Z,G));return Y.length===1&&JSON.stringify(Y[0])===JSON.stringify(et(G,K))}function Ut(P,G){return P.find((K)=>Gl(K,G))}function Bt(P,G,K){let Y=Array.isArray(P.hooks)?P.hooks.find((Z)=>Si(Z,G)):void 0;return[...P.matcher===void 0||P.matcher===""||P.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...Y?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...Y?.timeout===K?[]:[`Managed hook "timeout" is not ${K}; reinstall to repair`]]}var at=wn.devin,no=30,ky={config:{},hooks:{},preToolUse:[]};function to(P,G=process.platform){let K=G==="win32"?P.env.get("APPDATA")||Ri(P.home,"AppData","Roaming"):P.env.get("XDG_CONFIG_HOME")||Ri(P.home,".config");return Ri(K,"devin","config.json")}function ql(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Cy(P){try{return{ok:!0,value:JSON.parse(gn(by(P,"utf-8")))}}catch(G){return{ok:!1,message:G instanceof Error?G.message:String(G)}}}function Ei(P){let G=Cy(P);if(!G.ok)return`Failed to parse Devin CLI config ${P}: ${G.message}`;let K=G.value;if(!ql(K))return`Devin CLI config ${P} must be a JSON object`;let Y=K.hooks===void 0?{}:K.hooks;if(!ql(Y))return`Devin CLI config ${P} "hooks" must be an object`;let Z=Y.PreToolUse===void 0?[]:Y.PreToolUse;if(!Array.isArray(Z))return`Devin CLI config ${P} "hooks.PreToolUse" must be an array`;return{config:K,hooks:Y,preToolUse:Z}}function Kl(P){let G=Ei(P);if(typeof G==="string")throw Error(G);return G}function Jl(P,G,K){let Y={...G.config,hooks:{...G.hooks,PreToolUse:K}};sn(P,`${JSON.stringify(Y,null,2)}
41
+ `)}function zl(P){let G=to(P),K=Vl(G)?Kl(G):ky;if(Mt(K.preToolUse,at,no))return{path:G,alreadyInstalled:!0};return vy(wy(G),{recursive:!0}),Jl(G,K,[...jn(K.preToolUse,at),et(at,no)]),{path:G,alreadyInstalled:!1}}function Wl(P){let G=to(P);if(!Vl(G))return{path:G,alreadyInstalled:!1};let K=Kl(G),Y=jn(K.preToolUse,at);if(JSON.stringify(Y)===JSON.stringify(K.preToolUse))return{path:G,alreadyInstalled:!1};return Jl(G,K,Y),{path:G,alreadyInstalled:!0}}function Yl(P){let G=to(P.environment);if(!xy(G))return{platform:"devin",status:"n/a",configPath:G};let K=Ei(G);if(typeof K==="string")return{platform:"devin",status:"n/a",configPath:G,errors:[K]};let Y=Ut(K.preToolUse,at);if(!Y)return{platform:"devin",status:"n/a",configPath:G};let Z=Bt(Y,at,no);return{platform:"devin",status:"configured",method:"hook config",configPath:G,errors:Z.length>0?Z:void 0}}import{existsSync as _y,readFileSync as Iy}from"node:fs";import{existsSync as Gt,mkdirSync as Py,readFileSync as Sy,rmSync as Ry}from"node:fs";import{dirname as Ey,join as Ai}from"node:path";var yt=wn.droid,ro=30;function oo(P){return Ai(P.home,".factory","hooks.json")}function Zl(P){return Ai(P.home,".factory","settings.json")}function Xl(P){return Ai(P.home,".factory","hooks","hooks.json")}function Ti(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Ql(P){try{return JSON.parse(gn(Sy(P,"utf-8")))}catch(G){if(G instanceof SyntaxError)throw Error(`Failed to parse Factory Droid hooks config ${P}: ${G.message}`);throw G}}function _i(P){let G=Ql(P);if(!Ti(G))throw Error(`Factory Droid hooks config ${P} must be a JSON object`);if(G.PreToolUse===void 0||Array.isArray(G.PreToolUse))return G;throw Error(`Factory Droid hooks config ${P} "PreToolUse" must be an array`)}function Ty(P){if(!Gt(P))return{};let G=Ql(P);return Ti(G)&&Ti(G.hooks)&&G.hooks.PreToolUse!==void 0?{PreToolUse:G.hooks.PreToolUse}:{}}function Ay(P){let G=Xl(P);return{...Ty(Zl(P)),...Gt(G)?_i(G):{}}}function ec(P){return Array.isArray(P.PreToolUse)?P.PreToolUse:[]}function nc(P,G,K){sn(P,`${JSON.stringify({...G,PreToolUse:K},null,2)}
42
+ `)}function tc(P){let G=oo(P),K=Gt(G),Y=K?_i(G):Ay(P),Z=ec(Y);if(K&&Mt(Z,yt,ro))return{path:G,alreadyInstalled:!0};return Py(Ey(G),{recursive:!0}),nc(G,Y,[...jn(Z,yt),et(yt,ro)]),{path:G,alreadyInstalled:!1}}function rc(P){let G=oo(P);if(!Gt(G))return{path:G,alreadyInstalled:!1};let K=_i(G),Y=ec(K),Z=jn(Y,yt);if(JSON.stringify(Z)===JSON.stringify(Y))return{path:G,alreadyInstalled:!1};let X=Gt(Zl(P))||Gt(Xl(P));if(Z.length===0&&Object.keys(K).length===1&&!X)return Ry(G),{path:G,alreadyInstalled:!0};return nc(G,K,Z),{path:G,alreadyInstalled:!0}}function oc(P){let G=oo(P.environment);if(!_y(G))return{platform:"droid",status:"n/a",configPath:G};let K;try{K=JSON.parse(gn(Iy(G,"utf-8")))}catch(ie){return{platform:"droid",status:"n/a",configPath:G,errors:[`Failed to parse Factory Droid hooks config ${G}: ${ie instanceof Error?ie.message:String(ie)}`]}}let Y=typeof K==="object"&&K!==null&&"PreToolUse"in K?K.PreToolUse:void 0,Z=Ut(Array.isArray(Y)?Y:[],yt);if(!Z)return{platform:"droid",status:"n/a",configPath:G};let X=[...Z.commandRegex===void 0||Z.commandRegex===""?[]:['Managed hook has a "commandRegex" that narrows coverage; reinstall to repair'],...Bt(Z,yt,ro)];return{platform:"droid",status:"configured",method:"hook config",configPath:G,errors:X.length>0?X:void 0}}import{existsSync as Oy}from"node:fs";import{join as Ii}from"node:path";var Oi="gemini-safety-net";function $i(P){let G=Ii(P.home,".gemini","extensions"),K=Ii(G,Oi);if(!Oy(K))return{platform:"gemini-cli",status:"n/a"};let Y=Ii(G,"extension-enablement.json"),Z=yn(Y);if(Z.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let X=Z.kind==="ok"?Fe(Fe(Z.value,Oi),"overrides"):void 0;if(Array.isArray(X)&&X.some((ae)=>typeof ae==="string"&&ae.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:Y,errors:[`${Oi} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:K}}function ic(P){return $i(P.environment)}import{existsSync as Ly,readFileSync as mc,statSync as jy}from"node:fs";import{dirname as fc,join as Fy}from"node:path";import{existsSync as ac,mkdirSync as $y,readFileSync as lc,rmSync as Dy}from"node:fs";import{dirname as Ny,join as sc}from"node:path";var Gn=wn["grok-build"],so=30,Di=et(Gn,so);function ao(P){return sc(P.env.get("GROK_HOME")??sc(P.home,".grok"),"hooks","cc-safety-net.json")}function lo(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function cc(P){try{let G=JSON.parse(P);return lo(G)?G:null}catch{return null}}function dc(P){let G=lo(P.hooks)?P.hooks.PreToolUse:void 0;return Array.isArray(G)?G:[]}function io(P,G,K){let Y=lo(G.hooks)?G.hooks:{};sn(P,`${JSON.stringify({...G,hooks:{...Y,PreToolUse:K}},null,2)}
43
+ `)}function uc(P){let G=ao(P);if(!ac(G))return $y(Ny(G),{recursive:!0}),io(G,{},[Di]),{path:G,alreadyInstalled:!1};let K=cc(lc(G,"utf-8"));if(!K)return io(G,{},[Di]),{path:G,alreadyInstalled:!1};let Y=dc(K);if(Mt(Y,Gn,so))return{path:G,alreadyInstalled:!0};return io(G,K,[...jn(Y,Gn),Di]),{path:G,alreadyInstalled:!1}}function pc(P){let G=ao(P);if(!ac(G))return{path:G,alreadyInstalled:!1};let K=cc(lc(G,"utf-8"));if(!K)return{path:G,alreadyInstalled:!1};let Y=dc(K),Z=jn(Y,Gn);if(JSON.stringify(Z)===JSON.stringify(Y))return{path:G,alreadyInstalled:!1};let X=lo(K.hooks)?K.hooks:{};if(Z.length===0&&Object.keys(K).length===1&&Object.keys(X).length===1)return Dy(G),{path:G,alreadyInstalled:!0};return io(G,K,Z),{path:G,alreadyInstalled:!0}}function Ni(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function Hy(P){try{return jy(P,{throwIfNoEntry:!1})?.isFile()===!0?mc(P,"utf-8"):""}catch{return}}function gc(P){let G=ao(P.environment);if(!Ly(G))return{platform:"grok-build",status:"n/a",configPath:G};let K;try{K=JSON.parse(mc(G,"utf-8"))}catch(Re){return{platform:"grok-build",status:"n/a",configPath:G,errors:[`Failed to parse Grok Build hooks config ${G}: ${Re instanceof Error?Re.message:String(Re)}`]}}let Y=Ni(K)&&Ni(K.hooks)&&Array.isArray(K.hooks.PreToolUse)?K.hooks.PreToolUse:[],Z=Ut(Y,Gn);if(!Z)return{platform:"grok-build",status:"n/a",configPath:G};let X=Array.isArray(Z.hooks)?Z.hooks.findIndex((Re)=>Ni(Re)&&Re.command===Gn):-1,ie=`global/cc-safety-net:pre_tool_use[${Y.indexOf(Z)}].hooks[${X}]`,ae=Fy(fc(fc(G)),"disabled-hooks"),ge=Hy(ae),ye=ge?.split(`
44
+ `).some((Re)=>Re.trim()===ie)===!0,Pe=[...ge===void 0?[`Cannot read ${ae}, so doctor cannot tell whether Grok Build skips the hook`]:[],...ye?[`Grok Build skips the hook: ${ie} is listed in ${ae}; enable it in /hooks`]:[],...Bt(Z,Gn,so)];return{platform:"grok-build",status:ye?"disabled":"configured",method:"hook config",configPath:G,errors:Pe.length>0?Pe:void 0}}import{readFileSync as Pc}from"node:fs";import{join as Sc}from"node:path";var Pn="cc-safety-net",Li="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",My=30;function yc(P){return`${Li}
45
45
  # version: ${P}
46
- `}function Hy(P){return`${gc(P)}name: ${Sn}
46
+ `}function Uy(P){return`${yc(P)}name: ${Pn}
47
47
  version: "${P}"
48
48
  description: "Block destructive commands and secret-file access before Hermes runs a tool."
49
49
  author: "cc-safety-net"
50
50
  provides_hooks:
51
51
  - pre_tool_call
52
- `}function My(P){return`${gc(P)}"""CC Safety Net guard for Hermes Agent.
52
+ `}function By(P){return`${yc(P)}"""CC Safety Net guard for Hermes Agent.
53
53
 
54
54
  Registers pre_tool_call and forwards the tool call to the packaged CC Safety Net
55
55
  adapter (cc-safety-net hook --hermes-agent) over JSON stdin. The adapter prints nothing
@@ -65,8 +65,8 @@ import subprocess
65
65
 
66
66
  HOOK_EVENT = "pre_tool_call"
67
67
  SUPPORTED_TOOLS = ("patch", "read_file", "terminal", "write_file")
68
- ANALYZER = [${kn["hermes-agent"].split(" ").map((L)=>`"${L}"`).join(", ")}]
69
- TIMEOUT_SECONDS = ${Fy}
68
+ ANALYZER = [${wn["hermes-agent"].split(" ").map((G)=>`"${G}"`).join(", ")}]
69
+ TIMEOUT_SECONDS = ${My}
70
70
 
71
71
 
72
72
  def _block(detail):
@@ -219,85 +219,85 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
219
219
 
220
220
  def register(ctx):
221
221
  ctx.register_hook("pre_tool_call", _pre_tool_call)
222
- `}function cr(P){return[{name:"__init__.py",content:My(P)},{name:"plugin.yaml",content:Hy(P)}]}import{mkdirSync as Uy,readdirSync as By,readFileSync as yc,rmSync as Li}from"node:fs";import{basename as Gy,dirname as qy,join as Fn}from"node:path";var Vy="__pycache__",Ky=/^[a-z0-9][a-z0-9_-]{0,63}$/;function Jy(P){try{return yc(P,"utf-8").trim()}catch{return}}function ji(P){let L=P.env.get("HERMES_HOME")?.trim();if(L&&Gy(qy(L))==="profiles")return L;let H=L||Fn(P.home,".hermes"),Y=Fn(H,"active_profile"),Z=Jy(Y),oe=Z?.toLowerCase();if(!oe||oe==="default")return H;if(!Ky.test(oe))throw Error(`Invalid Hermes profile name "${Z}" in ${Y}; run \`hermes profile use <name>\` with a valid profile.`);return Fn(H,"profiles",oe)}function Fi(P){return Fn(ji(P),"plugins",Sn)}function Hi(P){return P.startsWith(Ni)}function Mi(P,L){let H=Fi(P),Y=dn(H);if(Y&&(Y.isSymbolicLink()||!Y.isDirectory()))throw Error(`Refusing to ${L} ${H}: not a regular directory. Move or remove it and rerun ${L==="install"?"install":"uninstall"} --hermes-agent.`);return H}function hc(P,L){let H=dn(P);if(!H)return;if(H.isSymbolicLink()||!H.isFile())throw Error(`Refusing to ${L} ${P}: not a regular file. Move or remove it.`);let Y=yc(P,"utf-8");if(!Hi(Y))throw Error(`Refusing to ${L} unmanaged file at ${P}. Move or remove it.`);return Y}function vc(P){let L=Mi(P,"install"),H=cr(pn());if(H.map((Z)=>hc(Fn(L,Z.name),"overwrite")).every((Z,oe)=>Z===H[oe]?.content))return{path:L,alreadyInstalled:!0};return Uy(L,{recursive:!0}),H.forEach((Z)=>{an(Fn(L,Z.name),Z.content)}),{path:L,alreadyInstalled:!1}}function Ui(P){let L=Mi(P,"remove");if(!dn(L))return[];return cr(pn()).filter((H)=>hc(Fn(L,H.name),"remove")!==void 0)}function bc(P){let L=Mi(P,"remove");if(!dn(L))return{path:L,alreadyInstalled:!1};let H=Ui(P);if(H.forEach((Y)=>{Li(Fn(L,Y.name))}),Li(Fn(L,Vy),{recursive:!0,force:!0}),By(L).length===0)Li(L,{recursive:!0});return{path:L,alreadyInstalled:H.length>0}}var dr="hermes-agent",wc=/^([^\s#][^:]*):/,zy=/^\s+([A-Za-z_][\w-]*):/,kc=/^\s+-\s*(.*)$/;function Wy(P){return P.trim().replace(/^(["'])(.*)\1$/,"$2")}function Yy(P){let L=P.split(/\r?\n/),H=L.findIndex((oe)=>wc.exec(oe)?.[1]?.trim()==="plugins");if(H===-1)return[];let Y=L.slice(H+1),Z=Y.findIndex((oe)=>wc.test(oe));return Z===-1?Y:Y.slice(0,Z)}function Cc(P,L){let H=Yy(P),Y=H.findIndex((se)=>zy.exec(se)?.[1]===L);if(Y===-1)return[];let Z=H.slice(Y+1),oe=Z.findIndex((se)=>!kc.test(se));return(oe===-1?Z:Z.slice(0,oe)).map((se)=>Wy(kc.exec(se)?.[1]??""))}function Zy(P){try{return xc(Pc(ji(P),"config.yaml"),"utf-8")}catch{return}}function Bi(P){let L=Zy(P)??"";return Cc(L,"enabled").includes(Sn)&&!Cc(L,"disabled").includes(Sn)}function Sc(P){return/^# version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function Xy(P,L){let H=dn(P);if(!H)return{error:`${L.name} is missing from ${P}; run install --hermes-agent`};if(H.isSymbolicLink()||!H.isFile())return{error:`${P} is a symlink or not a regular file; move or remove it`};try{let Y=xc(P,"utf-8");if(!Hi(Y))return{error:`Unmanaged ${L.name} occupies ${P}; move or remove it`};if(Sc(Y)===pn()&&Y!==L.content)return{error:`Modified ${L.name} occupies ${P}; run install --hermes-agent to restore it`};return{content:Y}}catch(Y){return{error:`Failed to read ${P}: ${Y instanceof Error?Y.message:String(Y)}`}}}function Qy(P){try{return{path:Fi(P)}}catch(L){return{error:L instanceof Error?L.message:String(L)}}}function Rc(P){let L=Qy(P.environment);if("error"in L)return{platform:dr,status:"n/a",errors:[L.error]};let H=L.path,Y=Gr(dr,H);if(Y)return Y;let Z=cr(pn()).map((he)=>Xy(Pc(H,he.name),he)),oe=Z.flatMap((he)=>("error"in he)?[he.error]:[]);if(oe.length>0)return{platform:dr,status:"n/a",configPath:H,errors:oe};let se=Z.some((he)=>("content"in he)&&Sc(he.content)!==pn()),me=se?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!Bi(P.environment))return{platform:dr,status:"disabled",method:"plugin directory",configPath:H,errors:[`${Sn} is not enabled in Hermes; run \`hermes plugins enable ${Sn}\``,...me]};return{platform:dr,status:"configured",method:"plugin directory",configPath:H,errors:se?me:void 0}}import{existsSync as eh,readFileSync as nh}from"node:fs";import{join as Vi}from"node:path";var th=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/,Gi="cc-safety-net",uo="plugin config",rh=new Set(["event","matcher","command","timeout"]),oh=new Set(["PreToolUse","PostToolUse","PostToolUseFailure","PermissionRequest","PermissionResult","UserPromptSubmit","UserPromptQueued","TurnStarted","Stop","StopFailure","Interrupt","SessionStart","SessionEnd","SessionHeartbeat","SubagentStart","SubagentStop","TaskStarted","PreCompact","PostCompact","Notification"]);function Ec(P){return P.env.get("KIMI_CODE_HOME")||Vi(P.home,".kimi-code")}function co(P,L){let H=[""],Y="",Z=0;for(let oe=0;oe<P.length;oe++){let se=P[oe];if(Y!==""){let me=Y==='"'&&se==="\\"?P[++oe]??"":"";if(H[H.length-1]+=se+me,me===""&&se===Y)Y="";continue}if(se==="#"){let me=P.indexOf(`
223
- `,oe);oe=(me===-1?P.length:me)-1;continue}if(se===L&&Z===0){H.push("");continue}if(se==='"'||se==="'")Y=se;if(se==="["||se==="{")Z++;if(se==="]"||se==="}")Z--;H[H.length-1]+=se}return H.map((oe)=>oe.trim()).filter((oe)=>oe!=="")}function Tc(P){let L=/^(?:"([^"]*)"|'([^']*)'|([^\s="']+))\s*=\s*([\s\S]+)$/.exec(P);return L?{key:L[1]??L[2]??L[3]??"",value:L[4]??""}:void 0}function qi(P){return P===void 0?void 0:/^("""|'''|"|')([\s\S]*)\1$/.exec(P)?.[2]}function ih(P){let L=P.split(/(?=^\s*\[)/m),H=L.filter((Y)=>!/^\s*\[/.test(Y)).flatMap((Y)=>co(Y,`
224
- `)).map(Tc).find((Y)=>Y?.key==="hooks")?.value;if(H!==void 0)return co(H.slice(1,-1),",").map((Y)=>co(Y.slice(1,-1),","));return L.filter((Y)=>/^\s*\[\[hooks]]/.test(Y)).map((Y)=>co(Y.replace(/^\s*\[\[hooks]]/,""),`
225
- `))}function sh(P){let L=P.map(Tc),H=P.find((Pe,Te)=>L[Te]===void 0),Y=L.find((Pe)=>Pe!==void 0&&!rh.has(Pe.key))?.key,Z=L.find((Pe,Te)=>Pe!==void 0&&L.findIndex((_e)=>_e?.key===Pe.key)<Te)?.key,oe=(Pe)=>L.find((Te)=>Te?.key===Pe)?.value,se=oe("matcher"),me=oe("timeout"),he=Number(me?.replace(/(?<=[\da-f])_(?=[\da-f])/gi,""));return[[H!==void 0,`"${H}" is not a key = value pair`],[Y!==void 0,`unknown key "${Y}"`],[Z!==void 0,`duplicate key "${Z}"`],[!oh.has(qi(oe("event"))??""),'"event" is not a Kimi Code hook event'],[se!==void 0&&qi(se)===void 0,'"matcher" is not a string'],[!qi(oe("command")),'"command" is missing or empty'],[me!==void 0&&!(Number.isInteger(he)&&he>=1&&he<=600),'"timeout" is not an integer from 1 to 600']].find(([Pe])=>Pe)?.[1]}function ah(P){let L=Vi(Ec(P),"plugins","installed.json"),H=vn(L);if(H.kind==="missing")return;let Y=H.kind==="ok"?Xe(H.value,"plugins"):void 0;if(!Array.isArray(Y))return{platform:"kimi-code",status:"n/a",configPath:L,errors:[`Cannot read ${L}, so doctor cannot tell whether the Kimi Code plugin is installed`]};let Z=Y.find((oe)=>Xe(oe,"id")===Gi);if(Z===void 0)return;if(Xe(Z,"enabled")!==!0)return{platform:"kimi-code",status:"disabled",method:uo,configPath:L,errors:[`${Gi} is installed but not enabled in Kimi Code; run /plugins enable ${Gi}`]};return{platform:"kimi-code",status:"configured",method:uo,configPath:L}}function po(P){let L=Vi(Ec(P.environment),"config.toml"),H=()=>ah(P.environment)??{platform:"kimi-code",status:"n/a",configPath:L};if(!eh(L))return H();let Y;try{Y=nh(L,"utf-8")}catch(se){return{platform:"kimi-code",status:"n/a",configPath:L,errors:[`Failed to read ${L}: ${se instanceof Error?se.message:String(se)}`]}}if(!th.test(Y))return H();let oe=(/"""|'''/.test(Y)?[]:ih(Y)).flatMap((se,me)=>{let he=sh(se);return he===void 0?[]:[`Kimi Code ignores every hook because hooks entry ${me+1} is invalid (${he}); fix it in ${L}`]});return{platform:"kimi-code",status:oe.length>0?"disabled":"configured",method:"hook config",configPath:L,errors:oe.length>0?oe:void 0}}import{readFileSync as jc}from"node:fs";import{join as pr}from"node:path";var un="cc-safety-net",xn="index.js",qt="openclaw.plugin.json",Vt="package.json";var fo="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as lh,lstatSync as ch,readdirSync as dh,readFileSync as uh}from"node:fs";import{dirname as Ac,join as qn}from"node:path";import{fileURLToPath as ph}from"node:url";var Ki=qn("openclaw",un),bt=`run \`openclaw plugins enable ${un}\``,fh="config reload superseded by a newer runtime config source",mh=[xn,qt,Vt];function _c(P){let L=P.env.get("OPENCLAW_HOME")?.trim();return L?Nn(L,P.home):P.home}function Ic(P){let L=_c(P),H=P.env.get("OPENCLAW_STATE_DIR")?.trim();if(H)return Nn(H,L);let Y=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return Y?Ac(Nn(Y,L)):qn(L,".openclaw")}function Oc(P){let L=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return L?Nn(L,_c(P)):qn(Ic(P),"openclaw.json")}function ur(P){return qn(Ic(P),"extensions",un)}function gh(P){let L=dh(P);if(L.length===0)return!0;if(L.some((Z)=>!mh.includes(Z)))return!1;let H=qn(P,xn),Y=dn(H);return Y!==void 0&&!Y.isSymbolicLink()&&Y.isFile()&&uh(H,"utf-8").startsWith(fo)}function Ji(P){let L=ur(P),H=dn(L);if(!H)return;if(!H.isSymbolicLink()&&H.isDirectory()&&gh(L))return;throw Error(`Refusing to modify ${L}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function $c(){let P=Ac(ph(import.meta.url));return[qn(P,Ki),qn(P,"..",Ki),qn(P,"..","..","..","dist",Ki)]}function zi(P=$c()){return P.find((L)=>lh(L)&&ch(L).isDirectory())}function yh(P=$c()){let L=zi(P);if(!L)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return L}function Dc(P=yh()){return[["openclaw","plugins","install",P,"--force","--accept-capabilities"]]}function hh(P){let L=(()=>{try{return JSON.parse(P)}catch{return}})(),H=Xe(Xe(L,"plugin"),"status");return typeof H==="string"?H:void 0}async function vh(){await fn(["openclaw","plugins","enable",un]).catch((P)=>{if(!(P instanceof Error&&P.message.includes(fh)))throw P})}async function Nc(P){let L=async()=>hh(await fn(["openclaw","plugins","inspect",un,"--runtime","--json"],{stdoutOnly:!0})),H=await L(),Y=H==="disabled"&&P;if(Y)await vh();let Z=Y?await L():H;if(Z==="loaded")return;throw Error(`${Z===void 0?`The ${un} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:Z==="disabled"?`OpenClaw reports the ${un} plugin with status "disabled"; ${bt}.`:`OpenClaw reports the ${un} plugin with status "${Z}".`} Run \`openclaw plugins inspect ${un} --runtime\` for details.`)}var mo="openclaw";function Kt(P,L){let H=pr(P,L),Y=dn(H);if(!Y)return{error:`${L} is missing from ${H}; run install --openclaw`};if(Y.isSymbolicLink()||!Y.isFile())return{error:`${H} is a symlink or not a regular file; move or remove it`};try{return{content:jc(H,"utf-8")}}catch(Z){return{error:`Failed to read ${H}: ${Z instanceof Error?Z.message:String(Z)}`}}}function Fc(P){try{return JSON.parse(yn(P))}catch{return}}function bh(P){let L=Kt(P,qt);if("error"in L)return L.error;if(Xe(Fc(L.content),"id")===un)return;return`${pr(P,qt)} is not a valid ${un} manifest; run install --openclaw`}function wh(P){let L=Kt(P,Vt);if("error"in L)return L.error;let H=Xe(Xe(Fc(L.content),"openclaw"),"extensions");if(Array.isArray(H)&&H.includes(`./${xn}`))return;return`${pr(P,Vt)} does not point OpenClaw at ${xn}; run install --openclaw`}function Lc(P){return Array.isArray(P)?P.filter((L)=>typeof L==="string"):[]}function kh(P){let L=Oc(P);if(!dn(L))return`${un} is not enabled; ${bt}`;let H=(()=>{try{return JSON.parse(yn(jc(L,"utf-8")))}catch{return}})();if(H===void 0)return`Failed to read ${L}; fix it, then ${bt}`;let Y=Xe(H,"plugins");if(Xe(Y,"enabled")===!1)return`plugins.enabled is false in ${L}; no OpenClaw plugin loads`;let Z=Xe(Xe(Xe(Y,"entries"),un),"enabled");if(Lc(Xe(Y,"deny")).includes(un)||Z===!1)return`${un} is disabled in ${L}; ${bt}`;let oe=Lc(Xe(Y,"allow"));if(oe.length>0&&!oe.includes(un))return`plugins.allow in ${L} does not list ${un}; add it, then ${bt}`;if(oe.includes(un)||Z===!0)return;return`${un} is not enabled; ${bt}`}function Hc(P){return/^\/\/ version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function Ch(P,L,H){if(H===void 0)return[];let Y=Kt(H,xn);if(!(("content"in Y)&&Hc(Y.content)===L))return[];return[xn,qt,Vt].flatMap((oe)=>{let se=Kt(P,oe),me=Kt(H,oe);if("error"in se||"error"in me||se.content===me.content)return[];return[`Modified ${oe} occupies ${pr(P,oe)}; run install --openclaw to restore it`]})}function Mc(P){let L=ur(P.environment),H=Gr(mo,L);if(H)return H;let Y=Kt(L,xn),oe=["error"in Y?Y.error:Y.content.startsWith(fo)?void 0:`Unmanaged ${xn} occupies ${pr(L,xn)}; move or remove it`,bh(L),wh(L)].filter((Pe)=>Pe!==void 0),se="content"in Y?Hc(Y.content):void 0,me=oe.length>0?oe:Ch(L,se,zi());if(me.length>0)return{platform:mo,status:"n/a",configPath:L,errors:me};let he=se===pn()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],ke=kh(P.environment);if(ke)return{platform:mo,status:"disabled",method:"plugin directory",configPath:L,errors:[ke,...he]};return{platform:mo,status:"configured",method:"plugin directory",configPath:L,errors:he.length>0?he:void 0}}import{existsSync as Ih,readFileSync as Oh}from"node:fs";import{basename as $h}from"node:path";import{existsSync as go,readFileSync as Yi,rmSync as xh}from"node:fs";import{join as _n}from"node:path";import{pathToFileURL as Ph}from"node:url";var fr="cc-safety-net",Pt=`${fr}@latest`,Zi=["opencode.json","opencode.jsonc"],Sh=60,Rh=250,Uc="CCSafetyNetPlugin",Eh={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function Bc(P){return _n(P.env.get("XDG_CONFIG_HOME")||_n(P.home,".config"),"opencode")}function Xi(P){return P.env.get("OPENCODE_CONFIG_DIR")||Bc(P)}function Qi(P){return Zi.map((L)=>_n(Xi(P),L))}function es(P){return[...new Set([Xi(P),Bc(P)])].flatMap((L)=>Zi.map((H)=>_n(L,H)))}function Gc(P){return _n(P.env.get("XDG_CACHE_HOME")||_n(P.home,".cache"),"opencode","packages",Pt)}function qc(P){xh(Gc(P),{recursive:!0,force:!0})}async function Vc(P){let L=(await fn(["opencode","--version"],{stdoutOnly:!0})).trim(),H=/^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(L),Y=Number(H?.[1]),Z=Number(H?.[2]),oe=Number(H?.[3]);if(!H||Y!==1&&Y!==2||Y===1&&(Z<18||Z===18&&oe<29)||Y===2&&Z===0&&oe<6)throw Error(`OpenCode 1.18.29+ or 2.0.6+ is required; found ${L||"an unknown version"}.`);if(Y===2){for(let se of Qi(P)){if(!go(se))continue;let me=ts(Yi(se,"utf-8"),se);if(["plugin","plugins"].some((ke)=>{let Pe=Xe(me,ke);return Array.isArray(Pe)&&Pe.some((Te)=>yo(Te)&&(typeof Te==="string"?Te:Xe(Te,"package"))!==Pt)}))throw Error(`Change the cc-safety-net package spec in ${se} to ${Pt}, preserving its options, then retry. Adding another spec would create a duplicate plugin ID.`)}return{commands:[],afterInstall:async()=>{if((await fn(["opencode","plugin","add",Pt],{stdoutOnly:!0})).includes("is already configured in"))await Wi(),await fn(["opencode","plugin","update",Pt]);let me=await Wi();if(!/^cc-safety-net\s+\S+\s+cc-safety-net@latest\s*$/m.test(me))throw Error("OpenCode did not load cc-safety-net from cc-safety-net@latest. Run `opencode plugin list` for details.");let he=["--param",`location[directory]=${process.cwd()}`];await fn(["opencode","api","integration.list",...he]);let ke=await fn(["opencode","api","plugin.list",...he],{stdoutOnly:!0}),Pe=ns(ke);if(Pe)throw Error(Pe);if(!Kc(ke).some(Jc))throw Error("OpenCode lists no active cc-safety-net for this directory. Run `opencode api plugin.list` for details.")}}}return qc(P),{commands:[["opencode","plugin","-g","-f",Pt]],afterInstall:()=>Ah(P)}}function Kc(P){return Th(P).filter((L)=>Xe(L,"id")===fr||yo(Xe(Xe(L,"source"),"target"))).map((L)=>Xe(L,"state"))}function Jc(P){return Xe(P,"status")==="active"}function ns(P){let L=Kc(P);if(L.some(Jc))return;let H=L.find((Y)=>Xe(Y,"status")==="failed");if(!H)return;return`OpenCode reports cc-safety-net failed: ${String(Xe(H,"error")).split(`
226
- `)[0]}`}function Th(P){if(!P)return[];try{let L=Xe(JSON.parse(P),"data");return Array.isArray(L)?L:[]}catch{return[]}}async function Wi(P=1){let L=await fn(["opencode","plugin","list"],{stdoutOnly:!0});if(/^cc-safety-net\s|\scc-safety-net@latest\s*$/m.test(L)||P===Sh)return L;return await new Promise((H)=>setTimeout(H,Rh)),Wi(P+1)}async function Ah(P){let L=_n(Gc(P),"node_modules",fr),H=_n(L,"package.json");if(!go(H))throw Error(`The OpenCode plugin cache at ${L} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${Pt}\` for details.`);let Y=Xe(JSON.parse(Yi(H,"utf-8")),"main");if(typeof Y!=="string")throw Error(`The cached OpenCode plugin at ${L} declares no "main" entry.`);let Z=_n(L,Y);if(typeof(await import(Ph(Z).href))[Uc]==="function")return;throw Error(`The cached OpenCode plugin at ${Z} does not export a callable ${Uc}, so OpenCode would load nothing and fail open.`)}function ts(P,L){try{return JSON.parse(yn(P))}catch(H){if(H instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${L}: ${H.message}`);throw H}}function yo(P){let L=typeof P==="string"?P:Xe(P,"package");return typeof L==="string"&&(L===fr||L.startsWith(`${fr}@`))}function rs(P){return["plugin","plugins"].some((L)=>{let H=Xe(P,L);return Array.isArray(H)&&H.some(yo)})}function _h(P,L){let Y=["plugin","plugins"].flatMap((Z)=>{let oe=hl(P,Z,Eh);if(!oe)return[];let se=[],me=0,he=oe.start+1,ke=P.slice(oe.start+1,oe.end).matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|[^"\s{}[\],/]+|[{}[\],]/g);for(let Pe of ke){if(Pe[0].startsWith("//")||Pe[0].startsWith("/*"))continue;let Te=oe.start+1+Pe.index;if(me===0)he=Te;if(Pe[0]==="{"||Pe[0]==="[")me++;if(Pe[0]==="}"||Pe[0]==="]")me--;if(me!==0||Pe[0]===",")continue;let _e=Te+Pe[0].length;if(yo(JSON.parse(yn(P.slice(he,_e)))))se.push({start:he,end:_e})}return se}).sort((Z,oe)=>Z.start-oe.start).reverse().reduce((Z,oe)=>{let se=/^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*,/.exec(Z.slice(oe.end));if(se?.[0].includes("/")){let me=oe.end+se[0].length-1;return Z.slice(0,oe.start)+Z.slice(oe.end,me)+Z.slice(me+1)}return yl(Z,oe)},P);return ts(Y,L),Y}function zc(P){qc(P);let L=es(P),H=L.find((oe)=>go(oe)),Y=[],Z=[];for(let oe of L){if(!go(oe))continue;try{let se=Yi(oe,"utf-8");if(!rs(ts(se,oe)))continue;an(oe,_h(se,oe)),Z.push(oe)}catch(se){Y.push(se instanceof Error?se.message:String(se))}}if(Y.length>0)throw Error(Y.join(`
227
- `));return{path:Z[0]??H??_n(Xi(P),Zi[0]),alreadyInstalled:Z.length>0}}function Jt(P){let L=[];for(let H of P.openCodeVersion?.startsWith("2.")?Qi(P.environment):es(P.environment))if(Ih(H))try{let Y=Oh(H,"utf-8"),Z=yn(Y),oe=JSON.parse(Z);if(rs(oe)){let se=ns(P.openCodePluginListOutput);if(se)return{platform:"opencode",status:"disabled",method:"opencode api plugin.list",configPath:H,errors:[...L,se]};return{platform:"opencode",status:"configured",method:"plugin array",configPath:H,errors:L.length>0?L:void 0}}}catch(Y){L.push(`Failed to parse ${$h(H)}: ${Y instanceof Error?Y.message:String(Y)}`)}return{platform:"opencode",status:"n/a",errors:L.length>0?L:void 0}}import{join as Wc}from"node:path";var Zc="dist/pi/index.js",Yc=new Set([Zc,"index.js"]),Dh=/[*?[\]{}]/;function os(P){let L=P.env.get("PI_CODING_AGENT_DIR");return Wc(L?Nn(L,P.home):Wc(P.home,".pi","agent"),"settings.json")}function is(P){if(typeof P!=="string")return!1;return P==="npm:cc-safety-net"||P.startsWith("npm:cc-safety-net@")}function Nh(P){if(!Array.isArray(P)||P.length===0)return!1;if(!P.every((Y)=>typeof Y==="string"))return!1;let L=(Y)=>P.some((Z)=>Z.startsWith(Y)&&Z.slice(1).replace(/^\.[/\\]/,"")===Zc);if(L("-"))return!1;if(L("+"))return!0;let H=P.filter((Y)=>!/^[-+!]/.test(Y));return(H.length===0||H.some((Y)=>Yc.has(Y)))&&!P.some((Y)=>Y.startsWith("!")&&(Yc.has(Y.slice(1))||Dh.test(Y)))}function Xc(P){let L=os(P.environment),H=vn(L);if(H.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(H.kind==="missing")return{platform:"pi",status:"n/a"};let Y=Xe(H.value,"packages");if(!Array.isArray(Y))return{platform:"pi",status:"n/a"};let Z=Y.find((se)=>is(typeof se==="string"?se:Xe(se,"source")));if(Z===void 0)return{platform:"pi",status:"n/a"};let oe=Xe(Z,"extensions");if(oe!==void 0&&!Nh(oe))return{platform:"pi",status:"disabled",method:"package config",configPath:L,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:L}}var Lh={amp:nl,"antigravity-cli":il,"claude-code":dl,codex:pl,"copilot-cli":_l,cursor:Hl,"deepseek-harness":Ul,devin:Wl,droid:rc,"gemini-cli":oc,"grok-build":mc,"hermes-agent":Rc,"kimi-code":po,openclaw:Mc,opencode:Jt,pi:Xc};function zt(P,L,H){let Y={...H,cwd:L,environment:P};return Er.map((Z)=>jh(Lh[Z](Y)))}function jh(P){if(P.status==="not-inspected")return{platform:P.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:P.platform,detected:P.status!=="n/a",configured:P.status==="configured",inspectionStatus:P.status!=="n/a"?"verified":P.errors&&P.errors.length>0?"failed":"not-applicable",method:P.method,configPath:P.configPath,configPaths:P.configPaths,errors:P.errors}}import{join as Fh}from"node:path";var Hh=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}]),Mh=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),commandTools:Object.freeze([]),safety:Object.freeze({level:"standard"}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),Uh={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 Qc(P){let L=Fh(P.tmpdir,"cc-safety-net-self-test"),H=Hh.map((Y)=>{let Z=B(P,l("self-test",{command:Y.command},{kind:"command",shell:"auto"},{configCwd:L,executionCwd:L},Y.command),{guard:{dependencies:{loadPolicySnapshot:()=>Mh,getModes:()=>Uh,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),oe=Y.expectBlocked?"blocked":"allowed",se=Z.decision.kind==="deny"?"blocked":"allowed";return{command:Y.command,description:Y.description,expected:oe,actual:se,passed:oe===se,reason:Z.decision.kind==="deny"?Z.decision.reason:void 0,ruleId:Z.decision.kind==="deny"?Z.decision.ruleId:void 0}});return{passed:H.filter((Y)=>Y.passed).length,failed:H.filter((Y)=>!Y.passed).length,total:H.length,results:H}}function ss(P){let L=mn({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},P);if($n(L.errors))return null;return{json:L.flags.json,skipUpdateCheck:L.flags.skipUpdateCheck}}async function ed(P,L={}){let H=await tr(!L.json,()=>{let Y=Gh(P,L);return{ready:Y,finish:()=>Y}},()=>nr(),{loadingMessage:"Checking system status…"});if(L.json)console.log(JSON.stringify(H,null,2));else qh(H);return H.engineSelfTest.failed>0||H.findings.some((Y)=>Y.severity==="error")?1:0}async function Gh(P,L){let H=L.cwd??process.cwd(),Y=await Nr((Fe)=>Jt({environment:P,cwd:H,openCodeVersion:Fe}).status!=="n/a",void 0,H),Z=zt(P,H,{ampPluginListOutput:Y.ampPluginListOutput,codexPluginListOutput:Y.codexPluginListOutput,copilotCliVersion:Y.versions["copilot-cli"],openCodeVersion:Y.versions.opencode,openCodePluginListOutput:Y.openCodePluginListOutput}),oe=va(P,H),se=ba(P),me=R(P,{cwd:H}),he=me.policy,ke=_(he,P.env),Pe=K(he,ke.capabilities),Te=Ir(P,7),_e=Ya(P,H),Ae=[Lt(H),jt(P)].filter((Fe)=>Bh(Fe)),Le=L.skipUpdateCheck?{currentVersion:pn(),latestVersion:null,updateAvailable:!1}:await Bn(),We={hooks:Z,engineSelfTest:Qc(P),userConfig:oe.userConfig,projectConfig:oe.projectConfig,configState:Ve(me),effectiveRules:oe.effectiveRules,environment:se,effectiveSafety:{selectedPreset:he.safety.level,level:ke.effectiveLevel,capabilities:ke.capabilities,ruleOverrides:he.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(Pe).filter(([,Fe])=>Fe.source==="rule_override"&&Fe.override==="off"&&Fe.inheritedEnabled&&Fe.changesInherited).map(([Fe])=>Fe),ruleCounts:{stored:Object.keys(he.destructiveCommandRuleOverrides).length,effective:Object.values(Pe).filter((Fe)=>Fe.changesInherited).length},...me.policyScopes?{policyScopes:me.policyScopes}:{}},..._e.length>0?{v2Leftovers:_e}:{},...Ae.length>0?{legacyConfigs:Ae}:{},posture:$a(P,oe.userConfig.path),activity:Te,update:Le,system:Y};return{...We,findings:ka(We)}}function qh(P){console.log(),console.log(xa(P.hooks)),console.log(),console.log(Pa(P.engineSelfTest)),console.log(),console.log(Sa(P)),console.log(),console.log(Ra(P.environment)),console.log(),console.log(Ea(P)),console.log(),console.log(Ta(P.findings)),console.log(),console.log(Aa(P.activity)),console.log(),console.log(Ia(P.system)),console.log(),console.log(_a(P.update)),console.log(Oa(P))}import{existsSync as Vh}from"node:fs";var Kh=/^[A-Za-z0-9_@%+=:,./-]+$/,nd="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function as(P){let L=mn({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},P);if($n(L.errors))return console.error(nd),console.error("Pass -- before a command that starts with dashes."),null;if(L.values.cwd!==void 0&&!Vh(L.values.cwd))return console.error(`Error: --cwd path does not exist: ${L.values.cwd}`),null;let H=L.positionals.length===1?L.positionals[0]:L.positionals.map((Y)=>Kh.test(Y)?Y:`'${Y.replaceAll("'","'\\''")}'`).join(" ");if(!H)return console.error("Error: No command provided"),console.error(nd),null;return{json:L.flags.json,cwd:L.values.cwd,command:H}}function td(P){if(P)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function rd(P,L){let Y=L-18;return[`${P.dtl}${P.dh.repeat(L)}${P.dtr}`,`${P.dv} Command Analysis${" ".repeat(Y)}${P.dv}`,`${P.dbl}${P.dh.repeat(L)}${P.dbr}`]}function ls(P){return JSON.stringify(P)}function od(P,L=0){return`[${P.map((Y,Z)=>Ca(Y,Z,L)).join(",")}]`}function mr(P,L,H=70){let Y=P.split(" "),Z=[],oe="";for(let se of Y)if(oe&&oe.length+se.length+1>H)Z.push(oe),oe=se;else oe=oe?`${oe} ${se}`:se;if(oe)Z.push(oe);return Z.map((se,me)=>me===0?se:`${L}${se}`)}function id(P,L,H){let Y=[];switch(P.type){case"parse":return null;case"env-strip":return Y.push(""),Y.push(`STEP ${L} ${H.h} Strip environment variables`),Y.push(` Removed: ${P.envVars.map((Z)=>`${Z}=<redacted>`).join(", ")}`),Y.push(` Tokens: ${ls(P.output)}`),{lines:Y,incrementStep:!0};case"leading-tokens-stripped":return Y.push(""),Y.push(`STEP ${L} ${H.h} Strip wrappers`),Y.push(` Removed: ${P.removed.join(", ")}`),Y.push(` Tokens: ${ls(P.output)}`),{lines:Y,incrementStep:!0};case"shell-wrapper":return Y.push(""),Y.push(`STEP ${L} ${H.h} Detect shell wrapper`),Y.push(` Wrapper: ${P.wrapper} -c`),Y.push(` Inner: ${P.innerCommand}`),{lines:Y,incrementStep:!0};case"interpreter":{if(Y.push(""),Y.push(`STEP ${L} ${H.h} Detect interpreter`),Y.push(` Interpreter: ${P.interpreter}`),Y.push(` Code: ${P.codeArg}`),P.paranoidBlocked)Y.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:Y,incrementStep:!0}}case"busybox":return Y.push(""),Y.push(`STEP ${L} ${H.h} Busybox wrapper`),Y.push(` Subcommand: ${P.subcommand}`),{lines:Y,incrementStep:!0};case"transparent-wrapper":return Y.push(""),Y.push(`STEP ${L} ${H.h} Transparent wrapper`),Y.push(` Wrapper: ${P.wrapper}`),Y.push(` Tokens: ${ls(P.output)}`),{lines:Y,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(Y.push(""),Y.push(`STEP ${L} ${H.h} Match rules`),Y.push(` Rule: ${P.rule}()`),P.matched)Y.push(" Result: MATCHED");else Y.push(" Result: No match");return{lines:Y,incrementStep:!0}}case"worktree-relaxation":return Y.push(""),Y.push(`STEP ${L} ${H.h} Worktree relaxation`),Y.push(` Mode: ${n.worktree.name}`),Y.push(` Git cwd: ${P.gitCwd}`),Y.push(" Result: Allowed local discard in linked worktree"),{lines:Y,incrementStep:!0};case"temp-root-relaxation":return Y.push(""),Y.push(`STEP ${L} ${H.h} Temp-root relaxation`),Y.push(` Git cwd: ${P.gitCwd}`),Y.push(" Result: Allowed git discard in a temp-root repository"),{lines:Y,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(P.embeddedCommandFound)return Y.push(""),Y.push(`STEP ${L} ${H.h} Fallback scan`),Y.push(` Found: ${P.embeddedCommandFound}`),{lines:Y,incrementStep:!0};return null}case"custom-rules-check":{if(P.rulesChecked){if(Y.push(""),Y.push(`STEP ${L} ${H.h} Custom rules`),P.matched)Y.push(" Result: MATCHED");else Y.push(" Result: No match");return{lines:Y,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(P.matched)return Y.push(""),Y.push(`STEP ${L} ${H.h} Dangerous text check`),Y.push(` Token: ${P.token}`),Y.push(" Result: MATCHED"),{lines:Y,incrementStep:!0};return null}case"strict-unparseable":return Y.push(""),Y.push(`STEP ${L} ${H.h} Strict mode check`),Y.push(` Command: ${P.rawCommand}`),Y.push(" Result: ✗ UNPARSEABLE"),{lines:Y,incrementStep:!0};case"segment-skipped":return null;case"error":return Y.push(""),Y.push(`ERROR: ${P.message}`),{lines:Y,incrementStep:!1};default:return P}}function cs(P,L){let H=td(L?.asciiOnly??!1),Y=58,Z=[],oe=1;Z.push(...rd(H,58)),Z.push("");let se=P.trace.steps.find((Le)=>Le.type==="error");if(se&&se.type==="error"){Z.push("ERROR"),Z.push(` ${se.message}`),Z.push(""),Z.push("RESULT"),Z.push(` Status: ${P.result==="blocked"?en.red("BLOCKED"):en.green("ALLOWED")}`),Z.push(""),Z.push("CONFIG");let Le=P.configSource??"none";return Z.push(` Path: ${Le}`),Z.join(`
228
- `)}let me=P.trace.steps.find((Le)=>Le.type==="parse");if(me&&me.type==="parse"){Z.push("INPUT"),Z.push(` ${me.input}`),Z.push(""),Z.push(`STEP ${oe} ${H.h} Split shell commands`),oe++;for(let Le=0;Le<me.segments.length;Le++){let We=me.segments[Le];if(We){let Fe=Math.random();Z.push(` Segment ${Le+1}: ${od(We,Fe)}`)}}}let he=P.trace.segments,ke=he.length>1;for(let Le of he){if(ke){Z.push("");let tn="";if(me&&me.type==="parse"){let Bo=me.segments[Le.index];if(Bo)tn=Bo.join(" ")}let on=54,ln=tn,nn=` Segment ${Le.index+1}: `,sn=" ";if(tn){if(nn.length+tn.length+sn.length>on){let bf=on-nn.length-sn.length;ln=`${tn.substring(0,bf-1)}…`}}let Pn=tn?`${nn}${ln}${sn}`:` Segment ${Le.index+1} `,hf=tn?`${nn}${en.cyan(ln)}${sn}`:Pn,Ks=58-Pn.length,Js=Math.floor(Ks/2),vf=Ks-Js;Z.push(`${H.sh.repeat(Js)}${hf}${H.sh.repeat(vf)}`)}if(Le.steps.find((tn)=>tn.type==="segment-skipped")){Z.push(""),Z.push(" (skipped — prior segment blocked)");continue}let Fe=!1,Ze=!1;for(let tn of Le.steps){let on=id(tn,oe,H);if(on){if(Ze=!0,tn.type==="recurse"){Z.push("");let ln=" RECURSING ",nn=58-ln.length-4;Z.push(` ${H.tl}${H.h}${ln}${H.h.repeat(nn)}`),Z.push(` ${H.v}`),Fe=!0;continue}for(let ln of on.lines)if(Fe)Z.push(` ${H.v} ${ln}`);else Z.push(ln);if(on.incrementStep)oe++}}if(Fe)Z.push(` ${H.v}`),Z.push(` ${H.bl}${H.h.repeat(56)}`);if(!Ze)Z.push(""),Z.push(` ${en.green("✓")} Allowed (no matching rules)`)}if(Z.push(""),Z.push("RESULT"),P.result==="blocked"){if(Z.push(` Status: ${en.red("BLOCKED")}`),P.customRule){if(Z.push(` Rule: ${P.customRule.id}`),P.customRule.rulebook)Z.push(` Rulebook: ${P.customRule.rulebook.name} ${P.customRule.rulebook.version}`);if(P.customRule.source)Z.push(` Source: ${P.customRule.source}`);if(P.customRule.override)Z.push(` Override: reason ${P.customRule.override.reason}`)}if(P.reason){let Le=mr(P.reason," ");Z.push(` Reason: ${Le[0]}`);for(let We=1;We<Le.length;We++)Z.push(Le[We]??"")}}else Z.push(` Status: ${en.green("ALLOWED")}`);Z.push(""),Z.push("CONFIG");let Pe=P.configSource??"none",Te=P.configValid?"":" (invalid)";Z.push(` Path: ${Pe}${Te}`);let _e=P.safetyPresetScope;Z.push(` Safety preset: ${P.selectedPreset??"standard"}${_e?` (${Or(_e)})`:""}`),Z.push(` Effective capabilities: ${P.effectiveLevel}`);let Ae=Object.entries(P.destructiveCommandRuleOverrides??{});if(Z.push(` Rule customizations: ${Ae.length}`),P.ruleActivation)Z.push(` Rule activation: ${P.ruleActivation.id} — ${P.ruleActivation.enabled?"on":"off"} via ${P.ruleActivation.source}`);return Z.join(`
229
- `)}function ds(P){return JSON.stringify(P,null,2)}import{resolve as Yh}from"node:path";var sd=512,ad={maxTextLength:2048,maxListLength:128,maxObjectProperties:128,maxDepth:16},Jh=["AKIA","ASIA","ghp_","gho_","ghu_","ghs_","ghr_","github_pat_","glpat-","xox","npm_","pypi-","rk_","sk-","sk_","gsk_","xai-","pplx-","bastn_","tgp_v1_","flp_","wfr_","fw_","fwp_","tp-","psk-"];function fs(P){let L=0,H={allocateSegment(){return L++},getNextSegmentIndex(){return L},branch(){let Y=P.fork(),Z=fs(Y);return{trace:Z,adopt(){P.replaceSegmentEvents(Y.finish().events),L=Z.getNextSegmentIndex()}}},recordGlobal(Y){P.record({scope:"global",step:Y})},recordSegment(Y,Z=H.currentSegmentIndex){if(Z===void 0)return;P.record({scope:"segment",segmentIndex:Z,step:Y})}};return H}function ms(P=new Set){let L=[];return{record(H){if(L.length>=sd)return;ho(H.step,P,ad),L.push({...H,step:us(H.step,ad,P)})},fork(){return ms(P)},replaceSegmentEvents(H){L.splice(0,L.length,...[...L.filter((Y)=>Y.scope==="global"),...H].slice(0,sd))},finish(){return{events:L}}}}function ho(P,L,H,Y=0,Z=new WeakSet){if(typeof P==="string"){let me=P.slice(0,H.maxTextLength);if(!rt(me))return;for(let he of vt(me))for(let ke of he.match(/[^\s"'()$]+/g)??[])L.add(ld(ke));return}if(!P||typeof P!=="object"||Y>=H.maxDepth||Z.has(P))return;if(Z.add(P),Array.isArray(P)){let me=Math.min(P.length,H.maxListLength);for(let he=0;he<me;he++)ho(P[he],L,H,Y+1,Z);return}let oe=0,se=new Set;for(let me in P){if(!Object.hasOwn(P,me))continue;if(oe>=H.maxObjectProperties)break;oe++,ho(me,L,H);let he=ps(me,H,L);if(se.has(he))continue;se.add(he),ho(P[me],L,H,Y+1,Z)}}function us(P,L,H,Y=0,Z=new WeakSet){if(typeof P==="string")return ps(P,L,H);if(!P||typeof P!=="object")return P;if(Y>=L.maxDepth)return;if(Z.has(P))return;if(Z.add(P),Array.isArray(P)){let me=[],he=Math.min(P.length,L.maxListLength);for(let ke=0;ke<he;ke++)me.push(us(P[ke],L,H,Y+1,Z));return me}let oe={},se=0;for(let me in P){if(!Object.hasOwn(P,me))continue;if(se>=L.maxObjectProperties)break;se++;let he=ps(me,L,H);if(Object.hasOwn(oe,he))continue;Object.defineProperty(oe,he,{value:us(P[me],L,H,Y+1,Z),enumerable:!0,configurable:!0,writable:!0})}return oe}function ps(P,L,H){let Y=P.slice(0,L.maxTextLength),Z=rt(Y)?nt(Y):Y,oe=H.size>0?Wh(Z,H):Z;return(zh(oe)?Me(oe):oe).slice(0,L.maxTextLength)}function zh(P){return P.includes("PRIVATE KEY")||P.includes("://")||P.includes("eyJ")||P.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(P)||P.length>=14&&Jh.some((L)=>P.includes(L))||P.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(P)}function Wh(P,L){return P.replace(/[^\s"'()$]+/g,(H)=>L.has(ld(H))?"<redacted>":H)}function ld(P){let L=2166136261,H=2166136261;for(let Y=0;Y<P.length;Y++)L=Math.imul(L^P.charCodeAt(Y),16777619),H=Math.imul(H^P.charCodeAt(P.length-Y-1),16777619);return`${L>>>0}:${H>>>0}:${P.length}`}function gr(P,L={},H){let Y=Yh(L.cwd??process.cwd()),Z=L.policySnapshot??R(H,{cwd:Y,userConfigDir:L.userConfigDir}),oe=_(Z.policy,H.env),se=qe({policySnapshot:Z,effectiveCapabilities:oe.capabilities,worktreeMode:oe.worktreeMode}),me={effectiveLevel:se.effectiveLevel,selectedPreset:Z.policy.safety.level,...Z.policyScopes?{safetyPresetScope:Z.policyScopes.levelScope}:{},effectiveCapabilities:se.effectiveCapabilities,destructiveCommandRuleOverrides:Z.policy.destructiveCommandRuleOverrides},{configSource:he,configValid:ke}=Xh(H,{cwd:Y,userConfigDir:L.userConfigDir});if(!P||!P.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:he,configValid:ke,...me};let Pe=v(P,"auto");if(Pe.status==="limited")throw new b;let Te=Pe.dialect==="powershell"?v(P,"posix"):Pe,_e=Rt(Te),Ae=ms(),Le=fs(Ae);Le.recordGlobal({type:"parse",input:P,segments:_e.map((Pn)=>[...Pn])});let We=l("Bash",{command:P},{kind:"command",shell:"auto"},{configCwd:Y,executionCwd:Y},P),Fe=U(We,{environment:H,trace:Le,dependencies:{loadPolicySnapshot:()=>Z}}),Ze=Fe.decision.kind==="deny"?Fe.decision:null;if(Ze&&(Fe.stage==="policy-protection"||Fe.stage==="secret-protection"))return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Zh(Ze),matched:!0,reason:Ze.reason}]}]},result:"blocked",reason:T(Ze.reason),segment:T(cd(Ze,P)),ruleId:T(Ze.ruleId),configSource:he,configValid:ke,...me};let tn=Le.getNextSegmentIndex();if(Ze&&tn>0&&tn<_e.length)Le.recordSegment({type:"segment-skipped",index:tn,reason:"prior-segment-blocked"},tn);let on=Ae.finish(),ln=Ze?.ruleId??Qh(We,Z,oe,H),nn=q.find((Pn)=>Pn.id===ln&&Pn.activationCapability),sn=nn?se.policy.effectiveDestructiveCommandRules[nn.id]:void 0;return{trace:nv(on),result:Ze?"blocked":"allowed",reason:Ze?T(Ze.reason):void 0,segment:Ze?T(cd(Ze,P)):void 0,ruleId:Ze?T(Ze.ruleId):void 0,customRule:ev(tv(Ze?.ruleId,Z)),configSource:he,configValid:ke,...me,...nn&&sn?{ruleActivation:{id:nn.id,...sn}}:{}}}function cd(P,L){return P.evidence?.segment??L}function Zh(P){if(P.reason===Je)return"policy-protection:findPolicyConfigMutationTargetInSemanticFacts";if(P.reason===Ke)return"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts";if(P.reason===g)return"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts";return"secret-protection:findSensitiveTargetInSemanticFacts"}function Xh(P,L){let H=A(L.cwd),Y=z(P,L),Z=Q(P,{cwd:L.cwd,userConfigDir:L.userConfigDir});try{if(r(Z.projectConfigTarget)!==null){if(Un(Z.projectConfigTarget).errors.length===0)return{configSource:H,configValid:!0};return{configSource:H,configValid:!1}}}catch(oe){if(oe instanceof o)return{configSource:H,configValid:!1};throw oe}try{if(r(Z.userConfigTarget)!==null){let oe=Un(Z.userConfigTarget);return{configSource:Y,configValid:oe.errors.length===0}}return{configSource:null,configValid:!0}}catch(oe){if(oe instanceof o)return{configSource:Y,configValid:!1};throw oe}}function Qh(P,L,H,Y){let Z=L.policy,oe=Ne({...Z,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...Z.destructiveCommandRuleOverrides,...Object.fromEntries(q.flatMap((me)=>me.activationCapability?[[me.id,"on"]]:[]))}},L.state==="degraded"?{diagnostics:L.diagnostics,reason:L.reason}:void 0),se=U(P,{environment:Y,dependencies:{loadPolicySnapshot:()=>oe,getModes:()=>({...H,strict:!0,paranoidRm:!0,paranoidInterpreters:!0,capabilities:{fail_closed:{...H.capabilities.fail_closed,enabled:!0},paranoid_rm:{...H.capabilities.paranoid_rm,enabled:!0},paranoid_interpreters:{...H.capabilities.paranoid_interpreters,enabled:!0}}}),findSensitiveTarget:()=>null}});return se.decision.kind==="deny"?se.decision.ruleId:void 0}function ev(P){if(!P)return;return{id:T(P.id),...P.rulebook?{rulebook:{name:T(P.rulebook.name),version:T(P.rulebook.version)}}:{},...P.source?{source:T(P.source)}:{},...P.override?{override:{type:"reason",reason:T(P.override.reason)}}:{}}}function nv(P){let L=P.events.flatMap((Y)=>Y.scope==="global"?[Y.step]:[]),H=new Map;for(let Y of P.events){if(Y.scope!=="segment")continue;let Z=H.get(Y.segmentIndex)??{index:Y.segmentIndex,steps:[]};Z.steps.push(Y.step),H.set(Y.segmentIndex,Z)}return{steps:L,segments:[...H.values()]}}function tv(P,L){let H=P?.replace(/^custom\./,"");if(!H||!L.policy.rules.some((Y)=>Y.name===H))return;return L.ruleMetadata[H]??Object.freeze({id:H})}function dd(P){return new Promise((L)=>{process.stdout.write(`${P}
230
- `,()=>L())})}async function ud(P,L){let H=as(L);if(!H)return 1;try{let Y=gr(H.command,{cwd:H.cwd},P),Z=!!process.env.NO_COLOR||!process.stdout.isTTY;return await dd(H.json?ds(Y):cs(Y,{asciiOnly:Z})),0}catch(Y){let Z=rv(Y instanceof f?Y.cause:Y);if(Z===void 0)throw Y;if(H.json)return await dd(JSON.stringify({error:Z})),1;return console.error(Z),1}}function rv(P){if(P instanceof b)return P.message;if(P instanceof j)return P.message;if(P instanceof m)return P.message;if(P instanceof s&&a[P.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var pd="2.6.16",En=" ",St="cc-safety-net";function fd(P){return P.argument?`${P.flags} ${P.argument}`:P.flags}function ov(P){return Math.max(...P.map((L)=>fd(L).length))}function iv(P){return Math.max(...P.map((L)=>L.usage.length))}function sv(P){return Math.max(...P.map((L)=>`${St} ${L.usage}`.length))}function av(P,L){let H=`${St} ${P.usage}`;return`${En}${H.padEnd(L+2)}${P.description}`}function In(P,L){return`${En}${P.padEnd(Math.max(40,P.length+2))}${L}`}function Wt(P,L=console.log){let H=[];if(H.push(`${St} ${P.name}`),H.push(""),H.push(`${En}${P.description}`),H.push(""),H.push("USAGE:"),H.push(`${En}${St} ${P.usage}`),H.push(""),P.subcommands&&P.subcommands.length>0){H.push("SUBCOMMANDS:");let Y=iv(P.subcommands);for(let Z of P.subcommands)H.push(`${En}${Z.usage.padEnd(Y+2)}${Z.description}`);H.push("")}if(P.options.length>0){H.push("OPTIONS:");let Y=ov(P.options);for(let Z of P.options){let oe=fd(Z),se=Z.default?`${Z.description} (default: ${Z.default})`:Z.description;H.push(`${En}${oe.padEnd(Y+2)}${se}`)}H.push("")}if(P.examples&&P.examples.length>0){H.push("EXAMPLES:");for(let Y of P.examples)H.push(`${En}${Y}`)}L(H.join(`
231
- `))}function gs(){let P=sv(Ar),L=[];L.push(`${St} v${pd}`),L.push(""),L.push("Blocks destructive commands and secret access."),L.push(""),L.push("COMMANDS:");for(let H of Ar)L.push(av(H,P));L.push(""),L.push("GLOBAL OPTIONS:"),L.push(`${En}-h, --help Show help (use with command for command-specific help)`),L.push(`${En}-V, --version Show version`),L.push(""),L.push("HELP:"),L.push(`${En}${St} help <command> Show help for a specific command`),L.push(`${En}${St} <command> --help Show help for a specific command`),L.push(""),L.push("ENVIRONMENT VARIABLES:"),L.push(In(`${n.level.name}=standard|strict|paranoid`,"Set session safety level")),L.push(In(`${n.worktree.name}=1`,"Allow local git discards in linked worktrees")),L.push(In(`${n.debug.name}=1`,"Print diagnostic messages to stderr")),L.push(In(`${n.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),L.push(In(`${n.projectTightenOnly.name}=1`,"Ignore project policy settings that weaken the user policy")),L.push(In("CC_SAFETY_NET_HOME","Override rule config home directory")),L.push(""),L.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),L.push(In(`${n.strict.name}=1`,"Force safety.overrides.fail_closed on")),L.push(In(`${n.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),L.push(In(`${n.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),L.push(In(`${n.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),L.push(""),L.push("Documentation: https://ccsafetynet.com/docs"),console.log(L.join(`
232
- `))}function md(){console.log(pd)}function yr(P,L=console.log){let H=_r(P);if(!H)return!1;if(H.name.toLowerCase()!==P.toLowerCase())return!1;return Wt(H,L),!0}import{existsSync as So,readFileSync as wu}from"node:fs";import{join as Po}from"node:path";import*as Vn from"node:readline";function lv(P){return P==="install"?"Install":"Uninstall"}function cv(P){return P==="install"?"Installing":"Uninstalling"}function dv(P){return P==="install"?"into":"from"}function hd(P){return P?.available===!0}function uv(P,L){let H=new Set(L);return P.filter((Y)=>H.has(Y.target)).map((Y)=>Y.target)}function gd(P,L,H){if(P.every((Y)=>!Y.available))return L;return Array.from({length:P.length},(Y,Z)=>Z+1).map((Y)=>(L+Y*H+P.length)%P.length).find((Y)=>hd(P[Y]))}function pv(P,L,H){if(H.ctrl&&H.name==="c")return"interrupt";if(H.name==="escape"||L==="q")return"abort";if(P==="install"&&(L==="u"||L==="U"))return"update";if(H.name==="up"||L==="k")return"up";if(H.name==="down"||L==="j")return"down";if(H.name==="space"||L===" ")return"toggle";if(H.name==="return"||H.name==="enter")return"confirm";return null}function fv(P){return{cursor:P.findIndex((L)=>L.available),selected:[]}}function mv(P,L,H){if(H==="confirm"||H==="update"||H==="abort"||H==="interrupt")return{state:P,done:H};if(H==="up")return{state:{...P,cursor:gd(L,P.cursor,-1)}};if(H==="down")return{state:{...P,cursor:gd(L,P.cursor,1)}};let Y=L[P.cursor];if(!hd(Y))return{state:P};let Z=P.selected.includes(Y.target)?P.selected.filter((oe)=>oe!==Y.target):uv(L,[...P.selected,Y.target]);return{state:{...P,selected:Z}}}var vd="◉",bd="◯",wd=">",kd=" ";function gv(P,L,H){return["",`${lv(P)} CC Safety Net ${dv(P)}:`,"",...L.map((Y,Z)=>{let oe=H.selected.includes(Y.target),se=Z===H.cursor,me=oe?vd:bd,he=se?wd:kd,ke=Y.available?"":` (${Y.unavailableReason??"not installed"})`,Pe=`${me} ${Y.label}${ke}`,Te=!Y.available?en.dim(Pe):oe?en.green(Pe):se?en.bold(Pe):Pe;return`${he} ${Te}`}),"",P==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":L.some((Y)=>Y.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${P}. q/Esc: close`].join(`
233
- `)}var yd=["global-hook","plugin"];function yv(P,L,H={}){let Y=H.color!==!1?en.bold:(oe)=>oe;return["","Install the Kimi Code integration as:","",...[`Global hook — ${L?"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((oe,se)=>{let me=se===P,he=`${me?vd:bd} ${oe}`;return`${me?wd:kd} ${me?Y(he):he}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
234
- `)}function Cd(P){let{input:L,output:H}=P;Vn.emitKeypressEvents(L);let Y=L.isRaw===!0;L.setRawMode(!0),L.resume();let Z=0,oe=()=>{if(Z===0)return;Vn.moveCursor(H,0,-Z),Vn.cursorTo(H,0),Vn.clearScreenDown(H)},se=()=>{oe();let me=P.render();H.write(`${me}
235
- `),Z=me.split(`
236
- `).length};return new Promise((me)=>{let he=(Pe)=>{L.off("keypress",ke),L.setRawMode(Y),L.pause(),oe(),me(Pe)};function ke(Pe,Te){P.onKey(Pe,Te,{finish:he,draw:se})}L.on("keypress",ke),se()})}function xd(P={}){let L=0;return Cd({input:P.input??process.stdin,output:P.output??process.stdout,render:()=>yv(L,P.globalHookInstalled===!0),onKey:(H,Y,Z)=>{if(Y.ctrl&&Y.name==="c"){Z.finish(null),(P.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(Y.name==="escape"||H==="q")return Z.finish(null);if(Y.name==="return"||Y.name==="enter")return Z.finish(yd[L]);if(Y.name==="up"||Y.name==="down"||H==="k"||H==="j")L=(L+1)%yd.length,Z.draw()}})}function ys(P=process.stdin,L=process.stdout){return Boolean(P.isTTY&&L.isTTY&&typeof P.setRawMode==="function")}function Pd(P,L,H={}){let Y=H.output??process.stdout,Z=fv(L);return Cd({input:H.input??process.stdin,output:Y,render:()=>gv(P,L,Z),onKey:(oe,se,me)=>{let he=pv(P,oe,se);if(!he)return;let ke=mv(Z,L,he);if(Z=ke.state,ke.done==="interrupt"){me.finish(null),(H.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(ke.done==="abort")return me.finish(null);if(ke.done==="update")return me.finish("update");if(ke.done==="confirm"){if(Z.selected.length===0){Y.write("\x07"),me.draw();return}me.finish([...Z.selected]),Y.write(`${cv(P)} selected integrations...
237
- `);return}me.draw()}})}import{existsSync as Sd,lstatSync as vv,mkdirSync as bv,mkdtempSync as wv,readdirSync as kv,readFileSync as Zt,rmSync as bo}from"node:fs";import{basename as Cv,dirname as xv,join as Cn}from"node:path";import{fileURLToPath as Pv}from"node:url";var hs="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",Tt="cc-safety-net",At="cc-safety-net/index.ts";import{spawn as hv}from"node:child_process";var vs=(P,L)=>{let H=Xn([...P],process.env);return new Promise((Y)=>{let Z=hv(H.cmd,H.args,{cwd:L,stdio:["ignore","pipe","pipe"]}),oe=ui(Z),se=!1,me=setTimeout(()=>{se=!0,Z.kill()},120000);Z.on("error",(he)=>{clearTimeout(me),Y({status:null,errorCode:he.code,stdout:oe.stdout,stderr:[he.message,oe.stderr].filter(Boolean).join(`
238
- `)})}),Z.on("close",(he)=>{clearTimeout(me),Y({status:se?null:he,errorCode:se?"ETIMEDOUT":void 0,stdout:oe.stdout,stderr:oe.stderr})})})};var Yt="cc-safety-net.ts",bs=Cn("amp",At);function Sv(P){return Cn(P.home,".config","amp","plugins","cc-safety-net.ts")}function Rv(){let P=xv(Pv(import.meta.url)),L=Cn(P,bs),H=Cn(P,"..",bs),Y=Cn(P,"..","..","..","dist",bs);return[L,H,Y]}function Ev(P=Rv()){let L=P.find((H)=>Sd(H)&&vv(H).isFile());if(!L)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return L}function Rd(P){try{return JSON.parse(P)}catch{return}}function wo(P){return P.subarray(0,Buffer.byteLength(hs)).toString("utf-8")===hs}async function hr(P,L,H){let Y=await P(L,H);if(Y.status===0)return Y;throw Error([`Failed to run ${L.join(" ")}${Y.status===null?"":` (exit ${Y.status})`}.`,[Y.stdout,Y.stderr].filter(Boolean).join(`
222
+ `}function cr(P){return[{name:"__init__.py",content:By(P)},{name:"plugin.yaml",content:Uy(P)}]}import{mkdirSync as Gy,readdirSync as qy,readFileSync as hc,rmSync as ji}from"node:fs";import{basename as Vy,dirname as Ky,join as Fn}from"node:path";var Jy="__pycache__",zy=/^[a-z0-9][a-z0-9_-]{0,63}$/;function Wy(P){try{return hc(P,"utf-8").trim()}catch{return}}function Fi(P){let G=P.env.get("HERMES_HOME")?.trim();if(G&&Vy(Ky(G))==="profiles")return G;let K=G||Fn(P.home,".hermes"),Y=Fn(K,"active_profile"),Z=Wy(Y),X=Z?.toLowerCase();if(!X||X==="default")return K;if(!zy.test(X))throw Error(`Invalid Hermes profile name "${Z}" in ${Y}; run \`hermes profile use <name>\` with a valid profile.`);return Fn(K,"profiles",X)}function Hi(P){return Fn(Fi(P),"plugins",Pn)}function Mi(P){return P.startsWith(Li)}function Ui(P,G){let K=Hi(P),Y=cn(K);if(Y&&(Y.isSymbolicLink()||!Y.isDirectory()))throw Error(`Refusing to ${G} ${K}: not a regular directory. Move or remove it and rerun ${G==="install"?"install":"uninstall"} --hermes-agent.`);return K}function vc(P,G){let K=cn(P);if(!K)return;if(K.isSymbolicLink()||!K.isFile())throw Error(`Refusing to ${G} ${P}: not a regular file. Move or remove it.`);let Y=hc(P,"utf-8");if(!Mi(Y))throw Error(`Refusing to ${G} unmanaged file at ${P}. Move or remove it.`);return Y}function bc(P){let G=Ui(P,"install"),K=cr(un());if(K.map((Z)=>vc(Fn(G,Z.name),"overwrite")).every((Z,X)=>Z===K[X]?.content))return{path:G,alreadyInstalled:!0};return Gy(G,{recursive:!0}),K.forEach((Z)=>{sn(Fn(G,Z.name),Z.content)}),{path:G,alreadyInstalled:!1}}function Bi(P){let G=Ui(P,"remove");if(!cn(G))return[];return cr(un()).filter((K)=>vc(Fn(G,K.name),"remove")!==void 0)}function wc(P){let G=Ui(P,"remove");if(!cn(G))return{path:G,alreadyInstalled:!1};let K=Bi(P);if(K.forEach((Y)=>{ji(Fn(G,Y.name))}),ji(Fn(G,Jy),{recursive:!0,force:!0}),qy(G).length===0)ji(G,{recursive:!0});return{path:G,alreadyInstalled:K.length>0}}var dr="hermes-agent",kc=/^([^\s#][^:]*):/,Yy=/^\s+([A-Za-z_][\w-]*):/,Cc=/^\s+-\s*(.*)$/;function Zy(P){return P.trim().replace(/^(["'])(.*)\1$/,"$2")}function Xy(P){let G=P.split(/\r?\n/),K=G.findIndex((X)=>kc.exec(X)?.[1]?.trim()==="plugins");if(K===-1)return[];let Y=G.slice(K+1),Z=Y.findIndex((X)=>kc.test(X));return Z===-1?Y:Y.slice(0,Z)}function xc(P,G){let K=Xy(P),Y=K.findIndex((ie)=>Yy.exec(ie)?.[1]===G);if(Y===-1)return[];let Z=K.slice(Y+1),X=Z.findIndex((ie)=>!Cc.test(ie));return(X===-1?Z:Z.slice(0,X)).map((ie)=>Zy(Cc.exec(ie)?.[1]??""))}function Qy(P){try{return Pc(Sc(Fi(P),"config.yaml"),"utf-8")}catch{return}}function Gi(P){let G=Qy(P)??"";return xc(G,"enabled").includes(Pn)&&!xc(G,"disabled").includes(Pn)}function Rc(P){return/^# version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function eh(P,G){let K=cn(P);if(!K)return{error:`${G.name} is missing from ${P}; run install --hermes-agent`};if(K.isSymbolicLink()||!K.isFile())return{error:`${P} is a symlink or not a regular file; move or remove it`};try{let Y=Pc(P,"utf-8");if(!Mi(Y))return{error:`Unmanaged ${G.name} occupies ${P}; move or remove it`};if(Rc(Y)===un()&&Y!==G.content)return{error:`Modified ${G.name} occupies ${P}; run install --hermes-agent to restore it`};return{content:Y}}catch(Y){return{error:`Failed to read ${P}: ${Y instanceof Error?Y.message:String(Y)}`}}}function nh(P){try{return{path:Hi(P)}}catch(G){return{error:G instanceof Error?G.message:String(G)}}}function Ec(P){let G=nh(P.environment);if("error"in G)return{platform:dr,status:"n/a",errors:[G.error]};let K=G.path,Y=Gr(dr,K);if(Y)return Y;let Z=cr(un()).map((ge)=>eh(Sc(K,ge.name),ge)),X=Z.flatMap((ge)=>("error"in ge)?[ge.error]:[]);if(X.length>0)return{platform:dr,status:"n/a",configPath:K,errors:X};let ie=Z.some((ge)=>("content"in ge)&&Rc(ge.content)!==un()),ae=ie?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!Gi(P.environment))return{platform:dr,status:"disabled",method:"plugin directory",configPath:K,errors:[`${Pn} is not enabled in Hermes; run \`hermes plugins enable ${Pn}\``,...ae]};return{platform:dr,status:"configured",method:"plugin directory",configPath:K,errors:ie?ae:void 0}}import{existsSync as th,readFileSync as rh}from"node:fs";import{join as Ki}from"node:path";var oh=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/,qi="cc-safety-net",uo="plugin config",ih=new Set(["event","matcher","command","timeout"]),sh=new Set(["PreToolUse","PostToolUse","PostToolUseFailure","PermissionRequest","PermissionResult","UserPromptSubmit","UserPromptQueued","TurnStarted","Stop","StopFailure","Interrupt","SessionStart","SessionEnd","SessionHeartbeat","SubagentStart","SubagentStop","TaskStarted","PreCompact","PostCompact","Notification"]);function Tc(P){return P.env.get("KIMI_CODE_HOME")||Ki(P.home,".kimi-code")}function co(P,G){let K=[""],Y="",Z=0;for(let X=0;X<P.length;X++){let ie=P[X];if(Y!==""){let ae=Y==='"'&&ie==="\\"?P[++X]??"":"";if(K[K.length-1]+=ie+ae,ae===""&&ie===Y)Y="";continue}if(ie==="#"){let ae=P.indexOf(`
223
+ `,X);X=(ae===-1?P.length:ae)-1;continue}if(ie===G&&Z===0){K.push("");continue}if(ie==='"'||ie==="'")Y=ie;if(ie==="["||ie==="{")Z++;if(ie==="]"||ie==="}")Z--;K[K.length-1]+=ie}return K.map((X)=>X.trim()).filter((X)=>X!=="")}function Ac(P){let G=/^(?:"([^"]*)"|'([^']*)'|([^\s="']+))\s*=\s*([\s\S]+)$/.exec(P);return G?{key:G[1]??G[2]??G[3]??"",value:G[4]??""}:void 0}function Vi(P){return P===void 0?void 0:/^("""|'''|"|')([\s\S]*)\1$/.exec(P)?.[2]}function ah(P){let G=P.split(/(?=^\s*\[)/m),K=G.filter((Y)=>!/^\s*\[/.test(Y)).flatMap((Y)=>co(Y,`
224
+ `)).map(Ac).find((Y)=>Y?.key==="hooks")?.value;if(K!==void 0)return co(K.slice(1,-1),",").map((Y)=>co(Y.slice(1,-1),","));return G.filter((Y)=>/^\s*\[\[hooks]]/.test(Y)).map((Y)=>co(Y.replace(/^\s*\[\[hooks]]/,""),`
225
+ `))}function lh(P){let G=P.map(Ac),K=P.find((Pe,Re)=>G[Re]===void 0),Y=G.find((Pe)=>Pe!==void 0&&!ih.has(Pe.key))?.key,Z=G.find((Pe,Re)=>Pe!==void 0&&G.findIndex((_e)=>_e?.key===Pe.key)<Re)?.key,X=(Pe)=>G.find((Re)=>Re?.key===Pe)?.value,ie=X("matcher"),ae=X("timeout"),ge=Number(ae?.replace(/(?<=[\da-f])_(?=[\da-f])/gi,""));return[[K!==void 0,`"${K}" is not a key = value pair`],[Y!==void 0,`unknown key "${Y}"`],[Z!==void 0,`duplicate key "${Z}"`],[!sh.has(Vi(X("event"))??""),'"event" is not a Kimi Code hook event'],[ie!==void 0&&Vi(ie)===void 0,'"matcher" is not a string'],[!Vi(X("command")),'"command" is missing or empty'],[ae!==void 0&&!(Number.isInteger(ge)&&ge>=1&&ge<=600),'"timeout" is not an integer from 1 to 600']].find(([Pe])=>Pe)?.[1]}function ch(P){let G=Ki(Tc(P),"plugins","installed.json"),K=yn(G);if(K.kind==="missing")return;let Y=K.kind==="ok"?Fe(K.value,"plugins"):void 0;if(!Array.isArray(Y))return{platform:"kimi-code",status:"n/a",configPath:G,errors:[`Cannot read ${G}, so doctor cannot tell whether the Kimi Code plugin is installed`]};let Z=Y.find((X)=>Fe(X,"id")===qi);if(Z===void 0)return;if(Fe(Z,"enabled")!==!0)return{platform:"kimi-code",status:"disabled",method:uo,configPath:G,errors:[`${qi} is installed but not enabled in Kimi Code; run /plugins enable ${qi}`]};return{platform:"kimi-code",status:"configured",method:uo,configPath:G}}function po(P){let G=Ki(Tc(P.environment),"config.toml"),K=()=>ch(P.environment)??{platform:"kimi-code",status:"n/a",configPath:G};if(!th(G))return K();let Y;try{Y=rh(G,"utf-8")}catch(ie){return{platform:"kimi-code",status:"n/a",configPath:G,errors:[`Failed to read ${G}: ${ie instanceof Error?ie.message:String(ie)}`]}}if(!oh.test(Y))return K();let X=(/"""|'''/.test(Y)?[]:ah(Y)).flatMap((ie,ae)=>{let ge=lh(ie);return ge===void 0?[]:[`Kimi Code ignores every hook because hooks entry ${ae+1} is invalid (${ge}); fix it in ${G}`]});return{platform:"kimi-code",status:X.length>0?"disabled":"configured",method:"hook config",configPath:G,errors:X.length>0?X:void 0}}import{readFileSync as Fc}from"node:fs";import{join as pr}from"node:path";var dn="cc-safety-net",Cn="index.js",qt="openclaw.plugin.json",Vt="package.json";var fo="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as dh,lstatSync as uh,readdirSync as ph,readFileSync as fh}from"node:fs";import{dirname as _c,join as qn}from"node:path";import{fileURLToPath as mh}from"node:url";var Ji=qn("openclaw",dn),vt=`run \`openclaw plugins enable ${dn}\``,gh="config reload superseded by a newer runtime config source",yh=[Cn,qt,Vt];function Ic(P){let G=P.env.get("OPENCLAW_HOME")?.trim();return G?Nn(G,P.home):P.home}function Oc(P){let G=Ic(P),K=P.env.get("OPENCLAW_STATE_DIR")?.trim();if(K)return Nn(K,G);let Y=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return Y?_c(Nn(Y,G)):qn(G,".openclaw")}function $c(P){let G=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return G?Nn(G,Ic(P)):qn(Oc(P),"openclaw.json")}function ur(P){return qn(Oc(P),"extensions",dn)}function hh(P){let G=ph(P);if(G.length===0)return!0;if(G.some((Z)=>!yh.includes(Z)))return!1;let K=qn(P,Cn),Y=cn(K);return Y!==void 0&&!Y.isSymbolicLink()&&Y.isFile()&&fh(K,"utf-8").startsWith(fo)}function zi(P){let G=ur(P),K=cn(G);if(!K)return;if(!K.isSymbolicLink()&&K.isDirectory()&&hh(G))return;throw Error(`Refusing to modify ${G}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function Dc(){let P=_c(mh(import.meta.url));return[qn(P,Ji),qn(P,"..",Ji),qn(P,"..","..","..","dist",Ji)]}function Wi(P=Dc()){return P.find((G)=>dh(G)&&uh(G).isDirectory())}function vh(P=Dc()){let G=Wi(P);if(!G)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return G}function Nc(P=vh()){return[["openclaw","plugins","install",P,"--force","--accept-capabilities"]]}function bh(P){let G=(()=>{try{return JSON.parse(P)}catch{return}})(),K=Fe(Fe(G,"plugin"),"status");return typeof K==="string"?K:void 0}async function wh(){await pn(["openclaw","plugins","enable",dn]).catch((P)=>{if(!(P instanceof Error&&P.message.includes(gh)))throw P})}async function Lc(P){let G=async()=>bh(await pn(["openclaw","plugins","inspect",dn,"--runtime","--json"],{stdoutOnly:!0})),K=await G(),Y=K==="disabled"&&P;if(Y)await wh();let Z=Y?await G():K;if(Z==="loaded")return;throw Error(`${Z===void 0?`The ${dn} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:Z==="disabled"?`OpenClaw reports the ${dn} plugin with status "disabled"; ${vt}.`:`OpenClaw reports the ${dn} plugin with status "${Z}".`} Run \`openclaw plugins inspect ${dn} --runtime\` for details.`)}var mo="openclaw";function Kt(P,G){let K=pr(P,G),Y=cn(K);if(!Y)return{error:`${G} is missing from ${K}; run install --openclaw`};if(Y.isSymbolicLink()||!Y.isFile())return{error:`${K} is a symlink or not a regular file; move or remove it`};try{return{content:Fc(K,"utf-8")}}catch(Z){return{error:`Failed to read ${K}: ${Z instanceof Error?Z.message:String(Z)}`}}}function Hc(P){try{return JSON.parse(gn(P))}catch{return}}function kh(P){let G=Kt(P,qt);if("error"in G)return G.error;if(Fe(Hc(G.content),"id")===dn)return;return`${pr(P,qt)} is not a valid ${dn} manifest; run install --openclaw`}function Ch(P){let G=Kt(P,Vt);if("error"in G)return G.error;let K=Fe(Fe(Hc(G.content),"openclaw"),"extensions");if(Array.isArray(K)&&K.includes(`./${Cn}`))return;return`${pr(P,Vt)} does not point OpenClaw at ${Cn}; run install --openclaw`}function jc(P){return Array.isArray(P)?P.filter((G)=>typeof G==="string"):[]}function xh(P){let G=$c(P);if(!cn(G))return`${dn} is not enabled; ${vt}`;let K=(()=>{try{return JSON.parse(gn(Fc(G,"utf-8")))}catch{return}})();if(K===void 0)return`Failed to read ${G}; fix it, then ${vt}`;let Y=Fe(K,"plugins");if(Fe(Y,"enabled")===!1)return`plugins.enabled is false in ${G}; no OpenClaw plugin loads`;let Z=Fe(Fe(Fe(Y,"entries"),dn),"enabled");if(jc(Fe(Y,"deny")).includes(dn)||Z===!1)return`${dn} is disabled in ${G}; ${vt}`;let X=jc(Fe(Y,"allow"));if(X.length>0&&!X.includes(dn))return`plugins.allow in ${G} does not list ${dn}; add it, then ${vt}`;if(X.includes(dn)||Z===!0)return;return`${dn} is not enabled; ${vt}`}function Mc(P){return/^\/\/ version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function Ph(P,G,K){if(K===void 0)return[];let Y=Kt(K,Cn);if(!(("content"in Y)&&Mc(Y.content)===G))return[];return[Cn,qt,Vt].flatMap((X)=>{let ie=Kt(P,X),ae=Kt(K,X);if("error"in ie||"error"in ae||ie.content===ae.content)return[];return[`Modified ${X} occupies ${pr(P,X)}; run install --openclaw to restore it`]})}function Uc(P){let G=ur(P.environment),K=Gr(mo,G);if(K)return K;let Y=Kt(G,Cn),X=["error"in Y?Y.error:Y.content.startsWith(fo)?void 0:`Unmanaged ${Cn} occupies ${pr(G,Cn)}; move or remove it`,kh(G),Ch(G)].filter((Pe)=>Pe!==void 0),ie="content"in Y?Mc(Y.content):void 0,ae=X.length>0?X:Ph(G,ie,Wi());if(ae.length>0)return{platform:mo,status:"n/a",configPath:G,errors:ae};let ge=ie===un()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],ye=xh(P.environment);if(ye)return{platform:mo,status:"disabled",method:"plugin directory",configPath:G,errors:[ye,...ge]};return{platform:mo,status:"configured",method:"plugin directory",configPath:G,errors:ge.length>0?ge:void 0}}import{existsSync as $h,readFileSync as Dh}from"node:fs";import{basename as Nh}from"node:path";import{existsSync as go,readFileSync as Zi,rmSync as Sh}from"node:fs";import{join as _n}from"node:path";import{pathToFileURL as Rh}from"node:url";var fr="cc-safety-net",bt=`${fr}@latest`,Xi=["opencode.json","opencode.jsonc"],Eh=60,Th=250,Bc="CCSafetyNetPlugin",Ah={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function Gc(P){return _n(P.env.get("XDG_CONFIG_HOME")||_n(P.home,".config"),"opencode")}function Qi(P){return P.env.get("OPENCODE_CONFIG_DIR")||Gc(P)}function es(P){return Xi.map((G)=>_n(Qi(P),G))}function ns(P){return[...new Set([Qi(P),Gc(P)])].flatMap((G)=>Xi.map((K)=>_n(G,K)))}function qc(P){return _n(P.env.get("XDG_CACHE_HOME")||_n(P.home,".cache"),"opencode","packages",bt)}function Vc(P){Sh(qc(P),{recursive:!0,force:!0})}async function Kc(P){let G=(await pn(["opencode","--version"],{stdoutOnly:!0})).trim(),K=/^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(G),Y=Number(K?.[1]),Z=Number(K?.[2]),X=Number(K?.[3]);if(!K||Y!==1&&Y!==2||Y===1&&(Z<18||Z===18&&X<29)||Y===2&&Z===0&&X<6)throw Error(`OpenCode 1.18.29+ or 2.0.6+ is required; found ${G||"an unknown version"}.`);if(Y===2){for(let ie of es(P)){if(!go(ie))continue;let ae=rs(Zi(ie,"utf-8"),ie);if(["plugin","plugins"].some((ye)=>{let Pe=Fe(ae,ye);return Array.isArray(Pe)&&Pe.some((Re)=>yo(Re)&&(typeof Re==="string"?Re:Fe(Re,"package"))!==bt)}))throw Error(`Change the cc-safety-net package spec in ${ie} to ${bt}, preserving its options, then retry. Adding another spec would create a duplicate plugin ID.`)}return{commands:[],afterInstall:async()=>{if((await pn(["opencode","plugin","add",bt],{stdoutOnly:!0})).includes("is already configured in"))await Yi(),await pn(["opencode","plugin","update",bt]);let ae=await Yi();if(!/^cc-safety-net\s+\S+\s+cc-safety-net@latest\s*$/m.test(ae))throw Error("OpenCode did not load cc-safety-net from cc-safety-net@latest. Run `opencode plugin list` for details.");let ge=["--param",`location[directory]=${process.cwd()}`];await pn(["opencode","api","integration.list",...ge]);let ye=await pn(["opencode","api","plugin.list",...ge],{stdoutOnly:!0}),Pe=ts(ye);if(Pe)throw Error(Pe);if(!Jc(ye).some(zc))throw Error("OpenCode lists no active cc-safety-net for this directory. Run `opencode api plugin.list` for details.")}}}return Vc(P),{commands:[["opencode","plugin","-g","-f",bt]],afterInstall:()=>Ih(P)}}function Jc(P){return _h(P).filter((G)=>Fe(G,"id")===fr||yo(Fe(Fe(G,"source"),"target"))).map((G)=>Fe(G,"state"))}function zc(P){return Fe(P,"status")==="active"}function ts(P){let G=Jc(P);if(G.some(zc))return;let K=G.find((Y)=>Fe(Y,"status")==="failed");if(!K)return;return`OpenCode reports cc-safety-net failed: ${String(Fe(K,"error")).split(`
226
+ `)[0]}`}function _h(P){if(!P)return[];try{let G=Fe(JSON.parse(P),"data");return Array.isArray(G)?G:[]}catch{return[]}}async function Yi(P=1){let G=await pn(["opencode","plugin","list"],{stdoutOnly:!0});if(/^cc-safety-net\s|\scc-safety-net@latest\s*$/m.test(G)||P===Eh)return G;return await new Promise((K)=>setTimeout(K,Th)),Yi(P+1)}async function Ih(P){let G=_n(qc(P),"node_modules",fr),K=_n(G,"package.json");if(!go(K))throw Error(`The OpenCode plugin cache at ${G} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${bt}\` for details.`);let Y=Fe(JSON.parse(Zi(K,"utf-8")),"main");if(typeof Y!=="string")throw Error(`The cached OpenCode plugin at ${G} declares no "main" entry.`);let Z=_n(G,Y);if(typeof(await import(Rh(Z).href))[Bc]==="function")return;throw Error(`The cached OpenCode plugin at ${Z} does not export a callable ${Bc}, so OpenCode would load nothing and fail open.`)}function rs(P,G){try{return JSON.parse(gn(P))}catch(K){if(K instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${G}: ${K.message}`);throw K}}function yo(P){let G=typeof P==="string"?P:Fe(P,"package");return typeof G==="string"&&(G===fr||G.startsWith(`${fr}@`))}function os(P){return["plugin","plugins"].some((G)=>{let K=Fe(P,G);return Array.isArray(K)&&K.some(yo)})}function Oh(P,G){let Y=["plugin","plugins"].flatMap((Z)=>{let X=vl(P,Z,Ah);if(!X)return[];let ie=[],ae=0,ge=X.start+1,ye=P.slice(X.start+1,X.end).matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|[^"\s{}[\],/]+|[{}[\],]/g);for(let Pe of ye){if(Pe[0].startsWith("//")||Pe[0].startsWith("/*"))continue;let Re=X.start+1+Pe.index;if(ae===0)ge=Re;if(Pe[0]==="{"||Pe[0]==="[")ae++;if(Pe[0]==="}"||Pe[0]==="]")ae--;if(ae!==0||Pe[0]===",")continue;let _e=Re+Pe[0].length;if(yo(JSON.parse(gn(P.slice(ge,_e)))))ie.push({start:ge,end:_e})}return ie}).sort((Z,X)=>Z.start-X.start).reverse().reduce((Z,X)=>{let ie=/^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*,/.exec(Z.slice(X.end));if(ie?.[0].includes("/")){let ae=X.end+ie[0].length-1;return Z.slice(0,X.start)+Z.slice(X.end,ae)+Z.slice(ae+1)}return hl(Z,X)},P);return rs(Y,G),Y}function Wc(P){Vc(P);let G=ns(P),K=G.find((X)=>go(X)),Y=[],Z=[];for(let X of G){if(!go(X))continue;try{let ie=Zi(X,"utf-8");if(!os(rs(ie,X)))continue;sn(X,Oh(ie,X)),Z.push(X)}catch(ie){Y.push(ie instanceof Error?ie.message:String(ie))}}if(Y.length>0)throw Error(Y.join(`
227
+ `));return{path:Z[0]??K??_n(Qi(P),Xi[0]),alreadyInstalled:Z.length>0}}function Jt(P){let G=[];for(let K of P.openCodeVersion?.startsWith("2.")?es(P.environment):ns(P.environment))if($h(K))try{let Y=Dh(K,"utf-8"),Z=gn(Y),X=JSON.parse(Z);if(os(X)){let ie=ts(P.openCodePluginListOutput);if(ie)return{platform:"opencode",status:"disabled",method:"opencode api plugin.list",configPath:K,errors:[...G,ie]};return{platform:"opencode",status:"configured",method:"plugin array",configPath:K,errors:G.length>0?G:void 0}}}catch(Y){G.push(`Failed to parse ${Nh(K)}: ${Y instanceof Error?Y.message:String(Y)}`)}return{platform:"opencode",status:"n/a",errors:G.length>0?G:void 0}}import{join as Yc}from"node:path";var Xc="dist/pi/index.js",Zc=new Set([Xc,"index.js"]),Lh=/[*?[\]{}]/;function is(P){let G=P.env.get("PI_CODING_AGENT_DIR");return Yc(G?Nn(G,P.home):Yc(P.home,".pi","agent"),"settings.json")}function ss(P){if(typeof P!=="string")return!1;return P==="npm:cc-safety-net"||P.startsWith("npm:cc-safety-net@")}function jh(P){if(!Array.isArray(P)||P.length===0)return!1;if(!P.every((Y)=>typeof Y==="string"))return!1;let G=(Y)=>P.some((Z)=>Z.startsWith(Y)&&Z.slice(1).replace(/^\.[/\\]/,"")===Xc);if(G("-"))return!1;if(G("+"))return!0;let K=P.filter((Y)=>!/^[-+!]/.test(Y));return(K.length===0||K.some((Y)=>Zc.has(Y)))&&!P.some((Y)=>Y.startsWith("!")&&(Zc.has(Y.slice(1))||Lh.test(Y)))}function Qc(P){let G=is(P.environment),K=yn(G);if(K.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(K.kind==="missing")return{platform:"pi",status:"n/a"};let Y=Fe(K.value,"packages");if(!Array.isArray(Y))return{platform:"pi",status:"n/a"};let Z=Y.find((ie)=>ss(typeof ie==="string"?ie:Fe(ie,"source")));if(Z===void 0)return{platform:"pi",status:"n/a"};let X=Fe(Z,"extensions");if(X!==void 0&&!jh(X))return{platform:"pi",status:"disabled",method:"package config",configPath:G,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:G}}var Fh={amp:tl,"antigravity-cli":sl,"claude-code":ul,codex:fl,"copilot-cli":Il,cursor:Ml,"deepseek-harness":Bl,devin:Yl,droid:oc,"gemini-cli":ic,"grok-build":gc,"hermes-agent":Ec,"kimi-code":po,openclaw:Uc,opencode:Jt,pi:Qc};function zt(P,G,K){let Y={...K,cwd:G,environment:P};return Er.map((Z)=>Hh(Fh[Z](Y)))}function Hh(P){if(P.status==="not-inspected")return{platform:P.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:P.platform,detected:P.status!=="n/a",configured:P.status==="configured",inspectionStatus:P.status!=="n/a"?"verified":P.errors&&P.errors.length>0?"failed":"not-applicable",method:P.method,configPath:P.configPath,configPaths:P.configPaths,errors:P.errors}}import{join as Mh}from"node:path";var Uh=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}]),Bh=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),commandTools:Object.freeze([]),safety:Object.freeze({level:"standard"}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),Gh={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 ed(P){let G=Mh(P.tmpdir,"cc-safety-net-self-test"),K=Uh.map((Y)=>{let Z=H(P,l("self-test",{command:Y.command},{kind:"command",shell:"auto"},{configCwd:G,executionCwd:G},Y.command),{guard:{dependencies:{loadPolicySnapshot:()=>Bh,getModes:()=>Gh,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),X=Y.expectBlocked?"blocked":"allowed",ie=Z.decision.kind==="deny"?"blocked":"allowed";return{command:Y.command,description:Y.description,expected:X,actual:ie,passed:X===ie,reason:Z.decision.kind==="deny"?Z.decision.reason:void 0,ruleId:Z.decision.kind==="deny"?Z.decision.ruleId:void 0}});return{passed:K.filter((Y)=>Y.passed).length,failed:K.filter((Y)=>!Y.passed).length,total:K.length,results:K}}function as(P){let G=fn({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},P);if($n(G.errors))return null;return{json:G.flags.json,skipUpdateCheck:G.flags.skipUpdateCheck}}async function nd(P,G={}){let K=await tr(!G.json,()=>{let Y=Vh(P,G);return{ready:Y,finish:()=>Y}},()=>nr(),{loadingMessage:"Checking system status…"});if(G.json)console.log(JSON.stringify(K,null,2));else Kh(K);return K.engineSelfTest.failed>0||K.findings.some((Y)=>Y.severity==="error")?1:0}async function Vh(P,G){let K=G.cwd??process.cwd(),Y=await Nr((Oe)=>Jt({environment:P,cwd:K,openCodeVersion:Oe}).status!=="n/a",void 0,K),Z=zt(P,K,{ampPluginListOutput:Y.ampPluginListOutput,codexPluginListOutput:Y.codexPluginListOutput,copilotCliVersion:Y.versions["copilot-cli"],openCodeVersion:Y.versions.opencode,openCodePluginListOutput:Y.openCodePluginListOutput}),X=ba(P,K),ie=wa(P),ae=R(P,{cwd:K}),ge=ae.policy,ye=_(ge,P.env),Pe=q(ge,ye.capabilities),Re=Ir(P,7),_e=Za(P,K),Ae=[Lt(K),jt(P)].filter((Oe)=>qh(Oe)),Ie=G.skipUpdateCheck?{currentVersion:un(),latestVersion:null,updateAvailable:!1}:await Bn(),je={hooks:Z,engineSelfTest:ed(P),userConfig:X.userConfig,projectConfig:X.projectConfig,configState:Ke(ae),effectiveRules:X.effectiveRules,environment:ie,effectiveSafety:{selectedPreset:ge.safety.level,level:ye.effectiveLevel,capabilities:ye.capabilities,ruleOverrides:ge.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(Pe).filter(([,Oe])=>Oe.source==="rule_override"&&Oe.override==="off"&&Oe.inheritedEnabled&&Oe.changesInherited).map(([Oe])=>Oe),ruleCounts:{stored:Object.keys(ge.destructiveCommandRuleOverrides).length,effective:Object.values(Pe).filter((Oe)=>Oe.changesInherited).length},...ae.policyScopes?{policyScopes:ae.policyScopes}:{}},..._e.length>0?{v2Leftovers:_e}:{},...Ae.length>0?{legacyConfigs:Ae}:{},posture:Da(P,X.userConfig.path),activity:Re,update:Ie,system:Y};return{...je,findings:Ca(je)}}function Kh(P){console.log(),console.log(Pa(P.hooks)),console.log(),console.log(Sa(P.engineSelfTest)),console.log(),console.log(Ra(P)),console.log(),console.log(Ea(P.environment)),console.log(),console.log(Ta(P)),console.log(),console.log(Aa(P.findings)),console.log(),console.log(_a(P.activity)),console.log(),console.log(Oa(P.system)),console.log(),console.log(Ia(P.update)),console.log($a(P))}import{existsSync as Jh}from"node:fs";var zh=/^[A-Za-z0-9_@%+=:,./-]+$/,td="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function ls(P){let G=fn({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},P);if($n(G.errors))return console.error(td),console.error("Pass -- before a command that starts with dashes."),null;if(G.values.cwd!==void 0&&!Jh(G.values.cwd))return console.error(`Error: --cwd path does not exist: ${G.values.cwd}`),null;let K=G.positionals.length===1?G.positionals[0]:G.positionals.map((Y)=>zh.test(Y)?Y:`'${Y.replaceAll("'","'\\''")}'`).join(" ");if(!K)return console.error("Error: No command provided"),console.error(td),null;return{json:G.flags.json,cwd:G.values.cwd,command:K}}function rd(P){if(P)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function od(P,G){let Y=G-18;return[`${P.dtl}${P.dh.repeat(G)}${P.dtr}`,`${P.dv} Command Analysis${" ".repeat(Y)}${P.dv}`,`${P.dbl}${P.dh.repeat(G)}${P.dbr}`]}function cs(P){return JSON.stringify(P)}function id(P,G=0){return`[${P.map((Y,Z)=>xa(Y,Z,G)).join(",")}]`}function mr(P,G,K=70){let Y=P.split(" "),Z=[],X="";for(let ie of Y)if(X&&X.length+ie.length+1>K)Z.push(X),X=ie;else X=X?`${X} ${ie}`:ie;if(X)Z.push(X);return Z.map((ie,ae)=>ae===0?ie:`${G}${ie}`)}function sd(P,G,K){let Y=[];switch(P.type){case"parse":return null;case"env-strip":return Y.push(""),Y.push(`STEP ${G} ${K.h} Strip environment variables`),Y.push(` Removed: ${P.envVars.map((Z)=>`${Z}=<redacted>`).join(", ")}`),Y.push(` Tokens: ${cs(P.output)}`),{lines:Y,incrementStep:!0};case"leading-tokens-stripped":return Y.push(""),Y.push(`STEP ${G} ${K.h} Strip wrappers`),Y.push(` Removed: ${P.removed.join(", ")}`),Y.push(` Tokens: ${cs(P.output)}`),{lines:Y,incrementStep:!0};case"shell-wrapper":return Y.push(""),Y.push(`STEP ${G} ${K.h} Detect shell wrapper`),Y.push(` Wrapper: ${P.wrapper} -c`),Y.push(` Inner: ${P.innerCommand}`),{lines:Y,incrementStep:!0};case"interpreter":{if(Y.push(""),Y.push(`STEP ${G} ${K.h} Detect interpreter`),Y.push(` Interpreter: ${P.interpreter}`),Y.push(` Code: ${P.codeArg}`),P.paranoidBlocked)Y.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:Y,incrementStep:!0}}case"busybox":return Y.push(""),Y.push(`STEP ${G} ${K.h} Busybox wrapper`),Y.push(` Subcommand: ${P.subcommand}`),{lines:Y,incrementStep:!0};case"transparent-wrapper":return Y.push(""),Y.push(`STEP ${G} ${K.h} Transparent wrapper`),Y.push(` Wrapper: ${P.wrapper}`),Y.push(` Tokens: ${cs(P.output)}`),{lines:Y,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(Y.push(""),Y.push(`STEP ${G} ${K.h} Match rules`),Y.push(` Rule: ${P.rule}()`),P.matched)Y.push(" Result: MATCHED");else Y.push(" Result: No match");return{lines:Y,incrementStep:!0}}case"worktree-relaxation":return Y.push(""),Y.push(`STEP ${G} ${K.h} Worktree relaxation`),Y.push(` Mode: ${n.worktree.name}`),Y.push(` Git cwd: ${P.gitCwd}`),Y.push(" Result: Allowed local discard in linked worktree"),{lines:Y,incrementStep:!0};case"temp-root-relaxation":return Y.push(""),Y.push(`STEP ${G} ${K.h} Temp-root relaxation`),Y.push(` Git cwd: ${P.gitCwd}`),Y.push(" Result: Allowed git discard in a temp-root repository"),{lines:Y,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(P.embeddedCommandFound)return Y.push(""),Y.push(`STEP ${G} ${K.h} Fallback scan`),Y.push(` Found: ${P.embeddedCommandFound}`),{lines:Y,incrementStep:!0};return null}case"custom-rules-check":{if(P.rulesChecked){if(Y.push(""),Y.push(`STEP ${G} ${K.h} Custom rules`),P.matched)Y.push(" Result: MATCHED");else Y.push(" Result: No match");return{lines:Y,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(P.matched)return Y.push(""),Y.push(`STEP ${G} ${K.h} Dangerous text check`),Y.push(` Token: ${P.token}`),Y.push(" Result: MATCHED"),{lines:Y,incrementStep:!0};return null}case"strict-unparseable":return Y.push(""),Y.push(`STEP ${G} ${K.h} Strict mode check`),Y.push(` Command: ${P.rawCommand}`),Y.push(" Result: ✗ UNPARSEABLE"),{lines:Y,incrementStep:!0};case"segment-skipped":return null;case"error":return Y.push(""),Y.push(`ERROR: ${P.message}`),{lines:Y,incrementStep:!1};default:return P}}function ds(P,G){let K=rd(G?.asciiOnly??!1),Y=58,Z=[],X=1;Z.push(...od(K,58)),Z.push("");let ie=P.trace.steps.find((Ie)=>Ie.type==="error");if(ie&&ie.type==="error"){Z.push("ERROR"),Z.push(` ${ie.message}`),Z.push(""),Z.push("RESULT"),Z.push(` Status: ${P.result==="blocked"?Qe.red("BLOCKED"):Qe.green("ALLOWED")}`),Z.push(""),Z.push("CONFIG");let Ie=P.configSource??"none";return Z.push(` Path: ${Ie}`),Z.join(`
228
+ `)}let ae=P.trace.steps.find((Ie)=>Ie.type==="parse");if(ae&&ae.type==="parse"){Z.push("INPUT"),Z.push(` ${ae.input}`),Z.push(""),Z.push(`STEP ${X} ${K.h} Split shell commands`),X++;for(let Ie=0;Ie<ae.segments.length;Ie++){let je=ae.segments[Ie];if(je){let Oe=Math.random();Z.push(` Segment ${Ie+1}: ${id(je,Oe)}`)}}}let ge=P.trace.segments,ye=ge.length>1;for(let Ie of ge){if(ye){Z.push("");let nn="";if(ae&&ae.type==="parse"){let Bo=ae.segments[Ie.index];if(Bo)nn=Bo.join(" ")}let rn=54,an=nn,en=` Segment ${Ie.index+1}: `,on=" ";if(nn){if(en.length+nn.length+on.length>rn){let kf=rn-en.length-on.length;an=`${nn.substring(0,kf-1)}…`}}let xn=nn?`${en}${an}${on}`:` Segment ${Ie.index+1} `,bf=nn?`${en}${Qe.cyan(an)}${on}`:xn,Js=58-xn.length,zs=Math.floor(Js/2),wf=Js-zs;Z.push(`${K.sh.repeat(zs)}${bf}${K.sh.repeat(wf)}`)}if(Ie.steps.find((nn)=>nn.type==="segment-skipped")){Z.push(""),Z.push(" (skipped — prior segment blocked)");continue}let Oe=!1,Ve=!1;for(let nn of Ie.steps){let rn=sd(nn,X,K);if(rn){if(Ve=!0,nn.type==="recurse"){Z.push("");let an=" RECURSING ",en=58-an.length-4;Z.push(` ${K.tl}${K.h}${an}${K.h.repeat(en)}`),Z.push(` ${K.v}`),Oe=!0;continue}for(let an of rn.lines)if(Oe)Z.push(` ${K.v} ${an}`);else Z.push(an);if(rn.incrementStep)X++}}if(Oe)Z.push(` ${K.v}`),Z.push(` ${K.bl}${K.h.repeat(56)}`);if(!Ve)Z.push(""),Z.push(` ${Qe.green("✓")} Allowed (no matching rules)`)}if(Z.push(""),Z.push("RESULT"),P.result==="blocked"){if(Z.push(` Status: ${Qe.red("BLOCKED")}`),P.customRule){if(Z.push(` Rule: ${P.customRule.id}`),P.customRule.rulebook)Z.push(` Rulebook: ${P.customRule.rulebook.name} ${P.customRule.rulebook.version}`);if(P.customRule.source)Z.push(` Source: ${P.customRule.source}`);if(P.customRule.override)Z.push(` Override: reason ${P.customRule.override.reason}`)}if(P.reason){let Ie=mr(P.reason," ");Z.push(` Reason: ${Ie[0]}`);for(let je=1;je<Ie.length;je++)Z.push(Ie[je]??"")}}else Z.push(` Status: ${Qe.green("ALLOWED")}`);Z.push(""),Z.push("CONFIG");let Pe=P.configSource??"none",Re=P.configValid?"":" (invalid)";Z.push(` Path: ${Pe}${Re}`);let _e=P.safetyPresetScope;Z.push(` Safety preset: ${P.selectedPreset??"standard"}${_e?` (${Or(_e)})`:""}`),Z.push(` Effective capabilities: ${P.effectiveLevel}`);let Ae=Object.entries(P.destructiveCommandRuleOverrides??{});if(Z.push(` Rule customizations: ${Ae.length}`),P.ruleActivation)Z.push(` Rule activation: ${P.ruleActivation.id} — ${P.ruleActivation.enabled?"on":"off"} via ${P.ruleActivation.source}`);return Z.join(`
229
+ `)}function us(P){return JSON.stringify(P,null,2)}import{resolve as Xh}from"node:path";var ad=512,ld={maxTextLength:2048,maxListLength:128,maxObjectProperties:128,maxDepth:16},Wh=["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 ms(P){let G=0,K={allocateSegment(){return G++},getNextSegmentIndex(){return G},branch(){let Y=P.fork(),Z=ms(Y);return{trace:Z,adopt(){P.replaceSegmentEvents(Y.finish().events),G=Z.getNextSegmentIndex()}}},recordGlobal(Y){P.record({scope:"global",step:Y})},recordSegment(Y,Z=K.currentSegmentIndex){if(Z===void 0)return;P.record({scope:"segment",segmentIndex:Z,step:Y})}};return K}function gs(P=new Set){let G=[];return{record(K){if(G.length>=ad)return;ho(K.step,P,ld),G.push({...K,step:ps(K.step,ld,P)})},fork(){return gs(P)},replaceSegmentEvents(K){G.splice(0,G.length,...[...G.filter((Y)=>Y.scope==="global"),...K].slice(0,ad))},finish(){return{events:G}}}}function ho(P,G,K,Y=0,Z=new WeakSet){if(typeof P==="string"){let ae=P.slice(0,K.maxTextLength);if(!it(ae))return;for(let ge of xt(ae))for(let ye of ge.match(/[^\s"'()$]+/g)??[])G.add(cd(ye));return}if(!P||typeof P!=="object"||Y>=K.maxDepth||Z.has(P))return;if(Z.add(P),Array.isArray(P)){let ae=Math.min(P.length,K.maxListLength);for(let ge=0;ge<ae;ge++)ho(P[ge],G,K,Y+1,Z);return}let X=0,ie=new Set;for(let ae in P){if(!Object.hasOwn(P,ae))continue;if(X>=K.maxObjectProperties)break;X++,ho(ae,G,K);let ge=fs(ae,K,G);if(ie.has(ge))continue;ie.add(ge),ho(P[ae],G,K,Y+1,Z)}}function ps(P,G,K,Y=0,Z=new WeakSet){if(typeof P==="string")return fs(P,G,K);if(!P||typeof P!=="object")return P;if(Y>=G.maxDepth)return;if(Z.has(P))return;if(Z.add(P),Array.isArray(P)){let ae=[],ge=Math.min(P.length,G.maxListLength);for(let ye=0;ye<ge;ye++)ae.push(ps(P[ye],G,K,Y+1,Z));return ae}let X={},ie=0;for(let ae in P){if(!Object.hasOwn(P,ae))continue;if(ie>=G.maxObjectProperties)break;ie++;let ge=fs(ae,G,K);if(Object.hasOwn(X,ge))continue;Object.defineProperty(X,ge,{value:ps(P[ae],G,K,Y+1,Z),enumerable:!0,configurable:!0,writable:!0})}return X}function fs(P,G,K){let Y=P.slice(0,G.maxTextLength),Z=it(Y)?ot(Y):Y,X=K.size>0?Zh(Z,K):Z;return(Yh(X)?$e(X):X).slice(0,G.maxTextLength)}function Yh(P){return P.includes("PRIVATE KEY")||P.includes("://")||P.includes("eyJ")||P.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(P)||P.length>=14&&Wh.some((G)=>P.includes(G))||P.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(P)}function Zh(P,G){return P.replace(/[^\s"'()$]+/g,(K)=>G.has(cd(K))?"<redacted>":K)}function cd(P){let G=2166136261,K=2166136261;for(let Y=0;Y<P.length;Y++)G=Math.imul(G^P.charCodeAt(Y),16777619),K=Math.imul(K^P.charCodeAt(P.length-Y-1),16777619);return`${G>>>0}:${K>>>0}:${P.length}`}function gr(P,G={},K){let Y=Xh(G.cwd??process.cwd()),Z=G.policySnapshot??R(K,{cwd:Y,userConfigDir:G.userConfigDir}),X=_(Z.policy,K.env),ie=Je({policySnapshot:Z,effectiveCapabilities:X.capabilities,worktreeMode:X.worktreeMode}),ae={effectiveLevel:ie.effectiveLevel,selectedPreset:Z.policy.safety.level,...Z.policyScopes?{safetyPresetScope:Z.policyScopes.levelScope}:{},effectiveCapabilities:ie.effectiveCapabilities,destructiveCommandRuleOverrides:Z.policy.destructiveCommandRuleOverrides},{configSource:ge,configValid:ye}=ev(K,{cwd:Y,userConfigDir:G.userConfigDir});if(!P||!P.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:ge,configValid:ye,...ae};let Pe=v(P,"auto");if(Pe.status==="limited")throw new b;let Re=Pe.dialect==="powershell"?v(P,"posix"):Pe,_e=Pt(Re),Ae=gs(),Ie=ms(Ae);Ie.recordGlobal({type:"parse",input:P,segments:_e.map((xn)=>[...xn])});let je=l("Bash",{command:P},{kind:"command",shell:"auto"},{configCwd:Y,executionCwd:Y},P),Oe=j(je,{environment:K,trace:Ie,dependencies:{loadPolicySnapshot:()=>Z}}),Ve=Oe.decision.kind==="deny"?Oe.decision:null;if(Ve&&(Oe.stage==="policy-protection"||Oe.stage==="secret-protection"))return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Qh(Ve),matched:!0,reason:Ve.reason}]}]},result:"blocked",reason:T(Ve.reason),segment:T(dd(Ve,P)),ruleId:T(Ve.ruleId),configSource:ge,configValid:ye,...ae};let nn=Ie.getNextSegmentIndex();if(Ve&&nn>0&&nn<_e.length)Ie.recordSegment({type:"segment-skipped",index:nn,reason:"prior-segment-blocked"},nn);let rn=Ae.finish(),an=Ve?.ruleId??nv(je,Z,X,K),en=V.find((xn)=>xn.id===an&&xn.activationCapability),on=en?ie.policy.effectiveDestructiveCommandRules[en.id]:void 0;return{trace:rv(rn),result:Ve?"blocked":"allowed",reason:Ve?T(Ve.reason):void 0,segment:Ve?T(dd(Ve,P)):void 0,ruleId:Ve?T(Ve.ruleId):void 0,customRule:tv(ov(Ve?.ruleId,Z)),configSource:ge,configValid:ye,...ae,...en&&on?{ruleActivation:{id:en.id,...on}}:{}}}function dd(P,G){return P.evidence?.segment??G}function Qh(P){if(P.reason===Ze)return"policy-protection:findPolicyConfigMutationTargetInSemanticFacts";if(P.reason===Ye)return"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts";if(P.reason===g)return"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts";return"secret-protection:findSensitiveTargetInSemanticFacts"}function ev(P,G){let K=A(G.cwd),Y=W(P,G),Z=ee(P,{cwd:G.cwd,userConfigDir:G.userConfigDir});try{if(r(Z.projectConfigTarget)!==null){if(Un(Z.projectConfigTarget).errors.length===0)return{configSource:K,configValid:!0};return{configSource:K,configValid:!1}}}catch(X){if(X instanceof o)return{configSource:K,configValid:!1};throw X}try{if(r(Z.userConfigTarget)!==null){let X=Un(Z.userConfigTarget);return{configSource:Y,configValid:X.errors.length===0}}return{configSource:null,configValid:!0}}catch(X){if(X instanceof o)return{configSource:Y,configValid:!1};throw X}}function nv(P,G,K,Y){let Z=G.policy,X=Me({...Z,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...Z.destructiveCommandRuleOverrides,...Object.fromEntries(V.flatMap((ae)=>ae.activationCapability?[[ae.id,"on"]]:[]))}},G.state==="degraded"?{diagnostics:G.diagnostics,reason:G.reason}:void 0),ie=j(P,{environment:Y,dependencies:{loadPolicySnapshot:()=>X,getModes:()=>({...K,strict:!0,paranoidRm:!0,paranoidInterpreters:!0,capabilities:{fail_closed:{...K.capabilities.fail_closed,enabled:!0},paranoid_rm:{...K.capabilities.paranoid_rm,enabled:!0},paranoid_interpreters:{...K.capabilities.paranoid_interpreters,enabled:!0}}}),findSensitiveTarget:()=>null}});return ie.decision.kind==="deny"?ie.decision.ruleId:void 0}function tv(P){if(!P)return;return{id:T(P.id),...P.rulebook?{rulebook:{name:T(P.rulebook.name),version:T(P.rulebook.version)}}:{},...P.source?{source:T(P.source)}:{},...P.override?{override:{type:"reason",reason:T(P.override.reason)}}:{}}}function rv(P){let G=P.events.flatMap((Y)=>Y.scope==="global"?[Y.step]:[]),K=new Map;for(let Y of P.events){if(Y.scope!=="segment")continue;let Z=K.get(Y.segmentIndex)??{index:Y.segmentIndex,steps:[]};Z.steps.push(Y.step),K.set(Y.segmentIndex,Z)}return{steps:G,segments:[...K.values()]}}function ov(P,G){let K=P?.replace(/^custom\./,"");if(!K||!G.policy.rules.some((Y)=>Y.name===K))return;return G.ruleMetadata[K]??Object.freeze({id:K})}function ud(P){return new Promise((G)=>{process.stdout.write(`${P}
230
+ `,()=>G())})}async function pd(P,G){let K=ls(G);if(!K)return 1;try{let Y=gr(K.command,{cwd:K.cwd},P),Z=!!process.env.NO_COLOR||!process.stdout.isTTY;return await ud(K.json?us(Y):ds(Y,{asciiOnly:Z})),0}catch(Y){let Z=iv(Y instanceof f?Y.cause:Y);if(Z===void 0)throw Y;if(K.json)return await ud(JSON.stringify({error:Z})),1;return console.error(Z),1}}function iv(P){if(P instanceof b)return P.message;if(P instanceof F)return P.message;if(P instanceof m)return P.message;if(P instanceof s&&a[P.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var fd="2.6.18",Rn=" ",Ct="cc-safety-net";function md(P){return P.argument?`${P.flags} ${P.argument}`:P.flags}function sv(P){return Math.max(...P.map((G)=>md(G).length))}function av(P){return Math.max(...P.map((G)=>G.usage.length))}function lv(P){return Math.max(...P.map((G)=>`${Ct} ${G.usage}`.length))}function cv(P,G){let K=`${Ct} ${P.usage}`;return`${Rn}${K.padEnd(G+2)}${P.description}`}function In(P,G){return`${Rn}${P.padEnd(Math.max(40,P.length+2))}${G}`}function Wt(P,G=console.log){let K=[];if(K.push(`${Ct} ${P.name}`),K.push(""),K.push(`${Rn}${P.description}`),K.push(""),K.push("USAGE:"),K.push(`${Rn}${Ct} ${P.usage}`),K.push(""),P.subcommands&&P.subcommands.length>0){K.push("SUBCOMMANDS:");let Y=av(P.subcommands);for(let Z of P.subcommands)K.push(`${Rn}${Z.usage.padEnd(Y+2)}${Z.description}`);K.push("")}if(P.options.length>0){K.push("OPTIONS:");let Y=sv(P.options);for(let Z of P.options){let X=md(Z),ie=Z.default?`${Z.description} (default: ${Z.default})`:Z.description;K.push(`${Rn}${X.padEnd(Y+2)}${ie}`)}K.push("")}if(P.examples&&P.examples.length>0){K.push("EXAMPLES:");for(let Y of P.examples)K.push(`${Rn}${Y}`)}G(K.join(`
231
+ `))}function ys(){let P=lv(Ar),G=[];G.push(`${Ct} v${fd}`),G.push(""),G.push("Blocks destructive commands and secret access."),G.push(""),G.push("COMMANDS:");for(let K of Ar)G.push(cv(K,P));G.push(""),G.push("GLOBAL OPTIONS:"),G.push(`${Rn}-h, --help Show help (use with command for command-specific help)`),G.push(`${Rn}-V, --version Show version`),G.push(""),G.push("HELP:"),G.push(`${Rn}${Ct} help <command> Show help for a specific command`),G.push(`${Rn}${Ct} <command> --help Show help for a specific command`),G.push(""),G.push("ENVIRONMENT VARIABLES:"),G.push(In(`${n.level.name}=standard|strict|paranoid`,"Set session safety level")),G.push(In(`${n.worktree.name}=1`,"Allow local git discards in linked worktrees")),G.push(In(`${n.debug.name}=1`,"Print diagnostic messages to stderr")),G.push(In(`${n.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),G.push(In(`${n.projectTightenOnly.name}=1`,"Ignore project policy settings that weaken the user policy")),G.push(In("CC_SAFETY_NET_HOME","Override rule config home directory")),G.push(""),G.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),G.push(In(`${n.strict.name}=1`,"Force safety.overrides.fail_closed on")),G.push(In(`${n.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),G.push(In(`${n.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),G.push(In(`${n.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),G.push(""),G.push("Documentation: https://ccsafetynet.com/docs"),console.log(G.join(`
232
+ `))}function gd(){console.log(fd)}function yr(P,G=console.log){let K=_r(P);if(!K)return!1;if(K.name.toLowerCase()!==P.toLowerCase())return!1;return Wt(K,G),!0}import{existsSync as So,readFileSync as Cu}from"node:fs";import{join as Po}from"node:path";import*as Vn from"node:readline";function dv(P){return P==="install"?"Install":"Uninstall"}function uv(P){return P==="install"?"Installing":"Uninstalling"}function pv(P){return P==="install"?"into":"from"}function vd(P){return P?.available===!0}function fv(P,G){let K=new Set(G);return P.filter((Y)=>K.has(Y.target)).map((Y)=>Y.target)}function yd(P,G,K){if(P.every((Y)=>!Y.available))return G;return Array.from({length:P.length},(Y,Z)=>Z+1).map((Y)=>(G+Y*K+P.length)%P.length).find((Y)=>vd(P[Y]))}function mv(P,G,K){if(K.ctrl&&K.name==="c")return"interrupt";if(K.name==="escape"||G==="q")return"abort";if(P==="install"&&(G==="u"||G==="U"))return"update";if(K.name==="up"||G==="k")return"up";if(K.name==="down"||G==="j")return"down";if(K.name==="space"||G===" ")return"toggle";if(K.name==="return"||K.name==="enter")return"confirm";return null}function gv(P){return{cursor:P.findIndex((G)=>G.available),selected:[]}}function yv(P,G,K){if(K==="confirm"||K==="update"||K==="abort"||K==="interrupt")return{state:P,done:K};if(K==="up")return{state:{...P,cursor:yd(G,P.cursor,-1)}};if(K==="down")return{state:{...P,cursor:yd(G,P.cursor,1)}};let Y=G[P.cursor];if(!vd(Y))return{state:P};let Z=P.selected.includes(Y.target)?P.selected.filter((X)=>X!==Y.target):fv(G,[...P.selected,Y.target]);return{state:{...P,selected:Z}}}var bd="◉",wd="◯",kd=">",Cd=" ";function hv(P,G,K){return["",`${dv(P)} CC Safety Net ${pv(P)}:`,"",...G.map((Y,Z)=>{let X=K.selected.includes(Y.target),ie=Z===K.cursor,ae=X?bd:wd,ge=ie?kd:Cd,ye=Y.available?"":` (${Y.unavailableReason??"not installed"})`,Pe=`${ae} ${Y.label}${ye}`,Re=!Y.available?Qe.dim(Pe):X?Qe.green(Pe):ie?Qe.bold(Pe):Pe;return`${ge} ${Re}`}),"",P==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":G.some((Y)=>Y.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${P}. q/Esc: close`].join(`
233
+ `)}var hd=["global-hook","plugin"];function vv(P,G,K={}){let Y=K.color!==!1?Qe.bold:(X)=>X;return["","Install the Kimi Code integration as:","",...[`Global hook — ${G?"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((X,ie)=>{let ae=ie===P,ge=`${ae?bd:wd} ${X}`;return`${ae?kd:Cd} ${ae?Y(ge):ge}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
234
+ `)}function xd(P){let{input:G,output:K}=P;Vn.emitKeypressEvents(G);let Y=G.isRaw===!0;G.setRawMode(!0),G.resume();let Z=0,X=()=>{if(Z===0)return;Vn.moveCursor(K,0,-Z),Vn.cursorTo(K,0),Vn.clearScreenDown(K)},ie=()=>{X();let ae=P.render();K.write(`${ae}
235
+ `),Z=ae.split(`
236
+ `).length};return new Promise((ae)=>{let ge=(Pe)=>{G.off("keypress",ye),G.setRawMode(Y),G.pause(),X(),ae(Pe)};function ye(Pe,Re){P.onKey(Pe,Re,{finish:ge,draw:ie})}G.on("keypress",ye),ie()})}function Pd(P={}){let G=0;return xd({input:P.input??process.stdin,output:P.output??process.stdout,render:()=>vv(G,P.globalHookInstalled===!0),onKey:(K,Y,Z)=>{if(Y.ctrl&&Y.name==="c"){Z.finish(null),(P.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(Y.name==="escape"||K==="q")return Z.finish(null);if(Y.name==="return"||Y.name==="enter")return Z.finish(hd[G]);if(Y.name==="up"||Y.name==="down"||K==="k"||K==="j")G=(G+1)%hd.length,Z.draw()}})}function hs(P=process.stdin,G=process.stdout){return Boolean(P.isTTY&&G.isTTY&&typeof P.setRawMode==="function")}function Sd(P,G,K={}){let Y=K.output??process.stdout,Z=gv(G);return xd({input:K.input??process.stdin,output:Y,render:()=>hv(P,G,Z),onKey:(X,ie,ae)=>{let ge=mv(P,X,ie);if(!ge)return;let ye=yv(Z,G,ge);if(Z=ye.state,ye.done==="interrupt"){ae.finish(null),(K.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(ye.done==="abort")return ae.finish(null);if(ye.done==="update")return ae.finish("update");if(ye.done==="confirm"){if(Z.selected.length===0){Y.write("\x07"),ae.draw();return}ae.finish([...Z.selected]),Y.write(`${uv(P)} selected integrations...
237
+ `);return}ae.draw()}})}import{existsSync as Rd,lstatSync as wv,mkdirSync as kv,mkdtempSync as Cv,readdirSync as xv,readFileSync as Zt,rmSync as bo}from"node:fs";import{basename as Pv,dirname as Sv,join as kn}from"node:path";import{fileURLToPath as Rv}from"node:url";var vs="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",St="cc-safety-net",At="cc-safety-net/index.ts";import{spawn as bv}from"node:child_process";var bs=(P,G)=>{let K=Zn([...P],process.env);return new Promise((Y)=>{let Z=bv(K.cmd,K.args,{cwd:G,stdio:["ignore","pipe","pipe"]}),X=pi(Z),ie=!1,ae=setTimeout(()=>{ie=!0,Z.kill()},120000);Z.on("error",(ge)=>{clearTimeout(ae),Y({status:null,errorCode:ge.code,stdout:X.stdout,stderr:[ge.message,X.stderr].filter(Boolean).join(`
238
+ `)})}),Z.on("close",(ge)=>{clearTimeout(ae),Y({status:ie?null:ge,errorCode:ie?"ETIMEDOUT":void 0,stdout:X.stdout,stderr:X.stderr})})})};var Yt="cc-safety-net.ts",ws=kn("amp",At);function Ev(P){return kn(P.home,".config","amp","plugins","cc-safety-net.ts")}function Tv(){let P=Sv(Rv(import.meta.url)),G=kn(P,ws),K=kn(P,"..",ws),Y=kn(P,"..","..","..","dist",ws);return[G,K,Y]}function Av(P=Tv()){let G=P.find((K)=>Rd(K)&&wv(K).isFile());if(!G)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return G}function Ed(P){try{return JSON.parse(P)}catch{return}}function wo(P){return P.subarray(0,Buffer.byteLength(vs)).toString("utf-8")===vs}async function hr(P,G,K){let Y=await P(G,K);if(Y.status===0)return Y;throw Error([`Failed to run ${G.join(" ")}${Y.status===null?"":` (exit ${Y.status})`}.`,[Y.stdout,Y.stderr].filter(Boolean).join(`
239
239
  `).trim()].filter(Boolean).join(`
240
- `))}async function Ed(P){let L=await P(["amp","plugins","repositories","--json"]);if(L.status===null)throw Error(`${L.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 (${L.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
241
- ${L.stderr}`.trim());if(L.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${L.status}). Sign in with "amp login" and rerun install --amp.
242
- ${[L.stdout,L.stderr].filter(Boolean).join(`
243
- `)}`.trim());let H=Rd(L.stdout),Y=(Array.isArray(H)?H:[]).filter((Z)=>Xe(Z,"scope")==="user"&&Xe(Z,"exists")===!0&&Xe(Z,"viewerCanWrite")===!0).map((Z)=>Xe(Z,"cloneRef")).find((Z)=>typeof Z==="string"&&Z.length>0);if(!Y)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 Y}async function Td(P,L,H){let Y=wv(Cn(L.tmpdir,"cc-safety-net-amp-"));try{return await hr(P,["amp","clone","user-plugins",Y]),await H(Y)}finally{bo(Y,{recursive:!0,force:!0})}}function ws(P){return`rerun ${P==="overwrite"?"install":"uninstall"} --amp`}function Ad(P,L,H){let Y=Cn(P,L),Z=dn(Y);if(!Z)return;if(Z.isSymbolicLink()||!Z.isFile())throw Error(`Refusing to ${H} ${L} in your Amp personal plugins repository: not a regular file. Remove it there and ${ws(H)}.`);let oe=Zt(Y);if(wo(oe))return oe;throw Error(`Refusing to ${H} unmanaged file ${L} in your Amp personal plugins repository. Remove it there and ${ws(H)}.`)}function _d(P,L){let H=Cn(P,Tt),Y=dn(H);if(!Y)return;if(Y.isSymbolicLink()||!Y.isDirectory())throw Error(`Refusing to ${L} ${Tt} in your Amp personal plugins repository: not a regular directory. Remove it there and ${ws(L)}.`);return Ad(P,At,L)}function Tv(P){let L=Cn(P,Yt),H=dn(L);if(!H||H.isSymbolicLink()||!H.isFile())return;let Y=Zt(L);return wo(Y)?Y:void 0}async function Id(P,L,H,Y){if(await hr(P,H,L),(await hr(P,["git","status","--porcelain"],L)).stdout.trim()==="")return!1;return await hr(P,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",Y],L),await hr(P,["git","push","origin","HEAD"],L),!0}function vo(P,L){Av(P,L),_v(P,L)}function Od(P,L){if(L==="keep")return;throw Error(`Local Amp plugin ${P} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function Av(P,L){let H=Sv(P),Y=dn(H);if(!Y)return;if(!Y.isSymbolicLink()&&Y.isFile()&&wo(Zt(H))){bo(H);return}Od(H,L)}function _v(P,L){let H=Cn(P.home,".config","amp","plugins",Tt),Y=dn(H);if(!Y)return;if(!Y.isSymbolicLink()&&Y.isDirectory()&&Iv(H)){bo(H,{recursive:!0});return}Od(H,L)}function Iv(P){let L=Cv(At);if(kv(P).join("\x00")!==L)return!1;let H=Cn(P,L),Y=dn(H);return!!Y&&!Y.isSymbolicLink()&&Y.isFile()&&wo(Zt(H))}function Ov(P){let L=u(P);if(!Sd(L))return"";let H=Rd(Zt(L,"utf-8"));if(!H||typeof H!=="object"||Array.isArray(H))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(k(H,P.home))};
244
- `}async function $d(P,L=Ev(),H=vs){let Y=Buffer.concat([Zt(L),Buffer.from(Ov(P),"utf-8")]),Z=await Ed(H);return Td(H,P,async(oe)=>{let se=`${Z}/${Tt}`,me=_d(oe,"overwrite"),he=Ad(oe,Yt,"overwrite");if(me?.equals(Y)&&!he)return vo(P,"fail"),{path:se,alreadyInstalled:!0};if(bv(Cn(oe,Tt),{recursive:!0}),an(Cn(oe,At),Y),he)bo(Cn(oe,Yt));let ke=await Id(H,oe,["git","add","--",At,...he?[Yt]:[]],`chore: update cc-safety-net plugin to v${pn()}`);return vo(P,"fail"),{path:se,alreadyInstalled:!ke}})}async function Dd(P,L=vs){let H=await Ed(L);return Td(L,P,async(Y)=>{let Z=_d(Y,"remove"),oe=Tv(Y),se=`${H}/${oe&&!Z?Yt:Tt}`;if(!Z&&!oe)return vo(P,"keep"),{path:se,alreadyInstalled:!1};return await Id(L,Y,["git","rm","--",...Z?[At]:[],...oe?[Yt]:[]],`chore: remove cc-safety-net plugin v${pn()}`),vo(P,"keep"),{path:se,alreadyInstalled:!0}})}import{existsSync as Nd,mkdirSync as $v,readFileSync as Dv}from"node:fs";import{dirname as Nv}from"node:path";var ks=kn["antigravity-cli"],_t="cc-safety-net";function It(P){return Boolean(P)&&typeof P==="object"&&!Array.isArray(P)}function Co(){return{PreToolUse:[{hooks:[{type:"command",command:ks,timeout:30}]}]}}function Ld(P){try{let L=JSON.parse(Dv(P,"utf-8"));if(!L||typeof L!=="object"||Array.isArray(L))throw Error("Antigravity hooks config must be a JSON object");return L}catch(L){if(L instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${P}: ${L.message}`);throw L}}function jd(P){let L=P[_t];if(L===void 0){let Y=Co();return P[_t]=Y,{definition:Y,preToolUse:Y.PreToolUse??[]}}if(!It(L))throw Error(`Antigravity hooks config entry "${_t}" must be an object`);let H=Array.isArray(L.PreToolUse)?L.PreToolUse:[];return L.PreToolUse=H,{definition:L,preToolUse:H}}function Fd(P){if(!Array.isArray(P.PreToolUse))return!1;return P.PreToolUse.some((L)=>It(L)&&Array.isArray(L.hooks)&&L.hooks.some((H)=>It(H)&&H.command===ks))}function Lv(P){return Object.values(P).some((L)=>It(L)&&L.enabled!==!1&&Fd(L))}function jv(P){if(P[_t]===void 0)return!1;let L=jd(P);if(L.definition.enabled!==!1||!Fd(L.definition))return!1;return L.definition.enabled=!0,!0}function Fv(P){if(P[_t]===void 0){P[_t]=Co();return}let L=jd(P);L.definition.enabled=!0,L.preToolUse.push(Co().PreToolUse?.[0]??{hooks:[]})}function Hv(P){let L=!1;for(let H of Object.values(P)){if(!It(H)||!Array.isArray(H.PreToolUse))continue;H.PreToolUse=H.PreToolUse.flatMap((Y)=>{if(!It(Y)||!Array.isArray(Y.hooks))return[Y];let Z=Y.hooks.filter((oe)=>!It(oe)||oe.command!==ks);if(Z.length!==Y.hooks.length)L=!0;return Z.length===0?[]:[{...Y,hooks:Z}]})}return L}function ko(P,L){an(P,`${JSON.stringify(L,null,2)}
245
- `)}function Hd(P){let L=rr(P.home);if($v(Nv(L),{recursive:!0}),!Nd(L))return ko(L,{[_t]:Co()}),{path:L,alreadyInstalled:!1};let H=Ld(L);if(Lv(H))return{path:L,alreadyInstalled:!0};if(jv(H))return ko(L,H),{path:L,alreadyInstalled:!1};return Fv(H),ko(L,H),{path:L,alreadyInstalled:!1}}function Md(P){let L=rr(P.home);if(!Nd(L))return{path:L,alreadyInstalled:!1};let H=Ld(L);if(!Hv(H))return{path:L,alreadyInstalled:!1};return ko(L,H),{path:L,alreadyInstalled:!0}}import{existsSync as Ps,readlinkSync as Bv}from"node:fs";import{join as Kn}from"node:path";import{spawn as Mv}from"node:child_process";var On=Rn.map((P)=>({target:P.id,flag:P.flag,label:cn(P.id),probeCommand:P.probeCommand}));function Cs(P){let L=new Set(P);return On.map((H)=>H.target).filter((H)=>L.has(H))}async function Ud(P,L){for(let H of P)await L(H)}var Uv=5000;function vr(P,L=Uv){return new Promise((H)=>{let Y=Xn([...P],process.env),Z=Mv(Y.cmd,Y.args,{env:process.env,stdio:"ignore"}),oe=!1,se=(he)=>{if(oe)return;oe=!0,clearTimeout(me),H(he)},me=setTimeout(()=>{Z.kill(),se(!1)},L);Z.on("error",()=>se(!1)),Z.on("close",(he)=>se(he===0))})}function Bd(P=vr,L={}){let H=new Set(L.configuredTargets??[]);return Promise.all(On.map(async(Y)=>({target:Y.target,flag:Y.flag,label:Y.label,...qd(L.action,await P(Y.probeCommand)||Y.target==="cursor"&&await P(ia),H.has(Y.target))})))}function Gd(P,L){let H=new Set(L.configuredTargets??[]);return P.map((Y)=>({...Y,...qd(L.action,Y.available,H.has(Y.target))}))}function qd(P,L,H){if(P==="uninstall")return H?{available:!0}:{available:!1,unavailableReason:"not installed"};if(P==="install"&&H)return{available:!1,unavailableReason:"already installed"};if(!L)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}var Jn="cc-safety-net",zd=["npx","-y","@deepseek-ai/dsh"],Vd="DeepSeek Harness",Kd=["@deepseek-ai","dsh-desktop"],Wd="Quit DeepSeek Harness Desktop, then run this command again: Desktop plugins can only change while it is closed.",xs=(P)=>`DeepSeek Harness Desktop is not in its default location, so ${P} ${Jn} from its Plugins page.`,Yd=(P,L)=>Ps(Kn(ki(P),L,"package.json"));function Ss(P,L){let H=L.platform??process.platform,Y=Yd(P,"desktop"),Z=H==="darwin"?[Kn(P.home,"Applications"),L.systemApplications??"/Applications"].map((oe)=>Kn(oe,`${Vd}.app`,"Contents","Resources","runtime","cli","bin","dsh")):H==="win32"?[Kn(P.env.get("LOCALAPPDATA")||Kn(P.home,"AppData","Local"),"Programs",Vd,"resources","runtime","cli","bin","dsh.cmd")]:[];return{profile:Y,cli:Y?Z.find((oe)=>Ps(oe)):void 0}}function Zd(P,L=process.platform){if(L==="win32")return Ps(Kn(P.env.get("APPDATA")||Kn(P.home,"AppData","Roaming"),...Kd,"lockfile"));let H=Gv(Kn(P.home,"Library","Application Support",...Kd,"SingletonLock")),Y=Number(/-(\d+)$/.exec(H??"")?.[1]);return Number.isInteger(Y)&&Y>0&&qv(Y)}function Gv(P){try{return Bv(P)}catch{return}}function qv(P){try{return process.kill(P,0),!0}catch(L){return L.code==="EPERM"}}async function Xd(P,L={}){let H=Ss(P,L);if(H.cli&&Zd(P,L.platform))throw Error(Wd);let Y=!H.cli||Yd(P,"web")||await(L.probe??vr)(qo),Z=[...H.cli?[{profile:"desktop",label:"Desktop",dsh:[H.cli]}]:[],...Y?[{profile:"web",label:"web",dsh:zd}]:[]];return{commands:Z.map((oe)=>[...oe.dsh,"plugin","--profile",oe.profile,"add",`${Jn}@${pn()}`]),afterInstall:async()=>{let oe=new Set(Ci(P).filter((me)=>me.enabled).map((me)=>me.name)),se=Z.filter((me)=>!oe.has(me.profile));if(se.length>0)throw Error(`DeepSeek Harness installed ${Jn} in the ${Jd(se)} but did not enable it. Enable it from the Plugins page.`)},message:[`Added ${Jn} to the DeepSeek Harness ${Jd(Z)}.`,...H.profile&&!H.cli?[xs("add")]:[]].join(`
246
- `)}}function Jd(P){return`${P.map((L)=>L.label).join(" and ")} profile${P.length>1?"s":""}`}function Qd(P,L={}){let H=new Set(Ci(P).map((oe)=>oe.name));if(!H.has("desktop")&&!H.has("web"))throw Error(`${Jn} is not installed in the DeepSeek Harness web or Desktop profile`);let Y=H.has("desktop")?Ss(P,L).cli:void 0,Z=H.has("desktop")&&!Y;if(Z&&!H.has("web"))throw Error(xs("remove"));if(Y&&Zd(P,L.platform))throw Error(Wd);return{commands:[...Y?[[Y,"plugin","--profile","desktop","remove",Jn]]:[],...H.has("web")?[[...zd,"plugin","--profile","web","remove",Jn]]:[]],...Z?{afterUninstall:()=>{throw Error(`Removed ${Jn} from the DeepSeek Harness web profile, but ${xs("remove")}`)}}:{}}}function eu(P,L,H={}){let Y=Ss(L,H).cli!==void 0;return P.map((Z)=>Z.target==="deepseek-harness"&&Y?{...Z,available:!0,unavailableReason:void 0}:Z)}import{existsSync as Vv,readdirSync as Kv,rmSync as Jv}from"node:fs";import{join as zv}from"node:path";function nu(P,L=process.platform,H){if(!Vv(P))return;let Y=L==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);Kv(P).filter((Z)=>Z!==H&&Y.test(Z)).forEach((Z)=>{Jv(zv(P,Z),{recursive:!0,force:!0})})}import{existsSync as tu,readdirSync as Wv,rmSync as Yv}from"node:fs";import{join as Xt}from"node:path";function xo(P,L=process.platform){let H=Xt(P.env.get("npm_config_cache")||(L==="win32"?Xt(P.env.get("LOCALAPPDATA")||Xt(P.home,"AppData","Local"),"npm-cache"):Xt(P.home,".npm")),"_npx");if(!tu(H))return;Wv(H).filter((Y)=>tu(Xt(H,Y,"node_modules","cc-safety-net"))).forEach((Y)=>{Yv(Xt(H,Y),{recursive:!0,force:!0})})}import{existsSync as lu,mkdirSync as Xv,readFileSync as cu}from"node:fs";import{dirname as Qv,join as au}from"node:path";function Zv(P,L){if(P[L]!=="#")return L;let H=P.indexOf(`
247
- `,L+1);return H===-1?P.length:H+1}function Rs(P,L,H){let Y=new RegExp(`^(\\s*)${L}\\s*=\\s*\\[`),Z=0;for(let oe of P.split(`
248
- `)){if(/^\s*\[/.test(oe))return;let se=Y.exec(oe);if(se){let me=Z+se[0].lastIndexOf("[");return{start:me,end:li(P,me,{skipComment:Zv,...H})}}Z+=oe.length+1}return}function ru(P,L,H){let Y=P.slice(0,L.end).trimEnd(),Z=gl(P,L.end),oe=Z===""?" ":`${Z} `,se=!Y.endsWith("[")&&!Y.endsWith(",");return`${Y}${se?",":""}
249
- ${oe}${H}${P.slice(L.end)}`}function ou(P,L,H){let Y=P.indexOf(H,L.start);if(Y===-1||Y>L.end)return P;return`${P.slice(0,Y)}${P.slice(Y+H.length).replace(/^\s*,/,"")}`}function iu(P,L){let H=new RegExp(`^\\s*${L}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),Y=P.split(`
250
- `),Z=Y.findIndex((me)=>/^\s*\[/.test(me)),oe=Z===-1?Y:Y.slice(0,Z),se=Z===-1?[]:Y.slice(Z);return[...oe.filter((me)=>!H.test(me)),...se].join(`
251
- `)}function su(P,L,H){let Y=new RegExp(`^\\s*\\[\\[${L}]]\\s*$`,"m");return P.split(/(?=^\s*\[)/m).filter((Z)=>!Y.test(Z)||!Z.includes(H)).join("").trimEnd()}var br=kn["kimi-code"],Es=`[[hooks]]
240
+ `))}async function Td(P){let G=await P(["amp","plugins","repositories","--json"]);if(G.status===null)throw Error(`${G.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 (${G.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
241
+ ${G.stderr}`.trim());if(G.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${G.status}). Sign in with "amp login" and rerun install --amp.
242
+ ${[G.stdout,G.stderr].filter(Boolean).join(`
243
+ `)}`.trim());let K=Ed(G.stdout),Y=(Array.isArray(K)?K:[]).filter((Z)=>Fe(Z,"scope")==="user"&&Fe(Z,"exists")===!0&&Fe(Z,"viewerCanWrite")===!0).map((Z)=>Fe(Z,"cloneRef")).find((Z)=>typeof Z==="string"&&Z.length>0);if(!Y)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 Y}async function Ad(P,G,K){let Y=Cv(kn(G.tmpdir,"cc-safety-net-amp-"));try{return await hr(P,["amp","clone","user-plugins",Y]),await K(Y)}finally{bo(Y,{recursive:!0,force:!0})}}function ks(P){return`rerun ${P==="overwrite"?"install":"uninstall"} --amp`}function _d(P,G,K){let Y=kn(P,G),Z=cn(Y);if(!Z)return;if(Z.isSymbolicLink()||!Z.isFile())throw Error(`Refusing to ${K} ${G} in your Amp personal plugins repository: not a regular file. Remove it there and ${ks(K)}.`);let X=Zt(Y);if(wo(X))return X;throw Error(`Refusing to ${K} unmanaged file ${G} in your Amp personal plugins repository. Remove it there and ${ks(K)}.`)}function Id(P,G){let K=kn(P,St),Y=cn(K);if(!Y)return;if(Y.isSymbolicLink()||!Y.isDirectory())throw Error(`Refusing to ${G} ${St} in your Amp personal plugins repository: not a regular directory. Remove it there and ${ks(G)}.`);return _d(P,At,G)}function _v(P){let G=kn(P,Yt),K=cn(G);if(!K||K.isSymbolicLink()||!K.isFile())return;let Y=Zt(G);return wo(Y)?Y:void 0}async function Od(P,G,K,Y){if(await hr(P,K,G),(await hr(P,["git","status","--porcelain"],G)).stdout.trim()==="")return!1;return await hr(P,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",Y],G),await hr(P,["git","push","origin","HEAD"],G),!0}function vo(P,G){Iv(P,G),Ov(P,G)}function $d(P,G){if(G==="keep")return;throw Error(`Local Amp plugin ${P} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function Iv(P,G){let K=Ev(P),Y=cn(K);if(!Y)return;if(!Y.isSymbolicLink()&&Y.isFile()&&wo(Zt(K))){bo(K);return}$d(K,G)}function Ov(P,G){let K=kn(P.home,".config","amp","plugins",St),Y=cn(K);if(!Y)return;if(!Y.isSymbolicLink()&&Y.isDirectory()&&$v(K)){bo(K,{recursive:!0});return}$d(K,G)}function $v(P){let G=Pv(At);if(xv(P).join("\x00")!==G)return!1;let K=kn(P,G),Y=cn(K);return!!Y&&!Y.isSymbolicLink()&&Y.isFile()&&wo(Zt(K))}function Dv(P){let G=u(P);if(!Rd(G))return"";let K=Ed(Zt(G,"utf-8"));if(!K||typeof K!=="object"||Array.isArray(K))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(k(K,P.home))};
244
+ `}async function Dd(P,G=Av(),K=bs){let Y=Buffer.concat([Zt(G),Buffer.from(Dv(P),"utf-8")]),Z=await Td(K);return Ad(K,P,async(X)=>{let ie=`${Z}/${St}`,ae=Id(X,"overwrite"),ge=_d(X,Yt,"overwrite");if(ae?.equals(Y)&&!ge)return vo(P,"fail"),{path:ie,alreadyInstalled:!0};if(kv(kn(X,St),{recursive:!0}),sn(kn(X,At),Y),ge)bo(kn(X,Yt));let ye=await Od(K,X,["git","add","--",At,...ge?[Yt]:[]],`chore: update cc-safety-net plugin to v${un()}`);return vo(P,"fail"),{path:ie,alreadyInstalled:!ye}})}async function Nd(P,G=bs){let K=await Td(G);return Ad(G,P,async(Y)=>{let Z=Id(Y,"remove"),X=_v(Y),ie=`${K}/${X&&!Z?Yt:St}`;if(!Z&&!X)return vo(P,"keep"),{path:ie,alreadyInstalled:!1};return await Od(G,Y,["git","rm","--",...Z?[At]:[],...X?[Yt]:[]],`chore: remove cc-safety-net plugin v${un()}`),vo(P,"keep"),{path:ie,alreadyInstalled:!0}})}import{existsSync as Ld,mkdirSync as Nv,readFileSync as Lv}from"node:fs";import{dirname as jv}from"node:path";var Cs=wn["antigravity-cli"],_t="cc-safety-net";function It(P){return Boolean(P)&&typeof P==="object"&&!Array.isArray(P)}function Co(){return{PreToolUse:[{hooks:[{type:"command",command:Cs,timeout:30}]}]}}function jd(P){try{let G=JSON.parse(Lv(P,"utf-8"));if(!G||typeof G!=="object"||Array.isArray(G))throw Error("Antigravity hooks config must be a JSON object");return G}catch(G){if(G instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${P}: ${G.message}`);throw G}}function Fd(P){let G=P[_t];if(G===void 0){let Y=Co();return P[_t]=Y,{definition:Y,preToolUse:Y.PreToolUse??[]}}if(!It(G))throw Error(`Antigravity hooks config entry "${_t}" must be an object`);let K=Array.isArray(G.PreToolUse)?G.PreToolUse:[];return G.PreToolUse=K,{definition:G,preToolUse:K}}function Hd(P){if(!Array.isArray(P.PreToolUse))return!1;return P.PreToolUse.some((G)=>It(G)&&Array.isArray(G.hooks)&&G.hooks.some((K)=>It(K)&&K.command===Cs))}function Fv(P){return Object.values(P).some((G)=>It(G)&&G.enabled!==!1&&Hd(G))}function Hv(P){if(P[_t]===void 0)return!1;let G=Fd(P);if(G.definition.enabled!==!1||!Hd(G.definition))return!1;return G.definition.enabled=!0,!0}function Mv(P){if(P[_t]===void 0){P[_t]=Co();return}let G=Fd(P);G.definition.enabled=!0,G.preToolUse.push(Co().PreToolUse?.[0]??{hooks:[]})}function Uv(P){let G=!1;for(let K of Object.values(P)){if(!It(K)||!Array.isArray(K.PreToolUse))continue;K.PreToolUse=K.PreToolUse.flatMap((Y)=>{if(!It(Y)||!Array.isArray(Y.hooks))return[Y];let Z=Y.hooks.filter((X)=>!It(X)||X.command!==Cs);if(Z.length!==Y.hooks.length)G=!0;return Z.length===0?[]:[{...Y,hooks:Z}]})}return G}function ko(P,G){sn(P,`${JSON.stringify(G,null,2)}
245
+ `)}function Md(P){let G=rr(P.home);if(Nv(jv(G),{recursive:!0}),!Ld(G))return ko(G,{[_t]:Co()}),{path:G,alreadyInstalled:!1};let K=jd(G);if(Fv(K))return{path:G,alreadyInstalled:!0};if(Hv(K))return ko(G,K),{path:G,alreadyInstalled:!1};return Mv(K),ko(G,K),{path:G,alreadyInstalled:!1}}function Ud(P){let G=rr(P.home);if(!Ld(G))return{path:G,alreadyInstalled:!1};let K=jd(G);if(!Uv(K))return{path:G,alreadyInstalled:!1};return ko(G,K),{path:G,alreadyInstalled:!0}}import{existsSync as Ss,readlinkSync as qv}from"node:fs";import{join as Kn}from"node:path";import{spawn as Bv}from"node:child_process";var On=Sn.map((P)=>({target:P.id,flag:P.flag,label:ln(P.id),probeCommand:P.probeCommand}));function xs(P){let G=new Set(P);return On.map((K)=>K.target).filter((K)=>G.has(K))}async function Bd(P,G){for(let K of P)await G(K)}var Gv=5000;function vr(P,G=Gv){return new Promise((K)=>{let Y=Zn([...P],process.env),Z=Bv(Y.cmd,Y.args,{env:process.env,stdio:"ignore"}),X=!1,ie=(ge)=>{if(X)return;X=!0,clearTimeout(ae),K(ge)},ae=setTimeout(()=>{Z.kill(),ie(!1)},G);Z.on("error",()=>ie(!1)),Z.on("close",(ge)=>ie(ge===0))})}function Gd(P=vr,G={}){let K=new Set(G.configuredTargets??[]);return Promise.all(On.map(async(Y)=>({target:Y.target,flag:Y.flag,label:Y.label,...Vd(G.action,await P(Y.probeCommand)||Y.target==="cursor"&&await P(sa),K.has(Y.target))})))}function qd(P,G){let K=new Set(G.configuredTargets??[]);return P.map((Y)=>({...Y,...Vd(G.action,Y.available,K.has(Y.target))}))}function Vd(P,G,K){if(P==="uninstall")return K?{available:!0}:{available:!1,unavailableReason:"not installed"};if(P==="install"&&K)return{available:!1,unavailableReason:"already installed"};if(!G)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}var En="cc-safety-net",Wd=["npx","-y","@deepseek-ai/dsh"],Kd="DeepSeek Harness",Jd=["@deepseek-ai","dsh-desktop"],Yd="Quit DeepSeek Harness Desktop, then run this command again: Desktop plugins can only change while it is closed.",Ps=(P)=>`DeepSeek Harness Desktop is not in its default location, so ${P} ${En} from its Plugins page.`,Zd=(P,G)=>Kn(Ci(P),G,"package.json"),Xd=(P,G)=>Ss(Zd(P,G));function Vv(P,G){let K=yn(Zd(P,G)),Y=Fe(K.kind==="ok"?K.value:void 0,"dependencies");return typeof Y==="object"&&Y!==null?Object.keys(Y).filter((Z)=>Z!==En):[]}function Rs(P,G){let K=G.platform??process.platform,Y=Xd(P,"desktop"),Z=K==="darwin"?[Kn(P.home,"Applications"),G.systemApplications??"/Applications"].map((X)=>Kn(X,`${Kd}.app`,"Contents","Resources","runtime","cli","bin","dsh")):K==="win32"?[Kn(P.env.get("LOCALAPPDATA")||Kn(P.home,"AppData","Local"),"Programs",Kd,"resources","runtime","cli","bin","dsh.cmd")]:[];return{profile:Y,cli:Y?Z.find((X)=>Ss(X)):void 0}}function Qd(P,G=process.platform){if(G==="win32")return Ss(Kn(P.env.get("APPDATA")||Kn(P.home,"AppData","Roaming"),...Jd,"lockfile"));let K=Kv(Kn(P.home,"Library","Application Support",...Jd,"SingletonLock")),Y=Number(/-(\d+)$/.exec(K??"")?.[1]);return Number.isInteger(Y)&&Y>0&&Jv(Y)}function Kv(P){try{return qv(P)}catch{return}}function Jv(P){try{return process.kill(P,0),!0}catch(G){return G.code==="EPERM"}}async function eu(P,G={}){let K=Rs(P,G);if(K.cli&&Qd(P,G.platform))throw Error(Yd);let Y=!K.cli||Xd(P,"web")||await(G.probe??vr)(qo),Z=[...K.cli?[{profile:"desktop",label:"Desktop",dsh:[K.cli]}]:[],...Y?[{profile:"web",label:"web",dsh:Wd}]:[]],X=Z.map((ie)=>({label:ie.label,plugins:Vv(P,ie.profile)})).filter((ie)=>ie.plugins.length>0);return{commands:Z.map((ie)=>[...ie.dsh,"plugin","--profile",ie.profile,"add",`${En}@${un()}`]),afterInstall:async()=>{let ie=new Set(xi(P).filter((ge)=>ge.enabled).map((ge)=>ge.name)),ae=Z.filter((ge)=>!ie.has(ge.profile));if(ae.length>0)throw Error(`DeepSeek Harness installed ${En} in the ${zd(ae)} but did not enable it. Enable it from the Plugins page.`)},message:[`Added ${En} to the DeepSeek Harness ${zd(Z)}.`,...K.profile&&!K.cli?[Ps("add")]:[],...X.length>0?[...X.map((ie)=>`Other plugins in the DeepSeek Harness ${ie.label} profile: ${ie.plugins.join(", ")}.`),`CC Safety Net does not check commands a plugin's own shell tool runs until you declare it: npx -y ${En} rule tool add <tool-name>`,...X.map((ie)=>`DeepSeek Harness ${ie.label} 配置中的其他插件:${ie.plugins.join("、")}。`),`插件自带的 shell 工具需要声明后,CC Safety Net 才会检查它执行的命令:npx -y ${En} rule tool add <工具名>`]:[]].join(`
246
+ `)}}function zd(P){return`${P.map((G)=>G.label).join(" and ")} profile${P.length>1?"s":""}`}function nu(P,G={}){let K=new Set(xi(P).map((X)=>X.name));if(!K.has("desktop")&&!K.has("web"))throw Error(`${En} is not installed in the DeepSeek Harness web or Desktop profile`);let Y=K.has("desktop")?Rs(P,G).cli:void 0,Z=K.has("desktop")&&!Y;if(Z&&!K.has("web"))throw Error(Ps("remove"));if(Y&&Qd(P,G.platform))throw Error(Yd);return{commands:[...Y?[[Y,"plugin","--profile","desktop","remove",En]]:[],...K.has("web")?[[...Wd,"plugin","--profile","web","remove",En]]:[]],...Z?{afterUninstall:()=>{throw Error(`Removed ${En} from the DeepSeek Harness web profile, but ${Ps("remove")}`)}}:{}}}function tu(P,G,K={}){let Y=Rs(G,K).cli!==void 0;return P.map((Z)=>Z.target==="deepseek-harness"&&Y?{...Z,available:!0,unavailableReason:void 0}:Z)}import{existsSync as zv,readdirSync as Wv,rmSync as Yv}from"node:fs";import{join as Zv}from"node:path";function ru(P,G=process.platform,K){if(!zv(P))return;let Y=G==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);Wv(P).filter((Z)=>Z!==K&&Y.test(Z)).forEach((Z)=>{Yv(Zv(P,Z),{recursive:!0,force:!0})})}import{existsSync as ou,readdirSync as Xv,rmSync as Qv}from"node:fs";import{join as Xt}from"node:path";function xo(P,G=process.platform){let K=Xt(P.env.get("npm_config_cache")||(G==="win32"?Xt(P.env.get("LOCALAPPDATA")||Xt(P.home,"AppData","Local"),"npm-cache"):Xt(P.home,".npm")),"_npx");if(!ou(K))return;Xv(K).filter((Y)=>ou(Xt(K,Y,"node_modules","cc-safety-net"))).forEach((Y)=>{Qv(Xt(K,Y),{recursive:!0,force:!0})})}import{existsSync as du,mkdirSync as nb,readFileSync as uu}from"node:fs";import{dirname as tb,join as cu}from"node:path";function eb(P,G){if(P[G]!=="#")return G;let K=P.indexOf(`
247
+ `,G+1);return K===-1?P.length:K+1}function Es(P,G,K){let Y=new RegExp(`^(\\s*)${G}\\s*=\\s*\\[`),Z=0;for(let X of P.split(`
248
+ `)){if(/^\s*\[/.test(X))return;let ie=Y.exec(X);if(ie){let ae=Z+ie[0].lastIndexOf("[");return{start:ae,end:ci(P,ae,{skipComment:eb,...K})}}Z+=X.length+1}return}function iu(P,G,K){let Y=P.slice(0,G.end).trimEnd(),Z=yl(P,G.end),X=Z===""?" ":`${Z} `,ie=!Y.endsWith("[")&&!Y.endsWith(",");return`${Y}${ie?",":""}
249
+ ${X}${K}${P.slice(G.end)}`}function su(P,G,K){let Y=P.indexOf(K,G.start);if(Y===-1||Y>G.end)return P;return`${P.slice(0,Y)}${P.slice(Y+K.length).replace(/^\s*,/,"")}`}function au(P,G){let K=new RegExp(`^\\s*${G}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),Y=P.split(`
250
+ `),Z=Y.findIndex((ae)=>/^\s*\[/.test(ae)),X=Z===-1?Y:Y.slice(0,Z),ie=Z===-1?[]:Y.slice(Z);return[...X.filter((ae)=>!K.test(ae)),...ie].join(`
251
+ `)}function lu(P,G,K){let Y=new RegExp(`^\\s*\\[\\[${G}]]\\s*$`,"m");return P.split(/(?=^\s*\[)/m).filter((Z)=>!Y.test(Z)||!Z.includes(K)).join("").trimEnd()}var br=wn["kimi-code"],Ts=`[[hooks]]
252
252
  event = "PreToolUse"
253
- command = "${br}"`,du=`{ event = "PreToolUse", command = "${br}" }`,uu={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function pu(P){return au(P.env.get("KIMI_CODE_HOME")??au(P.home,".kimi-code"),"config.toml")}function eb(P){let L=Rs(P,"hooks",uu);if(L&&P.slice(L.start+1,L.end).trim())return ru(P,L,du);let H=iu(P,"hooks").trimEnd();if(H==="")return`${Es}
254
- `;return`${H}
255
-
256
- ${Es}
257
- `}function fu(P){let L=pu(P);if(Xv(Qv(L),{recursive:!0}),!lu(L))return an(L,`${Es}
258
- `),{path:L,alreadyInstalled:!1};let H=cu(L,"utf-8");if(H.includes(br))return{path:L,alreadyInstalled:!0};return an(L,eb(H)),{path:L,alreadyInstalled:!1}}function mu(P){let L=pu(P);if(!lu(L))return{path:L,alreadyInstalled:!1};let H=cu(L,"utf-8");if(!H.includes(br))return{path:L,alreadyInstalled:!1};let Y=Rs(H,"hooks",uu),Z=Y?ou(H,Y,du):`${su(H,"hooks",br)}
259
- `;return an(L,Z),{path:L,alreadyInstalled:!0}}var Ts="safety-net@cc-marketplace",gu=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),yu=new Set(["antigravity-cli","cursor","devin","droid","grok-build","hermes-agent","kimi-code"]);function As(P){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(P??"")}function ku(P){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(P??"")}function nb(P){return/^Marketplace `cc-marketplace`\s*$/m.test(P??"")}var Cu={"claude-code":{installCommands:(P)=>{let L=Kr(P,"cc-safety-net@cc-marketplace");return{commands:[...L?[["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"]],...si(P).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Kr(P,Ts)?[["claude","plugin","uninstall",Ts]]:[],update:L}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(P,L)=>{let H=L??await fn(["codex","plugin","list"]),Y=ku(H);return{commands:[Y||nb(H)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:As(H)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:Y}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:ul},"copilot-cli":{installCommands:async()=>{let P=await fn(["copilot","plugin","list"]),L=[...xl(P)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...Pl(P)?[["copilot","plugin","uninstall",wl]]:[]];if(kl(P))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",An]],cleanupCommands:L,update:!0};return{commands:[Cl(await fn(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",An]],cleanupCommands:L}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(P)=>{let L=Oi(P);if(L.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(L.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:Ji,installCommands:(P)=>{let L=!So(Po(ur(P),xn));return{commands:Dc(),afterInstall:()=>Nc(L)}},uninstallCommands:[["openclaw","plugins","uninstall",un,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
260
- `)},opencode:{installCommands:Vc},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]},"deepseek-harness":{installCommands:(P)=>Xd(P),uninstallCommands:(P)=>Qd(P)}};function xu(P,L=(H)=>H){try{let H=JSON.parse(L(wu(P,"utf-8")));if(!H||typeof H!=="object"||Array.isArray(H))throw Error(`Settings file ${P} must be a JSON object`);return H}catch(H){if(H instanceof SyntaxError)throw Error(`Failed to parse ${P}: ${H.message}`);throw H}}function tb(P){let L=Po(sr(P),"settings.json");if(!So(L))return;let H=xu(L,yn),Y=H.enabledPlugins;if(!Y||typeof Y!=="object"||Array.isArray(Y))return;if(Y[An]!==!1)return;let Z=wu(L,"utf-8"),oe=Z.replace(new RegExp(`("${An}"\\s*:\\s*)false`),"$1true");return Y[An]=!0,an(L,oe!==Z?oe:`${JSON.stringify(H,null,2)}
261
- `),`Enabled ${An} plugin in ${L}`}function rb(P){let L=os(P);if(!So(L))return;let H=xu(L);if(!Array.isArray(H.packages))return;let Y=H.packages.find((Z)=>!!Z&&typeof Z==="object"&&!Array.isArray(Z)&&is(Z.source)&&("extensions"in Z));if(!Y)return;return delete Y.extensions,an(L,`${JSON.stringify(H,null,2)}
262
- `),`Enabled npm:cc-safety-net extensions in ${L}`}function hu(P,L){let H=mn({label:L,booleans:Object.fromEntries(On.map((oe)=>[oe.target,[oe.flag]]))},P),Y=H.errors[0];if(Y)throw Error(Y);let Z=On.filter((oe)=>H.flags[oe.target]).map((oe)=>oe.target);if(Z.length!==1)throw Error(`Choose exactly one ${L} target: ${On.map((oe)=>oe.flag).join(", ")}`);return Z[0]}async function Pu(P,L=Ft){let[H,Y,Z]=await Promise.all([L(["amp","plugins","list"],30000),L(["codex","plugin","list"],30000),L(["copilot","--binary-version"])]);return{codexPluginListOutput:Y,hooks:zt(P,process.cwd(),{ampPluginListOutput:H,codexPluginListOutput:Y,copilotCliVersion:Z})}}async function ob(P,L,H=Ft){let Y=await Pu(P,H);return Y.hooks.filter((Z)=>L==="install"?Z.configured:Z.detected&&Z.method!==eo||Z.inspectionStatus==="not-inspected").filter((Z)=>!Eu(Z)).filter((Z)=>Z.platform!=="codex"||!As(Y.codexPluginListOutput)||ku(Y.codexPluginListOutput)).map((Z)=>Z.platform)}function ib(P,L,H,Y){if(H.length>0)return{finish:async()=>[hu(H,L)]};if(!Y.selectTargets&&!ys(Y.input,Y.output))return{finish:async()=>[hu(H,L)]};let Z=Y.detectConfiguredTargets??(()=>ob(P,L,Y.fetchVersion)),oe=Promise.all([Bd(Y.probeTargets).then((se)=>eu(se,P)),Z()]);return{ready:oe,finish:async()=>{let[se,me]=await oe,he=Gd(se,{action:L,configuredTargets:me}),ke=Y.selectTargets?await Y.selectTargets(L,bu(L,he)):await Pd(L,bu(L,he),{input:Y.input,output:Y.output});if(ke==="update")return ke;if(!ke||ke.length===0)return null;return Cs(ke)}}}async function sb(P,L,H=!1,Y){let Z=Cu[P];Z.beforeInstall?.(L);let oe=typeof Z.installCommands==="function"?await Z.installCommands(L,Y):{commands:Z.installCommands};return await pi(oe.commands),await Il(oe.cleanupCommands??[]),await oe.afterInstall?.(),[`${oe.update||H?"Updated":"Installed"} ${cn(P)} integration`,oe.message??Z.postInstallMessage].filter(Boolean).join(`
263
- `)}async function ab(P,L){let H=Cu[P];if(!H.uninstallCommands)throw Error(`${cn(P)} uninstall is not supported`);let Y=typeof H.uninstallCommands==="function"?H.uninstallCommands(L):{commands:H.uninstallCommands};return await pi(Y.commands),Y.afterUninstall?.(),`Uninstalled ${cn(P)} integration`}function lb(P){let L=zc(P);return L.alreadyInstalled?`Uninstalled OpenCode plugin from ${L.path}`:`OpenCode plugin not installed in ${L.path}`}var Su={"antigravity-cli":{install:Hd,uninstall:Md},cursor:{install:jl,uninstall:Fl},devin:{install:Jl,uninstall:zl},droid:{install:nc,uninstall:tc},"grok-build":{install:dc,uninstall:uc},"kimi-code":{install:fu,uninstall:mu}};function cb(P,L,H,Y=!1){if(P==="install"&&!Y)xo(H);let Z=Su[L][P](H),oe=cn(L),se=P!=="install"?"Uninstalled":Y?"Updated":"Installed";return P==="install"&&Z.alreadyInstalled?Y?`${oe} hook up to date in ${Z.path}`:`${oe} hook already installed in ${Z.path}`:P==="uninstall"&&!Z.alreadyInstalled?`${oe} hook not installed in ${Z.path}`:`${se} ${oe} hook ${P==="install"?"in":"from"} ${Z.path}`}var Ru={amp:{install:$d,uninstall:Dd,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:vc,uninstall:bc,afterInstall:async(P)=>{let L=Bi(P);return await fn(["hermes","plugins","enable",Sn,"--no-allow-tool-override"]),!L},beforeUninstall:async(P)=>{Ui(P);try{await fn(["hermes","plugins","disable",Sn])}catch(L){console.warn(`${L instanceof Error?L.message:String(L)}
264
- Removing the plugin files anyway; ${Sn} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function db(P,L,H,Y=!1){let Z=Ru[L];if(P==="uninstall")await Z.beforeUninstall?.(H);let oe=P==="install"?await Z.install(H):await Z.uninstall(H),se=P==="install"&&await Z.afterInstall?.(H),me=cn(L),he=!se&&(P==="install"&&oe.alreadyInstalled||P==="uninstall"&&!oe.alreadyInstalled);return[he?P==="install"?`${me} plugin ${Y?"up to date":"already installed"} at ${oe.path}`:`${me} plugin not installed at ${oe.path}`:`${P!=="install"?"Uninstalled":Y?"Updated":"Installed"} ${me} plugin ${P==="install"?"at":"from"} ${oe.path}`,he?void 0:Z.restartNote].filter(Boolean).join(`
265
- `)}var ub={"copilot-cli":{afterInstall:tb},cursor:{afterUninstall:$l},"hermes-agent":{beforeInstall:(P,L)=>{if(!L)xo(P)}},openclaw:{beforeUninstall:Ji},pi:{afterInstall:rb}};function pb(P){return P in Su}function fb(P){return P in Ru}var vu=["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/tree/plugin"," 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(`
266
- `);function Eu(P){return P.platform==="kimi-code"&&P.method===uo}function Tu(P){return po({environment:P,cwd:process.cwd()}).method==="hook config"}function mb(P){if(!Tu(P))return vu;return[vu,"",en.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
253
+ command = "${br}"`,pu=`{ event = "PreToolUse", command = "${br}" }`,fu={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function mu(P){return cu(P.env.get("KIMI_CODE_HOME")??cu(P.home,".kimi-code"),"config.toml")}function rb(P){let G=Es(P,"hooks",fu);if(G&&P.slice(G.start+1,G.end).trim())return iu(P,G,pu);let K=au(P,"hooks").trimEnd();if(K==="")return`${Ts}
254
+ `;return`${K}
255
+
256
+ ${Ts}
257
+ `}function gu(P){let G=mu(P);if(nb(tb(G),{recursive:!0}),!du(G))return sn(G,`${Ts}
258
+ `),{path:G,alreadyInstalled:!1};let K=uu(G,"utf-8");if(K.includes(br))return{path:G,alreadyInstalled:!0};return sn(G,rb(K)),{path:G,alreadyInstalled:!1}}function yu(P){let G=mu(P);if(!du(G))return{path:G,alreadyInstalled:!1};let K=uu(G,"utf-8");if(!K.includes(br))return{path:G,alreadyInstalled:!1};let Y=Es(K,"hooks",fu),Z=Y?su(K,Y,pu):`${lu(K,"hooks",br)}
259
+ `;return sn(G,Z),{path:G,alreadyInstalled:!0}}var As="safety-net@cc-marketplace",hu=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),vu=new Set(["antigravity-cli","cursor","devin","droid","grok-build","hermes-agent","kimi-code"]);function _s(P){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(P??"")}function xu(P){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(P??"")}function ob(P){return/^Marketplace `cc-marketplace`\s*$/m.test(P??"")}var Pu={"claude-code":{installCommands:(P)=>{let G=Kr(P,"cc-safety-net@cc-marketplace");return{commands:[...G?[["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"]],...ai(P).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Kr(P,As)?[["claude","plugin","uninstall",As]]:[],update:G}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(P,G)=>{let K=G??await pn(["codex","plugin","list"]),Y=xu(K);return{commands:[Y||ob(K)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:_s(K)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:Y}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:pl},"copilot-cli":{installCommands:async()=>{let P=await pn(["copilot","plugin","list"]),G=[...Pl(P)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...Sl(P)?[["copilot","plugin","uninstall",kl]]:[]];if(Cl(P))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",An]],cleanupCommands:G,update:!0};return{commands:[xl(await pn(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",An]],cleanupCommands:G}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(P)=>{let G=$i(P);if(G.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(G.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:zi,installCommands:(P)=>{let G=!So(Po(ur(P),Cn));return{commands:Nc(),afterInstall:()=>Lc(G)}},uninstallCommands:[["openclaw","plugins","uninstall",dn,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
260
+ `)},opencode:{installCommands:Kc},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]},"deepseek-harness":{installCommands:(P)=>eu(P),uninstallCommands:(P)=>nu(P)}};function Su(P,G=(K)=>K){try{let K=JSON.parse(G(Cu(P,"utf-8")));if(!K||typeof K!=="object"||Array.isArray(K))throw Error(`Settings file ${P} must be a JSON object`);return K}catch(K){if(K instanceof SyntaxError)throw Error(`Failed to parse ${P}: ${K.message}`);throw K}}function ib(P){let G=Po(sr(P),"settings.json");if(!So(G))return;let K=Su(G,gn),Y=K.enabledPlugins;if(!Y||typeof Y!=="object"||Array.isArray(Y))return;if(Y[An]!==!1)return;let Z=Cu(G,"utf-8"),X=Z.replace(new RegExp(`("${An}"\\s*:\\s*)false`),"$1true");return Y[An]=!0,sn(G,X!==Z?X:`${JSON.stringify(K,null,2)}
261
+ `),`Enabled ${An} plugin in ${G}`}function sb(P){let G=is(P);if(!So(G))return;let K=Su(G);if(!Array.isArray(K.packages))return;let Y=K.packages.find((Z)=>!!Z&&typeof Z==="object"&&!Array.isArray(Z)&&ss(Z.source)&&("extensions"in Z));if(!Y)return;return delete Y.extensions,sn(G,`${JSON.stringify(K,null,2)}
262
+ `),`Enabled npm:cc-safety-net extensions in ${G}`}function bu(P,G){let K=fn({label:G,booleans:Object.fromEntries(On.map((X)=>[X.target,[X.flag]]))},P),Y=K.errors[0];if(Y)throw Error(Y);let Z=On.filter((X)=>K.flags[X.target]).map((X)=>X.target);if(Z.length!==1)throw Error(`Choose exactly one ${G} target: ${On.map((X)=>X.flag).join(", ")}`);return Z[0]}async function Ru(P,G=Ft){let[K,Y,Z]=await Promise.all([G(["amp","plugins","list"],30000),G(["codex","plugin","list"],30000),G(["copilot","--binary-version"])]);return{codexPluginListOutput:Y,hooks:zt(P,process.cwd(),{ampPluginListOutput:K,codexPluginListOutput:Y,copilotCliVersion:Z})}}async function ab(P,G,K=Ft){let Y=await Ru(P,K);return Y.hooks.filter((Z)=>G==="install"?Z.configured:Z.detected&&Z.method!==eo||Z.inspectionStatus==="not-inspected").filter((Z)=>!Au(Z)).filter((Z)=>Z.platform!=="codex"||!_s(Y.codexPluginListOutput)||xu(Y.codexPluginListOutput)).map((Z)=>Z.platform)}function lb(P,G,K,Y){if(K.length>0)return{finish:async()=>[bu(K,G)]};if(!Y.selectTargets&&!hs(Y.input,Y.output))return{finish:async()=>[bu(K,G)]};let Z=Y.detectConfiguredTargets??(()=>ab(P,G,Y.fetchVersion)),X=Promise.all([Gd(Y.probeTargets).then((ie)=>tu(ie,P)),Z()]);return{ready:X,finish:async()=>{let[ie,ae]=await X,ge=qd(ie,{action:G,configuredTargets:ae}),ye=Y.selectTargets?await Y.selectTargets(G,ku(G,ge)):await Sd(G,ku(G,ge),{input:Y.input,output:Y.output});if(ye==="update")return ye;if(!ye||ye.length===0)return null;return xs(ye)}}}async function cb(P,G,K=!1,Y){let Z=Pu[P];Z.beforeInstall?.(G);let X=typeof Z.installCommands==="function"?await Z.installCommands(G,Y):{commands:Z.installCommands};return await fi(X.commands),await Ol(X.cleanupCommands??[]),await X.afterInstall?.(),[`${X.update||K?"Updated":"Installed"} ${ln(P)} integration`,X.message??Z.postInstallMessage].filter(Boolean).join(`
263
+ `)}async function db(P,G){let K=Pu[P];if(!K.uninstallCommands)throw Error(`${ln(P)} uninstall is not supported`);let Y=typeof K.uninstallCommands==="function"?K.uninstallCommands(G):{commands:K.uninstallCommands};return await fi(Y.commands),Y.afterUninstall?.(),`Uninstalled ${ln(P)} integration`}function ub(P){let G=Wc(P);return G.alreadyInstalled?`Uninstalled OpenCode plugin from ${G.path}`:`OpenCode plugin not installed in ${G.path}`}var Eu={"antigravity-cli":{install:Md,uninstall:Ud},cursor:{install:Fl,uninstall:Hl},devin:{install:zl,uninstall:Wl},droid:{install:tc,uninstall:rc},"grok-build":{install:uc,uninstall:pc},"kimi-code":{install:gu,uninstall:yu}};function pb(P,G,K,Y=!1){if(P==="install"&&!Y)xo(K);let Z=Eu[G][P](K),X=ln(G),ie=P!=="install"?"Uninstalled":Y?"Updated":"Installed";return P==="install"&&Z.alreadyInstalled?Y?`${X} hook up to date in ${Z.path}`:`${X} hook already installed in ${Z.path}`:P==="uninstall"&&!Z.alreadyInstalled?`${X} hook not installed in ${Z.path}`:`${ie} ${X} hook ${P==="install"?"in":"from"} ${Z.path}`}var Tu={amp:{install:Dd,uninstall:Nd,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:bc,uninstall:wc,afterInstall:async(P)=>{let G=Gi(P);return await pn(["hermes","plugins","enable",Pn,"--no-allow-tool-override"]),!G},beforeUninstall:async(P)=>{Bi(P);try{await pn(["hermes","plugins","disable",Pn])}catch(G){console.warn(`${G instanceof Error?G.message:String(G)}
264
+ Removing the plugin files anyway; ${Pn} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function fb(P,G,K,Y=!1){let Z=Tu[G];if(P==="uninstall")await Z.beforeUninstall?.(K);let X=P==="install"?await Z.install(K):await Z.uninstall(K),ie=P==="install"&&await Z.afterInstall?.(K),ae=ln(G),ge=!ie&&(P==="install"&&X.alreadyInstalled||P==="uninstall"&&!X.alreadyInstalled);return[ge?P==="install"?`${ae} plugin ${Y?"up to date":"already installed"} at ${X.path}`:`${ae} plugin not installed at ${X.path}`:`${P!=="install"?"Uninstalled":Y?"Updated":"Installed"} ${ae} plugin ${P==="install"?"at":"from"} ${X.path}`,ge?void 0:Z.restartNote].filter(Boolean).join(`
265
+ `)}var mb={"copilot-cli":{afterInstall:ib},cursor:{afterUninstall:Dl},"hermes-agent":{beforeInstall:(P,G)=>{if(!G)xo(P)}},openclaw:{beforeUninstall:zi},pi:{afterInstall:sb}};function gb(P){return P in Eu}function yb(P){return P in Tu}var wu=["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/tree/plugin"," 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(`
266
+ `);function Au(P){return P.platform==="kimi-code"&&P.method===uo}function _u(P){return po({environment:P,cwd:process.cwd()}).method==="hook config"}function hb(P){if(!_u(P))return wu;return[wu,"",Qe.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(`
267
267
  `))].join(`
268
- `)}function bu(P,L){return L.map((H)=>P==="install"&&H.target==="kimi-code"&&H.unavailableReason==="already installed"?{...H,available:!0,unavailableReason:void 0,label:`${H.label} (global hook installed)`}:H)}function gb(P,L){if(P.selectKimiInstallMethod)return P.selectKimiInstallMethod();if(!ys(P.input,P.output))return Promise.resolve("global-hook");return xd({input:P.input,output:P.output,globalHookInstalled:Tu(L)})}async function Au(P,L,H,Y=!1,Z){let oe=ub[L];if(P==="install")oe?.beforeInstall?.(H,Y);if(P==="uninstall")oe?.beforeUninstall?.(H);if(pb(L))return[cb(P,L,H,Y),P==="uninstall"?await oe?.afterUninstall?.(H):void 0].filter(Boolean).join(`
269
- `);if(fb(L))return db(P,L,H,Y);if(P==="uninstall")return L==="opencode"?lb(H):ab(L,H);return[await sb(L,H,Y,Z),await oe?.afterInstall?.(H)].filter(Boolean).join(`
270
- `)}function yb(P){let L=mn({label:"update"},P).errors[0];if(L)throw Error(L)}async function hb(P,L=Ft){let H=await Pu(P,L),Y=Po(sr(P),"installed-plugins");return{targets:Cs([...H.hooks.filter((oe)=>oe.platform!=="copilot-cli"&&oe.detected&&oe.method!==eo&&oe.method!==vi).map((oe)=>oe.platform),...[Jr,bl,vl].flatMap((oe)=>So(Po(Y,...oe))?["copilot-cli"]:[]),...Kr(P,Ts)?["claude-code"]:[],...As(H.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:H.codexPluginListOutput,kimiPlugin:H.hooks.some(Eu)}}async function vb(P){let L=c(),H=P.output??process.stdout,Y=(P.scriptPath??process.argv[1]??"").split(/[\\/]/),Z=Y.find((Ae)=>/^bunx-\d+-/.test(Ae)),oe=Z!==void 0||Y.includes("_npx")?null:(P.checkLatestVersion??Bn)(),se=async()=>{let Ae=oe&&await oe;if(Ae?.updateAvailable)H.write(`
268
+ `)}function ku(P,G){return G.map((K)=>P==="install"&&K.target==="kimi-code"&&K.unavailableReason==="already installed"?{...K,available:!0,unavailableReason:void 0,label:`${K.label} (global hook installed)`}:K)}function vb(P,G){if(P.selectKimiInstallMethod)return P.selectKimiInstallMethod();if(!hs(P.input,P.output))return Promise.resolve("global-hook");return Pd({input:P.input,output:P.output,globalHookInstalled:_u(G)})}async function Iu(P,G,K,Y=!1,Z){let X=mb[G];if(P==="install")X?.beforeInstall?.(K,Y);if(P==="uninstall")X?.beforeUninstall?.(K);if(gb(G))return[pb(P,G,K,Y),P==="uninstall"?await X?.afterUninstall?.(K):void 0].filter(Boolean).join(`
269
+ `);if(yb(G))return fb(P,G,K,Y);if(P==="uninstall")return G==="opencode"?ub(K):db(G,K);return[await cb(G,K,Y,Z),await X?.afterInstall?.(K)].filter(Boolean).join(`
270
+ `)}function bb(P){let G=fn({label:"update"},P).errors[0];if(G)throw Error(G)}async function wb(P,G=Ft){let K=await Ru(P,G),Y=Po(sr(P),"installed-plugins");return{targets:xs([...K.hooks.filter((X)=>X.platform!=="copilot-cli"&&X.detected&&X.method!==eo&&X.method!==bi).map((X)=>X.platform),...[Jr,wl,bl].flatMap((X)=>So(Po(Y,...X))?["copilot-cli"]:[]),...Kr(P,As)?["claude-code"]:[],..._s(K.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:K.codexPluginListOutput,kimiPlugin:K.hooks.some(Au)}}async function kb(P){let G=c(),K=P.output??process.stdout,Y=(P.scriptPath??process.argv[1]??"").split(/[\\/]/),Z=Y.find((Ae)=>/^bunx-\d+-/.test(Ae)),X=Z!==void 0||Y.includes("_npx")?null:(P.checkLatestVersion??Bn)(),ie=async()=>{let Ae=X&&await X;if(Ae?.updateAvailable)K.write(`
271
271
  Update available: cc-safety-net ${Ae.currentVersion} → ${Ae.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
272
- `)},me=hb(L,P.fetchVersion??Ft).then(async(Ae)=>{let Le=new Set(Ae.targets);return{targets:Ae.targets,codexPluginListOutput:Ae.codexPluginListOutput,kimiPlugin:Ae.kimiPlugin,available:new Map(await Promise.all(On.filter((We)=>Le.has(We.target)&&gu.has(We.target)).map(async(We)=>[We.target,await vr(We.probeCommand)])))}}),he=await tr(P.showBanner??!0,()=>({ready:me,finish:()=>me}),()=>nr({input:P.input??process.stdin,output:H}),{loadingMessage:"Checking installed integrations…",output:H}),ke=await Promise.resolve().then(()=>(nu(L.tmpdir,process.platform,Z),null)).catch((Ae)=>wr(Ae));if(he.targets.length===0){if(H.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),ke!==null)console.error(ke);return await se(),ke===null?0:1}let Pe=he.targets.some((Ae)=>yu.has(Ae))?await Promise.resolve().then(()=>(xo(L),null)).catch((Ae)=>wr(Ae)):null,Te=await Fr(Promise.all(he.targets.map((Ae)=>{if(Ae==="kimi-code"&&he.kimiPlugin)return Promise.resolve({message:"Kimi Code plugin skipped: update it in Kimi Code from /plugins (Installed tab, select cc-safety-net, press Enter)",failed:!1});if(gu.has(Ae)&&!he.available.get(Ae))return Promise.resolve({message:`${cn(Ae)} not found; skipped`,failed:!1});if(Pe!==null&&yu.has(Ae))return Promise.resolve({message:Pe,failed:!0});return Au("install",Ae,L,!0,he.codexPluginListOutput).then((Le)=>({message:Le,failed:!1}),(Le)=>({message:wr(Le),failed:!0}))})),{loadingMessage:`Updating ${he.targets.length} integration${he.targets.length===1?"":"s"}…`,output:H}),_e=ke===null?Te:[...Te,{message:ke,failed:!0}];return _e.forEach((Ae)=>Ae.failed?console.error(Ae.message):H.write(`${Ae.message}
273
- `)),await se(),_e.some((Ae)=>Ae.failed)?1:0}function _s(P,L={}){return Promise.resolve().then(()=>yb(P)).then(()=>vb(L)).catch((H)=>(console.error(wr(H)),1))}async function kr(P,L,H={}){try{let Y=c(),Z=await tr(!0,()=>ib(Y,P,L,H),()=>nr({input:H.input??process.stdin,output:H.output??process.stdout}),{loadingMessage:P==="install"?"Checking available integrations…":"Checking installed integrations…",output:H.output??process.stdout});if(!Z)return(H.output??process.stdout).write(`Cancelled: nothing was ${P}ed.
274
- `),0;if(Z==="update")return(H.runUpdate??(()=>_s([],{fetchVersion:H.fetchVersion,input:H.input,output:H.output,showBanner:!1})))();let oe=H.output??process.stdout;return await Ud(Z,async(se)=>{if(se==="kimi-code"&&P==="install"){let he=await gb(H,Y);if(he===null){oe.write(`Cancelled: Kimi Code integration was not installed.
275
- `);return}if(he==="plugin"){oe.write(`${mb(Y)}
276
- `);return}}let me=await Fr(Au(P,se,Y),{loadingMessage:`${P==="install"?"Installing":"Uninstalling"} ${cn(se)} integration…`,output:oe});oe.write(`${me}
277
- `)}),0}catch(Y){return console.error(wr(Y)),1}}function wr(P){let L=P instanceof Error?P.message:String(P),H=typeof P==="object"&&P!==null&&"code"in P?P.code:null;if(H==="EACCES"||H==="EPERM")return`${L}
278
- Check file permissions for the target config file and parent directory.`;if(H==="ENOENT")return`${L}
279
- Check that the target config path and parent directory exist.`;if(H==="ENOTDIR")return`${L}
280
- Check that every parent path component is a directory.`;return L}import{mkdirSync as Pb}from"node:fs";import{dirname as Sb}from"node:path";import{createInterface as Rb}from"node:readline";import{existsSync as Iu,readFileSync as bb}from"node:fs";function Ot(P,L){let H=ft(P,L);return{policy:H.policy,errors:de(ut(H.issues,pt,(Y)=>Y.kind==="custom")," "," ")}}function Cr(P,L){return Ot(P,L).errors}function _u(P,L){return{"safety.level":P.safety.level,...Is("safety.overrides",P.safety.overrides),"workflow.worktree_mode":String(P.workflow.worktree_mode),"destructive_command_protection.enabled":String(P.destructive_command_protection.enabled),...Is("destructive_command_protection.overrides",P.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Os(P.destructive_command_protection.allow_paths),"secret_protection.enabled":String(P.secret_protection.enabled),...Is("secret_protection.overrides",P.secret_protection.overrides),"secret_protection.deny_paths":Os(P.secret_protection.deny_paths),"secret_protection.allow_paths":Os(P.secret_protection.allow_paths),...L?{"audit.retention_days":String(P.audit.retention_days)}:{}}}function Ro(P,L,H){let Y=_u(P,H),Z=_u(L,H);return[...new Set([...Object.keys(Y),...Object.keys(Z)])].flatMap((oe)=>Y[oe]===Z[oe]?[]:[{field:oe,before:Y[oe],after:Z[oe]}])}function xr(P,L){let H=u(P,L);if(!Iu(H))return{baseline:k(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,P.home),diagnostics:[]};let Y=$t(H),Z=Ot(Y.value,P.home);return{baseline:Z.policy,diagnostics:Y.errors.length>0?Y.errors:Z.errors}}function $t(P){if(!Iu(P))return{errors:[`${P}: file not found`]};try{return{value:JSON.parse(bb(P,"utf-8")),errors:[]}}catch(L){let H=L instanceof Error?L.message:String(L);return{errors:[`${P}: ${L instanceof SyntaxError?`Invalid JSON: ${H}`:H}`]}}}function Eo(P,L){let H=wb(P)?P:{};return{version:L.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((Y)=>H[Y]!==void 0).map((Y)=>[Y,H[Y]]))}}function Is(P,L){return Object.fromEntries(Object.entries(L).flatMap(([H,Y])=>Y===void 0?[]:[[`${P}.${H}`,String(Y)]]))}function Os(P){return P.length===0?"(none)":P.join(", ")}function wb(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{chmodSync as kb,existsSync as Ou,mkdirSync as Cb,readFileSync as $u}from"node:fs";import{dirname as xb}from"node:path";function Du(P,L={}){let H=u(P,L);if(!Ou(H))return{path:H,exists:!1,raw:"",policy:I(),errors:[]};let Y=$u(H,"utf-8");if(!Y.trim())return{path:H,exists:!0,raw:Y,policy:I(),errors:["Config file is empty"]};try{let Z=Ot(JSON.parse(Y),P.home);return{path:H,exists:!0,raw:Y,policy:Z.policy,errors:Z.errors}}catch(Z){return{path:H,exists:!0,raw:Y,policy:I(),errors:[`Invalid JSON: ${Z instanceof Error?Z.message:String(Z)}`]}}}function Hn(P,L,H={}){let Y=u(P,H),Z=Ot(L,P.home);if(Z.errors.length>0)return{path:Y,policy:I(),errors:Z.errors};let oe=Z.policy;return Cb(xb(Y),{recursive:!0,mode:448}),h(ae(Y),`${JSON.stringify(oe,null,2)}
281
- `,384),kb(Y,384),{path:Y,policy:oe,errors:[]}}function Nu(P,L){let H=Ot(L,P.home);if(H.errors.length>0)return{errors:H.errors};return{preview:Be(H.policy,P.env),errors:[]}}function Lu(P,L={}){let H=u(P,L);if(!Ou(H))return Hn(P,ne,L);let Y=$u(H,"utf-8");if(!Y.trim())return Hn(P,ne,L);try{return Hn(P,k(JSON.parse(Y),P.home),L)}catch{return Hn(P,ne,L)}}var ju=new Set(["check","apply"]),Fu="(unset)";async function Mu(P,L,H={}){let Y=mn({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},L),Z=Y.positionals[0],oe=[...Y.errors,...Z&&!ju.has(Z)?[`Unknown policy subcommand: ${Z}`]:[],...Z&&ju.has(Z)&&!Y.positionals[1]?[`policy ${Z} requires a file`]:[],...Y.positionals.slice(2).map((We)=>`Unexpected policy argument: ${We}`)];if(oe.length>0){for(let We of oe)console.error(We);return 1}let se=Y.positionals[1];if(!Z||!se)return Wt(Tr,console.error),1;let me=H.cwd??process.cwd(),he=Y.flags.global?u(P):y(me);if(!Y.flags.global&&O(P,{cwd:me}))return console.error(`${he} is the user policy, not a project policy; use --global for the user scope, or run from a project directory`),1;let ke=$t(se),Pe=[...ke.errors,...Cr(ke.value,P.home).map((We)=>`${se}: ${We}`),...!Y.flags.global&&Ab(ke.value)&&ke.value.audit!==void 0?[`${se}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(Pe.length>0){for(let We of Pe)console.error(We);return 1}let Te=k(ke.value,P.home);if(console.log(`Scope: ${Y.flags.global?"user":"project"} (${he})`),console.log(`Proposal: ${se}`),Y.flags.global)Hu(k($t(he).value,P.home),Te,!0);if(!Y.flags.global){let We=xr(P).baseline;console.log("Effective policy (user + project merged):"),Hu(te(We,fe($t(he).value,P.home).policy).policy,te(We,fe(ke.value,P.home).policy).policy,!1)}if(Z==="check")return 0;let _e=H.input??process.stdin,Ae=H.output??process.stdout;if(!_e.isTTY||!Ae.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${se}${Y.flags.global?" --global":""}`),1;if(!await Eb(`Apply this policy to ${he}? [y/N] `,_e,Ae))return console.log("Cancelled; nothing was written."),0;return Tb(P,he,ke.value,Te,Y.flags.global),console.log(`Policy applied: ${he}`),0}function Eb(P,L,H){let Y=Rb({input:L,output:H,terminal:!1});return new Promise((Z)=>{Y.once("close",()=>Z(!1)),Y.question(P,(oe)=>{Z(/^y(es)?$/i.test(oe.trim())),Y.close()})})}function Tb(P,L,H,Y,Z){if(Z){Hn(P,Y);return}Pb(Sb(L),{recursive:!0}),bn(L,Eo(H,Y))}function Hu(P,L,H){let Y=Ro(P,L,H);if(Y.length===0){console.log("No changes.");return}console.log(`Changes (${Y.length}):`);for(let Z of Y)console.log(` ${Z.field}: ${Z.before??Fu} -> ${Z.after??Fu}`)}function Ab(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{join as Gw}from"node:path";var Uu="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Priority |\n|-------|-------------|---------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | Second |\n| GitHub source | Listed in a local `rule.json` | Vendored into the consumer's `<rulebook-name>/rulebook.json` by `rule add` | Source order |\n\nEvery rulebook is a live file: the runtime reads it on each tool call, so an edit applies to the next command with no publishing step.\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule verify` reports the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- `caffeinate`, `exec`, `nice`, `nohup`, `setsid`, `stdbuf`, `time`, and `timeout` are built-in transparent wrappers and need no configuration. Configure only other wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n- `command_tools`: Optional array of shell tools that a plugin adds to an agent and that CC Safety Net does not know. Each entry is a tool name such as `\"ops_bash\"`, or `{ \"name\": \"ops_run_background\", \"cwd\": \"cwd\" }` when the tool takes its working directory in a named argument (otherwise `workdir`, `cwd`, or `working_directory` is read). A call to a declared tool with a non-empty string `command` is analyzed like a built-in shell command. User and project lists merge; the user entry wins a name declared in both.\n- Built-in shell and file tools are already analyzed and cannot be declared; `rule verify` reports one declared by hand.\n- Use `cc-safety-net rule tool add ops_bash ops_run_background` to declare tools in the user config, or add `--project` for the project config.\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 To(P,L){if(!P.ok){Ju(P);return}qu(P,L)}function Gu(P,L,H){if(P.ok)console.log(H);if(!P.add){To(P,`Added rulebook source: ${L}`);return}if(!P.ok){Ju(P);return}if(P.add.added.length>0)console.log(`Added ${P.add.added.length} ${P.add.added.length===1?"rulebook":"rulebooks"} from ${P.add.source} at ${P.add.ref}:`),P.add.added.forEach((Y)=>{console.log(` - ${Y}`)});if(P.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${P.add.source} at ${P.add.ref}: ${P.add.alreadyConfigured.join(", ")}`);if(P.add.commits.length>0)console.log(`Vendored at ${P.add.commits.map((Y)=>Y.slice(0,7)).join(", ")}.`);qu(P,"Rule config updated.")}function qu(P,L){for(let H of P.changes??[])console.log(H);console.log(L),console.log(""),_b(P.entries)}function _b(P){if(P.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${P.length}):`);for(let L of P)console.log(` - ${L.name} ${L.version} (${Ib(L.ruleCount)})`),console.log(` Source: ${L.spec}`)}function Ib(P){return`${P} ${P===1?"rule":"rules"}`}function Vu(P){zn("Active sources",P.rulebooks,(L)=>[`[${L.source}] ${L.name} ${L.version}`,` Source: ${L.spec}`]),zn("Active rules",P.rules,(L)=>[`[${$b(P,L.name)}] ${L.name}`,...Ob(L),` Reason: ${L.reason}`]),zn("Disabled rules",Bu(P,"off"),(L)=>[L.key]),zn("Reason overrides",Bu(P,"reason"),(L)=>[L.key,` Reason: ${L.value.reason}`]),zn("Transparent wrappers",P.transparent_wrappers,(L)=>[L]),zn("Issues",P.errors,(L)=>[L]),zn("Warnings",P.warnings,(L)=>[L])}function Ku(P){zn("Command tools",P,(L)=>typeof L.tool==="string"?[`[${L.scope}] ${L.tool}`]:[`[${L.scope}] ${L.tool.name}`,...L.tool.cwd===void 0?[]:[` Cwd argument: ${L.tool.cwd}`]])}function zn(P,L,H){if(L.length===0){console.log(`${P}: (none)`);return}console.log(`${P} (${L.length}):`);for(let Y of L){let[Z,...oe]=H(Y);console.log(` - ${Z}`);for(let se of oe)console.log(` ${se}`)}}function Ob(P){if(!P.match)return[` Command: ${P.subcommand?`${P.command} ${P.subcommand}`:P.command}`,` Block args: ${P.block_args.join(", ")}`];return[` Command: ${[P.command,...P.match.command_path].join(" ")}`,...P.match.any_args?[` Any args: ${P.match.any_args.join(", ")}`]:[],...P.match.exclude_args?[` Exclude args: ${P.match.exclude_args.join(", ")}`]:[]]}function $b(P,L){return P.rulebooks.find((H)=>H.rules.includes(L))?.source??"project"}function Bu(P,L){return Object.entries({...P.userConfig?.overrides,...P.projectConfig?.overrides}).filter((H)=>{if(L==="off")return H[1]==="off";return!!H[1]&&typeof H[1]==="object"}).map(([H,Y])=>({key:H,value:Y}))}function Ju(P){for(let L of P.errors)console.error(L)}import{dirname as yp,join as Lo}from"node:path";import{join as Ls,resolve as Vb}from"node:path";function Pr(P){let L=d(P);if(L.errors.length>0)return{ok:!1,result:{ok:!1,errors:L.errors,entries:[]}};return{ok:!0,config:L.config??ue}}function zu(P){bn(P,ue)}function Wu(P){bn(P,{rulebook_version:1,name:"example-rules",version:"1.0.0",description:"Project-specific CC Safety Net rules.",author:"project",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as Oo}from"node:path";var Db="custom.";function Ao(P){if(P.rulebook_version!==2)return[];let L=P.rules.map((H)=>({name:H.name,command:H.command,block_args:[],match:H.match,reason:H.reason,intent:H.intent}));return(P.tests??[]).flatMap((H,Y)=>{let Z=$s(v(H.command));if(Z.length===0)return[`tests[${Y}]: could not parse fixture command: ${H.command}`];let oe=Z.reduce((se,me)=>se??N(me,L)?.id.slice(Db.length),void 0);if(H.expect==="blocked"){if(oe===H.rule)return[];let se=oe?`"${oe}" matched first`:"no rule matched";return[`tests[${Y}]: expected "${H.rule}" to block "${H.command}" but ${se}`]}return oe?[`tests[${Y}]: expected "${H.command}" to be allowed but "${oe}" matched`]:[]})}function $s(P){return P.nodes.flatMap((L)=>{if(L.kind==="group"||L.kind==="function")return $s(L.body);if(L.kind!=="command")return[];let H=Ee(re(L.dialect,L.words)).words.map(t);return[...H.length>0?[H]:[],...L.nested.flatMap((Y)=>$s(Y))]})}var _o=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function Io(P={}){return{requests:0,responseBytes:0,maxRequests:P.maxRequests??_o.maxRequests,maxResponseBytes:P.maxResponseBytes??_o.maxResponseBytes}}function Mn(P){return{controller:new AbortController,budget:Io(),resolveUrl:P}}function Yu(P){return P instanceof Error&&P.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function Zu(P){if(P.requests>=P.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.requests++}function Xu(P,L){if(L>P.maxResponseBytes-P.responseBytes)throw P.responseBytes+=L,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.responseBytes+=L}var np=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function Qu(P,L,H=w(Oo(Oo(L)),"rules policy"),Y=Mn()){if(C(P))return Fb(P,Y);return jb(P,L,H)}async function tp(P,L,H,Y,Z,oe){if(!C(P))return Qu(P,L,H,Y);let se=Z?null:Nb(P,L,H);if(se)return se;if(!Z&&!oe)throw Error(`${P} is not vendored; run rule update ${P} to vendor it`);return Qu(P,L,H,Y)}function Nb(P,L,H=w(Oo(Oo(L)),"rules policy")){let Y=M(P),Z=F(L,Y.name),oe=r(i(H,Z));if(oe===null)return null;let se=pe(Ds(oe,`Invalid rulebook ${Z}.`));if(se.name!==Y.name)throw Error(`rulebook name "${se.name}" in ${Z} must match "${Y.name}"`);return{spec:P,rulebook:se,content:oe}}async function rp(P,L={}){if(!X(P))throw Error(`Invalid GitHub repository source: ${P}`);let[H,Y]=P.split("/");if(!H||!Y)throw Error(`Invalid GitHub repository source: ${P}`);if(L.ref!==void 0&&!ce(L.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${L.ref}`);let Z=L.operation??Mn(),oe=L.ref??await Lb(H,Y,P,Z),se=await ip(H,Y,oe,P,Z),me=await $o(`https://api.github.com/repos/${H}/${Y}/git/trees/${se}?recursive=1`,"tree",Z),he=me.response;if(!he.ok)throw Error(`Failed to inspect ${P}: GitHub tree returned ${he.status}`);let ke=JSON.parse(me.content);if(!Array.isArray(ke?.tree))throw Error(`Failed to inspect ${P}: unexpected GitHub tree response`);let Pe=ke.tree,Te=[...new Set(Pe.flatMap((_e)=>{if(!_e||typeof _e!=="object")return[];let Ae=_e;if(Ae.type!=="blob"||typeof Ae.path!=="string")return[];let Le=Ae.path.match(Et);return Le?.[1]?[Le[1]]:[]}))].sort();if(Te.length===0)throw Error(`No rulebooks found in ${P} under ${be}/`);return{source:P,owner:H,repo:Y,ref:oe,commit:se,names:Te}}async function Lb(P,L,H,Y){let Z=await $o(`https://api.github.com/repos/${P}/${L}`,"metadata",Y),oe=Z.response;if(!oe.ok)throw Error(`Failed to inspect ${H}: GitHub returned ${oe.status}`);let me=JSON.parse(Z.content)?.default_branch;if(typeof me!=="string"||me==="")throw Error(`Failed to inspect ${H}: missing default branch`);if(!ce(me))throw Error(`GitHub returned an invalid default branch: ${me}`);return me}function jb(P,L,H){kt(P);let Y=F(L,P),Z=r(i(H,Y));if(Z===null)throw Error(`Rulebook source not found: ${P}`);let oe=op(Ds(Z,"Invalid local rulebook source."));if(oe.name!==P)throw Error(`rulebook name "${oe.name}" must match local source "${P}"`);return{spec:P,rulebook:oe,content:Z}}async function Fb(P,L){let H=M(P),Y=await ip(H.owner,H.repo,H.ref,P,L),Z=await $o(`https://raw.githubusercontent.com/${H.owner}/${H.repo}/${Y}/${H.path}`,"raw",L),oe=Z.response;if(!oe.ok)throw Error(`Failed to fetch ${P}: GitHub raw returned ${oe.status}`);let se=Z.content,me=op(Ds(se,"Invalid GitHub rulebook response."));if(me.name!==H.name)throw Error(`rulebook name "${me.name}" must match GitHub source "${H.name}"`);return{spec:P,rulebook:me,content:se}}function op(P){let L=pe(P),H=Ao(L);if(H.length>0)throw Error(H.join("; "));return L}function Ds(P,L){try{return JSON.parse(P)}catch{throw Error(L)}}async function ip(P,L,H,Y,Z){let oe=await $o(`https://api.github.com/repos/${P}/${L}/commits/${encodeURIComponent(H)}`,"commit",Z),se=oe.response;if(!se.ok)throw Error(`Failed to resolve ${Y}: GitHub returned ${se.status}`);let me=JSON.parse(oe.content);if(typeof me?.sha!=="string"||me.sha==="")throw Error(`Failed to resolve commit for ${Y}`);return me.sha}async function Hb(P,L,H={}){if(H.signal?.aborted)throw H.signal.reason;let Y=H.budget??Io(),Z=new AbortController,oe=()=>Z.abort(H.signal?.reason);H.signal?.addEventListener("abort",oe,{once:!0});let se=!1,me=setTimeout(()=>{if(Z.signal.aborted)return;se=!0,Z.abort()},H.timeoutMs??np.timeoutMs);try{if(H.signal?.aborted)throw H.signal.reason;Zu(Y);let he=await fetch(P,{signal:Z.signal,redirect:"error"});if(!he.ok)return sp(he),{response:he,content:""};return{response:he,content:await Mb(he,L,Y,()=>Z.abort())}}catch(he){if(se)throw Error("GitHub request timed out",{cause:he});if(H.signal?.aborted)throw H.signal.reason;throw he}finally{clearTimeout(me),H.signal?.removeEventListener("abort",oe)}}function $o(P,L,H){return Hb(H.resolveUrl?.(P)??P,L,{budget:H.budget,signal:H.controller.signal})}async function Mb(P,L,H=Io(),Y){let Z=np[`${L}Bytes`],oe=Number(P.headers.get("content-length"));if(Number.isFinite(oe)&&oe>Z)throw sp(P),Error(`GitHub ${L} response exceeds ${Z} bytes`);if(!P.body)return"";let se=P.body.getReader(),me=[],he=0;while(!0){let ke=await se.read();if(ke.done)break;try{Xu(H,ke.value.byteLength)}catch(Pe){throw Y?.(),ep(se),Pe}if(he+=ke.value.byteLength,he>Z)throw Y?.(),ep(se),Error(`GitHub ${L} response exceeds ${Z} bytes`);me.push(Buffer.from(ke.value))}return Buffer.concat(me,he).toString("utf-8")}function sp(P){if(!P.body)return;ap(()=>P.body?.cancel())}function ep(P){ap(()=>P.cancel())}function ap(P){try{Promise.resolve(P()).catch(()=>{})}catch{}}var Ub=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function lp(P,L){let H=up(P.rules,L);if(H.length>0)return{ok:!0,specs:H};return dp(P.rules,L)}function cp(P,L){let H=up(P,L);if(H.length>0)return{ok:!0,specs:H};let Y=Gb(P,L);if(Y.length>0)return{ok:!0,specs:Y};let Z=qb(P,L);if(!Z.ok)return Z;if(Z.specs.length>0)return{ok:!0,specs:Z.specs};return dp(P,L)}function dp(P,L){let H=P.filter((Y)=>Ns(Y)?.name===L);if(H.length===1)return{ok:!0,specs:H};return Bb(L,H)}function Bb(P,L){return{ok:!1,result:{ok:!1,errors:L.length===0?[`No configured rulebook matches ${P}`]:[`Ambiguous rulebook match ${P}: ${L.join(", ")}`],entries:[]}}}function up(P,L){return P.filter((H)=>H===L)}function Gb(P,L){let H=L.match(Ub),Y=H?.[1],Z=H?.[2],oe=H?.[3];if(!Y||!Z||!oe||!ce(oe))return[];return pp(P,(se)=>se.owner===Y&&se.repo===Z&&se.ref===oe)}function qb(P,L){if(!X(L))return{ok:!0,specs:[]};let[H,Y]=L.split("/"),Z=pp(P,(se)=>se.owner===H&&se.repo===Y);if(new Set(Z.map((se)=>Ns(se)?.ref).filter((se)=>!!se)).size<2)return{ok:!0,specs:Z};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${L}. Use an explicit ref:`,` cc-safety-net rule remove ${L}#<ref>`],entries:[]}}}function Ns(P){try{return M(P)}catch{return null}}function pp(P,L){return P.filter((H)=>{let Y=Ns(H);return Y?L(Y):!1})}async function No(P,L={}){return Kb(P,L,await Do(P,L,Mn()))}function Kb(P,L,H){if(!H.ok)return H;let Y=hn(P,L),Z=[...new Set(V(Y.configPath,Y.filesystemScope))];if(Z.length===0)return H;return{ok:!1,errors:Z,entries:H.entries}}async function Do(P,L,H,Y={},Z=new Set,oe=new Set){try{let se=hn(P,L),me=Pr(se.configTarget);if(!me.ok)return me.result;let he=me.config,ke=L.only?lp(he,L.only):{ok:!0,specs:he.rules};if(!ke.ok)return ke.result;let Pe=new Set([...L.refresh?ke.specs:[],...Z]),Te=(nn)=>tp(nn,se.configDir,se.filesystemScope,H,Pe.has(nn),!L.refresh||Pe.has(nn)),_e=await tw(he.rules,L.refresh?(nn)=>Te(nn).then((sn)=>({ok:!0,item:sn})).catch((sn)=>{if(Yu(sn))throw sn;return{ok:!1,spec:nn,message:sn instanceof Error?sn.message:String(sn)}}):async(nn)=>({ok:!0,item:await Te(nn)}),H),Ae=_e.filter((nn)=>!nn.ok),Le=_e.filter((nn)=>nn.ok).map((nn)=>nn.item),We=Le.flatMap((nn)=>Jb(nn,he.rules)),Fe=Le.flatMap((nn)=>zb(nn,oe,se)),Ze=new Set([...We,...Fe].map((nn)=>nn.spec)),tn=[...Ae,...We,...Fe],on=[],ln=Yb(on,()=>Le.flatMap((nn)=>Ze.has(nn.spec)||tn.length>0&&oe.has(nn.spec)?[]:Wb(nn,se,Y,on)));return{ok:tn.length===0,errors:tn.map((nn)=>`Failed to update ${nn.spec}: ${nn.message}`),entries:Le.map(Xb),changes:ln}}catch(se){return Rr(se)}}function Jb(P,L){if(!C(P.spec))return[];let H=Ge(P.spec),Y=L.filter((Z)=>Z!==P.spec&&Ge(Z).toLowerCase()===H.toLowerCase());if(Y.length===0)return[];return[{ok:!1,spec:P.spec,message:`rulebook name "${H}" is also claimed by ${Y.join(", ")}; rename one of them`}]}function zb(P,L,H){if(!L.has(P.spec)||!C(P.spec))return[];let Y=F(H.configDir,P.rulebook.name),Z=r(i(H.filesystemScope,Y));if(Z===null||Z===P.content)return[];return[{ok:!1,spec:P.spec,message:`${Y} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Wb(P,L,H,Y){if(!C(P.spec))return[];let Z=F(L.configDir,P.rulebook.name),oe=i(L.filesystemScope,Z),se=r(oe);if(se===P.content)return[];return Y?.push({target:oe,previous:se}),h(oe,P.content,void 0,H._testAfterPolicyRename),Zb(P,se)}function Yb(P,L){try{return L()}catch(H){for(let Y of[...P].reverse()){if(Y.previous===null){W(Y.target);continue}h(Y.target,Y.previous)}throw H}}function Zb(P,L){if(L===null)return[`Vendored ${P.spec} (${P.rulebook.version})`];let H=Ce(L),Y="problem"in H?null:H.rulebook,Z=new Map(Y?.rules.map((se)=>[se.name,JSON.stringify(se)])??[]),oe=new Set(P.rulebook.rules.map((se)=>se.name));return[`Updated ${P.spec} (${Y?.version??"unreadable"} -> ${P.rulebook.version})`,...[...oe].filter((se)=>!Z.has(se)).map((se)=>` + ${se}`),...[...Z.keys()].filter((se)=>!oe.has(se)).map((se)=>` - ${se}`),...P.rulebook.rules.filter((se)=>{let me=Z.get(se.name);return me!==void 0&&me!==JSON.stringify(se)}).map((se)=>` ~ ${se.name}`)]}function Xb(P){return{spec:P.spec,name:P.rulebook.name,version:P.rulebook.version,ruleCount:P.rulebook.rules.length}}async function fp(P,L,H={}){return Qb(P,L,H,Mn())}async function Qb(P,L,H,Y,Z={}){let oe=null,se=!1;try{let me=hn(P,H),he=r(me.configTarget);oe={target:me.configTarget,content:he};let ke=Pr(me.configTarget);if(!ke.ok)return ke.result;let Pe=ke.config,Te=X(L)?await rp(L,{ref:H.ref,operation:Y}):null,_e=Te?ew(Te,H.rulebooks):[],Ae=Te?_e.map((tn)=>nw(Pe.rules,Te,tn)??`${L}#${Te.ref}/${tn}`):[L],Le=Ae.filter((tn)=>!Pe.rules.includes(tn)),We=[...Pe.rules,...Le];if(We.length>xe)return rw();if(We.length!==Pe.rules.length)se=!0,bn(me.configTarget,{...Pe,rules:We},void 0,Z._testAfterPolicyRename);let Fe=await Do(P,H,Y,Z,new Set(Le),new Set(Le));if(!Fe.ok)Sr(me.configTarget,he);if(!Fe.ok||!Te)return Fe;let Ze=_e.filter((tn,on)=>Le.includes(Ae[on]??""));return{...Fe,add:{source:L,ref:Te.ref,selected:_e,added:Ze,alreadyConfigured:_e.filter((tn)=>!Ze.includes(tn)),commits:Le.length>0?[Te.commit]:[]}}}catch(me){if(se&&oe)try{Sr(oe.target,oe.content)}catch(he){return Rr(he)}return Rr(me)}}function ew(P,L){let H=L?[...new Set(L)]:P.names,Y=H.filter((Z)=>!P.names.includes(Z));if(Y.length>0)throw Error(`Rulebooks not found in ${P.source} at ${P.ref}: ${Y.join(", ")}
282
- Available rulebooks: ${P.names.join(", ")}`);return H}function nw(P,L,H){let Y=`${L.source}#${L.ref}/${H}`;if(P.includes(Y))return Y;let Z=`${L.source}#${L.commit}/${H}`;return P.find((oe)=>oe===Z)}async function tw(P,L,H=Mn()){if(P.length>xe)throw Error(Se);let Y=[],Z=0,oe,se=Array.from({length:Math.min(P.length,_o.concurrency)},async()=>{while(!oe){let me=Z;if(me>=P.length)return;Z++;try{Y[me]=await L(P[me],me,H.controller.signal)}catch(he){if(!oe)oe={value:he},Z=P.length,H.controller.abort(he);return}}});if(await Promise.all(se),oe)throw oe.value;return Y}function rw(){return{ok:!1,errors:[Se],entries:[]}}async function mp(P,L,H={}){try{return await ow(P,L,H,{})}catch(Y){return Rr(Y)}}async function ow(P,L,H,Y){let Z=hn(P,H),oe=d(Z.configTarget);if(oe.errors.length>0)return{ok:!1,errors:oe.errors,entries:[]};if(!oe.config)return{ok:!1,errors:[`No config found at ${Z.configPath}`],entries:[]};let se=cp(oe.config.rules,L);if(!se.ok)return se.result;let me=H.deleteSource?iw(Z.configDir,se.specs,Z.filesystemScope):{ok:!0,dirs:[]};if(!me.ok)return me.result;let he=r(Z.configTarget);if(he===null)return Rr(Error("Rules config is unavailable."));try{bn(Z.configTarget,{...oe.config,rules:oe.config.rules.filter((Te)=>!se.specs.includes(Te))},void 0,Y._testAfterPolicyRename)}catch(Te){throw Sr(Z.configTarget,he),Te}let ke=await Do(P,H,Mn(),Y);if(!ke.ok)return Sr(Z.configTarget,he),ke;let Pe=sw(me.dirs,Y,Z.filesystemScope);if(!Pe.ok){Sr(Z.configTarget,he);let Te=await Do(P,H,Mn(),Y);if(!Te.ok)return{ok:!1,errors:[...Pe.result.errors,...Te.errors],entries:Te.entries};return Pe.result}return ke}function iw(P,L,H){let Y=L.flatMap((me)=>p.test(me)?[]:["--delete-source can only delete local rulebook sources"]),Z=L.map((me)=>Ls(P,me)),oe=Y.length>0?[]:Z.flatMap((me)=>gp(me,H)),se=[...Y,...oe];return se.length>0?{ok:!1,result:{ok:!1,errors:se,entries:[]}}:{ok:!0,dirs:Z}}function gp(P,L){let H=Vb(P),Y=i(L,H),Z=ye(Y);if(!Z)return[`Local rulebook source directory not found: ${P}`];let oe=Z.find((se)=>se.name==="rulebook.json");if(!oe)return[`Local rulebook source directory is missing rulebook.json: ${P}`];if(oe.kind!=="file")throw new o(L.label);if(r(i(L,Ls(H,"rulebook.json"))),Z.length>1)return[`Local rulebook source directory contains extra files: ${P}. delete manually if you really want to remove the directory.`];return[]}function sw(P,L,H){let Y=P.flatMap((Z)=>{try{if(!ye(i(H,Z)))return[];let oe=gp(Z,H);if(oe.length>0)return oe;return aw(Z,L,H),[]}catch(oe){return[`Failed to delete local rulebook source ${Z}: ${oe instanceof Error?oe.message:String(oe)}`]}});return Y.length>0?{ok:!1,result:{ok:!1,errors:Y,entries:[]}}:{ok:!0}}function aw(P,L,H){if(L._testDeleteLocalSourceDir){L._testDeleteLocalSourceDir(P);return}W(i(H,Ls(P,ve))),Ct(i(H,P))}function Sr(P,L){if(L===null){W(P);return}h(P,L)}function Rr(P){return{ok:!1,errors:[P instanceof Error?P.message:String(P)],entries:[]}}var lw=".safety-net.json",cw="~/.cc-safety-net/config.json";async function bp(P,L){let H=O(P,{cwd:L.cwd});if(H)console.log(`Skipped the project scope: ${A(L.cwd)} is the user rule config, not a project rule config`);return[H||await hp(P,{legacyPath:Lt(L.cwd),configPath:A(L.cwd),defaultRulebookName:"project-rules",migratedFrom:lw,cleanup:L.cleanup,syncOptions:{cwd:L.cwd}}),await hp(P,{legacyPath:jt(P),configPath:z(P),defaultRulebookName:"user-rules",migratedFrom:cw,cleanup:L.cleanup,syncOptions:{cwd:L.cwd,global:!0}})].every((Z)=>Z)?0:1}async function hp(P,L){let H=hn(P,L.syncOptions),Y=i(H.filesystemScope,L.legacyPath),Z=r(Y);if(Z===null)return console.log(`No legacy config found at ${L.legacyPath}`),!0;let oe=uw(Z);if(!oe.ok){for(let Ae of oe.errors)console.error(Ae);return!1}let se=d(H.configTarget);if(se.errors.length>0){for(let Ae of se.errors)console.error(Ae);return!1}let me=se.config??ue,he=pw(yp(L.configPath),me.rules,L.defaultRulebookName,L.migratedFrom,H.filesystemScope),ke=Lo(yp(L.configPath),he,"rulebook.json"),Pe=i(H.filesystemScope,ke),Te=[vp(H.configTarget),vp(Pe)],_e=await dw(P,L,H.configTarget,Pe,he,oe.config.rules,{...me,rules:me.rules.includes(he)?me.rules:[...me.rules,he]});if(!_e.ok){gw(Te);for(let Ae of _e.errors)console.error(Ae);return!1}if(!L.cleanup)return console.log(`Migrated legacy config at ${L.legacyPath}. Legacy file is no longer used.`),!0;if(!mw(H.configTarget,Pe,he,L.migratedFrom,oe.config.rules))return console.error(`Migration cleanup verification failed for ${L.legacyPath}`),!1;return W(Y),console.log(`Deleted legacy config at ${L.legacyPath}`),!0}async function dw(P,L,H,Y,Z,oe,se){try{return bn(H,se),bn(Y,fw(Z,L.migratedFrom,oe)),await No(P,L.syncOptions)}catch(me){return{ok:!1,errors:[me instanceof Error?me.message:String(me)]}}}function uw(P){try{let L=JSON.parse(P),H=Wo(L);if(H.errors.length>0)return{ok:!1,errors:H.errors};return{ok:!0,config:{version:1,rules:L.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function pw(P,L,H,Y,Z){let oe=L.find((se)=>yw(i(Z,Lo(P,se,"rulebook.json")))===Y);if(oe)return oe;if(r(i(Z,Lo(P,H,"rulebook.json")))===null)return H;for(let se=2;;se++){let me=`${H}-${se}`;if(r(i(Z,Lo(P,me,"rulebook.json")))===null)return me}}function fw(P,L,H){return{rulebook_version:1,name:P,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:L,allowed_commands:[...new Set(H.map((Y)=>Y.command))],rules:H,tests:H.map((Y)=>({command:[Y.command,Y.subcommand,Y.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:Y.name}))}}function mw(P,L,H,Y,Z){if(!d(P).config?.rules.includes(H))return!1;try{let se=r(L);if(se===null)return!1;let me=JSON.parse(se);return me.migrated_from===Y&&JSON.stringify(me.rules)===JSON.stringify(Z)}catch{return!1}}function vp(P){return{target:P,content:r(P)}}function gw(P){for(let L of P){if(L.content===null){W(L.target);continue}h(L.target,L.content)}}function yw(P){let L=r(P);if(L===null)return null;try{let H=JSON.parse(L);return typeof H.migrated_from==="string"?H.migrated_from:null}catch{return null}}import{mkdir as hw,readFile as vw,writeFile as bw}from"node:fs/promises";import{dirname as ww,join as kw}from"node:path";var Cw=86400000,xw=604800000;async function kp(P,L=Date.now()){if(P.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let H=tt(P);if(!H)return null;let Y=kw(H,".cc-safety-net","update-check.json"),Z=await Pw(Y,L);if(!Z.lastCheck||L-Z.lastCheck>Cw){let me=await Bn();if(Z.lastCheck=L,me.latestVersion)Z.latestVersion=me.latestVersion;if(!await wp(Y,Z))return null;if(me.error)return null}let oe=Z.latestVersion,se=pn();if(!oe||!ni(oe,se))return null;if(Z.notifiedVersion===oe&&Z.notifiedAt!==void 0&&L-Z.notifiedAt<xw)return null;if(Z.notifiedVersion=oe,Z.notifiedAt=L,!await wp(Y,Z))return null;return`UPDATE_AVAILABLE: cc-safety-net v${oe} is available (running v${se}). 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 Pw(P,L){let H=await vw(P,"utf8").then((oe)=>JSON.parse(oe)).catch(()=>{return});if(!H||typeof H!=="object"||Array.isArray(H))return{};let Y=H,Z=(oe)=>typeof oe==="number"&&Number.isFinite(oe)&&oe<=L?oe:void 0;return{lastCheck:Z(Y.lastCheck),latestVersion:typeof Y.latestVersion==="string"?Y.latestVersion:void 0,notifiedVersion:typeof Y.notifiedVersion==="string"?Y.notifiedVersion:void 0,notifiedAt:Z(Y.notifiedAt)}}async function wp(P,L){return hw(ww(P),{recursive:!0,mode:448}).then(()=>bw(P,JSON.stringify(L),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as Aw,resolve as Hs}from"node:path";var Cp=new Map([["Bash","posix"],["PowerShell","powershell"],["Monitor","posix"]]);var xp=new Map([["Bash","auto"]]);var Pp=new Map([["bash","auto"],["Bash","auto"],["powershell","powershell"],["PowerShell","powershell"]]);var Sp=new Map([["Shell","auto"]]);var Rp=new Map([["exec","auto"]]),Ep="write_to_process";var Tp=new Map([["Execute","auto"]]);var Ap=new Map([["run_shell_command","auto"]]);var _p=new Map([["run_terminal_command","auto"],["run_terminal_cmd","auto"],["monitor","auto"],["bash","auto"],["Shell","auto"]]);var Ip=new Map([["terminal","posix"]]);var Op=new Map([["Bash","posix"]]);var $p="exec";var Ew=[["antigravity-cli",[...rl.keys(),ol]],["claude-code",[...Cp.keys()]],["codex",[...xp.keys()]],["copilot-cli",[...Pp.keys()]],["cursor",[...Sp.keys()]],["deepseek-harness",[...et.keys()]],["devin",[...Rp.keys(),Ep]],["droid",[...Tp.keys()]],["gemini-cli",[...Ap.keys()]],["grok-build",[..._p.keys()]],["hermes-agent",[...Ip.keys()]],["kimi-code",[...Op.keys()]],["openclaw",[$p]],["opencode",[Ye,Re]],["pi",[...Qe.keys()]]].flatMap(([P,L])=>L.map((H)=>({name:H,integration:cn(P)}))),Dp="and is already analyzed. Built-in tools cannot be declared.";function jo(P){let L=Ie(P),H=[...new Set(Ew.filter((Y)=>Ie(Y.name)===L).map((Y)=>Y.integration))].sort((Y,Z)=>Y.localeCompare(Z));if(H.length>0)return`"${P}" is a built-in shell tool of ${Tw(H)}, ${Dp}`;if(x(P)!=="unknown")return`"${P}" is a built-in file tool, ${Dp}`;return}function Tw(P){return P.length===1?P[0]??"":`${P.slice(0,-1).join(", ")} and ${P.at(-1)}`}var Lp="CC Safety Net Config",_w="═".repeat(Lp.length),Iw="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",Ow=new Set(["rule.json","rule.lock","cache"]);function jp(P,L={}){try{return $w(P,L)}catch(H){if(H instanceof o)return console.error(H.message),1;throw H}}function $w(P,L){let H=L.cwd??process.cwd(),Y=Q(P,{cwd:H}),Z=jt(P),oe=Lt(H),se=Hs(H,be),me=i(Y.userScope,Z),he=i(Y.projectScope,oe),ke=!1,Pe=!1,Te=[],_e=[],Ae=Dw(i(Y.projectScope,se));if(Lw(),r(Y.userConfigTarget)!==null){let Le=Un(Y.userConfigTarget);if(Le.errors.push(...V(Y.userConfigPath,Y.userScope),...Np(Y.userConfigTarget)),Te.push({scope:"User",path:Y.userConfigPath,result:Le,schema:"rules",target:Y.userConfigTarget}),Le.errors.length>0)ke=!0}if(r(me)!==null)if(Pe=!0,r(Y.userConfigTarget)!==null)_e.push(Fo("user","cleanup"));else{let Le=Yo(me);if(Te.push({scope:"User",path:Z,result:Le,schema:"legacy",inactive:!0,target:me}),_e.push(Fo("user",Le.errors.length>0?"fix-or-delete":"migrate")),Le.errors.length>0)ke=!0}if(r(Y.projectConfigTarget)!==null){let Le=Un(Y.projectConfigTarget);if(Le.errors.push(...V(Y.projectConfigPath,Y.projectScope),...Np(Y.projectConfigTarget)),Te.push({scope:"Project",path:Hs(Y.projectConfigPath),result:Le,schema:"rules",target:Y.projectConfigTarget}),Le.errors.length>0)ke=!0;if(r(he)!==null)Pe=!0,_e.push(Fo("project","cleanup"))}else if(r(he)!==null){Pe=!0,ke=!0;let Le=Yo(he);Te.push({scope:"Project",path:Hs(oe),result:Le,schema:"legacy",inactive:!0,target:he}),_e.push(Fo("project",Le.errors.length>0?"fix-or-delete":"migrate"))}if(Ae?.result.errors.length)ke=!0;if(Te.length===0&&!Ae)return console.log(`
283
- No config files found. Using built-in rules only.`),0;for(let Le of Te)if(Le.inactive)Fw(Le.scope,Le.path,Le.result);else if(Le.result.errors.length>0)Hw(Le.scope,Le.path,Le.result.errors);else{if(Le.schema==="rules"&&Bw(Le.target))console.log(`
284
- Added $schema to ${Le.scope.toLowerCase()} config.`);jw(Le.scope,Le.path,Le.result,Le.schema)}for(let Le of _e)console.error(`
285
- ${en.red(Le)}`);if(Ae)if(Ae.result.errors.length>0)Uw(Ae.path,Ae.result.errors);else Mw(Ae.path,Ae.result);if(ke)return console.error(`
272
+ `)},ae=wb(G,P.fetchVersion??Ft).then(async(Ae)=>{let Ie=new Set(Ae.targets);return{targets:Ae.targets,codexPluginListOutput:Ae.codexPluginListOutput,kimiPlugin:Ae.kimiPlugin,available:new Map(await Promise.all(On.filter((je)=>Ie.has(je.target)&&hu.has(je.target)).map(async(je)=>[je.target,await vr(je.probeCommand)])))}}),ge=await tr(P.showBanner??!0,()=>({ready:ae,finish:()=>ae}),()=>nr({input:P.input??process.stdin,output:K}),{loadingMessage:"Checking installed integrations…",output:K}),ye=await Promise.resolve().then(()=>(ru(G.tmpdir,process.platform,Z),null)).catch((Ae)=>wr(Ae));if(ge.targets.length===0){if(K.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),ye!==null)console.error(ye);return await ie(),ye===null?0:1}let Pe=ge.targets.some((Ae)=>vu.has(Ae))?await Promise.resolve().then(()=>(xo(G),null)).catch((Ae)=>wr(Ae)):null,Re=await Fr(Promise.all(ge.targets.map((Ae)=>{if(Ae==="kimi-code"&&ge.kimiPlugin)return Promise.resolve({message:"Kimi Code plugin skipped: update it in Kimi Code from /plugins (Installed tab, select cc-safety-net, press Enter)",failed:!1});if(hu.has(Ae)&&!ge.available.get(Ae))return Promise.resolve({message:`${ln(Ae)} not found; skipped`,failed:!1});if(Pe!==null&&vu.has(Ae))return Promise.resolve({message:Pe,failed:!0});return Iu("install",Ae,G,!0,ge.codexPluginListOutput).then((Ie)=>({message:Ie,failed:!1}),(Ie)=>({message:wr(Ie),failed:!0}))})),{loadingMessage:`Updating ${ge.targets.length} integration${ge.targets.length===1?"":"s"}…`,output:K}),_e=ye===null?Re:[...Re,{message:ye,failed:!0}];return _e.forEach((Ae)=>Ae.failed?console.error(Ae.message):K.write(`${Ae.message}
273
+ `)),await ie(),_e.some((Ae)=>Ae.failed)?1:0}function Is(P,G={}){return Promise.resolve().then(()=>bb(P)).then(()=>kb(G)).catch((K)=>(console.error(wr(K)),1))}async function kr(P,G,K={}){try{let Y=c(),Z=await tr(!0,()=>lb(Y,P,G,K),()=>nr({input:K.input??process.stdin,output:K.output??process.stdout}),{loadingMessage:P==="install"?"Checking available integrations…":"Checking installed integrations…",output:K.output??process.stdout});if(!Z)return(K.output??process.stdout).write(`Cancelled: nothing was ${P}ed.
274
+ `),0;if(Z==="update")return(K.runUpdate??(()=>Is([],{fetchVersion:K.fetchVersion,input:K.input,output:K.output,showBanner:!1})))();let X=K.output??process.stdout;return await Bd(Z,async(ie)=>{if(ie==="kimi-code"&&P==="install"){let ge=await vb(K,Y);if(ge===null){X.write(`Cancelled: Kimi Code integration was not installed.
275
+ `);return}if(ge==="plugin"){X.write(`${hb(Y)}
276
+ `);return}}let ae=await Fr(Iu(P,ie,Y),{loadingMessage:`${P==="install"?"Installing":"Uninstalling"} ${ln(ie)} integration…`,output:X});X.write(`${ae}
277
+ `)}),0}catch(Y){return console.error(wr(Y)),1}}function wr(P){let G=P instanceof Error?P.message:String(P),K=typeof P==="object"&&P!==null&&"code"in P?P.code:null;if(K==="EACCES"||K==="EPERM")return`${G}
278
+ Check file permissions for the target config file and parent directory.`;if(K==="ENOENT")return`${G}
279
+ Check that the target config path and parent directory exist.`;if(K==="ENOTDIR")return`${G}
280
+ Check that every parent path component is a directory.`;return G}import{mkdirSync as Eb}from"node:fs";import{dirname as Tb}from"node:path";import{createInterface as Ab}from"node:readline";import{existsSync as $u,readFileSync as Cb}from"node:fs";function Ot(P,G){let K=gt(P,G);return{policy:K.policy,errors:pe(pt(K.issues,mt,(Y)=>Y.kind==="custom")," "," ")}}function Cr(P,G){return Ot(P,G).errors}function Ou(P,G){return{"safety.level":P.safety.level,...Os("safety.overrides",P.safety.overrides),"workflow.worktree_mode":String(P.workflow.worktree_mode),"destructive_command_protection.enabled":String(P.destructive_command_protection.enabled),...Os("destructive_command_protection.overrides",P.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":$s(P.destructive_command_protection.allow_paths),"secret_protection.enabled":String(P.secret_protection.enabled),...Os("secret_protection.overrides",P.secret_protection.overrides),"secret_protection.deny_paths":$s(P.secret_protection.deny_paths),"secret_protection.allow_paths":$s(P.secret_protection.allow_paths),...G?{"audit.retention_days":String(P.audit.retention_days)}:{}}}function Ro(P,G,K){let Y=Ou(P,K),Z=Ou(G,K);return[...new Set([...Object.keys(Y),...Object.keys(Z)])].flatMap((X)=>Y[X]===Z[X]?[]:[{field:X,before:Y[X],after:Z[X]}])}function xr(P,G){let K=u(P,G);if(!$u(K))return{baseline:k(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,P.home),diagnostics:[]};let Y=$t(K),Z=Ot(Y.value,P.home);return{baseline:Z.policy,diagnostics:Y.errors.length>0?Y.errors:Z.errors}}function $t(P){if(!$u(P))return{errors:[`${P}: file not found`]};try{return{value:JSON.parse(Cb(P,"utf-8")),errors:[]}}catch(G){let K=G instanceof Error?G.message:String(G);return{errors:[`${P}: ${G instanceof SyntaxError?`Invalid JSON: ${K}`:K}`]}}}function Eo(P,G){let K=xb(P)?P:{};return{version:G.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((Y)=>K[Y]!==void 0).map((Y)=>[Y,K[Y]]))}}function Os(P,G){return Object.fromEntries(Object.entries(G).flatMap(([K,Y])=>Y===void 0?[]:[[`${P}.${K}`,String(Y)]]))}function $s(P){return P.length===0?"(none)":P.join(", ")}function xb(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{chmodSync as Pb,existsSync as Du,mkdirSync as Sb,readFileSync as Nu}from"node:fs";import{dirname as Rb}from"node:path";function Lu(P,G={}){let K=u(P,G);if(!Du(K))return{path:K,exists:!1,raw:"",policy:I(),errors:[]};let Y=Nu(K,"utf-8");if(!Y.trim())return{path:K,exists:!0,raw:Y,policy:I(),errors:["Config file is empty"]};try{let Z=Ot(JSON.parse(Y),P.home);return{path:K,exists:!0,raw:Y,policy:Z.policy,errors:Z.errors}}catch(Z){return{path:K,exists:!0,raw:Y,policy:I(),errors:[`Invalid JSON: ${Z instanceof Error?Z.message:String(Z)}`]}}}function Hn(P,G,K={}){let Y=u(P,K),Z=Ot(G,P.home);if(Z.errors.length>0)return{path:Y,policy:I(),errors:Z.errors};let X=Z.policy;return Sb(Rb(Y),{recursive:!0,mode:448}),h(ce(Y),`${JSON.stringify(X,null,2)}
281
+ `,384),Pb(Y,384),{path:Y,policy:X,errors:[]}}function ju(P,G){let K=Ot(G,P.home);if(K.errors.length>0)return{errors:K.errors};return{preview:ze(K.policy,P.env),errors:[]}}function Fu(P,G={}){let K=u(P,G);if(!Du(K))return Hn(P,re,G);let Y=Nu(K,"utf-8");if(!Y.trim())return Hn(P,re,G);try{return Hn(P,k(JSON.parse(Y),P.home),G)}catch{return Hn(P,re,G)}}var Hu=new Set(["check","apply"]),Mu="(unset)";async function Bu(P,G,K={}){let Y=fn({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},G),Z=Y.positionals[0],X=[...Y.errors,...Z&&!Hu.has(Z)?[`Unknown policy subcommand: ${Z}`]:[],...Z&&Hu.has(Z)&&!Y.positionals[1]?[`policy ${Z} requires a file`]:[],...Y.positionals.slice(2).map((je)=>`Unexpected policy argument: ${je}`)];if(X.length>0){for(let je of X)console.error(je);return 1}let ie=Y.positionals[1];if(!Z||!ie)return Wt(Tr,console.error),1;let ae=K.cwd??process.cwd(),ge=Y.flags.global?u(P):y(ae);if(!Y.flags.global&&O(P,{cwd:ae}))return console.error(`${ge} is the user policy, not a project policy; use --global for the user scope, or run from a project directory`),1;let ye=$t(ie),Pe=[...ye.errors,...Cr(ye.value,P.home).map((je)=>`${ie}: ${je}`),...!Y.flags.global&&Ob(ye.value)&&ye.value.audit!==void 0?[`${ie}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(Pe.length>0){for(let je of Pe)console.error(je);return 1}let Re=k(ye.value,P.home);if(console.log(`Scope: ${Y.flags.global?"user":"project"} (${ge})`),console.log(`Proposal: ${ie}`),Y.flags.global)Uu(k($t(ge).value,P.home),Re,!0);if(!Y.flags.global){let je=xr(P).baseline;console.log("Effective policy (user + project merged):"),Uu(ne(je,me($t(ge).value,P.home).policy).policy,ne(je,me(ye.value,P.home).policy).policy,!1)}if(Z==="check")return 0;let _e=K.input??process.stdin,Ae=K.output??process.stdout;if(!_e.isTTY||!Ae.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${ie}${Y.flags.global?" --global":""}`),1;if(!await _b(`Apply this policy to ${ge}? [y/N] `,_e,Ae))return console.log("Cancelled; nothing was written."),0;return Ib(P,ge,ye.value,Re,Y.flags.global),console.log(`Policy applied: ${ge}`),0}function _b(P,G,K){let Y=Ab({input:G,output:K,terminal:!1});return new Promise((Z)=>{Y.once("close",()=>Z(!1)),Y.question(P,(X)=>{Z(/^y(es)?$/i.test(X.trim())),Y.close()})})}function Ib(P,G,K,Y,Z){if(Z){Hn(P,Y);return}Eb(Tb(G),{recursive:!0}),vn(G,Eo(K,Y))}function Uu(P,G,K){let Y=Ro(P,G,K);if(Y.length===0){console.log("No changes.");return}console.log(`Changes (${Y.length}):`);for(let Z of Y)console.log(` ${Z.field}: ${Z.before??Mu} -> ${Z.after??Mu}`)}function Ob(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{join as Kw}from"node:path";var Gu="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Priority |\n|-------|-------------|---------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | Second |\n| GitHub source | Listed in a local `rule.json` | Vendored into the consumer's `<rulebook-name>/rulebook.json` by `rule add` | Source order |\n\nEvery rulebook is a live file: the runtime reads it on each tool call, so an edit applies to the next command with no publishing step.\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule verify` reports the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- `caffeinate`, `exec`, `nice`, `nohup`, `setsid`, `stdbuf`, `time`, and `timeout` are built-in transparent wrappers and need no configuration. Configure only other wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n- `command_tools`: Optional array of shell tools that a plugin adds to an agent and that CC Safety Net does not know. Each entry is a tool name such as `\"ops_bash\"`, or `{ \"name\": \"ops_run_background\", \"cwd\": \"cwd\" }` when the tool takes its working directory in a named argument (otherwise `workdir`, `cwd`, or `working_directory` is read). A call to a declared tool with a non-empty string `command` is analyzed like a built-in shell command. User and project lists merge; the user entry wins a name declared in both.\n- Built-in shell and file tools are already analyzed and cannot be declared; `rule verify` reports one declared by hand.\n- Use `cc-safety-net rule tool add ops_bash ops_run_background` to declare tools in the user config, or add `--project` for the project config.\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 To(P,G){if(!P.ok){Wu(P);return}Ku(P,G)}function Vu(P,G,K){if(P.ok)console.log(K);if(!P.add){To(P,`Added rulebook source: ${G}`);return}if(!P.ok){Wu(P);return}if(P.add.added.length>0)console.log(`Added ${P.add.added.length} ${P.add.added.length===1?"rulebook":"rulebooks"} from ${P.add.source} at ${P.add.ref}:`),P.add.added.forEach((Y)=>{console.log(` - ${Y}`)});if(P.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${P.add.source} at ${P.add.ref}: ${P.add.alreadyConfigured.join(", ")}`);if(P.add.commits.length>0)console.log(`Vendored at ${P.add.commits.map((Y)=>Y.slice(0,7)).join(", ")}.`);Ku(P,"Rule config updated.")}function Ku(P,G){for(let K of P.changes??[])console.log(K);console.log(G),console.log(""),$b(P.entries)}function $b(P){if(P.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${P.length}):`);for(let G of P)console.log(` - ${G.name} ${G.version} (${Db(G.ruleCount)})`),console.log(` Source: ${G.spec}`)}function Db(P){return`${P} ${P===1?"rule":"rules"}`}function Ju(P){Jn("Active sources",P.rulebooks,(G)=>[`[${G.source}] ${G.name} ${G.version}`,` Source: ${G.spec}`]),Jn("Active rules",P.rules,(G)=>[`[${Lb(P,G.name)}] ${G.name}`,...Nb(G),` Reason: ${G.reason}`]),Jn("Disabled rules",qu(P,"off"),(G)=>[G.key]),Jn("Reason overrides",qu(P,"reason"),(G)=>[G.key,` Reason: ${G.value.reason}`]),Jn("Transparent wrappers",P.transparent_wrappers,(G)=>[G]),Jn("Issues",P.errors,(G)=>[G]),Jn("Warnings",P.warnings,(G)=>[G])}function zu(P){Jn("Command tools",P,(G)=>typeof G.tool==="string"?[`[${G.scope}] ${G.tool}`]:[`[${G.scope}] ${G.tool.name}`,...G.tool.cwd===void 0?[]:[` Cwd argument: ${G.tool.cwd}`]])}function Jn(P,G,K){if(G.length===0){console.log(`${P}: (none)`);return}console.log(`${P} (${G.length}):`);for(let Y of G){let[Z,...X]=K(Y);console.log(` - ${Z}`);for(let ie of X)console.log(` ${ie}`)}}function Nb(P){if(!P.match)return[` Command: ${P.subcommand?`${P.command} ${P.subcommand}`:P.command}`,` Block args: ${P.block_args.join(", ")}`];return[` Command: ${[P.command,...P.match.command_path].join(" ")}`,...P.match.any_args?[` Any args: ${P.match.any_args.join(", ")}`]:[],...P.match.exclude_args?[` Exclude args: ${P.match.exclude_args.join(", ")}`]:[]]}function Lb(P,G){return P.rulebooks.find((K)=>K.rules.includes(G))?.source??"project"}function qu(P,G){return Object.entries({...P.userConfig?.overrides,...P.projectConfig?.overrides}).filter((K)=>{if(G==="off")return K[1]==="off";return!!K[1]&&typeof K[1]==="object"}).map(([K,Y])=>({key:K,value:Y}))}function Wu(P){for(let G of P.errors)console.error(G)}import{dirname as vp,join as Lo}from"node:path";import{join as js,resolve as zb}from"node:path";function Pr(P){let G=d(P);if(G.errors.length>0)return{ok:!1,result:{ok:!1,errors:G.errors,entries:[]}};return{ok:!0,config:G.config??de}}function Yu(P){vn(P,de)}function Zu(P){vn(P,{rulebook_version:1,name:"example-rules",version:"1.0.0",description:"Project-specific CC Safety Net rules.",author:"project",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as Oo}from"node:path";var jb="custom.";function Ao(P){if(P.rulebook_version!==2)return[];let G=P.rules.map((K)=>({name:K.name,command:K.command,block_args:[],match:K.match,reason:K.reason,intent:K.intent}));return(P.tests??[]).flatMap((K,Y)=>{let Z=Ds(v(K.command));if(Z.length===0)return[`tests[${Y}]: could not parse fixture command: ${K.command}`];let X=Z.reduce((ie,ae)=>ie??N(ae,G)?.id.slice(jb.length),void 0);if(K.expect==="blocked"){if(X===K.rule)return[];let ie=X?`"${X}" matched first`:"no rule matched";return[`tests[${Y}]: expected "${K.rule}" to block "${K.command}" but ${ie}`]}return X?[`tests[${Y}]: expected "${K.command}" to be allowed but "${X}" matched`]:[]})}function Ds(P){return P.nodes.flatMap((G)=>{if(G.kind==="group"||G.kind==="function")return Ds(G.body);if(G.kind!=="command")return[];let K=ke(oe(G.dialect,G.words)).words.map(t);return[...K.length>0?[K]:[],...G.nested.flatMap((Y)=>Ds(Y))]})}var _o=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function Io(P={}){return{requests:0,responseBytes:0,maxRequests:P.maxRequests??_o.maxRequests,maxResponseBytes:P.maxResponseBytes??_o.maxResponseBytes}}function Mn(P){return{controller:new AbortController,budget:Io(),resolveUrl:P}}function Xu(P){return P instanceof Error&&P.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function Qu(P){if(P.requests>=P.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.requests++}function ep(P,G){if(G>P.maxResponseBytes-P.responseBytes)throw P.responseBytes+=G,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.responseBytes+=G}var rp=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function np(P,G,K=w(Oo(Oo(G)),"rules policy"),Y=Mn()){if(C(P))return Ub(P,Y);return Mb(P,G,K)}async function op(P,G,K,Y,Z,X){if(!C(P))return np(P,G,K,Y);let ie=Z?null:Fb(P,G,K);if(ie)return ie;if(!Z&&!X)throw Error(`${P} is not vendored; run rule update ${P} to vendor it`);return np(P,G,K,Y)}function Fb(P,G,K=w(Oo(Oo(G)),"rules policy")){let Y=L(P),Z=M(G,Y.name),X=r(i(K,Z));if(X===null)return null;let ie=fe(Ns(X,`Invalid rulebook ${Z}.`));if(ie.name!==Y.name)throw Error(`rulebook name "${ie.name}" in ${Z} must match "${Y.name}"`);return{spec:P,rulebook:ie,content:X}}async function ip(P,G={}){if(!Q(P))throw Error(`Invalid GitHub repository source: ${P}`);let[K,Y]=P.split("/");if(!K||!Y)throw Error(`Invalid GitHub repository source: ${P}`);if(G.ref!==void 0&&!le(G.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${G.ref}`);let Z=G.operation??Mn(),X=G.ref??await Hb(K,Y,P,Z),ie=await ap(K,Y,X,P,Z),ae=await $o(`https://api.github.com/repos/${K}/${Y}/git/trees/${ie}?recursive=1`,"tree",Z),ge=ae.response;if(!ge.ok)throw Error(`Failed to inspect ${P}: GitHub tree returned ${ge.status}`);let ye=JSON.parse(ae.content);if(!Array.isArray(ye?.tree))throw Error(`Failed to inspect ${P}: unexpected GitHub tree response`);let Pe=ye.tree,Re=[...new Set(Pe.flatMap((_e)=>{if(!_e||typeof _e!=="object")return[];let Ae=_e;if(Ae.type!=="blob"||typeof Ae.path!=="string")return[];let Ie=Ae.path.match(Rt);return Ie?.[1]?[Ie[1]]:[]}))].sort();if(Re.length===0)throw Error(`No rulebooks found in ${P} under ${xe}/`);return{source:P,owner:K,repo:Y,ref:X,commit:ie,names:Re}}async function Hb(P,G,K,Y){let Z=await $o(`https://api.github.com/repos/${P}/${G}`,"metadata",Y),X=Z.response;if(!X.ok)throw Error(`Failed to inspect ${K}: GitHub returned ${X.status}`);let ae=JSON.parse(Z.content)?.default_branch;if(typeof ae!=="string"||ae==="")throw Error(`Failed to inspect ${K}: missing default branch`);if(!le(ae))throw Error(`GitHub returned an invalid default branch: ${ae}`);return ae}function Mb(P,G,K){Tt(P);let Y=M(G,P),Z=r(i(K,Y));if(Z===null)throw Error(`Rulebook source not found: ${P}`);let X=sp(Ns(Z,"Invalid local rulebook source."));if(X.name!==P)throw Error(`rulebook name "${X.name}" must match local source "${P}"`);return{spec:P,rulebook:X,content:Z}}async function Ub(P,G){let K=L(P),Y=await ap(K.owner,K.repo,K.ref,P,G),Z=await $o(`https://raw.githubusercontent.com/${K.owner}/${K.repo}/${Y}/${K.path}`,"raw",G),X=Z.response;if(!X.ok)throw Error(`Failed to fetch ${P}: GitHub raw returned ${X.status}`);let ie=Z.content,ae=sp(Ns(ie,"Invalid GitHub rulebook response."));if(ae.name!==K.name)throw Error(`rulebook name "${ae.name}" must match GitHub source "${K.name}"`);return{spec:P,rulebook:ae,content:ie}}function sp(P){let G=fe(P),K=Ao(G);if(K.length>0)throw Error(K.join("; "));return G}function Ns(P,G){try{return JSON.parse(P)}catch{throw Error(G)}}async function ap(P,G,K,Y,Z){let X=await $o(`https://api.github.com/repos/${P}/${G}/commits/${encodeURIComponent(K)}`,"commit",Z),ie=X.response;if(!ie.ok)throw Error(`Failed to resolve ${Y}: GitHub returned ${ie.status}`);let ae=JSON.parse(X.content);if(typeof ae?.sha!=="string"||ae.sha==="")throw Error(`Failed to resolve commit for ${Y}`);return ae.sha}async function Bb(P,G,K={}){if(K.signal?.aborted)throw K.signal.reason;let Y=K.budget??Io(),Z=new AbortController,X=()=>Z.abort(K.signal?.reason);K.signal?.addEventListener("abort",X,{once:!0});let ie=!1,ae=setTimeout(()=>{if(Z.signal.aborted)return;ie=!0,Z.abort()},K.timeoutMs??rp.timeoutMs);try{if(K.signal?.aborted)throw K.signal.reason;Qu(Y);let ge=await fetch(P,{signal:Z.signal,redirect:"error"});if(!ge.ok)return lp(ge),{response:ge,content:""};return{response:ge,content:await Gb(ge,G,Y,()=>Z.abort())}}catch(ge){if(ie)throw Error("GitHub request timed out",{cause:ge});if(K.signal?.aborted)throw K.signal.reason;throw ge}finally{clearTimeout(ae),K.signal?.removeEventListener("abort",X)}}function $o(P,G,K){return Bb(K.resolveUrl?.(P)??P,G,{budget:K.budget,signal:K.controller.signal})}async function Gb(P,G,K=Io(),Y){let Z=rp[`${G}Bytes`],X=Number(P.headers.get("content-length"));if(Number.isFinite(X)&&X>Z)throw lp(P),Error(`GitHub ${G} response exceeds ${Z} bytes`);if(!P.body)return"";let ie=P.body.getReader(),ae=[],ge=0;while(!0){let ye=await ie.read();if(ye.done)break;try{ep(K,ye.value.byteLength)}catch(Pe){throw Y?.(),tp(ie),Pe}if(ge+=ye.value.byteLength,ge>Z)throw Y?.(),tp(ie),Error(`GitHub ${G} response exceeds ${Z} bytes`);ae.push(Buffer.from(ye.value))}return Buffer.concat(ae,ge).toString("utf-8")}function lp(P){if(!P.body)return;cp(()=>P.body?.cancel())}function tp(P){cp(()=>P.cancel())}function cp(P){try{Promise.resolve(P()).catch(()=>{})}catch{}}var qb=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function dp(P,G){let K=fp(P.rules,G);if(K.length>0)return{ok:!0,specs:K};return pp(P.rules,G)}function up(P,G){let K=fp(P,G);if(K.length>0)return{ok:!0,specs:K};let Y=Kb(P,G);if(Y.length>0)return{ok:!0,specs:Y};let Z=Jb(P,G);if(!Z.ok)return Z;if(Z.specs.length>0)return{ok:!0,specs:Z.specs};return pp(P,G)}function pp(P,G){let K=P.filter((Y)=>Ls(Y)?.name===G);if(K.length===1)return{ok:!0,specs:K};return Vb(G,K)}function Vb(P,G){return{ok:!1,result:{ok:!1,errors:G.length===0?[`No configured rulebook matches ${P}`]:[`Ambiguous rulebook match ${P}: ${G.join(", ")}`],entries:[]}}}function fp(P,G){return P.filter((K)=>K===G)}function Kb(P,G){let K=G.match(qb),Y=K?.[1],Z=K?.[2],X=K?.[3];if(!Y||!Z||!X||!le(X))return[];return mp(P,(ie)=>ie.owner===Y&&ie.repo===Z&&ie.ref===X)}function Jb(P,G){if(!Q(G))return{ok:!0,specs:[]};let[K,Y]=G.split("/"),Z=mp(P,(ie)=>ie.owner===K&&ie.repo===Y);if(new Set(Z.map((ie)=>Ls(ie)?.ref).filter((ie)=>!!ie)).size<2)return{ok:!0,specs:Z};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${G}. Use an explicit ref:`,` cc-safety-net rule remove ${G}#<ref>`],entries:[]}}}function Ls(P){try{return L(P)}catch{return null}}function mp(P,G){return P.filter((K)=>{let Y=Ls(K);return Y?G(Y):!1})}async function No(P,G={}){return Wb(P,G,await Do(P,G,Mn()))}function Wb(P,G,K){if(!K.ok)return K;let Y=hn(P,G),Z=[...new Set(z(Y.configPath,Y.filesystemScope))];if(Z.length===0)return K;return{ok:!1,errors:Z,entries:K.entries}}async function Do(P,G,K,Y={},Z=new Set,X=new Set){try{let ie=hn(P,G),ae=Pr(ie.configTarget);if(!ae.ok)return ae.result;let ge=ae.config,ye=G.only?dp(ge,G.only):{ok:!0,specs:ge.rules};if(!ye.ok)return ye.result;let Pe=new Set([...G.refresh?ye.specs:[],...Z]),Re=(en)=>op(en,ie.configDir,ie.filesystemScope,K,Pe.has(en),!G.refresh||Pe.has(en)),_e=await iw(ge.rules,G.refresh?(en)=>Re(en).then((on)=>({ok:!0,item:on})).catch((on)=>{if(Xu(on))throw on;return{ok:!1,spec:en,message:on instanceof Error?on.message:String(on)}}):async(en)=>({ok:!0,item:await Re(en)}),K),Ae=_e.filter((en)=>!en.ok),Ie=_e.filter((en)=>en.ok).map((en)=>en.item),je=Ie.flatMap((en)=>Yb(en,ge.rules)),Oe=Ie.flatMap((en)=>Zb(en,X,ie)),Ve=new Set([...je,...Oe].map((en)=>en.spec)),nn=[...Ae,...je,...Oe],rn=[],an=Qb(rn,()=>Ie.flatMap((en)=>Ve.has(en.spec)||nn.length>0&&X.has(en.spec)?[]:Xb(en,ie,Y,rn)));return{ok:nn.length===0,errors:nn.map((en)=>`Failed to update ${en.spec}: ${en.message}`),entries:Ie.map(nw),changes:an}}catch(ie){return Rr(ie)}}function Yb(P,G){if(!C(P.spec))return[];let K=We(P.spec),Y=G.filter((Z)=>Z!==P.spec&&We(Z).toLowerCase()===K.toLowerCase());if(Y.length===0)return[];return[{ok:!1,spec:P.spec,message:`rulebook name "${K}" is also claimed by ${Y.join(", ")}; rename one of them`}]}function Zb(P,G,K){if(!G.has(P.spec)||!C(P.spec))return[];let Y=M(K.configDir,P.rulebook.name),Z=r(i(K.filesystemScope,Y));if(Z===null||Z===P.content)return[];return[{ok:!1,spec:P.spec,message:`${Y} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Xb(P,G,K,Y){if(!C(P.spec))return[];let Z=M(G.configDir,P.rulebook.name),X=i(G.filesystemScope,Z),ie=r(X);if(ie===P.content)return[];return Y?.push({target:X,previous:ie}),h(X,P.content,void 0,K._testAfterPolicyRename),ew(P,ie)}function Qb(P,G){try{return G()}catch(K){for(let Y of[...P].reverse()){if(Y.previous===null){B(Y.target);continue}h(Y.target,Y.previous)}throw K}}function ew(P,G){if(G===null)return[`Vendored ${P.spec} (${P.rulebook.version})`];let K=Ee(G),Y="problem"in K?null:K.rulebook,Z=new Map(Y?.rules.map((ie)=>[ie.name,JSON.stringify(ie)])??[]),X=new Set(P.rulebook.rules.map((ie)=>ie.name));return[`Updated ${P.spec} (${Y?.version??"unreadable"} -> ${P.rulebook.version})`,...[...X].filter((ie)=>!Z.has(ie)).map((ie)=>` + ${ie}`),...[...Z.keys()].filter((ie)=>!X.has(ie)).map((ie)=>` - ${ie}`),...P.rulebook.rules.filter((ie)=>{let ae=Z.get(ie.name);return ae!==void 0&&ae!==JSON.stringify(ie)}).map((ie)=>` ~ ${ie.name}`)]}function nw(P){return{spec:P.spec,name:P.rulebook.name,version:P.rulebook.version,ruleCount:P.rulebook.rules.length}}async function gp(P,G,K={}){return tw(P,G,K,Mn())}async function tw(P,G,K,Y,Z={}){let X=null,ie=!1;try{let ae=hn(P,K),ge=r(ae.configTarget);X={target:ae.configTarget,content:ge};let ye=Pr(ae.configTarget);if(!ye.ok)return ye.result;let Pe=ye.config,Re=Q(G)?await ip(G,{ref:K.ref,operation:Y}):null,_e=Re?rw(Re,K.rulebooks):[],Ae=Re?_e.map((nn)=>ow(Pe.rules,Re,nn)??`${G}#${Re.ref}/${nn}`):[G],Ie=Ae.filter((nn)=>!Pe.rules.includes(nn)),je=[...Pe.rules,...Ie];if(je.length>Se)return sw();if(je.length!==Pe.rules.length)ie=!0,vn(ae.configTarget,{...Pe,rules:je},void 0,Z._testAfterPolicyRename);let Oe=await Do(P,K,Y,Z,new Set(Ie),new Set(Ie));if(!Oe.ok)Sr(ae.configTarget,ge);if(!Oe.ok||!Re)return Oe;let Ve=_e.filter((nn,rn)=>Ie.includes(Ae[rn]??""));return{...Oe,add:{source:G,ref:Re.ref,selected:_e,added:Ve,alreadyConfigured:_e.filter((nn)=>!Ve.includes(nn)),commits:Ie.length>0?[Re.commit]:[]}}}catch(ae){if(ie&&X)try{Sr(X.target,X.content)}catch(ge){return Rr(ge)}return Rr(ae)}}function rw(P,G){let K=G?[...new Set(G)]:P.names,Y=K.filter((Z)=>!P.names.includes(Z));if(Y.length>0)throw Error(`Rulebooks not found in ${P.source} at ${P.ref}: ${Y.join(", ")}
282
+ Available rulebooks: ${P.names.join(", ")}`);return K}function ow(P,G,K){let Y=`${G.source}#${G.ref}/${K}`;if(P.includes(Y))return Y;let Z=`${G.source}#${G.commit}/${K}`;return P.find((X)=>X===Z)}async function iw(P,G,K=Mn()){if(P.length>Se)throw Error(we);let Y=[],Z=0,X,ie=Array.from({length:Math.min(P.length,_o.concurrency)},async()=>{while(!X){let ae=Z;if(ae>=P.length)return;Z++;try{Y[ae]=await G(P[ae],ae,K.controller.signal)}catch(ge){if(!X)X={value:ge},Z=P.length,K.controller.abort(ge);return}}});if(await Promise.all(ie),X)throw X.value;return Y}function sw(){return{ok:!1,errors:[we],entries:[]}}async function yp(P,G,K={}){try{return await aw(P,G,K,{})}catch(Y){return Rr(Y)}}async function aw(P,G,K,Y){let Z=hn(P,K),X=d(Z.configTarget);if(X.errors.length>0)return{ok:!1,errors:X.errors,entries:[]};if(!X.config)return{ok:!1,errors:[`No config found at ${Z.configPath}`],entries:[]};let ie=up(X.config.rules,G);if(!ie.ok)return ie.result;let ae=K.deleteSource?lw(Z.configDir,ie.specs,Z.filesystemScope):{ok:!0,dirs:[]};if(!ae.ok)return ae.result;let ge=r(Z.configTarget);if(ge===null)return Rr(Error("Rules config is unavailable."));try{vn(Z.configTarget,{...X.config,rules:X.config.rules.filter((Re)=>!ie.specs.includes(Re))},void 0,Y._testAfterPolicyRename)}catch(Re){throw Sr(Z.configTarget,ge),Re}let ye=await Do(P,K,Mn(),Y);if(!ye.ok)return Sr(Z.configTarget,ge),ye;let Pe=cw(ae.dirs,Y,Z.filesystemScope);if(!Pe.ok){Sr(Z.configTarget,ge);let Re=await Do(P,K,Mn(),Y);if(!Re.ok)return{ok:!1,errors:[...Pe.result.errors,...Re.errors],entries:Re.entries};return Pe.result}return ye}function lw(P,G,K){let Y=G.flatMap((ae)=>p.test(ae)?[]:["--delete-source can only delete local rulebook sources"]),Z=G.map((ae)=>js(P,ae)),X=Y.length>0?[]:Z.flatMap((ae)=>hp(ae,K)),ie=[...Y,...X];return ie.length>0?{ok:!1,result:{ok:!1,errors:ie,entries:[]}}:{ok:!0,dirs:Z}}function hp(P,G){let K=zb(P),Y=i(G,K),Z=ve(Y);if(!Z)return[`Local rulebook source directory not found: ${P}`];let X=Z.find((ie)=>ie.name==="rulebook.json");if(!X)return[`Local rulebook source directory is missing rulebook.json: ${P}`];if(X.kind!=="file")throw new o(G.label);if(r(i(G,js(K,"rulebook.json"))),Z.length>1)return[`Local rulebook source directory contains extra files: ${P}. delete manually if you really want to remove the directory.`];return[]}function cw(P,G,K){let Y=P.flatMap((Z)=>{try{if(!ve(i(K,Z)))return[];let X=hp(Z,K);if(X.length>0)return X;return dw(Z,G,K),[]}catch(X){return[`Failed to delete local rulebook source ${Z}: ${X instanceof Error?X.message:String(X)}`]}});return Y.length>0?{ok:!1,result:{ok:!1,errors:Y,entries:[]}}:{ok:!0}}function dw(P,G,K){if(G._testDeleteLocalSourceDir){G._testDeleteLocalSourceDir(P);return}B(i(K,js(P,be))),kt(i(K,P))}function Sr(P,G){if(G===null){B(P);return}h(P,G)}function Rr(P){return{ok:!1,errors:[P instanceof Error?P.message:String(P)],entries:[]}}var uw=".safety-net.json",pw="~/.cc-safety-net/config.json";async function kp(P,G){let K=O(P,{cwd:G.cwd});if(K)console.log(`Skipped the project scope: ${A(G.cwd)} is the user rule config, not a project rule config`);return[K||await bp(P,{legacyPath:Lt(G.cwd),configPath:A(G.cwd),defaultRulebookName:"project-rules",migratedFrom:uw,cleanup:G.cleanup,syncOptions:{cwd:G.cwd}}),await bp(P,{legacyPath:jt(P),configPath:W(P),defaultRulebookName:"user-rules",migratedFrom:pw,cleanup:G.cleanup,syncOptions:{cwd:G.cwd,global:!0}})].every((Z)=>Z)?0:1}async function bp(P,G){let K=hn(P,G.syncOptions),Y=i(K.filesystemScope,G.legacyPath),Z=r(Y);if(Z===null)return console.log(`No legacy config found at ${G.legacyPath}`),!0;let X=mw(Z);if(!X.ok){for(let Ae of X.errors)console.error(Ae);return!1}let ie=d(K.configTarget);if(ie.errors.length>0){for(let Ae of ie.errors)console.error(Ae);return!1}let ae=ie.config??de,ge=gw(vp(G.configPath),ae.rules,G.defaultRulebookName,G.migratedFrom,K.filesystemScope),ye=Lo(vp(G.configPath),ge,"rulebook.json"),Pe=i(K.filesystemScope,ye),Re=[wp(K.configTarget),wp(Pe)],_e=await fw(P,G,K.configTarget,Pe,ge,X.config.rules,{...ae,rules:ae.rules.includes(ge)?ae.rules:[...ae.rules,ge]});if(!_e.ok){vw(Re);for(let Ae of _e.errors)console.error(Ae);return!1}if(!G.cleanup)return console.log(`Migrated legacy config at ${G.legacyPath}. Legacy file is no longer used.`),!0;if(!hw(K.configTarget,Pe,ge,G.migratedFrom,X.config.rules))return console.error(`Migration cleanup verification failed for ${G.legacyPath}`),!1;return B(Y),console.log(`Deleted legacy config at ${G.legacyPath}`),!0}async function fw(P,G,K,Y,Z,X,ie){try{return vn(K,ie),vn(Y,yw(Z,G.migratedFrom,X)),await No(P,G.syncOptions)}catch(ae){return{ok:!1,errors:[ae instanceof Error?ae.message:String(ae)]}}}function mw(P){try{let G=JSON.parse(P),K=Wo(G);if(K.errors.length>0)return{ok:!1,errors:K.errors};return{ok:!0,config:{version:1,rules:G.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function gw(P,G,K,Y,Z){let X=G.find((ie)=>bw(i(Z,Lo(P,ie,"rulebook.json")))===Y);if(X)return X;if(r(i(Z,Lo(P,K,"rulebook.json")))===null)return K;for(let ie=2;;ie++){let ae=`${K}-${ie}`;if(r(i(Z,Lo(P,ae,"rulebook.json")))===null)return ae}}function yw(P,G,K){return{rulebook_version:1,name:P,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:G,allowed_commands:[...new Set(K.map((Y)=>Y.command))],rules:K,tests:K.map((Y)=>({command:[Y.command,Y.subcommand,Y.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:Y.name}))}}function hw(P,G,K,Y,Z){if(!d(P).config?.rules.includes(K))return!1;try{let ie=r(G);if(ie===null)return!1;let ae=JSON.parse(ie);return ae.migrated_from===Y&&JSON.stringify(ae.rules)===JSON.stringify(Z)}catch{return!1}}function wp(P){return{target:P,content:r(P)}}function vw(P){for(let G of P){if(G.content===null){B(G.target);continue}h(G.target,G.content)}}function bw(P){let G=r(P);if(G===null)return null;try{let K=JSON.parse(G);return typeof K.migrated_from==="string"?K.migrated_from:null}catch{return null}}import{mkdir as ww,readFile as kw,writeFile as Cw}from"node:fs/promises";import{dirname as xw,join as Pw}from"node:path";var Sw=86400000,Rw=604800000;async function xp(P,G=Date.now()){if(P.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let K=rt(P);if(!K)return null;let Y=Pw(K,".cc-safety-net","update-check.json"),Z=await Ew(Y,G);if(!Z.lastCheck||G-Z.lastCheck>Sw){let ae=await Bn();if(Z.lastCheck=G,ae.latestVersion)Z.latestVersion=ae.latestVersion;if(!await Cp(Y,Z))return null;if(ae.error)return null}let X=Z.latestVersion,ie=un();if(!X||!ni(X,ie))return null;if(Z.notifiedVersion===X&&Z.notifiedAt!==void 0&&G-Z.notifiedAt<Rw)return null;if(Z.notifiedVersion=X,Z.notifiedAt=G,!await Cp(Y,Z))return null;return`UPDATE_AVAILABLE: cc-safety-net v${X} is available (running v${ie}). 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 Ew(P,G){let K=await kw(P,"utf8").then((X)=>JSON.parse(X)).catch(()=>{return});if(!K||typeof K!=="object"||Array.isArray(K))return{};let Y=K,Z=(X)=>typeof X==="number"&&Number.isFinite(X)&&X<=G?X:void 0;return{lastCheck:Z(Y.lastCheck),latestVersion:typeof Y.latestVersion==="string"?Y.latestVersion:void 0,notifiedVersion:typeof Y.notifiedVersion==="string"?Y.notifiedVersion:void 0,notifiedAt:Z(Y.notifiedAt)}}async function Cp(P,G){return ww(xw(P),{recursive:!0,mode:448}).then(()=>Cw(P,JSON.stringify(G),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as Ow,resolve as Ms}from"node:path";var Pp=new Map([["Bash","posix"],["PowerShell","powershell"],["Monitor","posix"]]);var Sp=new Map([["Bash","auto"]]);var Rp=new Map([["bash","auto"],["Bash","auto"],["powershell","powershell"],["PowerShell","powershell"]]);var Ep=new Map([["Shell","auto"]]);var Tp=new Map([["exec","auto"]]),Ap="write_to_process";var _p=new Map([["Execute","auto"]]);var Ip=new Map([["run_shell_command","auto"]]);var Op=new Map([["run_terminal_command","auto"],["run_terminal_cmd","auto"],["monitor","auto"],["bash","auto"],["Shell","auto"]]);var $p=new Map([["terminal","posix"]]);var Dp=new Map([["Bash","posix"]]);var Np="exec";var _w=[["antigravity-cli",[...ol.keys(),il]],["claude-code",[...Pp.keys()]],["codex",[...Sp.keys()]],["copilot-cli",[...Rp.keys()]],["cursor",[...Ep.keys()]],["deepseek-harness",[...nt.keys()]],["devin",[...Tp.keys(),Ap]],["droid",[..._p.keys()]],["gemini-cli",[...Ip.keys()]],["grok-build",[...Op.keys()]],["hermes-agent",[...$p.keys()]],["kimi-code",[...Dp.keys()]],["openclaw",[Np]],["opencode",[Xe,Te]],["pi",[...tt.keys()]]].flatMap(([P,G])=>G.map((K)=>({name:K,integration:ln(P)}))),Lp="and is already analyzed. Built-in tools cannot be declared.";function jo(P){let G=De(P),K=[...new Set(_w.filter((Y)=>De(Y.name)===G).map((Y)=>Y.integration))].sort((Y,Z)=>Y.localeCompare(Z));if(K.length>0)return`"${P}" is a built-in shell tool of ${Iw(K)}, ${Lp}`;if(x(P)!=="unknown")return`"${P}" is a built-in file tool, ${Lp}`;return}function Iw(P){return P.length===1?P[0]??"":`${P.slice(0,-1).join(", ")} and ${P.at(-1)}`}var Fp="CC Safety Net Config",$w="═".repeat(Fp.length),Dw="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",Nw=new Set(["rule.json","rule.lock","cache"]);function Hp(P,G={}){try{return Lw(P,G)}catch(K){if(K instanceof o)return console.error(K.message),1;throw K}}function Lw(P,G){let K=G.cwd??process.cwd(),Y=ee(P,{cwd:K}),Z=jt(P),X=Lt(K),ie=Ms(K,xe),ae=i(Y.userScope,Z),ge=i(Y.projectScope,X),ye=!1,Pe=!1,Re=[],_e=[],Ae=jw(i(Y.projectScope,ie));if(Hw(),r(Y.userConfigTarget)!==null){let Ie=Un(Y.userConfigTarget);if(Ie.errors.push(...z(Y.userConfigPath,Y.userScope),...jp(Y.userConfigTarget)),Re.push({scope:"User",path:Y.userConfigPath,result:Ie,schema:"rules",target:Y.userConfigTarget}),Ie.errors.length>0)ye=!0}if(r(ae)!==null)if(Pe=!0,r(Y.userConfigTarget)!==null)_e.push(Fo("user","cleanup"));else{let Ie=Yo(ae);if(Re.push({scope:"User",path:Z,result:Ie,schema:"legacy",inactive:!0,target:ae}),_e.push(Fo("user",Ie.errors.length>0?"fix-or-delete":"migrate")),Ie.errors.length>0)ye=!0}if(r(Y.projectConfigTarget)!==null){let Ie=Un(Y.projectConfigTarget);if(Ie.errors.push(...z(Y.projectConfigPath,Y.projectScope),...jp(Y.projectConfigTarget)),Re.push({scope:"Project",path:Ms(Y.projectConfigPath),result:Ie,schema:"rules",target:Y.projectConfigTarget}),Ie.errors.length>0)ye=!0;if(r(ge)!==null)Pe=!0,_e.push(Fo("project","cleanup"))}else if(r(ge)!==null){Pe=!0,ye=!0;let Ie=Yo(ge);Re.push({scope:"Project",path:Ms(X),result:Ie,schema:"legacy",inactive:!0,target:ge}),_e.push(Fo("project",Ie.errors.length>0?"fix-or-delete":"migrate"))}if(Ae?.result.errors.length)ye=!0;if(Re.length===0&&!Ae)return console.log(`
283
+ No config files found. Using built-in rules only.`),0;for(let Ie of Re)if(Ie.inactive)Uw(Ie.scope,Ie.path,Ie.result);else if(Ie.result.errors.length>0)Bw(Ie.scope,Ie.path,Ie.result.errors);else{if(Ie.schema==="rules"&&Vw(Ie.target))console.log(`
284
+ Added $schema to ${Ie.scope.toLowerCase()} config.`);Mw(Ie.scope,Ie.path,Ie.result,Ie.schema)}for(let Ie of _e)console.error(`
285
+ ${Qe.red(Ie)}`);if(Ae)if(Ae.result.errors.length>0)qw(Ae.path,Ae.result.errors);else Gw(Ae.path,Ae.result);if(ye)return console.error(`
286
286
  Config validation failed.`),1;return console.log(Pe?`
287
287
  Configs valid with warnings.`:`
288
- All configs valid.`),0}function Np(P){return(d(P).config?.command_tools??[]).flatMap((L)=>jo(typeof L==="string"?L:L.name)??[])}function Fo(P,L){let H=`legacy ${P} config`;if(L==="cleanup")return`Warning: Legacy ${P} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(L==="migrate")return`Warning: Legacy ${P} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${P} config is no longer supported. Fix or delete the ${H}, then run \`npx -y cc-safety-net rule migrate\`.`}function Dw(P){if(ye(P)===null)return null;let L=Nw(P);if(L.ruleNames.size===0&&L.errors.length===0)return null;return{path:P.path,result:L}}function Nw(P){let L=[],H=new Set,Y=(ye(P)??[]).filter((Z)=>!Ow.has(Z.name)).sort((Z,oe)=>Z.name.localeCompare(oe.name));if(Y.length===0)return{errors:L,ruleNames:H};for(let Z of Y){if(!p.test(Z.name)){L.push(`rulebook directory names must match ${p}: ${Z.name}`);continue}if(Z.kind!=="directory"){L.push(`${Z.name} must be a rulebook directory`);continue}let oe=i(P.scope,Aw(P.path,Z.name,"rulebook.json")),se=r(oe);if(se===null){L.push(`${Z.name}/rulebook.json is required`);continue}try{let me;try{me=JSON.parse(se)}catch{L.push(`${Z.name}/rulebook.json: invalid JSON`);continue}let he=pe(me);if(he.name!==Z.name){L.push(`rulebook name "${he.name}" must match folder "${Z.name}"`);continue}let ke=Ao(he);if(ke.length>0){L.push(...ke.map((Pe)=>`${Z.name}/rulebook.json: ${Pe}`));continue}H.add(Z.name)}catch(me){L.push(me instanceof Error?`${Z.name}/rulebook.json: ${me.message}`:`${Z.name}/rulebook.json: ${String(me)}`)}}return{errors:L,ruleNames:H}}function Lw(){console.log(Lp),console.log(_w)}function jw(P,L,H,Y){if(console.log(`
289
- ✓ ${P} config: ${L}`),console.log(` Schema: ${Y==="rules"?"rulebook sources":"legacy inline rules"}`),H.ruleNames.size>0){console.log(` ${Y==="rules"?"Sources":"Rules"}:`);let Z=1;for(let oe of H.ruleNames)console.log(` ${Z}. ${oe}`),Z++}else console.log(` ${Y==="rules"?"Sources":"Rules"}: (none)`)}function Fw(P,L,H){if(console.error(`
290
- ✗ Legacy ${P.toLowerCase()} config: ${L}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),H.errors.length>0){console.error(" Errors:");let Y=1;for(let Z of H.errors)for(let oe of Z.split("; "))console.error(` ${Y}. ${oe}`),Y++;return}if(H.ruleNames.size>0){console.error(" Rules:");let Y=1;for(let Z of H.ruleNames)console.error(` ${Y}. ${Z}`),Y++;return}console.error(" Rules: (none)")}function Hw(P,L,H){Fp(`${P} config`,L,H)}function Mw(P,L){console.log(`
291
- ✓ GitHub source rules: ${P}`),console.log(" Rulebooks:");let H=1;for(let Y of L.ruleNames)console.log(` ${H}. ${Y}`),H++}function Uw(P,L){Fp("GitHub source rules",P,L)}function Fp(P,L,H){console.error(`
292
- ✗ ${P}: ${L}`),console.error(" Errors:");let Y=1;for(let Z of H)for(let oe of Z.split("; "))console.error(` ${Y}. ${oe}`),Y++}function Bw(P){try{let L=r(P);if(L===null)return!1;let H=JSON.parse(L);if(H.$schema)return!1;return h(P,JSON.stringify({$schema:Iw,...H},null,2)),!0}catch(L){if(L instanceof o)throw L;return!1}}var Hp=new Set(["init","add","remove","update","sync","list","wrapper","tool","migrate","doc","verify"]),qw=new Set(["init","add","remove","update","sync","wrapper"]),Up=new Set(["add","remove","list"]),Vw="cc-safety-net/rulebooks";async function Bp(P,L){try{return await Kw(P,L)}catch(H){if(H instanceof o)return console.error(H.message),1;throw H}}async function Kw(P,L){let H=zw(L),Y=H.help?Jw(H.positionals):null;if(Y)return Wt(Y),0;if(H.errors.length>0){for(let ke of H.errors)console.error(ke);return 1}let Z=H.positionals[0];if(!Z)return Wt(Nt,console.error),1;let oe=H.positionals[1],se={global:H.global},me=process.cwd();if((Z==="tool"?H.project:!H.global&&qw.has(Z)&&!(Z==="wrapper"&&oe==="list"))&&O(P,{cwd:me}))return console.error(`${A(me)} is the user rule config, not a project rule config; ${Z==="tool"?"drop --project":"use --global"} for the user scope, or run from a project directory`),1;if(Z==="init"){let ke=hn(P,se);Zw(ke.configTarget);let Pe=Gw(ke.configDir,"example-rules","rulebook.json"),Te=i(ke.filesystemScope,Pe);if(H.example&&r(Te)===null)Wu(Te);let _e=V(ke.configPath,ke.filesystemScope);for(let Ae of _e)console.error(Ae);if(_e.length>0)return 1;return console.log("Rule config initialized."),0}if(Z==="add"){let ke=Gp(H);if(!ke)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let Pe=hn(P,se),Te=await fp(P,ke,{...se,ref:H.ref,rulebooks:H.only.length>0?H.only:void 0});return Gu(Te,ke,`Scope: ${H.global?"user":"project"} (${Pe.configDir})`),Te.ok?0:1}if(Z==="remove"){if(!oe)return console.error("rule remove requires a source"),1;let ke=await mp(P,oe,{...se,deleteSource:H.deleteSource});return To(ke,`Removed rulebook source: ${oe}`),ke.ok?0:1}if(Z==="update"){let ke=await No(P,{...se,only:oe,refresh:!0});return To(ke,"Rule config updated."),ke.ok?0:1}if(Z==="sync")return Wa(P,{global:H.global});if(Z==="list"){let ke=ee(P,{cwd:me});return Vu(ke),ke.errors.length>0?1:0}if(Z==="wrapper")return Xw(P,H);if(Z==="tool")return ek(P,H,me);if(Z==="migrate")return bp(P,{cleanup:H.cleanup,cwd:me});if(Z==="doc"){console.log(Uu);let ke=await kp(P);if(ke)console.error(ke);return 0}if(Z==="verify")return jp(P);return 1}function Jw(P){if(P.length===0)return Nt;let L=Nt.subcommands.filter((Y)=>Y.usage.split(" ")[0]===P[0]);if(L.length===0)return null;if(P.length===1&&L.length>1)return{name:`rule ${P[0]}`,description:`Subcommands of rule ${P[0]}`,usage:`rule ${P[0]} <subcommand>`,subcommands:L,options:[]};let H=P.length===1?L[0]:L.find((Y)=>Y.usage.split(" ")[1]===P[1]);if(!H)return null;return{name:`rule ${P[0]}`,description:H.description,usage:`rule ${H.usage}`,options:P[0]==="add"?Ko:[],examples:P[0]==="add"?Jo:void 0}}function zw(P){let L=mn({label:"rule",booleans:{global:["-g","--global"],project:["--project"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"],cwdArg:["--cwd-arg"]},lists:{only:["--only"]},positionals:"list"},P),H={...L.flags,ref:L.values.ref,cwdArg:L.values.cwdArg,only:L.lists.only??[],help:L.help,positionals:L.positionals,errors:L.errors};return Ww(H),H}function Ww(P){let[L]=P.positionals;if(L&&!Hp.has(L))P.errors.push(`Unknown rule subcommand: ${L}`);if(P.deleteSource&&L!=="remove")if(L&&Hp.has(L))P.errors.push(`Unknown option for rule ${L}: --delete-source`);else P.errors.push("--delete-source is only valid with 'rule remove'");if(P.cleanup&&L!=="migrate")P.errors.push(Wn(L,"--cleanup"));if(P.example&&L!=="init")P.errors.push(Wn(L,"--example"));if(P.ref&&L!=="add")P.errors.push(Wn(L,"--ref"));if(P.only.length>0&&L!=="add")P.errors.push(Wn(L,"--only"));let H=L==="tool"?P.positionals[1]:void 0,Y=H&&Up.has(H)?`tool ${H}`:L;if(P.project&&H!=="add"&&H!=="remove")P.errors.push(Wn(Y,"--project"));if(P.cwdArg!==void 0&&H!=="add")P.errors.push(Wn(Y,"--cwd-arg"));if(L==="tool"&&P.global)P.errors.push(Wn(L,"--global"));if(L==="add")Yw(P);if(L==="migrate"){if(P.global)P.errors.push(Wn(L,"--global"));if(P.positionals.length>1)P.errors.push(`Unexpected rule migrate argument: ${P.positionals[1]}`)}else if(L==="wrapper")Mp(P,"a command");else if(L==="tool")Mp(P,"a tool name");else if(P.positionals.length>2)P.errors.push(`Unexpected rule argument: ${P.positionals[2]}`);if(L==="list"&&P.global)P.errors.push("Unknown option for rule list: --global")}function Gp(P){if(P.positionals[1])return P.positionals[1];if(P.ref||P.only.length>0)return Vw;return}function Yw(P){let L=Gp(P);if(!L)return;if((P.ref||P.only.length>0)&&!X(L)){if(P.ref)P.errors.push(`--ref can only select a ref for an owner/repo source: ${L}`);if(P.only.length>0)P.errors.push("--only can only select rulebooks from an owner/repo source");return}if(P.ref&&!ce(P.ref))P.errors.push(`--ref must use valid path segments: ${P.ref}`);let H=P.only.filter((Y)=>!p.test(Y));if(H.length>0)P.errors.push(`Invalid rulebook names: ${H.join(", ")}`)}function Wn(P,L){return P?`Unknown option for rule ${P}: ${L}`:`Unknown option for rule: ${L}`}function Mp(P,L){let H=P.positionals[0],Y=P.positionals[1],Z=P.positionals[2];if(!Y){P.errors.push(`rule ${H} requires add, remove, or list`);return}if(!Up.has(Y)){P.errors.push(`Unknown rule ${H} action: ${Y}`);return}if(Y==="list"){if(Z)P.errors.push(`Unexpected rule ${H} argument: ${Z}`);return}if(!Z){P.errors.push(`rule ${H} ${Y} requires ${L}`);return}if(H!=="tool"&&P.positionals.length>3)P.errors.push(`Unexpected rule ${H} argument: ${P.positionals[3]}`)}function Zw(P){if(r(P)===null){zu(P);return}let L=d(P);if(!L.config)return;bn(P,L.config)}async function Xw(P,L){let H=L.positionals[1],Y=L.positionals[2],Z=hn(P,{global:L.global}).configTarget;if(H==="list"){let he=d(Z);if(he.errors.length>0){for(let ke of he.errors)console.error(ke);return 1}return Qw(he.config?.transparent_wrappers??[]),0}if(!Y||!E.test(Y))return console.error("transparent wrapper must match command pattern"),1;if($e(Y))return console.error(`reserved command "${Y}" cannot be a wrapper`),1;let oe=d(Z);if(oe.errors.length>0){for(let he of oe.errors)console.error(he);return 1}let se=oe.config??ue,me=H==="add"?[...new Set([...se.transparent_wrappers??[],Y])]:(se.transparent_wrappers??[]).filter((he)=>he!==Y);return bn(Z,{...se,transparent_wrappers:me}),console.log(H==="add"?`Added transparent wrapper: ${Y}`:`Removed transparent wrapper: ${Y}`),0}function Qw(P){if(P.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${P.length}):`);for(let L of P)console.log(` - ${L}`)}function ek(P,L,H){let Y=L.positionals[1],Z=[...new Set(L.positionals.slice(2))];if(Y==="list")return nk(P,H);let oe=[...Z.flatMap((ke)=>{if(!Ue.test(ke))return[`"${ke}" is not a tool name: ${we}.`];let Pe=Y==="add"?jo(ke):void 0;return Pe?[Pe]:[]}),...L.cwdArg!==void 0&&!Ue.test(L.cwdArg)?[`"${L.cwdArg}" is not an argument name: ${we}.`]:[]];if(oe.length>0){for(let ke of oe)console.error(en.red(`Error: ${ke}`));return 1}let se=hn(P,{global:!L.project}),me=Pr(se.configTarget);if(!me.ok){for(let ke of me.result.errors)console.error(ke);return 1}let he=Z.reduce((ke,Pe)=>{let Te=L.cwdArg===void 0?Pe:{name:Pe,cwd:L.cwdArg},_e=(Ae)=>(typeof Ae==="string"?Ae:Ae.name)===Pe;if(Y==="remove")return ke.filter((Ae)=>!_e(Ae));return ke.some(_e)?ke.map((Ae)=>_e(Ae)?Te:Ae):[...ke,Te]},me.config.command_tools??[]);bn(se.configTarget,{...me.config,command_tools:he});for(let ke of Z)console.log(Y==="add"?`Added command tool: ${ke}${L.cwdArg===void 0?"":` (cwd argument: ${L.cwdArg})`}`:`Removed command tool: ${ke}`);return console.log(`Scope: ${L.project?"project":"user"} (${se.configPath})`),0}function nk(P,L){let H=(O(P,{cwd:L})?["user"]:["user","project"]).map((Z)=>{let oe=hn(P,{global:Z==="user"});return{scope:Z,path:oe.configPath,...d(oe.configTarget)}}),Y=H.flatMap((Z)=>Z.errors.map((oe)=>`${Z.path}: ${oe}`));if(Y.length>0){for(let Z of Y)console.error(Z);return 1}return Ku(H.flatMap((Z)=>(Z.config?.command_tools??[]).map((oe)=>({scope:Z.scope,tool:oe})))),0}import{sep as ak}from"node:path";import{existsSync as tk,readFileSync as rk}from"node:fs";import{join as ok}from"node:path";async function ik(P){if(P.isTTY)return null;return(await st(P).catch(()=>null))?.trim()||null}function sk(P){let L=P.env.get("CLAUDE_SETTINGS_PATH");if(L)return L;return ok(Vr(P),"settings.json")}function Ms(P){let L=sk(P);if(!tk(L))return!1;try{let H=rk(L,"utf-8"),Y=JSON.parse(H);if(!Y.enabledPlugins)return!1;let Z="cc-safety-net@cc-marketplace";if(!(Z in Y.enabledPlugins))return!1;return Y.enabledPlugins[Z]===!0}catch(H){if(S(n.debug,P.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${L}: ${H instanceof Error?H.message:String(H)}`);return!1}}async function Us(P,L=process.stdin){let H=Ms(P),Y;if(!H)Y="\uD83D\uDEE1️ CC Safety Net ❌";else{let oe=R(P,{cwd:process.cwd()}),se=oe.policy,me=_(se,P.env),he=Object.values(K(se,me.capabilities)).some((Te)=>Te.changesInherited),ke={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[he?"custom":me.effectiveLevel],Pe=oe.policyScopes&&!oe.policyScopes.weakeningsIgnored&&oe.policyScopes.weakenings.length>0?"\uD83D\uDD3B":"";Y=`\uD83D\uDEE1️ CC Safety Net ${ke}${me.worktreeMode?"\uD83C\uDF33":""}${Pe}${oe.state==="degraded"?"⚠️":""}`}let Z=await ik(L);if(Z&&!Z.startsWith("{"))console.log(`${Z} | ${Y}`);else console.log(Y)}function qp(P){let L=R(P,{cwd:process.cwd()}),H=L.policy,Y=_(H,P.env),Z=!!process.env.NO_COLOR||!process.stdout.isTTY,oe=Math.min(process.stdout.columns||80,100),se=Z?"ok":"✔",me=Z?"OFF":"✘",he=(We,Fe)=>{let Ze=` ${We.padEnd(13)}${Fe}`;return(Ze.length>oe?`${Ze.slice(0,oe-1)}…`:Ze).replaceAll(me,en.red(me))},ke=Object.values(K(H,Y.capabilities)).some((We)=>We.changesInherited),Pe=(We)=>We===P.home||We.startsWith(`${P.home}${ak}`)?`~${We.slice(P.home.length)}`:We,Te={ready:en.green,degraded:en.yellow}[L.state],_e=L.policyScopes?.weakenings??[],Ae=[...Ms(P)?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...L.diagnostics],Le=Z?"-":"·";console.log([`${Z?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Te(L.state)}`,"",he("Protection",`destructive ${H.destructiveCommandProtectionEnabled?se:me} secrets ${H.secretProtection.enabled?se:me}`),he("Level",ke?`${Y.effectiveLevel} (customised)`:Y.effectiveLevel),he("Rules",H.rules.length===0?"none active":`${H.rules.length} active`),he("Policy",Pe(u(P))),...L.policyScopes?[he("Project",Pe(y(process.cwd())))]:[],...Y.worktreeMode?[he("Worktree","relaxations active")]:[],"",..._e.length===0?[]:[L.policyScopes?.weakeningsIgnored?" Project policy (ignored)":" Project policy",..._e.flatMap((We)=>mr(We," ",oe-6).map((Fe,Ze)=>Ze===0?` ${Fe}`:Fe)),""],...Ae.length===0?[" Everything configured is active."]:[" Not active",...Ae.flatMap((We)=>mr(We," ",oe-6).map((Fe,Ze)=>Ze===0?` ${Le} ${Fe}`:Fe)),""," Full report: cc-safety-net doctor"]].join(`
293
- `))}import{spawn as df}from"node:child_process";import{randomBytes as hk}from"node:crypto";import{existsSync as uf,mkdirSync as vk,readFileSync as bk}from"node:fs";import{createServer as wk}from"node:http";import{dirname as pf,join as kk}from"node:path";import{Writable as Ck}from"node:stream";var Ho=500;function lk(P){let L=P.filter((Z)=>Z.decision!=="allow"),H=P.filter((Z)=>Z.decision==="allow"),Y=Math.min(L.length,Math.max(Ho-H.length,Math.ceil(Ho/2)));return[...L.slice(0,Y),...H.slice(0,Ho-Y)]}function Vp(P,L,H=G(P)){if(H)J(P,H);let Y=(Fe)=>new Date(Fe.getFullYear(),Fe.getMonth(),Fe.getDate()).getTime(),Z=Y(new Date),oe=new Date(Z);oe.setDate(oe.getDate()-(L-1));let se=oe.getTime(),me=[],he={count:0};for(let Fe of H?Yn(H,he):[])for(let Ze of Dt(Fe,he)){let tn=new Date(Ze.ts).getTime();if(!Number.isFinite(tn))continue;if(tn>=se)me.push(Ze)}me.sort((Fe,Ze)=>new Date(Ze.ts).getTime()-new Date(Fe.ts).getTime());let ke=Array.from({length:L},()=>0),Pe=Array.from({length:L},()=>0),Te={},_e={},Ae={},Le=0,We=0;for(let Fe of me){let Ze=Fe.agent||"unknown";Te[Ze]=(Te[Ze]??0)+1;let tn=Math.round((Z-Y(new Date(Fe.ts)))/86400000),on=L-1-tn,ln=tn>=0&&tn<L;if(ln)Pe[on]=(Pe[on]??0)+1;if(Fe.decision!=="allow"){if(Le++,Fe.ruleId)_e[Fe.ruleId]=(_e[Fe.ruleId]??0)+1;let nn=Go(Fe.segment||Fe.command);if(nn)Ae[nn]=(Ae[nn]??0)+1;if(Fe.failureStage)We++;if(ln)ke[on]=(ke[on]??0)+1}}return{days:L,logsDir:H,homeDir:P.home,totalInWindow:me.length,truncated:me.length>Ho,unreadable:he.count,counts:{blocked:Le,allowed:me.length-Le,agents:Te,blockedByDay:ke,analyzedByDay:Pe,rules:_e,commands:Ae,errors:We},entries:lk(me).sort((Fe,Ze)=>new Date(Ze.ts).getTime()-new Date(Fe.ts).getTime())}}import{spawn as ck}from"node:child_process";import{existsSync as dk,statSync as Kp}from"node:fs";import{delimiter as uk,join as pk}from"node:path";var fk=120000,Mo="Choose the project folder",mk=`try
288
+ All configs valid.`),0}function jp(P){return(d(P).config?.command_tools??[]).flatMap((G)=>jo(typeof G==="string"?G:G.name)??[])}function Fo(P,G){let K=`legacy ${P} config`;if(G==="cleanup")return`Warning: Legacy ${P} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(G==="migrate")return`Warning: Legacy ${P} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${P} config is no longer supported. Fix or delete the ${K}, then run \`npx -y cc-safety-net rule migrate\`.`}function jw(P){if(ve(P)===null)return null;let G=Fw(P);if(G.ruleNames.size===0&&G.errors.length===0)return null;return{path:P.path,result:G}}function Fw(P){let G=[],K=new Set,Y=(ve(P)??[]).filter((Z)=>!Nw.has(Z.name)).sort((Z,X)=>Z.name.localeCompare(X.name));if(Y.length===0)return{errors:G,ruleNames:K};for(let Z of Y){if(!p.test(Z.name)){G.push(`rulebook directory names must match ${p}: ${Z.name}`);continue}if(Z.kind!=="directory"){G.push(`${Z.name} must be a rulebook directory`);continue}let X=i(P.scope,Ow(P.path,Z.name,"rulebook.json")),ie=r(X);if(ie===null){G.push(`${Z.name}/rulebook.json is required`);continue}try{let ae;try{ae=JSON.parse(ie)}catch{G.push(`${Z.name}/rulebook.json: invalid JSON`);continue}let ge=fe(ae);if(ge.name!==Z.name){G.push(`rulebook name "${ge.name}" must match folder "${Z.name}"`);continue}let ye=Ao(ge);if(ye.length>0){G.push(...ye.map((Pe)=>`${Z.name}/rulebook.json: ${Pe}`));continue}K.add(Z.name)}catch(ae){G.push(ae instanceof Error?`${Z.name}/rulebook.json: ${ae.message}`:`${Z.name}/rulebook.json: ${String(ae)}`)}}return{errors:G,ruleNames:K}}function Hw(){console.log(Fp),console.log($w)}function Mw(P,G,K,Y){if(console.log(`
289
+ ✓ ${P} config: ${G}`),console.log(` Schema: ${Y==="rules"?"rulebook sources":"legacy inline rules"}`),K.ruleNames.size>0){console.log(` ${Y==="rules"?"Sources":"Rules"}:`);let Z=1;for(let X of K.ruleNames)console.log(` ${Z}. ${X}`),Z++}else console.log(` ${Y==="rules"?"Sources":"Rules"}: (none)`)}function Uw(P,G,K){if(console.error(`
290
+ ✗ Legacy ${P.toLowerCase()} config: ${G}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),K.errors.length>0){console.error(" Errors:");let Y=1;for(let Z of K.errors)for(let X of Z.split("; "))console.error(` ${Y}. ${X}`),Y++;return}if(K.ruleNames.size>0){console.error(" Rules:");let Y=1;for(let Z of K.ruleNames)console.error(` ${Y}. ${Z}`),Y++;return}console.error(" Rules: (none)")}function Bw(P,G,K){Mp(`${P} config`,G,K)}function Gw(P,G){console.log(`
291
+ ✓ GitHub source rules: ${P}`),console.log(" Rulebooks:");let K=1;for(let Y of G.ruleNames)console.log(` ${K}. ${Y}`),K++}function qw(P,G){Mp("GitHub source rules",P,G)}function Mp(P,G,K){console.error(`
292
+ ✗ ${P}: ${G}`),console.error(" Errors:");let Y=1;for(let Z of K)for(let X of Z.split("; "))console.error(` ${Y}. ${X}`),Y++}function Vw(P){try{let G=r(P);if(G===null)return!1;let K=JSON.parse(G);if(K.$schema)return!1;return h(P,JSON.stringify({$schema:Dw,...K},null,2)),!0}catch(G){if(G instanceof o)throw G;return!1}}var Up=new Set(["init","add","remove","update","sync","list","wrapper","tool","migrate","doc","verify"]),Jw=new Set(["init","add","remove","update","sync","wrapper"]),Gp=new Set(["add","remove","list"]),zw="cc-safety-net/rulebooks";async function qp(P,G){try{return await Ww(P,G)}catch(K){if(K instanceof o)return console.error(K.message),1;throw K}}async function Ww(P,G){let K=Zw(G),Y=K.help?Yw(K.positionals):null;if(Y)return Wt(Y),0;if(K.errors.length>0){for(let ye of K.errors)console.error(ye);return 1}let Z=K.positionals[0];if(!Z)return Wt(Nt,console.error),1;let X=K.positionals[1],ie={global:K.global},ae=process.cwd();if((Z==="tool"?K.project:!K.global&&Jw.has(Z)&&!(Z==="wrapper"&&X==="list"))&&O(P,{cwd:ae}))return console.error(`${A(ae)} is the user rule config, not a project rule config; ${Z==="tool"?"drop --project":"use --global"} for the user scope, or run from a project directory`),1;if(Z==="init"){let ye=hn(P,ie);ek(ye.configTarget);let Pe=Kw(ye.configDir,"example-rules","rulebook.json"),Re=i(ye.filesystemScope,Pe);if(K.example&&r(Re)===null)Zu(Re);let _e=z(ye.configPath,ye.filesystemScope);for(let Ae of _e)console.error(Ae);if(_e.length>0)return 1;return console.log("Rule config initialized."),0}if(Z==="add"){let ye=Vp(K);if(!ye)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let Pe=hn(P,ie),Re=await gp(P,ye,{...ie,ref:K.ref,rulebooks:K.only.length>0?K.only:void 0});return Vu(Re,ye,`Scope: ${K.global?"user":"project"} (${Pe.configDir})`),Re.ok?0:1}if(Z==="remove"){if(!X)return console.error("rule remove requires a source"),1;let ye=await yp(P,X,{...ie,deleteSource:K.deleteSource});return To(ye,`Removed rulebook source: ${X}`),ye.ok?0:1}if(Z==="update"){let ye=await No(P,{...ie,only:X,refresh:!0});return To(ye,"Rule config updated."),ye.ok?0:1}if(Z==="sync")return Ya(P,{global:K.global});if(Z==="list"){let ye=te(P,{cwd:ae});return Ju(ye),ye.errors.length>0?1:0}if(Z==="wrapper")return nk(P,K);if(Z==="tool")return rk(P,K,ae);if(Z==="migrate")return kp(P,{cleanup:K.cleanup,cwd:ae});if(Z==="doc"){console.log(Gu);let ye=await xp(P);if(ye)console.error(ye);return 0}if(Z==="verify")return Hp(P);return 1}function Yw(P){if(P.length===0)return Nt;let G=Nt.subcommands.filter((Y)=>Y.usage.split(" ")[0]===P[0]);if(G.length===0)return null;if(P.length===1&&G.length>1)return{name:`rule ${P[0]}`,description:`Subcommands of rule ${P[0]}`,usage:`rule ${P[0]} <subcommand>`,subcommands:G,options:[]};let K=P.length===1?G[0]:G.find((Y)=>Y.usage.split(" ")[1]===P[1]);if(!K)return null;return{name:`rule ${P[0]}`,description:K.description,usage:`rule ${K.usage}`,options:P[0]==="add"?Ko:[],examples:P[0]==="add"?Jo:void 0}}function Zw(P){let G=fn({label:"rule",booleans:{global:["-g","--global"],project:["--project"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"],cwdArg:["--cwd-arg"]},lists:{only:["--only"]},positionals:"list"},P),K={...G.flags,ref:G.values.ref,cwdArg:G.values.cwdArg,only:G.lists.only??[],help:G.help,positionals:G.positionals,errors:G.errors};return Xw(K),K}function Xw(P){let[G]=P.positionals;if(G&&!Up.has(G))P.errors.push(`Unknown rule subcommand: ${G}`);if(P.deleteSource&&G!=="remove")if(G&&Up.has(G))P.errors.push(`Unknown option for rule ${G}: --delete-source`);else P.errors.push("--delete-source is only valid with 'rule remove'");if(P.cleanup&&G!=="migrate")P.errors.push(zn(G,"--cleanup"));if(P.example&&G!=="init")P.errors.push(zn(G,"--example"));if(P.ref&&G!=="add")P.errors.push(zn(G,"--ref"));if(P.only.length>0&&G!=="add")P.errors.push(zn(G,"--only"));let K=G==="tool"?P.positionals[1]:void 0,Y=K&&Gp.has(K)?`tool ${K}`:G;if(P.project&&K!=="add"&&K!=="remove")P.errors.push(zn(Y,"--project"));if(P.cwdArg!==void 0&&K!=="add")P.errors.push(zn(Y,"--cwd-arg"));if(G==="tool"&&P.global)P.errors.push(zn(G,"--global"));if(G==="add")Qw(P);if(G==="migrate"){if(P.global)P.errors.push(zn(G,"--global"));if(P.positionals.length>1)P.errors.push(`Unexpected rule migrate argument: ${P.positionals[1]}`)}else if(G==="wrapper")Bp(P,"a command");else if(G==="tool")Bp(P,"a tool name");else if(P.positionals.length>2)P.errors.push(`Unexpected rule argument: ${P.positionals[2]}`);if(G==="list"&&P.global)P.errors.push("Unknown option for rule list: --global")}function Vp(P){if(P.positionals[1])return P.positionals[1];if(P.ref||P.only.length>0)return zw;return}function Qw(P){let G=Vp(P);if(!G)return;if((P.ref||P.only.length>0)&&!Q(G)){if(P.ref)P.errors.push(`--ref can only select a ref for an owner/repo source: ${G}`);if(P.only.length>0)P.errors.push("--only can only select rulebooks from an owner/repo source");return}if(P.ref&&!le(P.ref))P.errors.push(`--ref must use valid path segments: ${P.ref}`);let K=P.only.filter((Y)=>!p.test(Y));if(K.length>0)P.errors.push(`Invalid rulebook names: ${K.join(", ")}`)}function zn(P,G){return P?`Unknown option for rule ${P}: ${G}`:`Unknown option for rule: ${G}`}function Bp(P,G){let K=P.positionals[0],Y=P.positionals[1],Z=P.positionals[2];if(!Y){P.errors.push(`rule ${K} requires add, remove, or list`);return}if(!Gp.has(Y)){P.errors.push(`Unknown rule ${K} action: ${Y}`);return}if(Y==="list"){if(Z)P.errors.push(`Unexpected rule ${K} argument: ${Z}`);return}if(!Z){P.errors.push(`rule ${K} ${Y} requires ${G}`);return}if(K!=="tool"&&P.positionals.length>3)P.errors.push(`Unexpected rule ${K} argument: ${P.positionals[3]}`)}function ek(P){if(r(P)===null){Yu(P);return}let G=d(P);if(!G.config)return;vn(P,G.config)}async function nk(P,G){let K=G.positionals[1],Y=G.positionals[2],Z=hn(P,{global:G.global}).configTarget;if(K==="list"){let ge=d(Z);if(ge.errors.length>0){for(let ye of ge.errors)console.error(ye);return 1}return tk(ge.config?.transparent_wrappers??[]),0}if(!Y||!E.test(Y))return console.error("transparent wrapper must match command pattern"),1;if(Ue(Y))return console.error(`reserved command "${Y}" cannot be a wrapper`),1;let X=d(Z);if(X.errors.length>0){for(let ge of X.errors)console.error(ge);return 1}let ie=X.config??de,ae=K==="add"?[...new Set([...ie.transparent_wrappers??[],Y])]:(ie.transparent_wrappers??[]).filter((ge)=>ge!==Y);return vn(Z,{...ie,transparent_wrappers:ae}),console.log(K==="add"?`Added transparent wrapper: ${Y}`:`Removed transparent wrapper: ${Y}`),0}function tk(P){if(P.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${P.length}):`);for(let G of P)console.log(` - ${G}`)}function rk(P,G,K){let Y=G.positionals[1],Z=[...new Set(G.positionals.slice(2))];if(Y==="list")return ok(P,K);let X=[...Z.flatMap((ye)=>{if(!Ge.test(ye))return[`"${ye}" is not a tool name: ${Ce}.`];let Pe=Y==="add"?jo(ye):void 0;return Pe?[Pe]:[]}),...G.cwdArg!==void 0&&!Ge.test(G.cwdArg)?[`"${G.cwdArg}" is not an argument name: ${Ce}.`]:[]];if(X.length>0){for(let ye of X)console.error(Qe.red(`Error: ${ye}`));return 1}let ie=hn(P,{global:!G.project}),ae=Pr(ie.configTarget);if(!ae.ok){for(let ye of ae.result.errors)console.error(ye);return 1}let ge=Z.reduce((ye,Pe)=>{let Re=G.cwdArg===void 0?Pe:{name:Pe,cwd:G.cwdArg},_e=(Ae)=>(typeof Ae==="string"?Ae:Ae.name)===Pe;if(Y==="remove")return ye.filter((Ae)=>!_e(Ae));return ye.some(_e)?ye.map((Ae)=>_e(Ae)?Re:Ae):[...ye,Re]},ae.config.command_tools??[]);vn(ie.configTarget,{...ae.config,command_tools:ge});for(let ye of Z)console.log(Y==="add"?`Added command tool: ${ye}${G.cwdArg===void 0?"":` (cwd argument: ${G.cwdArg})`}`:`Removed command tool: ${ye}`);return console.log(`Scope: ${G.project?"project":"user"} (${ie.configPath})`),0}function ok(P,G){let K=(O(P,{cwd:G})?["user"]:["user","project"]).map((Z)=>{let X=hn(P,{global:Z==="user"});return{scope:Z,path:X.configPath,...d(X.configTarget)}}),Y=K.flatMap((Z)=>Z.errors.map((X)=>`${Z.path}: ${X}`));if(Y.length>0){for(let Z of Y)console.error(Z);return 1}return zu(K.flatMap((Z)=>(Z.config?.command_tools??[]).map((X)=>({scope:Z.scope,tool:X})))),0}import{sep as dk}from"node:path";import{existsSync as ik,readFileSync as sk}from"node:fs";import{join as ak}from"node:path";async function lk(P){if(P.isTTY)return null;return(await ct(P).catch(()=>null))?.trim()||null}function ck(P){let G=P.env.get("CLAUDE_SETTINGS_PATH");if(G)return G;return ak(Vr(P),"settings.json")}function Us(P){let G=ck(P);if(!ik(G))return!1;try{let K=sk(G,"utf-8"),Y=JSON.parse(K);if(!Y.enabledPlugins)return!1;let Z="cc-safety-net@cc-marketplace";if(!(Z in Y.enabledPlugins))return!1;return Y.enabledPlugins[Z]===!0}catch(K){if(S(n.debug,P.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${G}: ${K instanceof Error?K.message:String(K)}`);return!1}}async function Bs(P,G=process.stdin){let K=Us(P),Y;if(!K)Y="\uD83D\uDEE1️ CC Safety Net ❌";else{let X=R(P,{cwd:process.cwd()}),ie=X.policy,ae=_(ie,P.env),ge=Object.values(q(ie,ae.capabilities)).some((Re)=>Re.changesInherited),ye={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[ge?"custom":ae.effectiveLevel],Pe=X.policyScopes&&!X.policyScopes.weakeningsIgnored&&X.policyScopes.weakenings.length>0?"\uD83D\uDD3B":"";Y=`\uD83D\uDEE1️ CC Safety Net ${ye}${ae.worktreeMode?"\uD83C\uDF33":""}${Pe}${X.state==="degraded"?"⚠️":""}`}let Z=await lk(G);if(Z&&!Z.startsWith("{"))console.log(`${Z} | ${Y}`);else console.log(Y)}function Kp(P){let G=R(P,{cwd:process.cwd()}),K=G.policy,Y=_(K,P.env),Z=!!process.env.NO_COLOR||!process.stdout.isTTY,X=Math.min(process.stdout.columns||80,100),ie=Z?"ok":"✔",ae=Z?"OFF":"✘",ge=(je,Oe)=>{let Ve=` ${je.padEnd(13)}${Oe}`;return(Ve.length>X?`${Ve.slice(0,X-1)}…`:Ve).replaceAll(ae,Qe.red(ae))},ye=Object.values(q(K,Y.capabilities)).some((je)=>je.changesInherited),Pe=(je)=>je===P.home||je.startsWith(`${P.home}${dk}`)?`~${je.slice(P.home.length)}`:je,Re={ready:Qe.green,degraded:Qe.yellow}[G.state],_e=G.policyScopes?.weakenings??[],Ae=[...Us(P)?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...G.diagnostics],Ie=Z?"-":"·";console.log([`${Z?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Re(G.state)}`,"",ge("Protection",`destructive ${K.destructiveCommandProtectionEnabled?ie:ae} secrets ${K.secretProtection.enabled?ie:ae}`),ge("Level",ye?`${Y.effectiveLevel} (customised)`:Y.effectiveLevel),ge("Rules",K.rules.length===0?"none active":`${K.rules.length} active`),ge("Policy",Pe(u(P))),...G.policyScopes?[ge("Project",Pe(y(process.cwd())))]:[],...Y.worktreeMode?[ge("Worktree","relaxations active")]:[],"",..._e.length===0?[]:[G.policyScopes?.weakeningsIgnored?" Project policy (ignored)":" Project policy",..._e.flatMap((je)=>mr(je," ",X-6).map((Oe,Ve)=>Ve===0?` ${Oe}`:Oe)),""],...Ae.length===0?[" Everything configured is active."]:[" Not active",...Ae.flatMap((je)=>mr(je," ",X-6).map((Oe,Ve)=>Ve===0?` ${Ie} ${Oe}`:Oe)),""," Full report: cc-safety-net doctor"]].join(`
293
+ `))}import{spawn as pf}from"node:child_process";import{randomBytes as wk}from"node:crypto";import{existsSync as ff,mkdirSync as kk,readFileSync as Ck}from"node:fs";import{createServer as xk}from"node:http";import{dirname as mf,join as Pk}from"node:path";import{Writable as Sk}from"node:stream";var Ho=500;function uk(P){let G=P.filter((Z)=>Z.decision!=="allow"),K=P.filter((Z)=>Z.decision==="allow"),Y=Math.min(G.length,Math.max(Ho-K.length,Math.ceil(Ho/2)));return[...G.slice(0,Y),...K.slice(0,Ho-Y)]}function Jp(P,G,K=U(P)){if(K)J(P,K);let Y=(Oe)=>new Date(Oe.getFullYear(),Oe.getMonth(),Oe.getDate()).getTime(),Z=Y(new Date),X=new Date(Z);X.setDate(X.getDate()-(G-1));let ie=X.getTime(),ae=[],ge={count:0};for(let Oe of K?Wn(K,ge):[])for(let Ve of Dt(Oe,ge)){let nn=new Date(Ve.ts).getTime();if(!Number.isFinite(nn))continue;if(nn>=ie)ae.push(Ve)}ae.sort((Oe,Ve)=>new Date(Ve.ts).getTime()-new Date(Oe.ts).getTime());let ye=Array.from({length:G},()=>0),Pe=Array.from({length:G},()=>0),Re={},_e={},Ae={},Ie=0,je=0;for(let Oe of ae){let Ve=Oe.agent||"unknown";Re[Ve]=(Re[Ve]??0)+1;let nn=Math.round((Z-Y(new Date(Oe.ts)))/86400000),rn=G-1-nn,an=nn>=0&&nn<G;if(an)Pe[rn]=(Pe[rn]??0)+1;if(Oe.decision!=="allow"){if(Ie++,Oe.ruleId)_e[Oe.ruleId]=(_e[Oe.ruleId]??0)+1;let en=Go(Oe.segment||Oe.command);if(en)Ae[en]=(Ae[en]??0)+1;if(Oe.failureStage)je++;if(an)ye[rn]=(ye[rn]??0)+1}}return{days:G,logsDir:K,homeDir:P.home,totalInWindow:ae.length,truncated:ae.length>Ho,unreadable:ge.count,counts:{blocked:Ie,allowed:ae.length-Ie,agents:Re,blockedByDay:ye,analyzedByDay:Pe,rules:_e,commands:Ae,errors:je},entries:uk(ae).sort((Oe,Ve)=>new Date(Ve.ts).getTime()-new Date(Oe.ts).getTime())}}import{spawn as pk}from"node:child_process";import{existsSync as fk,statSync as zp}from"node:fs";import{delimiter as mk,join as gk}from"node:path";var yk=120000,Mo="Choose the project folder",hk=`try
294
294
  return POSIX path of (choose folder with prompt "${Mo}")
295
295
  on error number -128
296
296
  return ""
297
- end try`,gk=`Add-Type -AssemblyName System.Windows.Forms
297
+ end try`,vk=`Add-Type -AssemblyName System.Windows.Forms
298
298
  $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
299
299
  $dialog.Description = '${Mo}'
300
- if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,Jp=[{binary:"zenity",args:["--file-selection","--directory",`--title=${Mo}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",Mo]}],zp=(P,L)=>(L.PATH??"").split(uk).some((H)=>{if(H.length===0)return!1;try{let Y=Kp(pk(H,P));return Y.isFile()&&(Y.mode&73)!==0}catch{return!1}});function Bs(P,L){if(P==="darwin"||P==="win32")return!0;if(P!=="linux")return!1;if(!L.DISPLAY&&!L.WAYLAND_DISPLAY)return!1;return Jp.some((H)=>zp(H.binary,L))}function yk(P,L){if(P==="darwin")return{cmd:"osascript",args:["-e",mk]};if(P==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",gk]};let H=Jp.find((Y)=>zp(Y.binary,L));return H?{cmd:H.binary,args:H.args}:null}function Gs(P=process.platform,L=process.env){let H=yk(P,L);if(!H)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((Y)=>{let Z=ck(H.cmd,H.args,{env:L,stdio:["ignore","pipe","pipe"]}),oe="",se=!1,me=(ke)=>{if(se)return;se=!0,clearTimeout(he),Y(ke)},he=setTimeout(()=>{Z.kill(),me({error:"The folder dialog timed out"})},fk);Z.stdout.on("data",(ke)=>{oe+=ke.toString()}),Z.on("error",()=>me({error:`Could not open the folder dialog (${H.cmd})`})),Z.on("close",()=>{let ke=oe.trim().replace(/\/+$/,"");if(!ke)return me({cancelled:!0});if(!dk(ke)||!Kp(ke).isDirectory())return me({error:"That selection is not a folder on disk"});me({path:ke})})})}var Wp=["en","ja","zh-CN"],Yp=["light","dark"],Uo=(P,L)=>P.includes(L),Zp=(P)=>typeof P==="object"&&P!==null&&!Array.isArray(P),Xp=(P)=>{let L=Zp(P)?P:{};return{...Uo(Wp,L.language)?{language:L.language}:{},...Uo(Yp,L.theme)?{theme:L.theme}:{}}},Qp=(P)=>{if(!Zp(P))return null;let L=Object.keys(P).every((Z)=>Z==="language"||Z==="theme"),H=P.language===void 0||Uo(Wp,P.language),Y=P.theme===void 0||Uo([...Yp,"auto"],P.theme);return L&&H&&Y?P:null},ef=(P,L)=>{let H=L.language??P.language,Y=L.theme==="auto"?void 0:L.theme??P.theme;return{...H?{language:H}:{},...Y?{theme:Y}:{}}};var nf=`<!doctype html>
300
+ if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,Wp=[{binary:"zenity",args:["--file-selection","--directory",`--title=${Mo}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",Mo]}],Yp=(P,G)=>(G.PATH??"").split(mk).some((K)=>{if(K.length===0)return!1;try{let Y=zp(gk(K,P));return Y.isFile()&&(Y.mode&73)!==0}catch{return!1}});function Gs(P,G){if(P==="darwin"||P==="win32")return!0;if(P!=="linux")return!1;if(!G.DISPLAY&&!G.WAYLAND_DISPLAY)return!1;return Wp.some((K)=>Yp(K.binary,G))}function bk(P,G){if(P==="darwin")return{cmd:"osascript",args:["-e",hk]};if(P==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",vk]};let K=Wp.find((Y)=>Yp(Y.binary,G));return K?{cmd:K.binary,args:K.args}:null}function qs(P=process.platform,G=process.env){let K=bk(P,G);if(!K)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((Y)=>{let Z=pk(K.cmd,K.args,{env:G,stdio:["ignore","pipe","pipe"]}),X="",ie=!1,ae=(ye)=>{if(ie)return;ie=!0,clearTimeout(ge),Y(ye)},ge=setTimeout(()=>{Z.kill(),ae({error:"The folder dialog timed out"})},yk);Z.stdout.on("data",(ye)=>{X+=ye.toString()}),Z.on("error",()=>ae({error:`Could not open the folder dialog (${K.cmd})`})),Z.on("close",()=>{let ye=X.trim().replace(/\/+$/,"");if(!ye)return ae({cancelled:!0});if(!fk(ye)||!zp(ye).isDirectory())return ae({error:"That selection is not a folder on disk"});ae({path:ye})})})}var Zp=["en","ja","zh-CN"],Xp=["light","dark"],Uo=(P,G)=>P.includes(G),Qp=(P)=>typeof P==="object"&&P!==null&&!Array.isArray(P),ef=(P)=>{let G=Qp(P)?P:{};return{...Uo(Zp,G.language)?{language:G.language}:{},...Uo(Xp,G.theme)?{theme:G.theme}:{}}},nf=(P)=>{if(!Qp(P))return null;let G=Object.keys(P).every((Z)=>Z==="language"||Z==="theme"),K=P.language===void 0||Uo(Zp,P.language),Y=P.theme===void 0||Uo([...Xp,"auto"],P.theme);return G&&K&&Y?P:null},tf=(P,G)=>{let K=G.language??P.language,Y=G.theme==="auto"?void 0:G.theme??P.theme;return{...K?{language:K}:{},...Y?{theme:Y}:{}}};var rf=`<!doctype html>
301
301
  <html lang="en">
302
302
  <head>
303
303
  <meta charset="utf-8">
@@ -7063,7 +7063,7 @@ loadPolicy().then((loaded) => {
7063
7063
  </script>
7064
7064
  </body>
7065
7065
  </html>
7066
- `;var tf='<script id="ccsn-data" type="application/json">';function rf(P,L=nf){return L.replace(tf,()=>tf+JSON.stringify(P).replaceAll("<","\\u003c"))}var Vs="kenryu42/cc-safety-net",xk=`https://github.com/${Vs}`,ff=1e4,Pk=7,Sk="The project draft directory changed; reload the draft before applying.",Rk="audit settings are user scope only; remove the audit section from a project proposal";async function mf(P,L={}){let H=mn({label:"gui",booleans:{noOpen:["--no-open"]}},P),Y=L.log??console.log,Z=L.error??console.error;if(H.errors.length>0){for(let se of H.errors)Z(se);return Z("Usage: cc-safety-net gui [--no-open]"),1}let oe=await Ek(c,L);if(Y(`CC Safety Net policy GUI: ${oe.url}`),!H.flags.noOpen)try{await(L.openBrowser??Hk)(oe.url)}catch(se){Z(`Failed to open browser: ${se instanceof Error?se.message:String(se)}`),Z(`Open this URL manually: ${oe.url}`)}if(L.keepAlive===!1)return await oe.close(),0;return await Fk(oe),0}async function Ek(P,L={}){let H=hk(24).toString("base64url"),Y={dir:null,revision:0},Z=wk((me,he)=>{Tk(P,me,he,H,L,Y)});await new Promise((me,he)=>{Z.once("error",he),Z.listen(0,"127.0.0.1",()=>{Z.off("error",he),me()})});let se=`http://127.0.0.1:${Z.address().port}`;return{origin:se,token:H,url:`${se}/?token=${encodeURIComponent(H)}`,close:()=>jk(Z)}}async function Tk(P,L,H,Y,Z,oe){let se=P(),me=new URL(L.url??"/","http://127.0.0.1");if(L.method==="GET"&&me.pathname==="/favicon.ico"){H.writeHead(204,{"cache-control":"no-store"}),H.end();return}if(!Dk(L,me,Y)){rn(H,403,{error:"Forbidden"});return}if(L.method==="GET"&&me.pathname==="/"){let he=sf(of(se,Z));await Promise.resolve(Z.buildDocument?.()).then((ke)=>Lk(H,rf({token:Y,preferences:he},ke)),(ke)=>rn(H,500,{error:ke instanceof Error?ke.message:String(ke)}));return}if(L.method==="POST"&&me.pathname==="/api/preferences"){let he=await Qt(L);if(!he.ok){rn(H,he.status,{errors:[he.error]});return}let ke=Qp(he.value);if(!ke){rn(H,400,{errors:["preferences accept only language (en, ja, zh-CN) and theme (auto, light, dark)"]});return}let Pe=of(se,Z),Te=ef(sf(Pe),ke),_e=Ak(Pe,Te);rn(H,_e?500:200,_e?{errors:[_e]}:{preferences:Te});return}if(L.method==="GET"&&me.pathname==="/api/policy"){let he=Du(se,Z),ke=R(se,qs(Z));rn(H,200,{...he,configState:Ve(ke),...ke.policyScopes?{projectPolicy:{path:y(Z.cwd??process.cwd()),weakenings:ke.policyScopes.weakeningsIgnored?[]:ke.policyScopes.weakenings}}:{},destructiveCommandRules:q,secretPatterns:dt,version:pn(),preview:he.errors.length>0?null:Be(he.policy,se.env)});return}if(L.method==="POST"&&me.pathname==="/api/policy/preview"){let he=await Qt(L);if(!he.ok){rn(H,he.status,{errors:[he.error]});return}let ke=Nu(se,he.value);rn(H,ke.errors.length>0?400:200,ke);return}if(L.method==="POST"&&me.pathname==="/api/policy/explain"){let he=await Qt(L);if(!he.ok){rn(H,he.status,{errors:[he.error]});return}let ke=he.value;if(ke===null||typeof ke.command!=="string"){rn(H,400,{errors:["command must be a string"]});return}let Pe=Cr(ke.policy,se.home);if(Pe.length>0){rn(H,400,{errors:Pe});return}rn(H,200,Ok(se,ke.command,ke.policy,Z));return}if(L.method==="POST"&&me.pathname==="/api/policy"){let he=await Qt(L);if(!he.ok){rn(H,he.status,{errors:[he.error]});return}let ke=Hn(se,he.value,Z);rn(H,ke.errors.length>0?400:200,ke);return}if(L.method==="POST"&&me.pathname==="/api/reset"){rn(H,200,Hn(se,ne,Z));return}if(L.method==="POST"&&me.pathname==="/api/repair"){rn(H,200,Lu(se,Z));return}if(L.method==="POST"&&me.pathname==="/api/policy/project/choose-directory"){let he=await(Z.chooseDirectory??Gs)();if("path"in he)oe.dir=he.path,oe.revision+=1;rn(H,200,{cancelled:"cancelled"in he,..."error"in he?{error:he.error}:{}});return}if(L.method==="GET"&&me.pathname==="/api/policy/project"){let he=gf(oe,Z),ke=yf(se,he,Z),Pe=ke?{projection:{},diagnostics:[ke]}:af(he,se.home),Te=xr(se,Z);rn(H,200,{path:y(he),revision:oe.revision,baseline:Te.baseline,userPolicyDiagnostics:Te.diagnostics,projection:Pe.projection,projectionDiagnostics:Pe.diagnostics,canPickDirectory:Bs(process.platform,process.env)});return}if(L.method==="POST"&&me.pathname==="/api/policy/project/diff"){let he=await lf(se,L,H,oe,Z);if(!he)return;let ke=af(he.dir,se.home),Pe=xr(se,Z).baseline,Te=te(Pe,fe(he.proposal,se.home).policy);rn(H,200,{rows:Ro(te(Pe,ke.projection).policy,Te.policy,!1),weakenings:Te.weakenings,existingFileDiagnostics:ke.diagnostics});return}if(L.method==="POST"&&me.pathname==="/api/policy/project/apply"){let he=await lf(se,L,H,oe,Z);if(!he)return;let ke=Ik(he.dir,he.proposal,se.home);rn(H,ke.errors.length>0?500:200,ke);return}if(L.method==="GET"&&me.pathname==="/api/activity"){let he=ie(se,Z),ke=$k(me.searchParams.get("days"),he);if(ke===null){rn(H,400,{error:`days must be an integer between 1 and ${he}`});return}rn(H,200,Vp(se,ke,Z.activityLogsDir));return}if(L.method==="POST"&&me.pathname==="/api/rules/choose-directory"){rn(H,200,await Gs());return}if(L.method==="GET"&&me.pathname==="/api/rules"){let he=ee(se,qs(Z)),ke=new Map(he.rules.map((Pe)=>[Pe.name,Pe]));rn(H,200,{projectPath:Z.cwd??process.cwd(),canPickDirectory:Bs(process.platform,process.env),rulebooks:he.rulebooks.map((Pe)=>({source:Pe.source,spec:Pe.spec,name:Pe.name,version:Pe.version,rules:Pe.rules.flatMap((Te)=>{let _e=ke.get(Te);if(!_e)return[];return[{name:_e.name,command:_e.command,subcommand:_e.subcommand,block_args:_e.block_args,reason:_e.reason}]})})),errors:he.errors,warnings:he.warnings});return}if(L.method==="GET"&&me.pathname==="/api/star/context"){rn(H,200,await(Z.fetchStarContext??(()=>Vk(se,{logsDir:Z.activityLogsDir})))());return}if(L.method==="POST"&&me.pathname==="/api/star"){let he=await(Z.starRepo??Mk)();rn(H,200,he.ok?{ok:!0}:{ok:!1,fallbackUrl:xk});return}if(L.method==="GET"&&me.pathname==="/api/integrations"){rn(H,200,await(Z.fetchIntegrations??(()=>Uk(se)))());return}if(L.method==="GET"&&me.pathname==="/api/health"){rn(H,200,await(Z.fetchHealth??Gk)());return}if(L.method==="POST"&&(me.pathname==="/api/install"||me.pathname==="/api/uninstall")){let he=await Qt(L);if(!he.ok){rn(H,he.status,{errors:[he.error]});return}let ke=he.value?.target;if(typeof ke!=="string"||!On.some((Te)=>Te.target===ke)){rn(H,400,{error:"unknown target"});return}let Pe=me.pathname==="/api/install"?"install":"uninstall";rn(H,200,await(Z.runIntegration??qk)(Pe,ke));return}rn(H,404,{error:"Not found"})}function of(P,L){return kk(pf(le(P,L)),"gui.json")}function sf(P){if(!uf(P))return{};try{return Xp(JSON.parse(bk(P,"utf-8")))}catch{return{}}}function Ak(P,L){try{return vk(pf(P),{recursive:!0}),an(P,`${JSON.stringify(L,null,2)}
7067
- `),null}catch(H){return H instanceof Error?H.message:String(H)}}function qs(P){return{...P,cwd:P.cwd??process.cwd()}}function gf(P,L){return P.dir??L.cwd??process.cwd()}function yf(P,L,H){if(!O(P,{...H,cwd:L}))return null;return`${y(L)} is the user policy, not a project policy; choose a project directory, or run the GUI from one`}function af(P,L){let H=y(P),Y=uf(H)?$t(H):{value:void 0,errors:[]},Z=fe(Y.value,L);return{projection:Z.policy,diagnostics:[...Y.errors,...Z.diagnostics]}}async function lf(P,L,H,Y,Z){let oe=gf(Y,Z),se=Y.revision,me=await Qt(L);if(!me.ok)return rn(H,me.status,{errors:[me.error]}),null;let he=me.value;if(typeof he?.revision!=="number")return rn(H,400,{errors:["revision must be a number"]}),null;if(he.revision!==se)return rn(H,409,{errors:[Sk]}),null;let ke=yf(P,oe,Z);if(ke)return rn(H,400,{errors:[ke]}),null;let Pe=_k(he.proposal,P.home);if(Pe.length>0)return rn(H,400,{errors:Pe}),null;return{dir:oe,proposal:he.proposal}}function _k(P,L){let H=Cr(P,L);if(H.length>0)return H;return P?.audit===void 0?[]:[Rk]}function Ik(P,L,H){let Y=y(P),Z=Eo(L,k(L,H));try{return h(i(w(P,"project policy"),Y),`${JSON.stringify(Z,null,2)}
7068
- `),{path:Y,errors:[]}}catch(oe){return{path:Y,errors:[oe instanceof Error?oe.message:String(oe)]}}}function Ok(P,L,H,Y){let Z=k(H,P.home),oe=R(P,qs(Y)),se=Ne({rules:oe.policy.rules,transparentWrappers:oe.policy.transparentWrappers,commandTools:oe.policy.commandTools,safety:ze(Z.safety),worktreeMode:Z.workflow.worktree_mode,destructiveCommandProtectionEnabled:Z.destructive_command_protection.enabled,destructiveCommandRuleOverrides:Z.destructive_command_protection.overrides,destructiveCommandAllowPaths:Z.destructive_command_protection.allow_paths,secretProtection:{enabled:Z.secret_protection.enabled,disabledRules:mt(Z.secret_protection.overrides),denyPaths:Z.secret_protection.deny_paths,allowPaths:Z.secret_protection.allow_paths}});return gr(L,{policySnapshot:se,cwd:Y.cwd,userConfigDir:Y.userConfigDir},P)}function $k(P,L){if(P===null)return Math.min(Pk,L);let H=Number(P);if(!Number.isInteger(H)||H<1||H>L)return null;return H}function Dk(P,L,H){if(L.searchParams.get("token")!==H)return!1;if(P.method!=="POST")return!0;return P.headers["x-cc-safety-net-token"]===H}var Nk=1048576;async function Qt(P){let L=[],H=0;for await(let Y of P){let Z=Y;if(H+=Z.byteLength,H>Nk)return{ok:!1,status:413,error:"Request body is too large"};L.push(Z)}try{return{ok:!0,value:JSON.parse(Buffer.concat(L).toString("utf-8")||"{}")}}catch(Y){return{ok:!1,status:400,error:`Invalid JSON: ${Y instanceof Error?Y.message:String(Y)}`}}}function Lk(P,L){P.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),P.end(L)}function rn(P,L,H){P.writeHead(L,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),P.end(JSON.stringify(H))}function jk(P){return new Promise((L,H)=>{P.close((Y)=>Y?H(Y):L())})}function Fk(P){return new Promise((L)=>{let H=()=>{process.off("SIGINT",Y),process.off("SIGTERM",Y)},Y=()=>{H(),P.close().then(L)};process.once("SIGINT",Y),process.once("SIGTERM",Y)})}function Hk(P){let L=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",H=process.platform==="win32"?["/c","start","",P]:[P];return new Promise((Y,Z)=>{let oe=df(L,H,{detached:!0,stdio:"ignore"}),se=(he)=>{oe.off("spawn",me),Z(he)},me=()=>{oe.off("error",se),oe.unref(),Y()};oe.once("error",se),oe.once("spawn",me)})}async function Mk(P="gh",L=ff){return{ok:await Kk(P,["api","-X","PUT",`/user/starred/${Vs}`],L)===0}}async function Uk(P,L={}){let H=await Nr((Z)=>Jt({environment:P,cwd:process.cwd(),openCodeVersion:Z}).status!=="n/a",L.fetcher),Y=Bk(P,H);return{targets:Rn.map((Z)=>{let oe=Y.find((se)=>se.platform===Z.id);return{target:Z.id,label:cn(Z.id),version:H.versions[Z.id]??null,status:oe?.configured?"active":oe?.detected?"disabled":oe?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:H.version,nodeVersion:H.nodeVersion,platform:H.platform}}}function Bk(P,L){return zt(P,process.cwd(),{ampPluginListOutput:L.ampPluginListOutput,codexPluginListOutput:L.codexPluginListOutput,copilotCliVersion:L.versions["copilot-cli"],openCodeVersion:L.versions.opencode,openCodePluginListOutput:L.openCodePluginListOutput})}async function Gk(P={}){let L=await(P.checkUpdates??Bn)();return{update:{latestVersion:L.latestVersion??null,updateAvailable:L.updateAvailable}}}var cf=Promise.resolve();function qk(P,L,H={}){let Y=async()=>{let oe=[],{log:se,error:me}=console;console.log=(...he)=>oe.push(he.map(String).join(" ")),console.error=console.log;try{return{ok:await kr(P,[],{selectTargets:async()=>[L],output:new Ck({write(ke,Pe,Te){oe.push(String(ke).replace(/\n$/,"")),Te()}}),...H})===0,output:oe.join(`
7069
- `)}}finally{console.log=se,console.error=me}},Z=cf.then(Y);return cf=Z.then(()=>{return},()=>{return}),Z}async function Vk(P,L={}){let[H,Y]=await Promise.all([Jk(L.fetchRepo),Promise.resolve(Ir(P,ie(P),L.logsDir).totalBlocked)]);return{starCount:H,blockedTotal:Y}}function Kk(P,L,H){return new Promise((Y)=>{let Z=df(P,L,{stdio:"ignore",windowsHide:!0}),oe=!1,se=setTimeout(()=>{Z.kill(),me(null)},H),me=(he)=>{if(oe)return;oe=!0,clearTimeout(se),Y(he)};Z.once("error",()=>me(null)),Z.once("close",me)})}async function Jk(P=fetch){try{let L=await P(`https://api.github.com/repos/${Vs}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(ff)});if(!L.ok)return null;let H=await L.json();return typeof H.stargazers_count==="number"?H.stargazers_count:null}catch{return null}}function zk(P){if(P[0]!=="help")return!1;let L=P[1];if(!L)gs(),process.exit(0);if(yr(L))process.exit(0);console.error(`Unknown command: ${L}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var Wk={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),yr("hook",console.error),process.exit(1)},install:async(P)=>{process.exit(await kr("install",P))},update:async(P)=>{process.exit(await _s(P))},uninstall:async(P)=>{process.exit(await kr("uninstall",P))},rule:async(P)=>{process.exit(await Bp(c(),P))},policy:async(P)=>{process.exit(await Mu(c(),P))},status:async(P)=>{if($n(mn({label:"status"},P).errors))process.exit(1);qp(c())},statusline:async(P)=>{let L=mn({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},P);if(L.errors.length===0&&L.flags.claudeCode){await Us(c());return}if($n(L.errors),!L.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");yr("statusline",console.error),process.exit(1)},doctor:async(P)=>{let L=ss(P);if(!L)process.exit(1);let H=await ed(c(),{json:L.json,skipUpdateCheck:L.skipUpdateCheck});process.exit(H)},logs:async(P)=>{process.exit(await Qs(c(),P))},gui:async(P)=>{process.exit(await mf(P))},explain:async(P)=>{process.exit(await ud(c(),P))}};async function Yk(P){let L=mn({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},P);if(zk(P))return;let H=P[0],Y=H?_r(H):void 0;if(L.help&&Y&&Y.name!=="rule")yr(Y.name),process.exit(0);if(!H||L.help&&!Y)gs(),process.exit(0);if(L.flags.version)md(),process.exit(0);if(Y){await Wk[Y.name](P.slice(1));return}if(H==="--statusline"){await Us(c());return}console.error(H.startsWith("-")?`Unknown option: ${H}`:`Unknown command: ${H}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{Yk as runCli};
7066
+ `;var of='<script id="ccsn-data" type="application/json">';function sf(P,G=rf){return G.replace(of,()=>of+JSON.stringify(P).replaceAll("<","\\u003c"))}var Ks="kenryu42/cc-safety-net",Rk=`https://github.com/${Ks}`,gf=1e4,Ek=7,Tk="The project draft directory changed; reload the draft before applying.",Ak="audit settings are user scope only; remove the audit section from a project proposal";async function yf(P,G={}){let K=fn({label:"gui",booleans:{noOpen:["--no-open"]}},P),Y=G.log??console.log,Z=G.error??console.error;if(K.errors.length>0){for(let ie of K.errors)Z(ie);return Z("Usage: cc-safety-net gui [--no-open]"),1}let X=await _k(c,G);if(Y(`CC Safety Net policy GUI: ${X.url}`),!K.flags.noOpen)try{await(G.openBrowser??Bk)(X.url)}catch(ie){Z(`Failed to open browser: ${ie instanceof Error?ie.message:String(ie)}`),Z(`Open this URL manually: ${X.url}`)}if(G.keepAlive===!1)return await X.close(),0;return await Uk(X),0}async function _k(P,G={}){let K=wk(24).toString("base64url"),Y={dir:null,revision:0},Z=xk((ae,ge)=>{Ik(P,ae,ge,K,G,Y)});await new Promise((ae,ge)=>{Z.once("error",ge),Z.listen(0,"127.0.0.1",()=>{Z.off("error",ge),ae()})});let ie=`http://127.0.0.1:${Z.address().port}`;return{origin:ie,token:K,url:`${ie}/?token=${encodeURIComponent(K)}`,close:()=>Mk(Z)}}async function Ik(P,G,K,Y,Z,X){let ie=P(),ae=new URL(G.url??"/","http://127.0.0.1");if(G.method==="GET"&&ae.pathname==="/favicon.ico"){K.writeHead(204,{"cache-control":"no-store"}),K.end();return}if(!jk(G,ae,Y)){tn(K,403,{error:"Forbidden"});return}if(G.method==="GET"&&ae.pathname==="/"){let ge=lf(af(ie,Z));await Promise.resolve(Z.buildDocument?.()).then((ye)=>Hk(K,sf({token:Y,preferences:ge},ye)),(ye)=>tn(K,500,{error:ye instanceof Error?ye.message:String(ye)}));return}if(G.method==="POST"&&ae.pathname==="/api/preferences"){let ge=await Qt(G);if(!ge.ok){tn(K,ge.status,{errors:[ge.error]});return}let ye=nf(ge.value);if(!ye){tn(K,400,{errors:["preferences accept only language (en, ja, zh-CN) and theme (auto, light, dark)"]});return}let Pe=af(ie,Z),Re=tf(lf(Pe),ye),_e=Ok(Pe,Re);tn(K,_e?500:200,_e?{errors:[_e]}:{preferences:Re});return}if(G.method==="GET"&&ae.pathname==="/api/policy"){let ge=Lu(ie,Z),ye=R(ie,Vs(Z));tn(K,200,{...ge,configState:Ke(ye),...ye.policyScopes?{projectPolicy:{path:y(Z.cwd??process.cwd()),weakenings:ye.policyScopes.weakeningsIgnored?[]:ye.policyScopes.weakenings}}:{},destructiveCommandRules:V,secretPatterns:ft,version:un(),preview:ge.errors.length>0?null:ze(ge.policy,ie.env)});return}if(G.method==="POST"&&ae.pathname==="/api/policy/preview"){let ge=await Qt(G);if(!ge.ok){tn(K,ge.status,{errors:[ge.error]});return}let ye=ju(ie,ge.value);tn(K,ye.errors.length>0?400:200,ye);return}if(G.method==="POST"&&ae.pathname==="/api/policy/explain"){let ge=await Qt(G);if(!ge.ok){tn(K,ge.status,{errors:[ge.error]});return}let ye=ge.value;if(ye===null||typeof ye.command!=="string"){tn(K,400,{errors:["command must be a string"]});return}let Pe=Cr(ye.policy,ie.home);if(Pe.length>0){tn(K,400,{errors:Pe});return}tn(K,200,Nk(ie,ye.command,ye.policy,Z));return}if(G.method==="POST"&&ae.pathname==="/api/policy"){let ge=await Qt(G);if(!ge.ok){tn(K,ge.status,{errors:[ge.error]});return}let ye=Hn(ie,ge.value,Z);tn(K,ye.errors.length>0?400:200,ye);return}if(G.method==="POST"&&ae.pathname==="/api/reset"){tn(K,200,Hn(ie,re,Z));return}if(G.method==="POST"&&ae.pathname==="/api/repair"){tn(K,200,Fu(ie,Z));return}if(G.method==="POST"&&ae.pathname==="/api/policy/project/choose-directory"){let ge=await(Z.chooseDirectory??qs)();if("path"in ge)X.dir=ge.path,X.revision+=1;tn(K,200,{cancelled:"cancelled"in ge,..."error"in ge?{error:ge.error}:{}});return}if(G.method==="GET"&&ae.pathname==="/api/policy/project"){let ge=hf(X,Z),ye=vf(ie,ge,Z),Pe=ye?{projection:{},diagnostics:[ye]}:cf(ge,ie.home),Re=xr(ie,Z);tn(K,200,{path:y(ge),revision:X.revision,baseline:Re.baseline,userPolicyDiagnostics:Re.diagnostics,projection:Pe.projection,projectionDiagnostics:Pe.diagnostics,canPickDirectory:Gs(process.platform,process.env)});return}if(G.method==="POST"&&ae.pathname==="/api/policy/project/diff"){let ge=await df(ie,G,K,X,Z);if(!ge)return;let ye=cf(ge.dir,ie.home),Pe=xr(ie,Z).baseline,Re=ne(Pe,me(ge.proposal,ie.home).policy);tn(K,200,{rows:Ro(ne(Pe,ye.projection).policy,Re.policy,!1),weakenings:Re.weakenings,existingFileDiagnostics:ye.diagnostics});return}if(G.method==="POST"&&ae.pathname==="/api/policy/project/apply"){let ge=await df(ie,G,K,X,Z);if(!ge)return;let ye=Dk(ge.dir,ge.proposal,ie.home);tn(K,ye.errors.length>0?500:200,ye);return}if(G.method==="GET"&&ae.pathname==="/api/activity"){let ge=se(ie,Z),ye=Lk(ae.searchParams.get("days"),ge);if(ye===null){tn(K,400,{error:`days must be an integer between 1 and ${ge}`});return}tn(K,200,Jp(ie,ye,Z.activityLogsDir));return}if(G.method==="POST"&&ae.pathname==="/api/rules/choose-directory"){tn(K,200,await qs());return}if(G.method==="GET"&&ae.pathname==="/api/rules"){let ge=te(ie,Vs(Z)),ye=new Map(ge.rules.map((Pe)=>[Pe.name,Pe]));tn(K,200,{projectPath:Z.cwd??process.cwd(),canPickDirectory:Gs(process.platform,process.env),rulebooks:ge.rulebooks.map((Pe)=>({source:Pe.source,spec:Pe.spec,name:Pe.name,version:Pe.version,rules:Pe.rules.flatMap((Re)=>{let _e=ye.get(Re);if(!_e)return[];return[{name:_e.name,command:_e.command,subcommand:_e.subcommand,block_args:_e.block_args,reason:_e.reason}]})})),errors:ge.errors,warnings:ge.warnings});return}if(G.method==="GET"&&ae.pathname==="/api/star/context"){tn(K,200,await(Z.fetchStarContext??(()=>zk(ie,{logsDir:Z.activityLogsDir})))());return}if(G.method==="POST"&&ae.pathname==="/api/star"){let ge=await(Z.starRepo??Gk)();tn(K,200,ge.ok?{ok:!0}:{ok:!1,fallbackUrl:Rk});return}if(G.method==="GET"&&ae.pathname==="/api/integrations"){tn(K,200,await(Z.fetchIntegrations??(()=>qk(ie)))());return}if(G.method==="GET"&&ae.pathname==="/api/health"){tn(K,200,await(Z.fetchHealth??Kk)());return}if(G.method==="POST"&&(ae.pathname==="/api/install"||ae.pathname==="/api/uninstall")){let ge=await Qt(G);if(!ge.ok){tn(K,ge.status,{errors:[ge.error]});return}let ye=ge.value?.target;if(typeof ye!=="string"||!On.some((Re)=>Re.target===ye)){tn(K,400,{error:"unknown target"});return}let Pe=ae.pathname==="/api/install"?"install":"uninstall";tn(K,200,await(Z.runIntegration??Jk)(Pe,ye));return}tn(K,404,{error:"Not found"})}function af(P,G){return Pk(mf(ue(P,G)),"gui.json")}function lf(P){if(!ff(P))return{};try{return ef(JSON.parse(Ck(P,"utf-8")))}catch{return{}}}function Ok(P,G){try{return kk(mf(P),{recursive:!0}),sn(P,`${JSON.stringify(G,null,2)}
7067
+ `),null}catch(K){return K instanceof Error?K.message:String(K)}}function Vs(P){return{...P,cwd:P.cwd??process.cwd()}}function hf(P,G){return P.dir??G.cwd??process.cwd()}function vf(P,G,K){if(!O(P,{...K,cwd:G}))return null;return`${y(G)} is the user policy, not a project policy; choose a project directory, or run the GUI from one`}function cf(P,G){let K=y(P),Y=ff(K)?$t(K):{value:void 0,errors:[]},Z=me(Y.value,G);return{projection:Z.policy,diagnostics:[...Y.errors,...Z.diagnostics]}}async function df(P,G,K,Y,Z){let X=hf(Y,Z),ie=Y.revision,ae=await Qt(G);if(!ae.ok)return tn(K,ae.status,{errors:[ae.error]}),null;let ge=ae.value;if(typeof ge?.revision!=="number")return tn(K,400,{errors:["revision must be a number"]}),null;if(ge.revision!==ie)return tn(K,409,{errors:[Tk]}),null;let ye=vf(P,X,Z);if(ye)return tn(K,400,{errors:[ye]}),null;let Pe=$k(ge.proposal,P.home);if(Pe.length>0)return tn(K,400,{errors:Pe}),null;return{dir:X,proposal:ge.proposal}}function $k(P,G){let K=Cr(P,G);if(K.length>0)return K;return P?.audit===void 0?[]:[Ak]}function Dk(P,G,K){let Y=y(P),Z=Eo(G,k(G,K));try{return h(i(w(P,"project policy"),Y),`${JSON.stringify(Z,null,2)}
7068
+ `),{path:Y,errors:[]}}catch(X){return{path:Y,errors:[X instanceof Error?X.message:String(X)]}}}function Nk(P,G,K,Y){let Z=k(K,P.home),X=R(P,Vs(Y)),ie=Me({rules:X.policy.rules,transparentWrappers:X.policy.transparentWrappers,commandTools:X.policy.commandTools,safety:qe(Z.safety),worktreeMode:Z.workflow.worktree_mode,destructiveCommandProtectionEnabled:Z.destructive_command_protection.enabled,destructiveCommandRuleOverrides:Z.destructive_command_protection.overrides,destructiveCommandAllowPaths:Z.destructive_command_protection.allow_paths,secretProtection:{enabled:Z.secret_protection.enabled,disabledRules:ht(Z.secret_protection.overrides),denyPaths:Z.secret_protection.deny_paths,allowPaths:Z.secret_protection.allow_paths}});return gr(G,{policySnapshot:ie,cwd:Y.cwd,userConfigDir:Y.userConfigDir},P)}function Lk(P,G){if(P===null)return Math.min(Ek,G);let K=Number(P);if(!Number.isInteger(K)||K<1||K>G)return null;return K}function jk(P,G,K){if(G.searchParams.get("token")!==K)return!1;if(P.method!=="POST")return!0;return P.headers["x-cc-safety-net-token"]===K}var Fk=1048576;async function Qt(P){let G=[],K=0;for await(let Y of P){let Z=Y;if(K+=Z.byteLength,K>Fk)return{ok:!1,status:413,error:"Request body is too large"};G.push(Z)}try{return{ok:!0,value:JSON.parse(Buffer.concat(G).toString("utf-8")||"{}")}}catch(Y){return{ok:!1,status:400,error:`Invalid JSON: ${Y instanceof Error?Y.message:String(Y)}`}}}function Hk(P,G){P.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),P.end(G)}function tn(P,G,K){P.writeHead(G,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),P.end(JSON.stringify(K))}function Mk(P){return new Promise((G,K)=>{P.close((Y)=>Y?K(Y):G())})}function Uk(P){return new Promise((G)=>{let K=()=>{process.off("SIGINT",Y),process.off("SIGTERM",Y)},Y=()=>{K(),P.close().then(G)};process.once("SIGINT",Y),process.once("SIGTERM",Y)})}function Bk(P){let G=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",K=process.platform==="win32"?["/c","start","",P]:[P];return new Promise((Y,Z)=>{let X=pf(G,K,{detached:!0,stdio:"ignore"}),ie=(ge)=>{X.off("spawn",ae),Z(ge)},ae=()=>{X.off("error",ie),X.unref(),Y()};X.once("error",ie),X.once("spawn",ae)})}async function Gk(P="gh",G=gf){return{ok:await Wk(P,["api","-X","PUT",`/user/starred/${Ks}`],G)===0}}async function qk(P,G={}){let K=await Nr((Z)=>Jt({environment:P,cwd:process.cwd(),openCodeVersion:Z}).status!=="n/a",G.fetcher),Y=Vk(P,K);return{targets:Sn.map((Z)=>{let X=Y.find((ie)=>ie.platform===Z.id);return{target:Z.id,label:ln(Z.id),version:K.versions[Z.id]??null,status:X?.configured?"active":X?.detected?"disabled":X?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:K.version,nodeVersion:K.nodeVersion,platform:K.platform}}}function Vk(P,G){return zt(P,process.cwd(),{ampPluginListOutput:G.ampPluginListOutput,codexPluginListOutput:G.codexPluginListOutput,copilotCliVersion:G.versions["copilot-cli"],openCodeVersion:G.versions.opencode,openCodePluginListOutput:G.openCodePluginListOutput})}async function Kk(P={}){let G=await(P.checkUpdates??Bn)();return{update:{latestVersion:G.latestVersion??null,updateAvailable:G.updateAvailable}}}var uf=Promise.resolve();function Jk(P,G,K={}){let Y=async()=>{let X=[],{log:ie,error:ae}=console;console.log=(...ge)=>X.push(ge.map(String).join(" ")),console.error=console.log;try{return{ok:await kr(P,[],{selectTargets:async()=>[G],output:new Sk({write(ye,Pe,Re){X.push(String(ye).replace(/\n$/,"")),Re()}}),...K})===0,output:X.join(`
7069
+ `)}}finally{console.log=ie,console.error=ae}},Z=uf.then(Y);return uf=Z.then(()=>{return},()=>{return}),Z}async function zk(P,G={}){let[K,Y]=await Promise.all([Yk(G.fetchRepo),Promise.resolve(Ir(P,se(P),G.logsDir).totalBlocked)]);return{starCount:K,blockedTotal:Y}}function Wk(P,G,K){return new Promise((Y)=>{let Z=pf(P,G,{stdio:"ignore",windowsHide:!0}),X=!1,ie=setTimeout(()=>{Z.kill(),ae(null)},K),ae=(ge)=>{if(X)return;X=!0,clearTimeout(ie),Y(ge)};Z.once("error",()=>ae(null)),Z.once("close",ae)})}async function Yk(P=fetch){try{let G=await P(`https://api.github.com/repos/${Ks}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(gf)});if(!G.ok)return null;let K=await G.json();return typeof K.stargazers_count==="number"?K.stargazers_count:null}catch{return null}}function Zk(P){if(P[0]!=="help")return!1;let G=P[1];if(!G)ys(),process.exit(0);if(yr(G))process.exit(0);console.error(`Unknown command: ${G}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var Xk={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),yr("hook",console.error),process.exit(1)},install:async(P)=>{process.exit(await kr("install",P))},update:async(P)=>{process.exit(await Is(P))},uninstall:async(P)=>{process.exit(await kr("uninstall",P))},rule:async(P)=>{process.exit(await qp(c(),P))},policy:async(P)=>{process.exit(await Bu(c(),P))},status:async(P)=>{if($n(fn({label:"status"},P).errors))process.exit(1);Kp(c())},statusline:async(P)=>{let G=fn({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},P);if(G.errors.length===0&&G.flags.claudeCode){await Bs(c());return}if($n(G.errors),!G.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");yr("statusline",console.error),process.exit(1)},doctor:async(P)=>{let G=as(P);if(!G)process.exit(1);let K=await nd(c(),{json:G.json,skipUpdateCheck:G.skipUpdateCheck});process.exit(K)},logs:async(P)=>{process.exit(await ea(c(),P))},gui:async(P)=>{process.exit(await yf(P))},explain:async(P)=>{process.exit(await pd(c(),P))}};async function Qk(P){let G=fn({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},P);if(Zk(P))return;let K=P[0],Y=K?_r(K):void 0;if(G.help&&Y&&Y.name!=="rule")yr(Y.name),process.exit(0);if(!K||G.help&&!Y)ys(),process.exit(0);if(G.flags.version)gd(),process.exit(0);if(Y){await Xk[Y.name](P.slice(1));return}if(K==="--statusline"){await Bs(c());return}console.error(K.startsWith("-")?`Unknown option: ${K}`:`Unknown command: ${K}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{Qk as runCli};