cc-safety-net 2.6.1 → 2.6.3

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,49 +1,54 @@
1
- import{a,s,Pe,Be,R,nt,ze,c,n,qe,T,v,pe,ot,f,Ke,u,o,S,i,se,r,g,me,H,st,at,d,ge,he,ct,N,Z,ae,w,lt,_,h,ke,W,l,L,X,Je,Ye,M,C,I,ye,be,Ae,ut,m,e,Oe,Re,Ze,Xe,ce,Te,le,De,Q,B,Ne,xe,z,Qe,q,ee,te,ue,et,tt,E,F,Le,Fe,$e,k,je,_e,Ue,y,t,ne,ve,b,x,A,dt,Ge,He,p,V}from"./chunks/index-mqmy0cce.js";import{oe,K,We,U,G}from"./chunks/index-k4yfpsk1.js";var ep=["-h","--help"];function gn(P,O){let D=Object.entries(P.booleans??{}),j=Object.entries(P.values??{}),J=Object.entries(P.lists??{}),Y=Object.fromEntries(D.map(([Se])=>[Se,!1])),re={},ie=Object.fromEntries(J.map(([Se])=>[Se,[]])),de=[],fe=[],we=!1,Ce=-1;for(let[Se,Ie]of O.entries()){if(Se<=Ce)continue;if(Ie==="--"){de.push(...O.slice(Se+1));break}if(ep.includes(Ie)){we=!0;continue}let Ee=D.find(([,en])=>en.includes(Ie));if(Ee){Y[Ee[0]]=!0;continue}let Ve=j.find(([,en])=>en.includes(Ie));if(Ve){let en=O[Se+1];if(en===void 0||en.startsWith("-")){fe.push(`${Ie} requires a value`);continue}re[Ve[0]]=en,Ce=Se+1;continue}let Me=J.find(([,en])=>en.includes(Ie));if(Me){let en=O.slice(Se+1),on=en.findIndex((an)=>an.startsWith("-")),sn=en.slice(0,on===-1?en.length:on);if(sn.length===0){fe.push(`${Ie} requires at least one value`);continue}ie[Me[0]]=[...ie[Me[0]]??[],...sn],Ce=Se+sn.length;continue}if(Ie.startsWith("-")){fe.push(`Unknown option for ${P.label}: ${Ie}`);continue}if(P.positionals==="tail"){de.push(...O.slice(Se));break}de.push(Ie)}if(P.positionals!=="list"&&P.positionals!=="tail")fe.push(...de.map((Se)=>`Unexpected argument for ${P.label}: ${Se}`));return{flags:Y,values:re,lists:ie,positionals:de,help:we,errors:fe}}function Dn(P){for(let O of P)console.error(O);return P.length>0}import{readdirSync as ap,statSync as vs,unlinkSync as lp}from"node:fs";import{basename as bs,dirname as cp,isAbsolute as dp,join as up,relative as pp,resolve as fp,sep as mp}from"node:path";var gs=(P)=>{let O=Date.now()-new Date(P).getTime();if(!Number.isFinite(O))return"";let D=Math.floor(O/60000),j=Math.floor(D/60),J=Math.floor(j/24);if(J>0)return`${J}d ago`;if(j>0)return`${j}h ago`;if(D>0)return`${D}m ago`;return"just now"},ko=(P)=>{let O=(P??"").trim().split(/\s+/).filter((J)=>J&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(J)),D=O[0]?.split("/").pop();if(!D)return null;let j=O[1];return j&&/^[a-z][a-z0-9-]*$/.test(j)?`${D} ${j}`:D};function ys(P){let O=(J)=>`${J.sessionId}
2
- ${ko(J.segment||J.command)}`,D=P.filter((J)=>J.decision!=="allow"),j=D.filter((J)=>J.sessionId).reduce((J,Y)=>J.set(O(Y),(J.get(O(Y))??0)+1),new Map);return new Set(D.filter((J)=>J.failureStage||(j.get(O(J))??0)>=2))}import{existsSync as np,readdirSync as tp,readFileSync as rp}from"node:fs";import{join as op}from"node:path";function Wn(P,O){try{return tp(P,{withFileTypes:!0,encoding:"utf8"}).flatMap((D)=>{let j=op(P,D.name);if(D.isDirectory())return Wn(j,O);if(D.name.endsWith(".jsonl"))return[j];return[]})}catch{if(O&&np(P))O.count++;return[]}}var ip=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function sp(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let O=P;if(typeof O.ts!=="string"||typeof O.command!=="string")return!1;return ip.every((D)=>O[D]===void 0||typeof O[D]==="string")}function kt(P,O){try{return rp(P,"utf-8").split(`
3
- `).filter(Boolean).flatMap((D)=>{try{let j=JSON.parse(D);if(!sp(j)){if(O)O.count++;return[]}return[j]}catch{if(O)O.count++;return[]}})}catch{if(O)O.count++;return[]}}function yn(P){return Array.from(P,(O)=>{let D=O.charCodeAt(0);if(D<=31||D>=127&&D<=159)return`\\x${D.toString(16).padStart(2,"0")}`;return O}).join("")}function gp(P,O){let D=oe(P),j=gn({label:"logs",booleans:{all:["--all"],suspect:["--suspect"],json:["--json"],pruneLegacy:["--prune-legacy"],dryRun:["--dry-run"]},values:{id:["--id"],limit:["--limit"],since:["--since"],agent:["--agent"],rule:["--rule"],session:["--session"],project:["--project"]}},O);if(Dn(j.errors))return null;if(j.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(j.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let J=j.values.limit===void 0?20:hs(j.values.limit);if(J===null)return console.error("--limit must be a positive number"),null;let Y=j.values.since===void 0?Math.min(30,D):hs(j.values.since);if(Y===null||Y>D)return console.error(`--since must be a positive number of days no greater than ${D}`),null;let re={limit:J,limitExplicit:j.values.limit!==void 0,since:Y,sinceExplicit:j.values.since!==void 0,all:j.flags.all,json:j.flags.json,suspect:j.flags.suspect,pruneLegacy:j.flags.pruneLegacy,dryRun:j.flags.dryRun,id:j.values.id,agent:j.values.agent,rule:j.values.rule,session:j.values.session,project:j.values.project===void 0?void 0:fp(j.values.project)};if(re.id&&(re.agent!==void 0||re.rule!==void 0||re.session!==void 0||re.project!==void 0||re.suspect||re.sinceExplicit||re.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(re.pruneLegacy&&(re.id!==void 0||re.agent!==void 0||re.rule!==void 0||re.session!==void 0||re.project!==void 0||re.suspect||re.all||re.sinceExplicit||re.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(re.dryRun&&!re.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return re}async function ws(P,O,D={}){let j=gp(P,O);if(!j)return 1;let J=D.logsDir??U(P);if(j.pruneLegacy)return yp(J,j.json,j.dryRun);if(!J)return console.log(j.json?"[]":j.id?`No retained audit log entry found for id ${yn(j.id)}.`:"No audit log entries found."),0;K(P,J);let Y={count:0},re=Wn(J,Y).flatMap((Ce)=>kt(Ce,Y).map((Se)=>({entry:Se,file:Ce})));if(Y.count>0)console.error(`warning: ${Y.count} audit log ${Y.count===1?"source":"sources"} could not be read; these results are incomplete`);if(j.id)return wp(re,j,D.timeZone);let ie=Date.now()-j.since*24*60*60*1000,de=re.filter((Ce)=>kp(Ce,j,J,ie)),fe=j.suspect?ys(de.map((Ce)=>Ce.entry)):null,we=(fe?de.filter((Ce)=>fe.has(Ce.entry)):de).sort((Ce,Se)=>Date.parse(Se.entry.ts)-Date.parse(Ce.entry.ts)).slice(0,j.limit);if(j.json)return console.log(JSON.stringify(we.map((Ce)=>Ce.entry),null,2)),0;if(we.length===0)return console.log("No audit log entries found."),0;for(let Ce of we)console.log(Sp(Ce.entry,D.timeZone));return 0}function yp(P,O,D){let j=P?vp(P).map((ie)=>up(P,ie)):[];if(D)return hp(j,O);let J=[],Y=0,re=0;for(let ie of j){let de=vs(ie,{throwIfNoEntry:!1})?.size??0,fe=bp(ie);if(fe){J.push(`${bs(ie)}: ${fe}`);continue}Y++,re+=de}if(O)return console.log(JSON.stringify({removedFiles:Y,removedBytes:re,failedFiles:J.length})),J.length===0?0:1;console.log(Y===0&&J.length===0?"No legacy audit log files found.":`Removed ${Y} legacy audit log ${Y===1?"file":"files"} (${ks(re)}).`);for(let ie of J)console.error(`Could not remove ${yn(ie)}`);if(console.log("Nested v2 audit logs were not changed."),Y>0)console.log("This deletion cannot be undone.");return J.length===0?0:1}function hp(P,O){let D=P.reduce((j,J)=>j+(vs(J,{throwIfNoEntry:!1})?.size??0),0);if(O)return console.log(JSON.stringify({dryRun:!0,files:P.length,bytes:D})),0;if(console.log(P.length===0?"No legacy audit log files found.":`Would remove ${P.length} legacy audit log ${P.length===1?"file":"files"} (${ks(D)}).`),console.log("Nested v2 audit logs are not included."),P.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function vp(P){try{return ap(P,{withFileTypes:!0}).filter((O)=>O.isFile()&&O.name.endsWith(".jsonl")).map((O)=>O.name)}catch{return[]}}function bp(P){try{return lp(P),null}catch(O){return O instanceof Error?O.message:String(O)}}function ks(P){let O=["B","KiB","MiB","GiB"],D=Math.min(Math.floor(Math.log2(Math.max(P,1))/10),O.length-1);return`${Math.round(P/1024**D*10)/10} ${O[D]}`}function wp(P,O,D){let j=P.filter((Y)=>Y.entry.id===O.id);if(j.length>1)return console.error(`Multiple audit log entries found for id ${yn(O.id??"")}.`),1;if(O.json)return console.log(JSON.stringify(j.map((Y)=>Y.entry),null,2)),0;let J=j[0];if(!J)return console.log(`No retained audit log entry found for id ${yn(O.id??"")}.`),0;return console.log(Pp(J.entry,D)),0}function kp(P,O,D,j){if(!O.all&&P.entry.decision==="allow")return!1;if(Date.parse(P.entry.ts)<j)return!1;if(O.agent!==void 0&&P.entry.agent!==O.agent)return!1;if(O.rule!==void 0&&P.entry.ruleId!==O.rule)return!1;if(O.session!==void 0&&!xp(P,D,O.session))return!1;if(O.project!==void 0&&!Cp(P.entry.cwd,O.project))return!1;return!0}function xp(P,O,D){if(P.entry.sessionId===D)return!0;return cp(P.file)===O&&bs(P.file,".jsonl")===D}function Cp(P,O){if(!P)return!1;let D=pp(O,P);return D!==".."&&!D.startsWith(`..${mp}`)&&!dp(D)}function Sp(P,O){let D=yn(P.id??"-"),j=yn(P.decision??"deny"),J=P.cwd?` [${yn(P.cwd)}]`:"",Y=P.segment||P.command,re=Y===P.command?"":"↳ ",ie=Y.length>50?`${Y.slice(0,50)}…`:Y;return`${D.padEnd(16)} ${yn(xs(P.ts,O))} ${j.padEnd(5)} ${yn(P.agent??"-").padEnd(15)} ${yn(P.ruleId??"-").padEnd(20)} ${re}${yn(ie)}${J}`}function Pp(P,O){let D=(J)=>yn(J===void 0||J===null||J===""?"-":J),j=P.shape?`${P.agent??"-"} (shape: ${P.shape})`:P.agent??"-";return[`id: ${D(P.id)}`,`ts: ${D(xs(P.ts,O))}`,`decision: ${D(P.decision)}`,`agent: ${D(j)}`,`level: ${D(P.level)}`,`tool: ${D(P.toolName)}`,`rule: ${D(P.ruleId)}`,`intent: ${D(P.intent)}`,`stage: ${D(P.failureStage)}`,`error: ${D(P.errorCode)}`,`session: ${D(P.sessionId)}`,`cwd: ${D(P.cwd)}`,`version: ${D(P.v)}`,`truncated: ${D(P.truncated===!0?"yes":void 0)}`,`reason: ${D(P.reason)}`,`command: ${D(P.command)}`,`segment: ${D(P.segment)}`].join(`
4
- `)}function xs(P,O){let D=new Date(P);if(Number.isNaN(D.getTime()))return P;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:O}).format(D)}function hs(P){let O=Number(P);return Number.isFinite(O)&&O>0?O:null}var Cs={name:"doctor",aliases:["--doctor"],description:"Run diagnostic checks to verify installation and configuration",usage:"doctor [options]",options:[{flags:"--json",description:"Output diagnostics as JSON"},{flags:"--skip-update-check",description:"Skip npm registry version check"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net doctor","cc-safety-net doctor --json","cc-safety-net doctor --skip-update-check"]};var Ss={name:"explain",description:"Show step-by-step analysis trace of how a command would be analyzed",usage:"explain [options] <command>",argument:"<command>",options:[{flags:"--json",description:"Output analysis as JSON"},{flags:"--cwd",argument:"<path>",description:"Use custom working directory"},{flags:"-h, --help",description:"Show this help"}],examples:['cc-safety-net explain "git reset --hard"','cc-safety-net explain --json "rm -rf /"','cc-safety-net explain --cwd /tmp "git status"']};var Ps={name:"gui",description:"Open the local policy editor GUI",usage:"gui [options]",options:[{flags:"--no-open",description:"Print the URL without opening a browser"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net gui","cc-safety-net gui --no-open"]};var xo=["npx","--offline","--no-install","@deepseek-ai/dsh","--version"],pr=[{id:"antigravity-cli",displayName:"Antigravity CLI",doctorOrder:3,runtime:{order:1,flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:2,flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",doctorOrder:1,runtime:{order:2,displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{order:3,flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",doctorOrder:4,runtime:{order:3,flags:["-cx","--codex"],description:"Run as a Codex PreToolUse hook",legacyTopLevelFlags:[]},install:{order:4,flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",doctorOrder:10,runtime:{order:8,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:10,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:9,runtime:{order:7,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:9,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",doctorOrder:11,runtime:{order:9,flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{order:11,flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:12,runtime:{order:10,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:12,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:13,runtime:{order:11,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:13,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:14,install:{order:14,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:15,install:{order:15,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:16,install:{order:16,flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",doctorOrder:5,runtime:{order:4,flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{order:5,flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"deepseek-harness",displayName:"DeepSeek Harness",doctorOrder:6,install:{order:6,flag:"--deepseek-harness",artifactKind:"package",probeCommand:xo}},{id:"devin",displayName:"Devin CLI",doctorOrder:7,runtime:{order:5,flags:["-dv","--devin"],description:"Run as Devin CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:7,flag:"--devin",artifactKind:"hook config",probeCommand:["devin","--version"]}},{id:"droid",displayName:"Factory Droid",doctorOrder:8,runtime:{order:6,flags:["-fd","--droid"],description:"Run as Factory Droid PreToolUse hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--droid",artifactKind:"hook config",probeCommand:["droid","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],fr=pr.slice().sort((P,O)=>P.doctorOrder-O.doctorOrder).map((P)=>P.id),Ht=pr.filter((P)=>("runtime"in P)).slice().sort((P,O)=>P.runtime.order-O.runtime.order).map((P)=>({id:P.id,displayName:"displayName"in P.runtime?P.runtime.displayName:P.displayName,flags:P.runtime.flags,legacyFlags:"legacyFlags"in P.runtime?P.runtime.legacyFlags:[],description:P.runtime.description,legacyTopLevelFlags:P.runtime.legacyTopLevelFlags})),En=pr.slice().sort((P,O)=>P.install.order-O.install.order).map((P)=>({id:P.id,...P.install})).map(({order:P,...O})=>O),Rp=Object.fromEntries(pr.map((P)=>[P.id,P.displayName]));function mn(P){return Rp[P]}var Ep=Ht.map((P)=>({flags:P.flags.join(", "),description:P.description})),_p=Ht.flatMap((P)=>P.flags.map((O)=>`cc-safety-net hook ${O}`)),Rs={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Ep,{flags:"-h, --help",description:"Show this help"}],examples:_p};var Es={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...En.map((P)=>({flags:P.flag,description:`Install ${mn(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...En.map((P)=>`cc-safety-net install ${P.flag}`)]},_s={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...En.map((P)=>({flags:P.flag,description:`Uninstall ${mn(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...En.map((P)=>`cc-safety-net uninstall ${P.flag}`)]},Ts={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 As={name:"logs",description:"Browse audit log entries recorded by hooks",usage:"logs [options]",options:[{flags:"--id",argument:"<id>",description:"Show one entry from retained history by its 16-character id (not guaranteed once it is older than the configured retention)"},{flags:"--limit",argument:"<n>",description:"Maximum entries to print",default:"20"},{flags:"--since",argument:"<days>",description:"Only include entries newer than this many days (max: the configured audit retention, 1-365)",default:"30"},{flags:"--agent",argument:"<name>",description:"Filter by agent name"},{flags:"--rule",argument:"<ruleId>",description:"Filter by rule id"},{flags:"--session",argument:"<id>",description:"Filter by session id"},{flags:"--project",argument:"<path>",description:"Filter by project path"},{flags:"--suspect",description:"Only denials that look like false positives"},{flags:"--all",description:"Include allow entries"},{flags:"--prune-legacy",description:"Permanently delete all legacy root-level logs; nested logs are untouched"},{flags:"--dry-run",description:"With --prune-legacy, report what would be deleted and delete nothing"},{flags:"--json",description:"Output entries as JSON"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net logs --id 3fa9c2d1a70e8b42","cc-safety-net logs --agent claude-code","cc-safety-net logs --project . --since 7","cc-safety-net logs --suspect --since 7","cc-safety-net logs --json","cc-safety-net logs --prune-legacy --dry-run","cc-safety-net logs --prune-legacy"]};var mr={name:"policy",description:"Check and apply project or user policy proposals",usage:"policy <subcommand>",subcommands:[{usage:"check <file>",description:"Validate a policy proposal and print its diff"},{usage:"apply <file>",description:"Apply a proposal after confirming in a terminal"}],options:[{flags:"-g, --global",description:"Use the user-scope policy instead of the project one"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net policy check proposal.json","cc-safety-net policy apply proposal.json","cc-safety-net policy apply proposal.json --global"]};var Co=[{flags:"--ref",argument:"<ref>",description:"Use a branch, tag, or commit"},{flags:"--only",argument:"<rulebook...>",description:"Add only these repository rulebooks"},{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"-h, --help",description:"Show this help"}],So=["cc-safety-net rule add project-rules","cc-safety-net rule add acme/safety-rules","cc-safety-net rule add acme/safety-rules --only aws gcloud","cc-safety-net rule add acme/safety-rules --ref v2 --only aws","cc-safety-net rule add --only terraform aws"],xt={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add [source] [--ref <ref>] [--only <rulebook...>]",description:"Add rulebook sources and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Re-fetch and vendor remote rulebooks"},{usage:"sync",description:"Deprecated: migrate lock and cache leftovers"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},...Co.slice(0,2),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net rule init","cc-safety-net rule init --example","cc-safety-net rule wrapper add rtk",...So,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var Is={name:"status",description:"Show what the runtime is enforcing right now",usage:"status",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net status"]};var $s={name:"statusline",description:"Print status line with mode indicators for shell integration",usage:"statusline --claude-code",options:[{flags:"-cc, --claude-code",description:"Print status line for Claude Code"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net statusline -cc","cc-safety-net statusline --claude-code"]};var gr=[Is,Cs,As,Ss,xt,mr,Es,Ts,_s,Rs,Ps,$s];function Tp(P){return P.aliases??[]}function yr(P){let O=P.toLowerCase();return gr.find((D)=>D.name.toLowerCase()===O||Tp(D).some((j)=>j.toLowerCase()===O))}import{existsSync as cy}from"node:fs";import{basename as Ap}from"node:path";function hr(P,O=7,D=U(P)){let j=Date.now()-O*24*60*60*1000,J=[],Y=new Set,re=0,ie,de,fe,we;if(D)K(P,D);let Ce={count:0},Se=D?Wn(D,Ce):[];for(let Ee of Se)for(let Ve of kt(Ee,Ce)){if(Ve.decision==="allow")continue;let Me=new Date(Ve.ts).getTime();if(Me>=j){if(re++,Y.add(Ve.sessionId??Ap(Ee,".jsonl")),de===void 0||Me<=de)ie=Ve.ts,de=Me;if(we===void 0||Me>we)fe=Ve.ts,we=Me;Ip(J,Ve,Me)}}let Ie=J.map((Ee)=>({timestamp:Ee.ts,command:Ee.command,reason:Ee.reason,relativeTime:gs(new Date(Ee.ts))}));return{totalBlocked:re,sessionCount:Y.size,recentEntries:Ie,oldestEntry:ie,newestEntry:fe,unreadable:Ce.count}}function Ip(P,O,D){let j=P.findIndex((J)=>D>new Date(J.ts).getTime());if(j===-1){if(P.length<3)P.push(O);return}if(P.splice(j,0,O),P.length>3)P.pop()}import{dirname as qp}from"node:path";import{dirname as $p,join as Op,resolve as Dp}from"node:path";var Lp="config.json";function wn(P,O,D,j){g(Np(P),`${JSON.stringify(O,null,2)}
5
- `,D,j)}function Np(P){return typeof P==="string"?se(P):P}function Ro(P){return{errors:ce(Fp(P),": "," "),ruleNames:new Set(De(P).map((O)=>O.toLowerCase()))}}var jp="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",Os="must match pattern (letters, numbers, hyphens, underscores)";function Fp(P){if(!Ds(P))return[e([],"Config must be an object")];return[...P.version===1?[]:[e(["version"],"must be 1")],...Hp(P.rules)]}function Hp(P){if(P===void 0)return[];if(!Array.isArray(P))return[e(["rules"],"must be an array")];return[...P.flatMap((O,D)=>Ds(O)?Mp(O,["rules",D]):[e(["rules",D],"must be an object")]),...Oe(P)]}function Mp(P,O){return[...Po(P.name,[...O,"name"],"required string",d,jp),...Po(P.command,[...O,"command"],"required string",C,Os),...P.subcommand===void 0?[]:Po(P.subcommand,[...O,"subcommand"],"must be a string if provided",C,Os),...Up(P.block_args,[...O,"block_args"]),...Gp(P.reason,[...O,"reason"]),...P.intent===void 0||Te(P.intent)?[]:[e([...O,"intent"],Re)]]}function Po(P,O,D,j,J){if(typeof P!=="string")return[e(O,D)];return j.test(P)?[]:[e(O,J)]}function Up(P,O){if(!Array.isArray(P))return[e(O,"required array")];if(P.length===0)return[e(O,"must have at least one element")];return P.flatMap((D,j)=>{if(typeof D!=="string")return[e([...O,j],"must be a string")];return D===""?[e([...O,j],"must not be empty")]:[]})}function Gp(P,O){if(typeof P!=="string")return[e(O,"required string")];if(P==="")return[e(O,"must not be empty")];return P.length>I?[e(O,`must be at most ${I} characters`)]:[]}function Ds(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function Eo(P){let O=Ls(P);if(!O.ok)return O.result;return Ro(O.parsed)}function Ls(P){let O=[],D=new Set;try{let j=typeof P==="string"?se(P):P,J=r(j);if(J===null)return O.push(`File not found: ${j.path}`),{ok:!1,result:{errors:O,ruleNames:D}};if(!J.trim())return O.push("Config file is empty"),{ok:!1,result:{errors:O,ruleNames:D}};return{ok:!0,parsed:JSON.parse(J)}}catch(j){if(j instanceof o)return O.push(j.message),{ok:!1,result:{errors:O,ruleNames:D}};let J=j instanceof Error?j.message:String(j);return O.push(j instanceof SyntaxError?"Invalid JSON":J),{ok:!1,result:{errors:O,ruleNames:D}}}}function vr(P){return Dp(P,".safety-net.json")}function Un(P){let O=Ls(P);if(!O.ok)return O.result;let D=Ze(O.parsed);return{errors:D.errors,ruleNames:D.sources}}function Ct(P,O={}){return Op($p(ke(P,O)),Lp)}function Ns(P,O,D){let j;try{if(r(O)===null)return{path:P,exists:!1,valid:!1,ruleCount:0};j=Un(O),j.errors.push(...B(P,D))}catch(J){if(!(J instanceof o))throw J;j={errors:[J.message],ruleNames:new Set}}return{path:P,exists:!0,valid:j.errors.length===0,ruleCount:j.ruleNames.size,...j.errors.length>0?{errors:j.errors}:{}}}function Bp(P,O){return{source:O,name:P.name,command:P.command,subcommand:P.subcommand,blockArgs:[...P.block_args],reason:P.reason}}function js(P,O){let D=W(P),j=_(O),J=qp(D),Y=Q(P,{cwd:O,userConfigPath:D,projectConfigPath:j,userConfigDir:J}),re=X(P,{cwd:O,userConfigPath:D,projectConfigPath:j,userConfigDir:J}),ie=new Map(Y.rulebooks.flatMap((de)=>de.rules.map((fe)=>[fe,de.source])));return{userConfig:Ns(D,re.userConfigTarget,re.userScope),projectConfig:Ns(j,re.projectConfigTarget,re.projectScope),effectiveRules:Y.rules.map((de)=>Bp(de,ie.get(de.name)??"project"))}}var Vp=[{flag:n.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:n.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:n.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:n.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:n.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:n.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:n.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:n.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"},{flag:n.projectTightenOnly,description:"Ignore project policy settings that weaken the user policy",defaultBehavior:"off"}];function Fs(P){return[...Vp.map((O)=>({name:O.flag.name,value:pe(O.flag,P.env),isSet:ot(O.flag,P.env),legacyName:O.flag.legacyName,legacyValue:O.flag.legacyName?P.env.get(O.flag.legacyName):void 0,legacyIsSet:O.flag.legacyName?P.env.get(O.flag.legacyName)!==void 0:void 0,description:O.description,defaultBehavior:O.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:P.env.get("CC_SAFETY_NET_HOME"),isSet:P.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var Hs={error:0,warning:1,info:2},Jp=["policy","config","audit"];function Wp(P){return P.map((O)=>{if(O==="ownership")return"is not owned by the current user";if(O==="permissions")return"has unsafe permissions";if(O==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Kp=[{derive:(P)=>P.hooks.length>0&&P.hooks.every((O)=>!O.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(P)=>P.hooks.filter((O)=>O.inspectionStatus==="failed").map((O)=>{let D=mn(O.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${D} inspection failed`,detail:`Doctor could not verify the ${D} integration configuration.`,fixHint:`Correct the reported ${D} configuration error, then run \`cc-safety-net doctor\` again.`,integration:O.platform}})},{derive:(P)=>P.userConfig.exists&&!P.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.userConfig.path}]:[]},{derive:(P)=>P.projectConfig.exists&&!P.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.projectConfig.path}]:[]},{derive:(P)=>P.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${P.configState.reason}`,fixHint:"Fix the file named in the reason, or run `cc-safety-net rule update` to vendor a remote source, then rerun doctor."}]:[]},{derive:(P)=>P.v2Leftovers&&P.v2Leftovers.length>0?[{checkId:"config.v2-leftovers",severity:"info",title:"Rulebook lock and cache leftovers detected",detail:`Files an earlier version left behind are no longer read: ${P.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(P)=>P.legacyConfigs&&P.legacyConfigs.length>0?[{checkId:"config.legacy-ignored",severity:"warning",title:"Legacy inline rule configs are ignored",detail:`CC Safety Net no longer loads these files, so their rules enforce nothing: ${P.legacyConfigs.join(", ")}.`,fixHint:"Run `cc-safety-net rule migrate` to convert them (add `--cleanup` to delete each file once it is converted), then rerun doctor."}]:[]},{derive:(P)=>{let O=P.environment.find((D)=>D.name==="CC_SAFETY_NET_AUDIT_SCOPE");return qe(O?.value)==="invalid"?[{checkId:"environment.audit-scope-invalid",severity:"warning",title:"Audit scope value is invalid",detail:"CC_SAFETY_NET_AUDIT_SCOPE is not `all` or `blocked`, so allowed command decisions are not recorded.",fixHint:"Set CC_SAFETY_NET_AUDIT_SCOPE to `all` or `blocked`, then restart the integration."}]:[]}},...Jp.map((P)=>({derive:(O)=>O.posture.directories.filter((D)=>D.kind===P&&D.status==="unsafe").map((D)=>({checkId:`posture.${P}-directory-unsafe`,severity:"error",title:`${P[0]?.toUpperCase()}${P.slice(1)} directory is unsafe`,detail:`The ${P} directory ${Wp(D.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...D.path?{path:D.path}:{}}))})),{derive:(P)=>{let O=[...P.effectiveSafety.weakenedRuleOverrides].sort();return O.length>0?[{checkId:"posture.rule-overrides-weaken-preset",severity:"warning",title:"Rule overrides weaken the selected preset",detail:`Explicit overrides disable rules the resolved preset would enable: ${O.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${O.join(", ")}.`}]:[]}}];function Ms(P){return Kp.flatMap((O,D)=>O.derive(P).map((j,J)=>({finding:j,catalogOrder:D,occurrence:J}))).sort((O,D)=>Hs[O.finding.severity]-Hs[D.finding.severity]||O.catalogOrder-D.catalogOrder||O.occurrence-D.occurrence).map((O)=>O.finding)}function Ln(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var zp=(P)=>Ln()?`\x1B[32m${P}\x1B[0m`:P,Yp=(P)=>Ln()?`\x1B[33m${P}\x1B[0m`:P,Zp=(P)=>Ln()?`\x1B[34m${P}\x1B[0m`:P,Xp=(P)=>Ln()?`\x1B[36m${P}\x1B[0m`:P,Qp=(P)=>Ln()?`\x1B[31m${P}\x1B[0m`:P,ef=(P)=>Ln()?`\x1B[2m${P}\x1B[0m`:P,nf=(P)=>Ln()?`\x1B[1m${P}\x1B[0m`:P,nn={green:zp,yellow:Yp,blue:Zp,cyan:Xp,red:Qp,dim:ef,bold:nf},tf="\x1B[0m",rf=[39,82,198,226,208,51,196,46,201,214,93,154,220,27,49,190,200,33,129,227,45,160,63,118,123,202];function of(P){let O=P;return()=>(O=(O*1664525+1013904223)%4294967296,O/4294967296)}function sf(P){let O=[...rf],D=of(P);for(let j=O.length-1;j>0;j--){let J=Math.floor(D()*(j+1)),Y=O[j];O[j]=O[J],O[J]=Y}return O}function af(P,O=0){if(!Ln())return"";let D=sf(O);return`\x1B[38;5;${D[P%D.length]}m`}function Us(P,O,D=0){if(!Ln())return`"${P}"`;return`${af(O,D)}"${P}"${tf}`}function br(P){return P==="default"?"built-in default":`${P} policy`}var lf=new RegExp("\x1B\\[[0-9;]*m","g"),_o=(P)=>P.replace(lf,"").length;function Kn(P){let O=(P.headers??P.rows[0]??[]).map((re,ie)=>{let de=Math.max(...P.rows.map((fe)=>_o(fe[ie]??"")));return Math.max(_o(re),de)}),D=(re,ie)=>re+" ".repeat(Math.max(0,ie-_o(re))),j=(re,ie)=>ie[0]+O.map((de)=>re.repeat(de+2)).join(ie[1])+ie[2],J=(re)=>`│ ${re.map((ie,de)=>D(ie,O[de]??0)).join(" │ ")} │`,Y=P.headers?[` ${J(P.headers)}`,` ${j("─",["├","┼","┤"])}`]:[];return[` ${j("─",["┌","┬","┐"])}`,...Y,...P.rows.map((re)=>` ${J(re)}`),` ${j("─",["└","┴","┘"])}`].join(`
6
- `)}function Gs(P){let O=[];O.push("Hook Integration"),O.push(cf(P));let D=[],j=[];for(let J of P){let Y=mn(J.platform);if(J.errors&&J.errors.length>0)for(let re of J.errors)if(J.configured)D.push({platform:Y,message:re});else j.push({platform:Y,message:re})}for(let J of D)O.push(` Warning (${J.platform}): ${J.message}`);for(let J of j)O.push(nn.red(` Error (${J.platform}): ${J.message}`));return O.join(`
7
- `)}function cf(P){let O=["Platform","Discovery","Configuration","Inspection"],D=P.map((j)=>{let J=mn(j.platform);if(j.inspectionStatus==="not-inspected"){let de=nn.dim("Not inspected");return[J,de,de,de]}let Y=j.detected?nn.green("Detected"):j.inspectionStatus==="failed"?nn.red("Unknown"):nn.dim("Not detected"),re=j.configured?nn.green("Configured"):j.detected?nn.yellow("Not configured"):j.inspectionStatus==="failed"?nn.red("Unknown"):nn.dim("Not applicable"),ie=j.inspectionStatus==="verified"?nn.green("Verified"):j.inspectionStatus==="failed"?nn.red("Failed"):nn.dim("Not applicable");return[J,Y,re,ie]});return Kn({headers:O,rows:D})}function qs(P){let D=["Guard Engine Verification",` Synthetic self-test: ${P.failed>0?nn.red(`${P.passed}/${P.total} FAIL`):nn.green(`${P.passed}/${P.total} passed`)}`],j=P.results.filter((J)=>!J.passed);if(j.length>0){D.push(""),D.push(nn.red(" Failures:"));for(let J of j)D.push(nn.red(` • ${J.description}`)),D.push(nn.red(` expected ${J.expected}, got ${J.actual}`))}return D.join(`
8
- `)}function df(P){if(P.length===0)return" (no custom rules)";let O=["Source","Name","Command","Block Args"],D=P.map((j)=>[j.source,j.name,j.subcommand?`${j.command} ${j.subcommand}`:j.command,j.blockArgs.join(", ")]);return Kn({headers:O,rows:D})}function Bs(P){let O=[];if(O.push("Configuration"),O.push(uf(P.userConfig,P.projectConfig)),O.push(""),P.effectiveRules.length>0)O.push(` Effective rules (${P.effectiveRules.length} total):`),O.push(df(P.effectiveRules));else O.push(" Effective rules: (none - using built-in rules only)");return O.join(`
9
- `)}function uf(P,O){let D=["Scope","Status"],j=(Y)=>{if(!Y.exists)return nn.dim("N/A");if(!Y.valid)return nn.red(`Invalid (${Y.errors?.[0]??"unknown error"})`);return nn.green("Configured")},J=[["User",j(P)],["Project",j(O)]];return Kn({headers:D,rows:J})}function Vs(P){let O=[];return O.push("Environment"),O.push(pf(P)),O.join(`
10
- `)}function Js(P){let O=P.effectiveSafety.policyScopes,D=["Effective Safety",` Selected preset: ${P.effectiveSafety.selectedPreset}${O?` (${br(O.levelScope)})`:""}`,` Effective: ${P.effectiveSafety.level}`],j=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[J,Y]of j){let re=P.effectiveSafety.capabilities[J],ie=re.enabled?nn.green("ON"):nn.dim("OFF"),de=re.sources.length>0?` (${re.sources.join(", ")})`:"";D.push(` ${Y}: ${ie} via ${re.source}${de}`)}if(O&&O.weakenings.length>0){D.push(` Project policy deltas${O.weakeningsIgnored?" (ignored)":""}:`);for(let J of O.weakenings)D.push(` ${J}`)}D.push(` Stored rule customizations: ${P.effectiveSafety.ruleCounts.stored}`),D.push(` Effective rule customizations: ${P.effectiveSafety.ruleCounts.effective}`);for(let[J,Y]of Object.entries(P.effectiveSafety.ruleOverrides))D.push(` ${J}: ${Y}`);return D.join(`
11
- `)}function Ws(P){let O=["Findings"];if(P.length===0)return O.push(" No findings from inspected doctor facts."),O.join(`
12
- `);for(let D of P){let j=`[${D.severity.toUpperCase()}] ${D.checkId}: ${yn(D.title)}`,J=D.severity==="error"?nn.red:D.severity==="warning"?nn.yellow:nn.blue;if(O.push(` ${J(j)}`),O.push(` ${yn(D.detail)}`),D.path)O.push(` Path: ${yn(D.path)}`);if(D.fixHint)O.push(` Fix: ${yn(D.fixHint)}`)}return O.join(`
13
- `)}function pf(P){let O=["Variable","Status","Legacy"],D=P.map((j)=>{let J=j.isSet?nn.green("✓"):nn.dim("✗"),Y=j.legacyName&&j.legacyIsSet?`${j.legacyName} ${nn.green("✓")}`:j.legacyName??"";return[j.name,J,Y]});return Kn({headers:O,rows:D})}function Ks(P){let O=[];if(P.totalBlocked===0)O.push("Recent Activity"),O.push(" No blocked commands in the last 7 days"),O.push(" Tip: This is normal for new installations");else O.push(`Recent Activity · last 7 days (${P.totalBlocked} blocked / ${P.sessionCount} sessions)`),O.push(ff(P.recentEntries));if(P.unreadable>0)O.push(` Warning: ${P.unreadable} audit log ${P.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return O.join(`
14
- `)}function ff(P){let O=["Time","Command"],D=P.map((j)=>{let J=yn(j.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),Y=J.length>40?`${J.slice(0,37)}...`:J;return[j.relativeTime,Y]});return Kn({headers:O,rows:D})}function zs(P){let O=[];if(O.push("Update Check"),P.latestVersion===null&&!P.error)return O.push(wr([["Status",nn.dim("Skipped")],["Installed",P.currentVersion]])),O.join(`
15
- `);if(P.error)return O.push(wr([["Status",`${nn.yellow("⚠")} Error`],["Installed",P.currentVersion],["Error",nn.dim(P.error)]])),O.join(`
16
- `);if(P.updateAvailable)return O.push(wr([["Status",`${nn.yellow("⚠")} Update Available`],["Current",P.currentVersion],["Latest",nn.green(P.latestVersion??"")]])),O.push(""),O.push(" Run: bunx cc-safety-net@latest doctor"),O.push(" Or: npx cc-safety-net@latest doctor"),O.join(`
17
- `);return O.push(wr([["Status",`${nn.green("✓")} Up to date`],["Version",P.currentVersion]])),O.join(`
18
- `)}function wr(P){return Kn({rows:P})}function Ys(P){let O=[];return O.push("System Info"),O.push(mf(P)),O.join(`
19
- `)}function mf(P){let O=["Component","Version"],D=(Y)=>{if(Y===null)return nn.dim("not found");return Y},J=[{label:"cc-safety-net",value:P.version},...fr.map((Y)=>({label:mn(Y),value:P.versions[Y]??null})),{label:"Node.js",value:P.nodeVersion},{label:"npm",value:P.npmVersion},{label:"Bun",value:P.bunVersion},{label:"Platform",value:P.platform}].map((Y)=>[Y.label,D(Y.value)]);return Kn({headers:O,rows:J})}function Zs(P){if(P.findings.length===0)return nn.green(`
1
+ import{a,s,Pe,Be,R,nt,ze,c,n,qe,T,v,pe,ot,f,Ke,u,o,S,i,se,r,g,me,H,st,at,d,ge,he,ct,N,Z,ae,w,lt,_,h,ke,W,l,L,X,Je,Ye,M,C,I,ye,be,Ae,ut,m,e,Oe,Re,Ze,Xe,ce,Te,le,De,Q,B,Ne,xe,z,Qe,q,ee,te,ue,et,tt,E,F,Le,Fe,$e,k,je,_e,Ue,y,t,ne,ve,b,x,A,dt,Ge,He,p,V}from"./chunks/index-mqmy0cce.js";import{oe,K,We,U,G}from"./chunks/index-heqg9274.js";var dp=["-h","--help"];function yn(P,O){let D=Object.entries(P.booleans??{}),j=Object.entries(P.values??{}),J=Object.entries(P.lists??{}),Y=Object.fromEntries(D.map(([Se])=>[Se,!1])),re={},ie=Object.fromEntries(J.map(([Se])=>[Se,[]])),de=[],fe=[],we=!1,Ce=-1;for(let[Se,Ie]of O.entries()){if(Se<=Ce)continue;if(Ie==="--"){de.push(...O.slice(Se+1));break}if(dp.includes(Ie)){we=!0;continue}let Ee=D.find(([,en])=>en.includes(Ie));if(Ee){Y[Ee[0]]=!0;continue}let Ve=j.find(([,en])=>en.includes(Ie));if(Ve){let en=O[Se+1];if(en===void 0||en.startsWith("-")){fe.push(`${Ie} requires a value`);continue}re[Ve[0]]=en,Ce=Se+1;continue}let Me=J.find(([,en])=>en.includes(Ie));if(Me){let en=O.slice(Se+1),on=en.findIndex((an)=>an.startsWith("-")),sn=en.slice(0,on===-1?en.length:on);if(sn.length===0){fe.push(`${Ie} requires at least one value`);continue}ie[Me[0]]=[...ie[Me[0]]??[],...sn],Ce=Se+sn.length;continue}if(Ie.startsWith("-")){fe.push(`Unknown option for ${P.label}: ${Ie}`);continue}if(P.positionals==="tail"){de.push(...O.slice(Se));break}de.push(Ie)}if(P.positionals!=="list"&&P.positionals!=="tail")fe.push(...de.map((Se)=>`Unexpected argument for ${P.label}: ${Se}`));return{flags:Y,values:re,lists:ie,positionals:de,help:we,errors:fe}}function Dn(P){for(let O of P)console.error(O);return P.length>0}import{readdirSync as hp,statSync as Es,unlinkSync as vp}from"node:fs";import{basename as _s,dirname as bp,isAbsolute as wp,join as kp,relative as xp,resolve as Cp,sep as Sp}from"node:path";var Ss=(P)=>{let O=Date.now()-new Date(P).getTime();if(!Number.isFinite(O))return"";let D=Math.floor(O/60000),j=Math.floor(D/60),J=Math.floor(j/24);if(J>0)return`${J}d ago`;if(j>0)return`${j}h ago`;if(D>0)return`${D}m ago`;return"just now"},Eo=(P)=>{let O=(P??"").trim().split(/\s+/).filter((J)=>J&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(J)),D=O[0]?.split("/").pop();if(!D)return null;let j=O[1];return j&&/^[a-z][a-z0-9-]*$/.test(j)?`${D} ${j}`:D};function Ps(P){let O=(J)=>`${J.sessionId}
2
+ ${Eo(J.segment||J.command)}`,D=P.filter((J)=>J.decision!=="allow"),j=D.filter((J)=>J.sessionId).reduce((J,Y)=>J.set(O(Y),(J.get(O(Y))??0)+1),new Map);return new Set(D.filter((J)=>J.failureStage||(j.get(O(J))??0)>=2))}import{existsSync as up,readdirSync as pp,readFileSync as fp}from"node:fs";import{join as mp}from"node:path";function Kn(P,O){try{return pp(P,{withFileTypes:!0,encoding:"utf8"}).flatMap((D)=>{let j=mp(P,D.name);if(D.isDirectory())return Kn(j,O);if(D.name.endsWith(".jsonl"))return[j];return[]})}catch{if(O&&up(P))O.count++;return[]}}var gp=["segment","reason","sessionId","decision","agent","ruleId","failureStage"];function yp(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let O=P;if(typeof O.ts!=="string"||typeof O.command!=="string")return!1;return gp.every((D)=>O[D]===void 0||typeof O[D]==="string")}function kt(P,O){try{return fp(P,"utf-8").split(`
3
+ `).filter(Boolean).flatMap((D)=>{try{let j=JSON.parse(D);if(!yp(j)){if(O)O.count++;return[]}return[j]}catch{if(O)O.count++;return[]}})}catch{if(O)O.count++;return[]}}function hn(P){return Array.from(P,(O)=>{let D=O.charCodeAt(0);if(D<=31||D>=127&&D<=159)return`\\x${D.toString(16).padStart(2,"0")}`;return O}).join("")}function Pp(P,O){let D=oe(P),j=yn({label:"logs",booleans:{all:["--all"],suspect:["--suspect"],json:["--json"],pruneLegacy:["--prune-legacy"],dryRun:["--dry-run"]},values:{id:["--id"],limit:["--limit"],since:["--since"],agent:["--agent"],rule:["--rule"],session:["--session"],project:["--project"]}},O);if(Dn(j.errors))return null;if(j.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(j.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let J=j.values.limit===void 0?20:Rs(j.values.limit);if(J===null)return console.error("--limit must be a positive number"),null;let Y=j.values.since===void 0?Math.min(30,D):Rs(j.values.since);if(Y===null||Y>D)return console.error(`--since must be a positive number of days no greater than ${D}`),null;let re={limit:J,limitExplicit:j.values.limit!==void 0,since:Y,sinceExplicit:j.values.since!==void 0,all:j.flags.all,json:j.flags.json,suspect:j.flags.suspect,pruneLegacy:j.flags.pruneLegacy,dryRun:j.flags.dryRun,id:j.values.id,agent:j.values.agent,rule:j.values.rule,session:j.values.session,project:j.values.project===void 0?void 0:Cp(j.values.project)};if(re.id&&(re.agent!==void 0||re.rule!==void 0||re.session!==void 0||re.project!==void 0||re.suspect||re.sinceExplicit||re.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(re.pruneLegacy&&(re.id!==void 0||re.agent!==void 0||re.rule!==void 0||re.session!==void 0||re.project!==void 0||re.suspect||re.all||re.sinceExplicit||re.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(re.dryRun&&!re.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return re}async function As(P,O,D={}){let j=Pp(P,O);if(!j)return 1;let J=D.logsDir??U(P);if(j.pruneLegacy)return Rp(J,j.json,j.dryRun);if(!J)return console.log(j.json?"[]":j.id?`No retained audit log entry found for id ${hn(j.id)}.`:"No audit log entries found."),0;K(P,J);let Y={count:0},re=Kn(J,Y).flatMap((Ce)=>kt(Ce,Y).map((Se)=>({entry:Se,file:Ce})));if(Y.count>0)console.error(`warning: ${Y.count} audit log ${Y.count===1?"source":"sources"} could not be read; these results are incomplete`);if(j.id)return Tp(re,j,D.timeZone);let ie=Date.now()-j.since*24*60*60*1000,de=re.filter((Ce)=>Ip(Ce,j,J,ie)),fe=j.suspect?Ps(de.map((Ce)=>Ce.entry)):null,we=(fe?de.filter((Ce)=>fe.has(Ce.entry)):de).sort((Ce,Se)=>Date.parse(Se.entry.ts)-Date.parse(Ce.entry.ts)).slice(0,j.limit);if(j.json)return console.log(JSON.stringify(we.map((Ce)=>Ce.entry),null,2)),0;if(we.length===0)return console.log("No audit log entries found."),0;for(let Ce of we)console.log(Dp(Ce.entry,D.timeZone));return 0}function Rp(P,O,D){let j=P?_p(P).map((ie)=>kp(P,ie)):[];if(D)return Ep(j,O);let J=[],Y=0,re=0;for(let ie of j){let de=Es(ie,{throwIfNoEntry:!1})?.size??0,fe=Ap(ie);if(fe){J.push(`${_s(ie)}: ${fe}`);continue}Y++,re+=de}if(O)return console.log(JSON.stringify({removedFiles:Y,removedBytes:re,failedFiles:J.length})),J.length===0?0:1;console.log(Y===0&&J.length===0?"No legacy audit log files found.":`Removed ${Y} legacy audit log ${Y===1?"file":"files"} (${Ts(re)}).`);for(let ie of J)console.error(`Could not remove ${hn(ie)}`);if(console.log("Nested v2 audit logs were not changed."),Y>0)console.log("This deletion cannot be undone.");return J.length===0?0:1}function Ep(P,O){let D=P.reduce((j,J)=>j+(Es(J,{throwIfNoEntry:!1})?.size??0),0);if(O)return console.log(JSON.stringify({dryRun:!0,files:P.length,bytes:D})),0;if(console.log(P.length===0?"No legacy audit log files found.":`Would remove ${P.length} legacy audit log ${P.length===1?"file":"files"} (${Ts(D)}).`),console.log("Nested v2 audit logs are not included."),P.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function _p(P){try{return hp(P,{withFileTypes:!0}).filter((O)=>O.isFile()&&O.name.endsWith(".jsonl")).map((O)=>O.name)}catch{return[]}}function Ap(P){try{return vp(P),null}catch(O){return O instanceof Error?O.message:String(O)}}function Ts(P){let O=["B","KiB","MiB","GiB"],D=Math.min(Math.floor(Math.log2(Math.max(P,1))/10),O.length-1);return`${Math.round(P/1024**D*10)/10} ${O[D]}`}function Tp(P,O,D){let j=P.filter((Y)=>Y.entry.id===O.id);if(j.length>1)return console.error(`Multiple audit log entries found for id ${hn(O.id??"")}.`),1;if(O.json)return console.log(JSON.stringify(j.map((Y)=>Y.entry),null,2)),0;let J=j[0];if(!J)return console.log(`No retained audit log entry found for id ${hn(O.id??"")}.`),0;return console.log(Lp(J.entry,D)),0}function Ip(P,O,D,j){if(!O.all&&P.entry.decision==="allow")return!1;if(Date.parse(P.entry.ts)<j)return!1;if(O.agent!==void 0&&P.entry.agent!==O.agent)return!1;if(O.rule!==void 0&&P.entry.ruleId!==O.rule)return!1;if(O.session!==void 0&&!$p(P,D,O.session))return!1;if(O.project!==void 0&&!Op(P.entry.cwd,O.project))return!1;return!0}function $p(P,O,D){if(P.entry.sessionId===D)return!0;return bp(P.file)===O&&_s(P.file,".jsonl")===D}function Op(P,O){if(!P)return!1;let D=xp(O,P);return D!==".."&&!D.startsWith(`..${Sp}`)&&!wp(D)}function Dp(P,O){let D=hn(P.id??"-"),j=hn(P.decision??"deny"),J=P.cwd?` [${hn(P.cwd)}]`:"",Y=P.segment||P.command,re=Y===P.command?"":"↳ ",ie=Y.length>50?`${Y.slice(0,50)}…`:Y;return`${D.padEnd(16)} ${hn(Is(P.ts,O))} ${j.padEnd(5)} ${hn(P.agent??"-").padEnd(15)} ${hn(P.ruleId??"-").padEnd(20)} ${re}${hn(ie)}${J}`}function Lp(P,O){let D=(J)=>hn(J===void 0||J===null||J===""?"-":J),j=P.shape?`${P.agent??"-"} (shape: ${P.shape})`:P.agent??"-";return[`id: ${D(P.id)}`,`ts: ${D(Is(P.ts,O))}`,`decision: ${D(P.decision)}`,`agent: ${D(j)}`,`level: ${D(P.level)}`,`tool: ${D(P.toolName)}`,`rule: ${D(P.ruleId)}`,`intent: ${D(P.intent)}`,`stage: ${D(P.failureStage)}`,`error: ${D(P.errorCode)}`,`session: ${D(P.sessionId)}`,`cwd: ${D(P.cwd)}`,`version: ${D(P.v)}`,`truncated: ${D(P.truncated===!0?"yes":void 0)}`,`reason: ${D(P.reason)}`,`command: ${D(P.command)}`,`segment: ${D(P.segment)}`].join(`
4
+ `)}function Is(P,O){let D=new Date(P);if(Number.isNaN(D.getTime()))return P;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:O}).format(D)}function Rs(P){let O=Number(P);return Number.isFinite(O)&&O>0?O:null}var $s={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 Os={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 Ds={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 _o=["npx","--offline","--no-install","@deepseek-ai/dsh","--version"],Ls=["cursor-agent","--version"],mr=[{id:"antigravity-cli",displayName:"Antigravity CLI",doctorOrder:3,runtime:{order:1,flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:2,flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",doctorOrder:1,runtime:{order:2,displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{order:3,flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",doctorOrder:4,runtime:{order:3,flags:["-cx","--codex"],description:"Run as a Codex PreToolUse hook",legacyTopLevelFlags:[]},install:{order:4,flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",doctorOrder:10,runtime:{order:8,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:10,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:9,runtime:{order:7,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:9,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"grok-build",displayName:"Grok Build",doctorOrder:11,runtime:{order:9,flags:["-gb","--grok-build"],description:"Run as Grok Build PreToolUse hook",legacyTopLevelFlags:[]},install:{order:11,flag:"--grok-build",artifactKind:"hook config",probeCommand:["grok","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:12,runtime:{order:10,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:12,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:13,runtime:{order:11,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:13,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:14,install:{order:14,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:15,install:{order:15,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:16,install:{order:16,flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",doctorOrder:5,runtime:{order:4,flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{order:5,flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"deepseek-harness",displayName:"DeepSeek Harness",doctorOrder:6,install:{order:6,flag:"--deepseek-harness",artifactKind:"package",probeCommand:_o}},{id:"devin",displayName:"Devin CLI",doctorOrder:7,runtime:{order:5,flags:["-dv","--devin"],description:"Run as Devin CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:7,flag:"--devin",artifactKind:"hook config",probeCommand:["devin","--version"]}},{id:"droid",displayName:"Factory Droid",doctorOrder:8,runtime:{order:6,flags:["-fd","--droid"],description:"Run as Factory Droid PreToolUse hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--droid",artifactKind:"hook config",probeCommand:["droid","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],gr=mr.slice().sort((P,O)=>P.doctorOrder-O.doctorOrder).map((P)=>P.id),Ht=mr.filter((P)=>("runtime"in P)).slice().sort((P,O)=>P.runtime.order-O.runtime.order).map((P)=>({id:P.id,displayName:"displayName"in P.runtime?P.runtime.displayName:P.displayName,flags:P.runtime.flags,legacyFlags:"legacyFlags"in P.runtime?P.runtime.legacyFlags:[],description:P.runtime.description,legacyTopLevelFlags:P.runtime.legacyTopLevelFlags})),En=mr.slice().sort((P,O)=>P.install.order-O.install.order).map((P)=>({id:P.id,...P.install})).map(({order:P,...O})=>O),Np=Object.fromEntries(mr.map((P)=>[P.id,P.displayName]));function mn(P){return Np[P]}var jp=Ht.map((P)=>({flags:P.flags.join(", "),description:P.description})),Fp=Ht.flatMap((P)=>P.flags.map((O)=>`cc-safety-net hook ${O}`)),Ns={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...jp,{flags:"-h, --help",description:"Show this help"}],examples:Fp};var js={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...En.map((P)=>({flags:P.flag,description:`Install ${mn(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...En.map((P)=>`cc-safety-net install ${P.flag}`)]},Fs={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...En.map((P)=>({flags:P.flag,description:`Uninstall ${mn(P.id)} ${P.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...En.map((P)=>`cc-safety-net uninstall ${P.flag}`)]},Hs={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 Ms={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 yr={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 Ao=[{flags:"--ref",argument:"<ref>",description:"Use a branch, tag, or commit"},{flags:"--only",argument:"<rulebook...>",description:"Add only these repository rulebooks"},{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"-h, --help",description:"Show this help"}],To=["cc-safety-net rule add project-rules","cc-safety-net rule add acme/safety-rules","cc-safety-net rule add acme/safety-rules --only aws gcloud","cc-safety-net rule add acme/safety-rules --ref v2 --only aws","cc-safety-net rule add --only terraform aws"],xt={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add [source] [--ref <ref>] [--only <rulebook...>]",description:"Add rulebook sources and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Re-fetch and vendor remote rulebooks"},{usage:"sync",description:"Deprecated: migrate lock and cache leftovers"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},...Ao.slice(0,2),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net rule init","cc-safety-net rule init --example","cc-safety-net rule wrapper add rtk",...To,"cc-safety-net rule update","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var Us={name:"status",description:"Show what the runtime is enforcing right now",usage:"status",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net status"]};var Gs={name:"statusline",description:"Print status line with mode indicators for shell integration",usage:"statusline --claude-code",options:[{flags:"-cc, --claude-code",description:"Print status line for Claude Code"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net statusline -cc","cc-safety-net statusline --claude-code"]};var hr=[Us,$s,Ms,Os,xt,yr,js,Hs,Fs,Ns,Ds,Gs];function Hp(P){return P.aliases??[]}function vr(P){let O=P.toLowerCase();return hr.find((D)=>D.name.toLowerCase()===O||Hp(D).some((j)=>j.toLowerCase()===O))}import{existsSync as Cy}from"node:fs";import{basename as Mp}from"node:path";function br(P,O=7,D=U(P)){let j=Date.now()-O*24*60*60*1000,J=[],Y=new Set,re=0,ie,de,fe,we;if(D)K(P,D);let Ce={count:0},Se=D?Kn(D,Ce):[];for(let Ee of Se)for(let Ve of kt(Ee,Ce)){if(Ve.decision==="allow")continue;let Me=new Date(Ve.ts).getTime();if(Me>=j){if(re++,Y.add(Ve.sessionId??Mp(Ee,".jsonl")),de===void 0||Me<=de)ie=Ve.ts,de=Me;if(we===void 0||Me>we)fe=Ve.ts,we=Me;Up(J,Ve,Me)}}let Ie=J.map((Ee)=>({timestamp:Ee.ts,command:Ee.command,reason:Ee.reason,relativeTime:Ss(new Date(Ee.ts))}));return{totalBlocked:re,sessionCount:Y.size,recentEntries:Ie,oldestEntry:ie,newestEntry:fe,unreadable:Ce.count}}function Up(P,O,D){let j=P.findIndex((J)=>D>new Date(J.ts).getTime());if(j===-1){if(P.length<3)P.push(O);return}if(P.splice(j,0,O),P.length>3)P.pop()}import{dirname as Qp}from"node:path";import{dirname as Gp,join as qp,resolve as Bp}from"node:path";var Vp="config.json";function wn(P,O,D,j){g(Jp(P),`${JSON.stringify(O,null,2)}
5
+ `,D,j)}function Jp(P){return typeof P==="string"?se(P):P}function $o(P){return{errors:ce(Wp(P),": "," "),ruleNames:new Set(De(P).map((O)=>O.toLowerCase()))}}var Kp="must match pattern (letters, numbers, hyphens, underscores; max 64 chars)",qs="must match pattern (letters, numbers, hyphens, underscores)";function Wp(P){if(!Bs(P))return[e([],"Config must be an object")];return[...P.version===1?[]:[e(["version"],"must be 1")],...zp(P.rules)]}function zp(P){if(P===void 0)return[];if(!Array.isArray(P))return[e(["rules"],"must be an array")];return[...P.flatMap((O,D)=>Bs(O)?Yp(O,["rules",D]):[e(["rules",D],"must be an object")]),...Oe(P)]}function Yp(P,O){return[...Io(P.name,[...O,"name"],"required string",d,Kp),...Io(P.command,[...O,"command"],"required string",C,qs),...P.subcommand===void 0?[]:Io(P.subcommand,[...O,"subcommand"],"must be a string if provided",C,qs),...Zp(P.block_args,[...O,"block_args"]),...Xp(P.reason,[...O,"reason"]),...P.intent===void 0||Te(P.intent)?[]:[e([...O,"intent"],Re)]]}function Io(P,O,D,j,J){if(typeof P!=="string")return[e(O,D)];return j.test(P)?[]:[e(O,J)]}function Zp(P,O){if(!Array.isArray(P))return[e(O,"required array")];if(P.length===0)return[e(O,"must have at least one element")];return P.flatMap((D,j)=>{if(typeof D!=="string")return[e([...O,j],"must be a string")];return D===""?[e([...O,j],"must not be empty")]:[]})}function Xp(P,O){if(typeof P!=="string")return[e(O,"required string")];if(P==="")return[e(O,"must not be empty")];return P.length>I?[e(O,`must be at most ${I} characters`)]:[]}function Bs(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function Oo(P){let O=Vs(P);if(!O.ok)return O.result;return $o(O.parsed)}function Vs(P){let O=[],D=new Set;try{let j=typeof P==="string"?se(P):P,J=r(j);if(J===null)return O.push(`File not found: ${j.path}`),{ok:!1,result:{errors:O,ruleNames:D}};if(!J.trim())return O.push("Config file is empty"),{ok:!1,result:{errors:O,ruleNames:D}};return{ok:!0,parsed:JSON.parse(J)}}catch(j){if(j instanceof o)return O.push(j.message),{ok:!1,result:{errors:O,ruleNames:D}};let J=j instanceof Error?j.message:String(j);return O.push(j instanceof SyntaxError?"Invalid JSON":J),{ok:!1,result:{errors:O,ruleNames:D}}}}function wr(P){return Bp(P,".safety-net.json")}function Un(P){let O=Vs(P);if(!O.ok)return O.result;let D=Ze(O.parsed);return{errors:D.errors,ruleNames:D.sources}}function Ct(P,O={}){return qp(Gp(ke(P,O)),Vp)}function Js(P,O,D){let j;try{if(r(O)===null)return{path:P,exists:!1,valid:!1,ruleCount:0};j=Un(O),j.errors.push(...B(P,D))}catch(J){if(!(J instanceof o))throw J;j={errors:[J.message],ruleNames:new Set}}return{path:P,exists:!0,valid:j.errors.length===0,ruleCount:j.ruleNames.size,...j.errors.length>0?{errors:j.errors}:{}}}function ef(P,O){return{source:O,name:P.name,command:P.command,subcommand:P.subcommand,blockArgs:[...P.block_args],reason:P.reason}}function Ks(P,O){let D=W(P),j=_(O),J=Qp(D),Y=Q(P,{cwd:O,userConfigPath:D,projectConfigPath:j,userConfigDir:J}),re=X(P,{cwd:O,userConfigPath:D,projectConfigPath:j,userConfigDir:J}),ie=new Map(Y.rulebooks.flatMap((de)=>de.rules.map((fe)=>[fe,de.source])));return{userConfig:Js(D,re.userConfigTarget,re.userScope),projectConfig:Js(j,re.projectConfigTarget,re.projectScope),effectiveRules:Y.rules.map((de)=>ef(de,ie.get(de.name)??"project"))}}var nf=[{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 Ws(P){return[...nf.map((O)=>({name:O.flag.name,value:pe(O.flag,P.env),isSet:ot(O.flag,P.env),legacyName:O.flag.legacyName,legacyValue:O.flag.legacyName?P.env.get(O.flag.legacyName):void 0,legacyIsSet:O.flag.legacyName?P.env.get(O.flag.legacyName)!==void 0:void 0,description:O.description,defaultBehavior:O.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:P.env.get("CC_SAFETY_NET_HOME"),isSet:P.env.get("CC_SAFETY_NET_HOME")!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var zs={error:0,warning:1,info:2},tf=["policy","config","audit"];function rf(P){return P.map((O)=>{if(O==="ownership")return"is not owned by the current user";if(O==="permissions")return"has unsafe permissions";if(O==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var of=[{derive:(P)=>P.hooks.length>0&&P.hooks.every((O)=>!O.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(P)=>P.hooks.filter((O)=>O.inspectionStatus==="failed").map((O)=>{let D=mn(O.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${D} inspection failed`,detail:`Doctor could not verify the ${D} integration configuration.`,fixHint:`Correct the reported ${D} configuration error, then run \`cc-safety-net doctor\` again.`,integration:O.platform}})},{derive:(P)=>P.userConfig.exists&&!P.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.userConfig.path}]:[]},{derive:(P)=>P.projectConfig.exists&&!P.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:P.projectConfig.path}]:[]},{derive:(P)=>P.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${P.configState.reason}`,fixHint:"Fix the file named in the reason, or run `cc-safety-net rule update` to vendor a remote source, then rerun doctor."}]:[]},{derive:(P)=>P.v2Leftovers&&P.v2Leftovers.length>0?[{checkId:"config.v2-leftovers",severity:"info",title:"Rulebook lock and cache leftovers detected",detail:`Files an earlier version left behind are no longer read: ${P.v2Leftovers.join(", ")}.`,fixHint:"Run `cc-safety-net rule sync` (add `--global` for user scope) to migrate them, then rerun doctor."}]:[]},{derive:(P)=>P.legacyConfigs&&P.legacyConfigs.length>0?[{checkId:"config.legacy-ignored",severity:"warning",title:"Legacy inline rule configs are ignored",detail:`CC Safety Net no longer loads these files, so their rules enforce nothing: ${P.legacyConfigs.join(", ")}.`,fixHint:"Run `cc-safety-net rule migrate` to convert them (add `--cleanup` to delete each file once it is converted), then rerun doctor."}]:[]},{derive:(P)=>{let O=P.environment.find((D)=>D.name==="CC_SAFETY_NET_AUDIT_SCOPE");return qe(O?.value)==="invalid"?[{checkId:"environment.audit-scope-invalid",severity:"warning",title:"Audit scope value is invalid",detail:"CC_SAFETY_NET_AUDIT_SCOPE is not `all` or `blocked`, so allowed command decisions are not recorded.",fixHint:"Set CC_SAFETY_NET_AUDIT_SCOPE to `all` or `blocked`, then restart the integration."}]:[]}},...tf.map((P)=>({derive:(O)=>O.posture.directories.filter((D)=>D.kind===P&&D.status==="unsafe").map((D)=>({checkId:`posture.${P}-directory-unsafe`,severity:"error",title:`${P[0]?.toUpperCase()}${P.slice(1)} directory is unsafe`,detail:`The ${P} directory ${rf(D.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...D.path?{path:D.path}:{}}))})),{derive:(P)=>{let O=[...P.effectiveSafety.weakenedRuleOverrides].sort();return O.length>0?[{checkId:"posture.rule-overrides-weaken-preset",severity:"warning",title:"Rule overrides weaken the selected preset",detail:`Explicit overrides disable rules the resolved preset would enable: ${O.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${O.join(", ")}.`}]:[]}}];function Ys(P){return of.flatMap((O,D)=>O.derive(P).map((j,J)=>({finding:j,catalogOrder:D,occurrence:J}))).sort((O,D)=>zs[O.finding.severity]-zs[D.finding.severity]||O.catalogOrder-D.catalogOrder||O.occurrence-D.occurrence).map((O)=>O.finding)}function Ln(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var sf=(P)=>Ln()?`\x1B[32m${P}\x1B[0m`:P,af=(P)=>Ln()?`\x1B[33m${P}\x1B[0m`:P,lf=(P)=>Ln()?`\x1B[34m${P}\x1B[0m`:P,cf=(P)=>Ln()?`\x1B[36m${P}\x1B[0m`:P,df=(P)=>Ln()?`\x1B[31m${P}\x1B[0m`:P,uf=(P)=>Ln()?`\x1B[2m${P}\x1B[0m`:P,pf=(P)=>Ln()?`\x1B[1m${P}\x1B[0m`:P,nn={green:sf,yellow:af,blue:lf,cyan:cf,red:df,dim:uf,bold:pf},ff="\x1B[0m",mf=[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 gf(P){let O=P;return()=>(O=(O*1664525+1013904223)%4294967296,O/4294967296)}function yf(P){let O=[...mf],D=gf(P);for(let j=O.length-1;j>0;j--){let J=Math.floor(D()*(j+1)),Y=O[j];O[j]=O[J],O[J]=Y}return O}function hf(P,O=0){if(!Ln())return"";let D=yf(O);return`\x1B[38;5;${D[P%D.length]}m`}function Zs(P,O,D=0){if(!Ln())return`"${P}"`;return`${hf(O,D)}"${P}"${ff}`}function kr(P){return P==="default"?"built-in default":`${P} policy`}var vf=new RegExp("\x1B\\[[0-9;]*m","g"),Do=(P)=>P.replace(vf,"").length;function Wn(P){let O=(P.headers??P.rows[0]??[]).map((re,ie)=>{let de=Math.max(...P.rows.map((fe)=>Do(fe[ie]??"")));return Math.max(Do(re),de)}),D=(re,ie)=>re+" ".repeat(Math.max(0,ie-Do(re))),j=(re,ie)=>ie[0]+O.map((de)=>re.repeat(de+2)).join(ie[1])+ie[2],J=(re)=>`│ ${re.map((ie,de)=>D(ie,O[de]??0)).join(" │ ")} │`,Y=P.headers?[` ${J(P.headers)}`,` ${j("─",["├","┼","┤"])}`]:[];return[` ${j("─",["┌","┬","┐"])}`,...Y,...P.rows.map((re)=>` ${J(re)}`),` ${j("─",["└","┴","┘"])}`].join(`
6
+ `)}function Xs(P){let O=[];O.push("Hook Integration"),O.push(bf(P));let D=[],j=[];for(let J of P){let Y=mn(J.platform);if(J.errors&&J.errors.length>0)for(let re of J.errors)if(J.configured)D.push({platform:Y,message:re});else j.push({platform:Y,message:re})}for(let J of D)O.push(` Warning (${J.platform}): ${J.message}`);for(let J of j)O.push(nn.red(` Error (${J.platform}): ${J.message}`));return O.join(`
7
+ `)}function bf(P){let O=["Platform","Discovery","Configuration","Inspection"],D=P.map((j)=>{let J=mn(j.platform);if(j.inspectionStatus==="not-inspected"){let de=nn.dim("Not inspected");return[J,de,de,de]}let Y=j.detected?nn.green("Detected"):j.inspectionStatus==="failed"?nn.red("Unknown"):nn.dim("Not detected"),re=j.configured?nn.green("Configured"):j.detected?nn.yellow("Not configured"):j.inspectionStatus==="failed"?nn.red("Unknown"):nn.dim("Not applicable"),ie=j.inspectionStatus==="verified"?nn.green("Verified"):j.inspectionStatus==="failed"?nn.red("Failed"):nn.dim("Not applicable");return[J,Y,re,ie]});return Wn({headers:O,rows:D})}function Qs(P){let D=["Guard Engine Verification",` Synthetic self-test: ${P.failed>0?nn.red(`${P.passed}/${P.total} FAIL`):nn.green(`${P.passed}/${P.total} passed`)}`],j=P.results.filter((J)=>!J.passed);if(j.length>0){D.push(""),D.push(nn.red(" Failures:"));for(let J of j)D.push(nn.red(` • ${J.description}`)),D.push(nn.red(` expected ${J.expected}, got ${J.actual}`))}return D.join(`
8
+ `)}function wf(P){if(P.length===0)return" (no custom rules)";let O=["Source","Name","Command","Block Args"],D=P.map((j)=>[j.source,j.name,j.subcommand?`${j.command} ${j.subcommand}`:j.command,j.blockArgs.join(", ")]);return Wn({headers:O,rows:D})}function ea(P){let O=[];if(O.push("Configuration"),O.push(kf(P.userConfig,P.projectConfig)),O.push(""),P.effectiveRules.length>0)O.push(` Effective rules (${P.effectiveRules.length} total):`),O.push(wf(P.effectiveRules));else O.push(" Effective rules: (none - using built-in rules only)");return O.join(`
9
+ `)}function kf(P,O){let D=["Scope","Status"],j=(Y)=>{if(!Y.exists)return nn.dim("N/A");if(!Y.valid)return nn.red(`Invalid (${Y.errors?.[0]??"unknown error"})`);return nn.green("Configured")},J=[["User",j(P)],["Project",j(O)]];return Wn({headers:D,rows:J})}function na(P){let O=[];return O.push("Environment"),O.push(xf(P)),O.join(`
10
+ `)}function ta(P){let O=P.effectiveSafety.policyScopes,D=["Effective Safety",` Selected preset: ${P.effectiveSafety.selectedPreset}${O?` (${kr(O.levelScope)})`:""}`,` Effective: ${P.effectiveSafety.level}`],j=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[J,Y]of j){let re=P.effectiveSafety.capabilities[J],ie=re.enabled?nn.green("ON"):nn.dim("OFF"),de=re.sources.length>0?` (${re.sources.join(", ")})`:"";D.push(` ${Y}: ${ie} via ${re.source}${de}`)}if(O&&O.weakenings.length>0){D.push(` Project policy deltas${O.weakeningsIgnored?" (ignored)":""}:`);for(let J of O.weakenings)D.push(` ${J}`)}D.push(` Stored rule customizations: ${P.effectiveSafety.ruleCounts.stored}`),D.push(` Effective rule customizations: ${P.effectiveSafety.ruleCounts.effective}`);for(let[J,Y]of Object.entries(P.effectiveSafety.ruleOverrides))D.push(` ${J}: ${Y}`);return D.join(`
11
+ `)}function ra(P){let O=["Findings"];if(P.length===0)return O.push(" No findings from inspected doctor facts."),O.join(`
12
+ `);for(let D of P){let j=`[${D.severity.toUpperCase()}] ${D.checkId}: ${hn(D.title)}`,J=D.severity==="error"?nn.red:D.severity==="warning"?nn.yellow:nn.blue;if(O.push(` ${J(j)}`),O.push(` ${hn(D.detail)}`),D.path)O.push(` Path: ${hn(D.path)}`);if(D.fixHint)O.push(` Fix: ${hn(D.fixHint)}`)}return O.join(`
13
+ `)}function xf(P){let O=["Variable","Status","Legacy"],D=P.map((j)=>{let J=j.isSet?nn.green("✓"):nn.dim("✗"),Y=j.legacyName&&j.legacyIsSet?`${j.legacyName} ${nn.green("✓")}`:j.legacyName??"";return[j.name,J,Y]});return Wn({headers:O,rows:D})}function oa(P){let O=[];if(P.totalBlocked===0)O.push("Recent Activity"),O.push(" No blocked commands in the last 7 days"),O.push(" Tip: This is normal for new installations");else O.push(`Recent Activity · last 7 days (${P.totalBlocked} blocked / ${P.sessionCount} sessions)`),O.push(Cf(P.recentEntries));if(P.unreadable>0)O.push(` Warning: ${P.unreadable} audit log ${P.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return O.join(`
14
+ `)}function Cf(P){let O=["Time","Command"],D=P.map((j)=>{let J=hn(j.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),Y=J.length>40?`${J.slice(0,37)}...`:J;return[j.relativeTime,Y]});return Wn({headers:O,rows:D})}function ia(P){let O=[];if(O.push("Update Check"),P.latestVersion===null&&!P.error)return O.push(xr([["Status",nn.dim("Skipped")],["Installed",P.currentVersion]])),O.join(`
15
+ `);if(P.error)return O.push(xr([["Status",`${nn.yellow("⚠")} Error`],["Installed",P.currentVersion],["Error",nn.dim(P.error)]])),O.join(`
16
+ `);if(P.updateAvailable)return O.push(xr([["Status",`${nn.yellow("⚠")} Update Available`],["Current",P.currentVersion],["Latest",nn.green(P.latestVersion??"")]])),O.push(""),O.push(" Run: bunx cc-safety-net@latest doctor"),O.push(" Or: npx cc-safety-net@latest doctor"),O.join(`
17
+ `);return O.push(xr([["Status",`${nn.green("✓")} Up to date`],["Version",P.currentVersion]])),O.join(`
18
+ `)}function xr(P){return Wn({rows:P})}function sa(P){let O=[];return O.push("System Info"),O.push(Sf(P)),O.join(`
19
+ `)}function Sf(P){let O=["Component","Version"],D=(Y)=>{if(Y===null)return nn.dim("not found");return Y},J=[{label:"cc-safety-net",value:P.version},...gr.map((Y)=>({label:mn(Y),value:P.versions[Y]??null})),{label:"Node.js",value:P.nodeVersion},{label:"npm",value:P.npmVersion},{label:"Bun",value:P.bunVersion},{label:"Platform",value:P.platform}].map((Y)=>[Y.label,D(Y.value)]);return Wn({headers:O,rows:J})}function aa(P){if(P.findings.length===0)return nn.green(`
20
20
  No findings from inspected doctor facts.`);let O={error:P.findings.filter((Y)=>Y.severity==="error").length,warning:P.findings.filter((Y)=>Y.severity==="warning").length,info:P.findings.filter((Y)=>Y.severity==="info").length},D=["error","warning","info"].filter((Y)=>O[Y]>0).map((Y)=>`${O[Y]} ${Y}`),j=P.findings.length===1?"finding":"findings",J=`
21
- ${P.findings.length} ${j}: ${D.join(", ")}.`;if(O.error>0)return nn.red(J);if(O.warning>0)return nn.yellow(J);return nn.blue(J)}import{lstatSync as gf}from"node:fs";import{dirname as To}from"node:path";function Ao(P,O){try{let D=gf(O);if(D.isSymbolicLink())return{kind:P,path:O,status:"unsafe",issues:["symlink"]};if(!D.isDirectory())return{kind:P,path:O,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:P,path:O,status:"unknown",issues:[]};let j=[...D.uid!==process.getuid()?["ownership"]:[],...(D.mode&18)!==0?["permissions"]:[]];return{kind:P,path:O,status:j.length>0?"unsafe":"safe",issues:j}}catch(D){if(typeof D==="object"&&D!==null&&"code"in D&&D.code==="ENOENT")return{kind:P,path:O,status:"not-applicable",issues:[]};return{kind:P,path:O,status:"unknown",issues:[]}}}function Xs(P,O){let D=U(P);return{directories:[Ao("policy",To(To(O))),Ao("config",To(O)),...D?[Ao("audit",D)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as yf}from"node:child_process";import{existsSync as Qs}from"node:fs";import{delimiter as hf,extname as vf,join as bf}from"node:path";import{stripVTControlCharacters as ea}from"node:util";var ta="2.6.1",wf=5000,kf="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function pn(){return ta}function Io(P,O){let D=P[O];if(D)return D;let j=Object.keys(P).find((J)=>J.toLowerCase()===O.toLowerCase()&&!!P[J]);return j?P[j]:D}function xf(P){return(Io(P,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((O)=>O.length>0)}function Cf(P,O){let D=vf(P)?[P]:[...xf(O).map((j)=>`${P}${j}`),P];if(P.includes("/")||P.includes("\\"))return D.find((j)=>Qs(j))??P;return(Io(O,"PATH")??"").split(hf).flatMap((j)=>D.map((J)=>bf(j,J))).find((j)=>Qs(j))??P}function na(P){if(!/[\s"&|<>^]/.test(P))return P;return`"${P.replace(/"/g,'""')}"`}function zn(P,O){let[D,...j]=P,J=O[kf]==="win32"?"win32":process.platform;if(!D||J!=="win32")return{cmd:D??"",args:j};let Y=Cf(D,O);if(!/\.(?:bat|cmd)$/i.test(Y))return{cmd:Y,args:j};return{cmd:Io(O,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",na(Y),...j.map(na)].join(" ")]}}var St=async(P,O=wf)=>{let D=await Sf(P,{timeoutMs:O});if(D.code!==0)return null;return ea(D.stdout).trim()||ea(D.stderr).trim()||null};function Sf(P,O){let[D,...j]=P;if(!D)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((J)=>{try{let Y=zn([D,...j],process.env),re=yf(Y.cmd,Y.args,{stdio:["ignore","pipe","pipe"]}),ie=!1,de="",fe="";re.stdout.on("data",(Se)=>{de+=Se.toString()}),re.stderr.on("data",(Se)=>{fe+=Se.toString()});let we=(Se)=>{if(ie)return;ie=!0,clearTimeout(Ce),J(Se)},Ce=setTimeout(()=>{re.kill(),we({code:null,stdout:de,stderr:fe})},O.timeoutMs);re.on("close",(Se)=>{we({code:Se,stdout:de,stderr:fe})}),re.on("error",()=>{we({code:null,stdout:de,stderr:fe})})}catch{J({code:null,stdout:"",stderr:""})}})}function kr(P){if(!P)return null;let O=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(P);if(O)return O[1]??null;let D=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(P);if(D)return D[1]??null;return P.split(`
22
- `)[0]?.trim()||null}async function xr(P,O=St,D=process.cwd()){let j=Promise.all(En.map(async(Ce)=>[Ce.id,kr(await O([...Ce.probeCommand]))])),[J,Y,re,ie,de,fe,we]=await Promise.all([j,j.then(async(Ce)=>{let Se=Ce.find(([Ve])=>Ve==="opencode")?.[1];if(!Se?.startsWith("2.")||!P(Se))return null;let Ie=["--param",`location[directory]=${D}`],Ee=["opencode","api","integration.list",...Ie];return await O(Ee,30000),O(["opencode","api","plugin.list",...Ie],30000)}),O(["codex","plugin","list"],30000),O(["amp","plugins","list"],30000),O(["node","--version"]),O(["npm","--version"]),O(["bun","--version"])]);return{version:ta,versions:Object.fromEntries(J),codexPluginListOutput:re,ampPluginListOutput:ie,openCodePluginListOutput:Y,nodeVersion:kr(de),npmVersion:kr(fe),bunVersion:kr(we),platform:`${process.platform} ${process.arch}`}}function $o(P,O){if(O==="dev")return!1;let D=P.split(".").map(Number),j=O.split(".").map(Number),[J=0,Y=0,re=0]=D,[ie=0,de=0,fe=0]=j;if(J!==ie)return J>ie;if(Y!==de)return Y>de;return re>fe}async function Gn(){let P=pn(),O=new AbortController,D=setTimeout(()=>O.abort(),3000);try{let j=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:O.signal});if(!j.ok)return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${j.status}`};let J=await j.json(),Y=$o(J.version,P);return{currentVersion:P,latestVersion:J.version,updateAvailable:Y}}catch(j){return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:j instanceof Error?j.message:"Network error"}}finally{clearTimeout(D)}}import*as da from"node:readline";var sa=(P)=>`\x1B[${P}B`,Pf=(P)=>`\x1B[${P}A`;var ra=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function Rf(P){return new Promise((O)=>setTimeout(O,P))}function Ef(P,O,D){if(!D)return O(P);if(D.aborted)return Promise.resolve();return new Promise((j,J)=>{let Y=()=>D.removeEventListener("abort",re),re=()=>{Y(),j()};D.addEventListener("abort",re,{once:!0}),O(P).then(()=>{Y(),j()},(ie)=>{Y(),J(ie)})})}function Cr(P){return Math.max(0,Math.min(1,P))}function Pt(P){return Math.max(0,Math.min(255,Math.round(P)))}function Oo(P){return P<=0.0031308?12.92*P:1.055*P**0.4166666666666667-0.055}function _f(P,O,D){let j=D*Math.PI/180,J=O*Math.cos(j),Y=O*Math.sin(j),re=(P+0.3963377774*J+0.2158037573*Y)**3,ie=(P-0.1055613458*J-0.0638541728*Y)**3,de=(P-0.0894841775*J-1.291485548*Y)**3;return{blue:Pt(Oo(Cr(-0.0041960863*re-0.7034186147*ie+1.707614701*de))*255),green:Pt(Oo(Cr(-1.2684380046*re+2.6097574011*ie-0.3413193965*de))*255),red:Pt(Oo(Cr(4.0767416621*re-3.3077115913*ie+0.2309699292*de))*255)}}function Do(P,O){let D=(O*P*180/Math.PI%360+360)%360;return _f(0.72,0.15,D)}function aa(P,O=0.1){let D=Do(O,P);return`\x1B[38;2;${D.red};${D.green};${D.blue}m`}function Tf(P,O){return{blue:Pt(P.blue+(255-P.blue)*O),green:Pt(P.green+(255-P.green)*O),red:Pt(P.red+(255-P.red)*O)}}function la(P,O,D){let j=Math.imul(P+2654435769,2246822507)^Math.imul(O+3266489909,668265263)^Math.imul(D+374761393,2654435761),J=j^j>>>15,Y=Math.imul(J,739982445),re=Y^Y>>>12,ie=Math.imul(re,695872825);return((ie^ie>>>15)>>>0)/4294967296}function Af(P,O,D){let j=Math.floor(la(P,O,D)*ra.length);return ra[j]??"░"}function oa(P){let O=Cr(P);return O*O*O*(O*(O*6-15)+10)}function If(P){if(P.length===0)return"";let O=[],D=!1,j="";for(let J of P){let Y=`${J.red};${J.green};${J.blue}`;if(J.bold!==D)O.push(J.bold?"\x1B[1m":"\x1B[22m"),D=J.bold;if(Y!==j)O.push(`\x1B[38;2;${Y}m`),j=Y;O.push(J.character)}return`${O.join("")}\x1B[22m\x1B[39m`}function $f(P,O,D,j,J){return P.map((Y,re)=>({...Do(D,j+O+re/J),bold:!1,character:Y}))}function Of(P,O,D,j,J,Y,re,ie){let de=Math.max(1,j*0.75),fe=Math.min(1,D/de),we=J*oa(fe),Ce=Math.max(0,(D-de)/Math.max(1,j-de)),Se=(1-oa(D/j))*ie*2,Ie=0.35*Math.max(0,1-Ce*2),Ee=fe>=1,Ve=Math.min(P.length,Math.ceil(we+2+1));return P.slice(0,Ve).map((Me,en)=>{let on=Do(Y,re+O+en/ie+Se),sn=en+la(O,en,7919)*2-1;if(sn>we+2)return{...on,bold:!1,character:" "};let an=we-sn,rn=0.8*Math.exp(-(an*an)/12.5),fn=Math.min(0.9,rn+Ie),On=!Ee&&sn>we-4;return{...Tf(on,fn),bold:fn>0.3,character:On?Af(O,en,D):Me}})}function ia(P){return`\x1B[?2026h${P.map((O,D)=>`\x1B8${D>0?sa(D):""}${If(O)}`).join("")}\x1B[?2026l`}async function Lo(P,O={}){if(!P)return;let D=O.output??process.stdout,j=O.sleep??Rf,J=O.seed??0,Y=P.split(`
21
+ ${P.findings.length} ${j}: ${D.join(", ")}.`;if(O.error>0)return nn.red(J);if(O.warning>0)return nn.yellow(J);return nn.blue(J)}import{lstatSync as Pf}from"node:fs";import{dirname as Lo}from"node:path";function No(P,O){try{let D=Pf(O);if(D.isSymbolicLink())return{kind:P,path:O,status:"unsafe",issues:["symlink"]};if(!D.isDirectory())return{kind:P,path:O,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:P,path:O,status:"unknown",issues:[]};let j=[...D.uid!==process.getuid()?["ownership"]:[],...(D.mode&18)!==0?["permissions"]:[]];return{kind:P,path:O,status:j.length>0?"unsafe":"safe",issues:j}}catch(D){if(typeof D==="object"&&D!==null&&"code"in D&&D.code==="ENOENT")return{kind:P,path:O,status:"not-applicable",issues:[]};return{kind:P,path:O,status:"unknown",issues:[]}}}function la(P,O){let D=U(P);return{directories:[No("policy",Lo(Lo(O))),No("config",Lo(O)),...D?[No("audit",D)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as Rf}from"node:child_process";import{existsSync as ca}from"node:fs";import{delimiter as Ef,extname as _f,join as Af}from"node:path";import{stripVTControlCharacters as da}from"node:util";var pa="2.6.3",Tf=5000,If="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function pn(){return pa}function jo(P,O){let D=P[O];if(D)return D;let j=Object.keys(P).find((J)=>J.toLowerCase()===O.toLowerCase()&&!!P[J]);return j?P[j]:D}function $f(P){return(jo(P,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((O)=>O.length>0)}function Of(P,O){let D=_f(P)?[P]:[...$f(O).map((j)=>`${P}${j}`),P];if(P.includes("/")||P.includes("\\"))return D.find((j)=>ca(j))??P;return(jo(O,"PATH")??"").split(Ef).flatMap((j)=>D.map((J)=>Af(j,J))).find((j)=>ca(j))??P}function ua(P){if(!/[\s"&|<>^]/.test(P))return P;return`"${P.replace(/"/g,'""')}"`}function zn(P,O){let[D,...j]=P,J=O[If]==="win32"?"win32":process.platform;if(!D||J!=="win32")return{cmd:D??"",args:j};let Y=Of(D,O);if(!/\.(?:bat|cmd)$/i.test(Y))return{cmd:Y,args:j};return{cmd:jo(O,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",ua(Y),...j.map(ua)].join(" ")]}}var St=async(P,O=Tf)=>{let D=await Df(P,{timeoutMs:O});if(D.code!==0)return null;return da(D.stdout).trim()||da(D.stderr).trim()||null};function Df(P,O){let[D,...j]=P;if(!D)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((J)=>{try{let Y=zn([D,...j],process.env),re=Rf(Y.cmd,Y.args,{stdio:["ignore","pipe","pipe"]}),ie=!1,de="",fe="";re.stdout.on("data",(Se)=>{de+=Se.toString()}),re.stderr.on("data",(Se)=>{fe+=Se.toString()});let we=(Se)=>{if(ie)return;ie=!0,clearTimeout(Ce),J(Se)},Ce=setTimeout(()=>{re.kill(),we({code:null,stdout:de,stderr:fe})},O.timeoutMs);re.on("close",(Se)=>{we({code:Se,stdout:de,stderr:fe})}),re.on("error",()=>{we({code:null,stdout:de,stderr:fe})})}catch{J({code:null,stdout:"",stderr:""})}})}function Cr(P){if(!P)return null;let O=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(P);if(O)return O[1]??null;let D=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(P);if(D)return D[1]??null;return P.split(`
22
+ `)[0]?.trim()||null}async function Sr(P,O=St,D=process.cwd()){let j=Promise.all(En.map(async(Ce)=>[Ce.id,Cr(await O([...Ce.probeCommand]))])),[J,Y,re,ie,de,fe,we]=await Promise.all([j,j.then(async(Ce)=>{let Se=Ce.find(([Ve])=>Ve==="opencode")?.[1];if(!Se?.startsWith("2.")||!P(Se))return null;let Ie=["--param",`location[directory]=${D}`],Ee=["opencode","api","integration.list",...Ie];return await O(Ee,30000),O(["opencode","api","plugin.list",...Ie],30000)}),O(["codex","plugin","list"],30000),O(["amp","plugins","list"],30000),O(["node","--version"]),O(["npm","--version"]),O(["bun","--version"])]);return{version:pa,versions:Object.fromEntries(J),codexPluginListOutput:re,ampPluginListOutput:ie,openCodePluginListOutput:Y,nodeVersion:Cr(de),npmVersion:Cr(fe),bunVersion:Cr(we),platform:`${process.platform} ${process.arch}`}}function Fo(P,O){if(O==="dev")return!1;let D=P.split(".").map(Number),j=O.split(".").map(Number),[J=0,Y=0,re=0]=D,[ie=0,de=0,fe=0]=j;if(J!==ie)return J>ie;if(Y!==de)return Y>de;return re>fe}async function Gn(){let P=pn(),O=new AbortController,D=setTimeout(()=>O.abort(),3000);try{let j=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:O.signal});if(!j.ok)return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${j.status}`};let J=await j.json(),Y=Fo(J.version,P);return{currentVersion:P,latestVersion:J.version,updateAvailable:Y}}catch(j){return{currentVersion:P,latestVersion:null,updateAvailable:!1,error:j instanceof Error?j.message:"Network error"}}finally{clearTimeout(D)}}import*as wa from"node:readline";var ya=(P)=>`\x1B[${P}B`,Lf=(P)=>`\x1B[${P}A`;var fa=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function Nf(P){return new Promise((O)=>setTimeout(O,P))}function jf(P,O,D){if(!D)return O(P);if(D.aborted)return Promise.resolve();return new Promise((j,J)=>{let Y=()=>D.removeEventListener("abort",re),re=()=>{Y(),j()};D.addEventListener("abort",re,{once:!0}),O(P).then(()=>{Y(),j()},(ie)=>{Y(),J(ie)})})}function Pr(P){return Math.max(0,Math.min(1,P))}function Pt(P){return Math.max(0,Math.min(255,Math.round(P)))}function Ho(P){return P<=0.0031308?12.92*P:1.055*P**0.4166666666666667-0.055}function Ff(P,O,D){let j=D*Math.PI/180,J=O*Math.cos(j),Y=O*Math.sin(j),re=(P+0.3963377774*J+0.2158037573*Y)**3,ie=(P-0.1055613458*J-0.0638541728*Y)**3,de=(P-0.0894841775*J-1.291485548*Y)**3;return{blue:Pt(Ho(Pr(-0.0041960863*re-0.7034186147*ie+1.707614701*de))*255),green:Pt(Ho(Pr(-1.2684380046*re+2.6097574011*ie-0.3413193965*de))*255),red:Pt(Ho(Pr(4.0767416621*re-3.3077115913*ie+0.2309699292*de))*255)}}function Mo(P,O){let D=(O*P*180/Math.PI%360+360)%360;return Ff(0.72,0.15,D)}function ha(P,O=0.1){let D=Mo(O,P);return`\x1B[38;2;${D.red};${D.green};${D.blue}m`}function Hf(P,O){return{blue:Pt(P.blue+(255-P.blue)*O),green:Pt(P.green+(255-P.green)*O),red:Pt(P.red+(255-P.red)*O)}}function va(P,O,D){let j=Math.imul(P+2654435769,2246822507)^Math.imul(O+3266489909,668265263)^Math.imul(D+374761393,2654435761),J=j^j>>>15,Y=Math.imul(J,739982445),re=Y^Y>>>12,ie=Math.imul(re,695872825);return((ie^ie>>>15)>>>0)/4294967296}function Mf(P,O,D){let j=Math.floor(va(P,O,D)*fa.length);return fa[j]??"░"}function ma(P){let O=Pr(P);return O*O*O*(O*(O*6-15)+10)}function Uf(P){if(P.length===0)return"";let O=[],D=!1,j="";for(let J of P){let Y=`${J.red};${J.green};${J.blue}`;if(J.bold!==D)O.push(J.bold?"\x1B[1m":"\x1B[22m"),D=J.bold;if(Y!==j)O.push(`\x1B[38;2;${Y}m`),j=Y;O.push(J.character)}return`${O.join("")}\x1B[22m\x1B[39m`}function Gf(P,O,D,j,J){return P.map((Y,re)=>({...Mo(D,j+O+re/J),bold:!1,character:Y}))}function qf(P,O,D,j,J,Y,re,ie){let de=Math.max(1,j*0.75),fe=Math.min(1,D/de),we=J*ma(fe),Ce=Math.max(0,(D-de)/Math.max(1,j-de)),Se=(1-ma(D/j))*ie*2,Ie=0.35*Math.max(0,1-Ce*2),Ee=fe>=1,Ve=Math.min(P.length,Math.ceil(we+2+1));return P.slice(0,Ve).map((Me,en)=>{let on=Mo(Y,re+O+en/ie+Se),sn=en+va(O,en,7919)*2-1;if(sn>we+2)return{...on,bold:!1,character:" "};let an=we-sn,rn=0.8*Math.exp(-(an*an)/12.5),fn=Math.min(0.9,rn+Ie),On=!Ee&&sn>we-4;return{...Hf(on,fn),bold:fn>0.3,character:On?Mf(O,en,D):Me}})}function ga(P){return`\x1B[?2026h${P.map((O,D)=>`\x1B8${D>0?ya(D):""}${Uf(O)}`).join("")}\x1B[?2026l`}async function Uo(P,O={}){if(!P)return;let D=O.output??process.stdout,j=O.sleep??Nf,J=O.seed??0,Y=P.split(`
23
23
  `).map((we)=>Array.from(we)),re=Math.max(...Y.map((we)=>we.length)),ie=12000*Y.filter((we)=>we.length>0).length/40,de=re>0?Math.max(1,Math.ceil(ie/16.666666666666668)):0,fe=de>0?ie/de:0;D.write(`\x1B[?25l${Y.length>1?`${`
24
- `.repeat(Y.length-1)}${Pf(Y.length-1)}`:""}\x1B7`);try{for(let we=1;we<=de;we+=1){if(O.signal?.aborted)break;D.write(ia(Y.map((Ce,Se)=>Of(Ce,Se,we,de,re,0.1,J,3)))),await Ef(fe,j,O.signal)}}finally{if(D.write(ia(Y.map((we,Ce)=>$f(we,Ce,0.1,J,3)))),D.write("\x1B8"),Y.length>1)D.write(sa(Y.length-1));D.write(`
25
- \x1B[0m\x1B[?25h`)}}var ca=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
- `);function Df(P){return Boolean(P.isTTY)}async function Mt(P={}){let O=P.output??process.stdout;if(!Df(O))return;let D=P.input??process.stdin,j={output:O,seed:P.seed??Math.random()*8192,sleep:P.sleep};if(!D.isTTY||typeof D.setRawMode!=="function"){await Lo(ca,j);return}let J=new AbortController,Y=D.readableFlowing===!0,re=D.isRaw===!0,ie=!1,de=(fe,we)=>{if(we.ctrl&&we.name==="c")ie=!0;if(ie||we.name==="return"||we.name==="enter")J.abort()};da.emitKeypressEvents(D),D.on("keypress",de),D.setRawMode(!0),D.resume();try{await Lo(ca,{...j,signal:J.signal})}finally{if(D.off("keypress",de),D.setRawMode(re),!Y)D.pause()}if(!ie)return;if(P.onInterrupt){P.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as Hf}from"node:crypto";import{existsSync as fa}from"node:fs";import{dirname as Sr,join as ma}from"node:path";import{dirname as ua,join as Lf,resolve as Nf}from"node:path";var jf="rule.lock";function Ff(P){return Lf(ua(P),jf)}function pa(P={}){return Nf(P.cwd??process.cwd(),".safety-net.json")}function kn(P,O){let D=O.global?O.userConfigPath??W(P,O):O.projectConfigPath??_(O.cwd??process.cwd()),j=O.global?Je(P,O):Ye(D,O.cwd??process.cwd()),J=Ff(D);return{configDir:ua(D),configPath:D,lockPath:J,filesystemScope:j,configTarget:i(j,D),lockTarget:i(j,J)}}var Mf="`cc-safety-net rule sync` is deprecated: rulebooks are live files that need no synchronization. This run only migrates the lock and cache an earlier version left behind.",Uf="cache",Gf="rulebooks";function ga(P,O={}){let D=kn(P,O),j=i(D.filesystemScope,ha(D.configDir)),J=r(D.lockTarget);if(console.log(Mf),J===null&&!fa(j.path))return console.log(`No v2 lock or cache leftovers found in ${Sr(D.configDir)}; nothing to migrate.`),0;let Y=Wf(J),re=m(D.configTarget);if(!re.config&&(r(D.configTarget)!==null||Y.size>0))return console.error(`Cannot migrate: the rules config in ${Sr(D.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let ie=re.config?.rules??[];for(let de of ie.flatMap((fe)=>qf(fe,Y,D,j,O.global===!0)))console.log(de);return H(D.lockTarget),st(j),console.log(`Removed the v2 lock and cache under ${Sr(D.configDir)}.`),0}function ya(P,O){return[...new Set([{cwd:O},{cwd:O,global:!0}].flatMap((D)=>{let j=kn(P,D);return[j.lockPath,ha(j.configDir)]}))].filter((D)=>fa(D))}function qf(P,O,D,j,J){if(!w(P))return[];let Y=N(P).name,re=i(D.filesystemScope,M(D.configDir,Y)),ie=r(re);if(ie!==null&&Bf(ie,Y))return[];let de=O.get(P),fe=de?Vf(de,Y,j.path,D.filesystemScope):null;if(fe===null)return[`Could not migrate ${P} from the v2 cache. Run \`cc-safety-net rule update ${P}${J?" --global":""}\` to vendor it.`];if(g(re,fe),ie!==null)return[`Restored ${P} from the v2 cache over an invalid file.`];return[`Vendored ${P} from the v2 cache.`]}function Bf(P,O){let D=xe(P);return!("problem"in D)&&D.rulebook.name===O}function Vf(P,O,D,j){let J=ma(D,Gf,`${Jf(P)}--${P.digest.replace("sha256:","").slice(0,12)}`,ge),Y=r(i(j,J));if(Y===null||Yf(Y)!==P.digest)return null;let re=xe(Y);if("problem"in re||re.rulebook.name!==O)return null;return Y}function ha(P){return ma(Sr(P),Uf)}function Jf(P){return([P.owner,P.repo,P.display_ref,P.name].every((j)=>typeof j==="string"&&j!=="")?`${P.owner}/${P.repo}#${P.display_ref}/${P.name}`:P.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function Wf(P){let O=P===null?null:zf(P),D=va(O)&&Array.isArray(O.rulebooks)?O.rulebooks:[];return new Map(D.filter(Kf).map((j)=>[j.spec,j]))}function Kf(P){return va(P)&&typeof P.spec==="string"&&typeof P.digest==="string"}function va(P){return!!P&&typeof P==="object"}function zf(P){try{return JSON.parse(P)}catch{return null}}function Yf(P){return`sha256:${Hf("sha256").update(P).digest("hex")}`}var ba="\r\x1B[2K",Zf="\x1B[?25l",Xf="\x1B[39m",Qf="\x1B[?25h",em=100,nm=0.55,tm=80,wa=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function rm(P){return new Promise((O)=>setTimeout(O,P))}async function Pr(P,O={}){let D=O.output??process.stdout;if(!D.isTTY)return P;let j=O.sleep??rm,J=!1,Y=P.then((ie)=>(J=!0,ie),(ie)=>{throw J=!0,ie});if(await Promise.race([Y.then(()=>!0),j(em).then(()=>!1)]))return Y;D.write(Zf);try{for(let ie=0;!J;ie+=1)D.write(`${ba}${aa(ie*nm)}${wa[ie%wa.length]}${Xf} ${O.loadingMessage??"Loading…"}`),await Promise.race([Y,j(tm)]);return await Y}finally{D.write(`${ba}${Qf}`)}}async function Ut(P,O,D,j={}){let J=O();if(P)await D();if(P&&J.ready)await Pr(J.ready,j);return J.finish()}import{stripVTControlCharacters as om}from"node:util";var Rr="amp plugins list",im=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function ka(P){if(!P.ampPluginListOutput)return{platform:"amp",status:"n/a"};let O=om(P.ampPluginListOutput).split(`
27
- `).map((D)=>im.exec(D)?.[1]).find((D)=>D!==void 0);if(!O)return{platform:"amp",status:"n/a"};if(O!=="active")return{platform:"amp",status:"disabled",method:Rr,configPath:Rr,errors:[`Amp personal plugin cc-safety-net is ${O}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:Rr,configPath:Rr}}import{existsSync as dm,readFileSync as um}from"node:fs";import{isAbsolute as Bx,join as cm}from"node:path";function Gt(P){return cm(P,".gemini","config","hooks.json")}var pm=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function fm(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];return Object.values(P).flatMap((O)=>{if(!O||typeof O!=="object"||Array.isArray(O))return[];let D=O,j=D.PreToolUse;if(!Array.isArray(j))return[];return j.flatMap((J)=>{if(!J||typeof J!=="object"||Array.isArray(J))return[];let Y=J.hooks;if(!Array.isArray(Y))return[];return Y.flatMap((re)=>{if(!re||typeof re!=="object"||Array.isArray(re))return[];let ie=re.command;if(typeof ie!=="string"||!pm.test(ie))return[];return[{command:ie,enabled:D.enabled!==!1}]})})})}function xa(P){let O=Gt(P.environment.home);if(!dm(O))return{platform:"antigravity-cli",status:"n/a",configPath:O};let D;try{D=fm(JSON.parse(um(O,"utf-8")))}catch(j){return{platform:"antigravity-cli",status:"n/a",configPath:O,errors:[`Failed to parse Antigravity hooks config ${O}: ${j instanceof Error?j.message:String(j)}`]}}if(D.some((j)=>j.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:O};if(D.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:O};return{platform:"antigravity-cli",status:"n/a",configPath:O}}import{join as jo}from"node:path";import{existsSync as mm,lstatSync as gm,readFileSync as ym}from"node:fs";import{join as hm}from"node:path";function Pn(P,O=(D)=>D){if(!mm(P))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(O(ym(P,"utf-8")))}}catch{return{kind:"unreadable"}}}function Nn(P,O){if(P==="~")return O;if(P.startsWith("~/")||P.startsWith("~\\"))return hm(O,P.slice(2));return P}function dn(P){try{return gm(P)}catch{return}}function Er(P,O){let D=dn(O);if(!D)return{platform:P,status:"n/a",configPath:O};if(!D.isSymbolicLink()&&D.isDirectory())return;return{platform:P,status:"n/a",configPath:O,errors:[`${O} is a symlink or not a directory; move or remove it before installing`]}}function tn(P,O){return typeof P==="object"&&P!==null?P[O]:void 0}var No="cc-safety-net@cc-marketplace";function _r(P){return P.env.get("CLAUDE_CONFIG_DIR")||jo(P.home,".claude")}function Ca(P){return jo(_r(P),"plugins","installed_plugins.json")}function Sa(P,O){let D=tn(tn(P,"plugins"),O);return Array.isArray(D)&&D.length>0}function Tr(P,O){let D=Pn(Ca(P));return D.kind==="ok"&&Sa(D.value,O)}function Fo(P){let O=Ca(P),D=Pn(O);if(D.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(D.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!Sa(D.value,No))return{platform:"claude-code",status:"n/a"};let j=jo(_r(P),"settings.json"),J=Pn(j);if(J.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(J.kind==="ok"&&tn(tn(J.value,"enabledPlugins"),No)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:j,errors:[`${No} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:O}}function Pa(P){return Fo(P.environment)}var Ra="Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it.";function Ea(P){if(!P.codexPluginListOutput)return{platform:"codex",status:"n/a"};let O=P.codexPluginListOutput.split(`
28
- `).find((D)=>D.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!O)return{platform:"codex",status:"n/a"};if(!O.includes("installed,"))return{platform:"codex",status:"n/a"};if(!O.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex runs only trusted hooks, and doctor cannot check trust. Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."]}}import{existsSync as Or,readdirSync as vm,readFileSync as bm}from"node:fs";import{join as bn}from"node:path";function vn(P){let O="",D=0,j=!1,J=!1,Y=-1;while(D<P.length){let re=P[D],ie=P[D+1];if(J){O+=re,J=!1,D++;continue}if(re==='"'&&!j){j=!0,Y=-1,O+=re,D++;continue}if(re==='"'&&j){j=!1,O+=re,D++;continue}if(re==="\\"&&j){J=!0,O+=re,D++;continue}if(j){O+=re,D++;continue}if(re==="/"&&ie==="/"){while(D<P.length&&P[D]!==`
29
- `)D++;continue}if(re==="/"&&ie==="*"){D+=2;while(D<P.length-1){if(P[D]==="*"&&P[D+1]==="/"){D+=2;break}D++}continue}if(re===","){Y=O.length,O+=re,D++;continue}if(re==="}"||re==="]"){if(Y!==-1){let de=O.slice(Y+1);if(/^\s*$/.test(de))O=O.slice(0,Y)+de}Y=-1,O+=re,D++;continue}if(!/\s/.test(re))Y=-1;O+=re,D++}return O}function Ta(P,O,D){let j=O+1,J=!1;while(j<P.length){if(J){J=!1,j++;continue}if(P[j]==="\\"){J=!0,j++;continue}if(P[j]==='"')return j+1;j++}throw Error(D)}function Mo(P,O,D){let j=P[O],J=j==="["?"]":"}",Y=0,re=O;while(re<P.length){let ie=D.skipComment?.(P,re)??re;if(ie!==re){re=ie;continue}if(P[re]==='"'){re=Ta(P,re,D.stringError);continue}if(P[re]===j)Y++;if(P[re]===J){if(Y--,Y===0)return re}re++}throw Error(D.bracketError)}function Aa(P,O){let D=P.lastIndexOf(`
30
- `,O)+1;return/^[ \t]*/.exec(P.slice(D))?.[0]??""}function Ia(P,O){let D=O.end+(/^\s*/.exec(P.slice(O.end))?.[0].length??0);if(P[D]===","){let re=P[D+1]===`
24
+ `.repeat(Y.length-1)}${Lf(Y.length-1)}`:""}\x1B7`);try{for(let we=1;we<=de;we+=1){if(O.signal?.aborted)break;D.write(ga(Y.map((Ce,Se)=>qf(Ce,Se,we,de,re,0.1,J,3)))),await jf(fe,j,O.signal)}}finally{if(D.write(ga(Y.map((we,Ce)=>Gf(we,Ce,0.1,J,3)))),D.write("\x1B8"),Y.length>1)D.write(ya(Y.length-1));D.write(`
25
+ \x1B[0m\x1B[?25h`)}}var ba=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
26
+ `);function Bf(P){return Boolean(P.isTTY)}async function Mt(P={}){let O=P.output??process.stdout;if(!Bf(O))return;let D=P.input??process.stdin,j={output:O,seed:P.seed??Math.random()*8192,sleep:P.sleep};if(!D.isTTY||typeof D.setRawMode!=="function"){await Uo(ba,j);return}let J=new AbortController,Y=D.readableFlowing===!0,re=D.isRaw===!0,ie=!1,de=(fe,we)=>{if(we.ctrl&&we.name==="c")ie=!0;if(ie||we.name==="return"||we.name==="enter")J.abort()};wa.emitKeypressEvents(D),D.on("keypress",de),D.setRawMode(!0),D.resume();try{await Uo(ba,{...j,signal:J.signal})}finally{if(D.off("keypress",de),D.setRawMode(re),!Y)D.pause()}if(!ie)return;if(P.onInterrupt){P.onInterrupt();return}process.kill(process.pid,"SIGINT")}import{createHash as zf}from"node:crypto";import{existsSync as Ca}from"node:fs";import{dirname as Rr,join as Sa}from"node:path";import{dirname as ka,join as Vf,resolve as Jf}from"node:path";var Kf="rule.lock";function Wf(P){return Vf(ka(P),Kf)}function xa(P={}){return Jf(P.cwd??process.cwd(),".safety-net.json")}function kn(P,O){let D=O.global?O.userConfigPath??W(P,O):O.projectConfigPath??_(O.cwd??process.cwd()),j=O.global?Je(P,O):Ye(D,O.cwd??process.cwd()),J=Wf(D);return{configDir:ka(D),configPath:D,lockPath:J,filesystemScope:j,configTarget:i(j,D),lockTarget:i(j,J)}}var Yf="`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.",Zf="cache",Xf="rulebooks";function Pa(P,O={}){let D=kn(P,O),j=i(D.filesystemScope,Ea(D.configDir)),J=r(D.lockTarget);if(console.log(Yf),J===null&&!Ca(j.path))return console.log(`No v2 lock or cache leftovers found in ${Rr(D.configDir)}; nothing to migrate.`),0;let Y=rm(J),re=m(D.configTarget);if(!re.config&&(r(D.configTarget)!==null||Y.size>0))return console.error(`Cannot migrate: the rules config in ${Rr(D.configDir)} is missing or unreadable while v2 leftovers remain. Restore rule.json, then re-run rule sync.`),1;let ie=re.config?.rules??[];for(let de of ie.flatMap((fe)=>Qf(fe,Y,D,j,O.global===!0)))console.log(de);return H(D.lockTarget),st(j),console.log(`Removed the v2 lock and cache under ${Rr(D.configDir)}.`),0}function Ra(P,O){return[...new Set([{cwd:O},{cwd:O,global:!0}].flatMap((D)=>{let j=kn(P,D);return[j.lockPath,Ea(j.configDir)]}))].filter((D)=>Ca(D))}function Qf(P,O,D,j,J){if(!w(P))return[];let Y=N(P).name,re=i(D.filesystemScope,M(D.configDir,Y)),ie=r(re);if(ie!==null&&em(ie,Y))return[];let de=O.get(P),fe=de?nm(de,Y,j.path,D.filesystemScope):null;if(fe===null)return[`Could not migrate ${P} from the v2 cache. Run \`cc-safety-net rule update ${P}${J?" --global":""}\` to vendor it.`];if(g(re,fe),ie!==null)return[`Restored ${P} from the v2 cache over an invalid file.`];return[`Vendored ${P} from the v2 cache.`]}function em(P,O){let D=xe(P);return!("problem"in D)&&D.rulebook.name===O}function nm(P,O,D,j){let J=Sa(D,Xf,`${tm(P)}--${P.digest.replace("sha256:","").slice(0,12)}`,ge),Y=r(i(j,J));if(Y===null||sm(Y)!==P.digest)return null;let re=xe(Y);if("problem"in re||re.rulebook.name!==O)return null;return Y}function Ea(P){return Sa(Rr(P),Zf)}function tm(P){return([P.owner,P.repo,P.display_ref,P.name].every((j)=>typeof j==="string"&&j!=="")?`${P.owner}/${P.repo}#${P.display_ref}/${P.name}`:P.spec).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"rulebook"}function rm(P){let O=P===null?null:im(P),D=_a(O)&&Array.isArray(O.rulebooks)?O.rulebooks:[];return new Map(D.filter(om).map((j)=>[j.spec,j]))}function om(P){return _a(P)&&typeof P.spec==="string"&&typeof P.digest==="string"}function _a(P){return!!P&&typeof P==="object"}function im(P){try{return JSON.parse(P)}catch{return null}}function sm(P){return`sha256:${zf("sha256").update(P).digest("hex")}`}var Aa="\r\x1B[2K",am="\x1B[?25l",lm="\x1B[39m",cm="\x1B[?25h",dm=100,um=0.55,pm=80,Ta=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function fm(P){return new Promise((O)=>setTimeout(O,P))}async function Er(P,O={}){let D=O.output??process.stdout;if(!D.isTTY)return P;let j=O.sleep??fm,J=!1,Y=P.then((ie)=>(J=!0,ie),(ie)=>{throw J=!0,ie});if(await Promise.race([Y.then(()=>!0),j(dm).then(()=>!1)]))return Y;D.write(am);try{for(let ie=0;!J;ie+=1)D.write(`${Aa}${ha(ie*um)}${Ta[ie%Ta.length]}${lm} ${O.loadingMessage??"Loading…"}`),await Promise.race([Y,j(pm)]);return await Y}finally{D.write(`${Aa}${cm}`)}}async function Ut(P,O,D,j={}){let J=O();if(P)await D();if(P&&J.ready)await Er(J.ready,j);return J.finish()}import{stripVTControlCharacters as mm}from"node:util";var _r="amp plugins list",gm=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function Ia(P){if(!P.ampPluginListOutput)return{platform:"amp",status:"n/a"};let O=mm(P.ampPluginListOutput).split(`
27
+ `).map((D)=>gm.exec(D)?.[1]).find((D)=>D!==void 0);if(!O)return{platform:"amp",status:"n/a"};if(O!=="active")return{platform:"amp",status:"disabled",method:_r,configPath:_r,errors:[`Amp personal plugin cc-safety-net is ${O}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:_r,configPath:_r}}import{existsSync as wm,readFileSync as km}from"node:fs";import{isAbsolute as oC,join as bm}from"node:path";function Gt(P){return bm(P,".gemini","config","hooks.json")}var xm=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Cm(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];return Object.values(P).flatMap((O)=>{if(!O||typeof O!=="object"||Array.isArray(O))return[];let D=O,j=D.PreToolUse;if(!Array.isArray(j))return[];return j.flatMap((J)=>{if(!J||typeof J!=="object"||Array.isArray(J))return[];let Y=J.hooks;if(!Array.isArray(Y))return[];return Y.flatMap((re)=>{if(!re||typeof re!=="object"||Array.isArray(re))return[];let ie=re.command;if(typeof ie!=="string"||!xm.test(ie))return[];return[{command:ie,enabled:D.enabled!==!1}]})})})}function $a(P){let O=Gt(P.environment.home);if(!wm(O))return{platform:"antigravity-cli",status:"n/a",configPath:O};let D;try{D=Cm(JSON.parse(km(O,"utf-8")))}catch(j){return{platform:"antigravity-cli",status:"n/a",configPath:O,errors:[`Failed to parse Antigravity hooks config ${O}: ${j instanceof Error?j.message:String(j)}`]}}if(D.some((j)=>j.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:O};if(D.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:O};return{platform:"antigravity-cli",status:"n/a",configPath:O}}import{existsSync as _m}from"node:fs";import{join as qt}from"node:path";import{existsSync as Sm,lstatSync as Pm,readFileSync as Rm}from"node:fs";import{join as Em}from"node:path";function xn(P,O=(D)=>D){if(!Sm(P))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(O(Rm(P,"utf-8")))}}catch{return{kind:"unreadable"}}}function Nn(P,O){if(P==="~")return O;if(P.startsWith("~/")||P.startsWith("~\\"))return Em(O,P.slice(2));return P}function dn(P){try{return Pm(P)}catch{return}}function Ar(P,O){let D=dn(O);if(!D)return{platform:P,status:"n/a",configPath:O};if(!D.isSymbolicLink()&&D.isDirectory())return;return{platform:P,status:"n/a",configPath:O,errors:[`${O} is a symlink or not a directory; move or remove it before installing`]}}function tn(P,O){return typeof P==="object"&&P!==null?P[O]:void 0}var Tr="cc-safety-net@cc-marketplace";function Ir(P){return P.env.get("CLAUDE_CONFIG_DIR")||qt(P.home,".claude")}function Go(P){return qt(Ir(P),"plugins","installed_plugins.json")}function Oa(P,O){let D=tn(tn(P,"plugins"),O);return Array.isArray(D)&&D.length>0}function $r(P,O){let D=xn(Go(P));return D.kind==="ok"&&Oa(D.value,O)}function Or(P){let O=Go(P),D=xn(O);if(D.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(D.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!Oa(D.value,Tr))return{platform:"claude-code",status:"n/a"};let j=qt(Ir(P),"settings.json"),J=xn(j);if(J.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(J.kind==="ok"&&tn(tn(J.value,"enabledPlugins"),Tr)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:j,errors:[`${Tr} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:O}}function Da(P){if(Or(P).status!=="configured")return;let O=xn(Go(P)),D=O.kind==="ok"?tn(tn(O.value,"plugins"),Tr):void 0,j=(Array.isArray(D)?D:[]).filter((ie)=>tn(ie,"scope")==="user").map((ie)=>tn(ie,"installPath")).find((ie)=>typeof ie==="string");if(!j)return;let J=qt(j,".cursor-plugin","plugin.json"),Y=xn(J),re=Y.kind==="ok"?tn(Y.value,"hooks"):void 0;return typeof re==="string"&&_m(qt(j,re))?J:void 0}function La(P){return Or(P.environment)}var Na="Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it.";function ja(P){if(!P.codexPluginListOutput)return{platform:"codex",status:"n/a"};let O=P.codexPluginListOutput.split(`
28
+ `).find((D)=>D.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!O)return{platform:"codex",status:"n/a"};if(!O.includes("installed,"))return{platform:"codex",status:"n/a"};if(!O.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex runs only trusted hooks, and doctor cannot check trust. Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."]}}import{existsSync as jr,readdirSync as Am,readFileSync as Tm}from"node:fs";import{join as bn}from"node:path";function vn(P){let O="",D=0,j=!1,J=!1,Y=-1;while(D<P.length){let re=P[D],ie=P[D+1];if(J){O+=re,J=!1,D++;continue}if(re==='"'&&!j){j=!0,Y=-1,O+=re,D++;continue}if(re==='"'&&j){j=!1,O+=re,D++;continue}if(re==="\\"&&j){J=!0,O+=re,D++;continue}if(j){O+=re,D++;continue}if(re==="/"&&ie==="/"){while(D<P.length&&P[D]!==`
29
+ `)D++;continue}if(re==="/"&&ie==="*"){D+=2;while(D<P.length-1){if(P[D]==="*"&&P[D+1]==="/"){D+=2;break}D++}continue}if(re===","){Y=O.length,O+=re,D++;continue}if(re==="}"||re==="]"){if(Y!==-1){let de=O.slice(Y+1);if(/^\s*$/.test(de))O=O.slice(0,Y)+de}Y=-1,O+=re,D++;continue}if(!/\s/.test(re))Y=-1;O+=re,D++}return O}function Ha(P,O,D){let j=O+1,J=!1;while(j<P.length){if(J){J=!1,j++;continue}if(P[j]==="\\"){J=!0,j++;continue}if(P[j]==='"')return j+1;j++}throw Error(D)}function Bo(P,O,D){let j=P[O],J=j==="["?"]":"}",Y=0,re=O;while(re<P.length){let ie=D.skipComment?.(P,re)??re;if(ie!==re){re=ie;continue}if(P[re]==='"'){re=Ha(P,re,D.stringError);continue}if(P[re]===j)Y++;if(P[re]===J){if(Y--,Y===0)return re}re++}throw Error(D.bracketError)}function Ma(P,O){let D=P.lastIndexOf(`
30
+ `,O)+1;return/^[ \t]*/.exec(P.slice(D))?.[0]??""}function Ua(P,O){let D=O.end+(/^\s*/.exec(P.slice(O.end))?.[0].length??0);if(P[D]===","){let re=P[D+1]===`
31
31
  `?D+2:D+1;return`${P.slice(0,O.start)}${P.slice(re)}`}let j=P.slice(0,O.start).search(/\s*$/)-1;if(P[j]!==",")return`${P.slice(0,O.start)}${P.slice(O.end)}`;let J=P.lastIndexOf(`
32
- `,j-1),Y=J!==-1&&/^\s*$/.test(P.slice(J+1,j))?J:j;return`${P.slice(0,Y)}${P.slice(O.end)}`}function Ho(P,O){if(P.startsWith("//",O)){let D=P.indexOf(`
33
- `,O+2);return D===-1?P.length:D+1}if(P.startsWith("/*",O)){let D=P.indexOf("*/",O+2);return D===-1?P.length:D+2}return O}function _a(P,O){let D=O;while(D<P.length){if(/\s/.test(P[D]??"")){D++;continue}let j=Ho(P,D);if(j===D)return D;D=j}return D}function $a(P,O,D){let j=0,J=0;while(J<P.length){let Y=Ho(P,J);if(Y!==J){J=Y;continue}if(P[J]==='"'){let re=Ta(P,J,D.stringError);if(j===1&&JSON.parse(P.slice(J,re))===O){let ie=_a(P,re),de=_a(P,ie+1);if(P[ie]===":"&&P[de]==="[")return{start:de,end:Mo(P,de,{skipComment:Ho,...D})}}J=re;continue}if(P[J]==="{"||P[J]==="[")j++;if(P[J]==="}"||P[J]==="]")j--;J++}return}var Tn="cc-safety-net@cc-marketplace",Ar=["cc-marketplace","cc-safety-net"],Oa=["_direct","copilot-safety-net"],Da=["cc-marketplace","safety-net"],La="safety-net@cc-marketplace";function Ir(P,O){let D=O.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${D}([^a-z0-9-]|$)`,"m").test(P??"")}function Na(P){return Ir(P,"cc-safety-net@cc-marketplace")}function ja(P){return Ir(P,"cc-marketplace")}function Fa(P){return Ir(P,"copilot-safety-net")}function Ha(P){return Ir(P,"safety-net@cc-marketplace")}function $r(P){if(!P?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(P)}function Ua(P,O){if(!P)return null;let D=P.match(/(\d+)\.(\d+)\.(\d+)/);if(!D)return null;let j=[Number(D[1]),Number(D[2]),Number(D[3])];for(let J=0;J<O.length;J++){let Y=j[J]??0,re=O[J]??0;if(Y!==re)return Y>re}return!0}function wm(P){return Ua(P,[0,0,422])}function km(P){return Ua(P,[1,0,8])}function Bt(P){return P.env.get("COPILOT_HOME")||bn(P.home,".copilot")}function Uo(P){return(P.hooks?.preToolUse??[]).some((D)=>{if(D.type!==void 0&&D.type!=="command")return!1;return $r(D.command)||$r(D.bash)||$r(D.powershell)||$r(D.exec&&[D.exec,...D.args??[]].join(" "))})}function qt(P){return P===void 0||typeof P==="string"}function xm(P){return P===void 0||Array.isArray(P)&&P.every((O)=>typeof O==="string")}function Cm(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let O=P;if(O.disableAllHooks!==void 0&&typeof O.disableAllHooks!=="boolean")return!1;if(O.hooks===void 0)return!0;if(!O.hooks||typeof O.hooks!=="object"||Array.isArray(O.hooks))return!1;let D=O.hooks.preToolUse;if(D===void 0)return!0;return Array.isArray(D)&&D.every((j)=>j!==null&&typeof j==="object"&&!Array.isArray(j)&&qt(j.type)&&qt(j.command)&&qt(j.bash)&&qt(j.powershell)&&qt(j.exec)&&xm(j.args))}function Go(P,O){try{let D=JSON.parse(vn(bm(P,"utf-8")));if(!Cm(D)){O?.push(`Invalid hook config ${P}: hooks.preToolUse must be an array of hook objects`);return}return D}catch(D){O?.push(`Failed to parse ${P}: ${D instanceof Error?D.message:String(D)}`);return}}function Ga(P,O){try{return vm(P).filter((D)=>D.endsWith(".json")).sort((D,j)=>D.localeCompare(j))}catch(D){return O?.push(`Failed to read ${P}: ${D instanceof Error?D.message:String(D)}`),[]}}function Sm(P,O){if(!Or(P))return[];let D=[];for(let j of Ga(P,O)){let J=bn(P,j),Y=Go(J,O);if(Y&&Uo(Y))D.push(J)}return D}function Rt(P,O){if(!Or(P))return;let D=Go(P,O);if(!D)return;return{path:P,config:D}}function Ma(P,O,D,j){if(O){P.push(`GitHub Copilot CLI ${O} does not support ${D}; requires ${j}+`);return}P.push(`GitHub Copilot CLI version unavailable; skipping ${D} because it requires ${j}+`)}function Pm(P){for(let O of P){if(O?.config.disableAllHooks===!0)return O.path;if(O?.config.disableAllHooks===!1)return}return}function Rm(P,O,D,j){let J=Bt(P),Y=bn(O,".github","hooks"),re=bn(J,"hooks"),ie=bn(O,".github","copilot"),de=bn(O,".claude"),fe=km(D),we=fe===!0?j:void 0,Ce=[Rt(bn(ie,"settings.local.json"),we),Rt(bn(ie,"settings.json"),we),Rt(bn(de,"settings.local.json"),we),Rt(bn(de,"settings.json"),we)],Se=[Rt(bn(J,"settings.json"),we),Rt(bn(J,"config.json"),we)];if(fe!==!1){let an=Pm([...Ce,...Se]);if(an){if(fe===null)j.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${an} as active`);return{activeConfigPaths:[],repoInlineSources:Ce,disabledBy:an}}}let Ie=Sm(Y,j),Ee=wm(D),Ve=Ee===!0?j:void 0,Me=Or(re)?Ga(re,Ve):[],en=[];for(let an of Me){let rn=bn(re,an),fn=Go(rn,Ve);if(fn&&Uo(fn))en.push(rn)}if(Ee!==!0&&en.length>0)Ma(j,D,`user hook files in ${re}`,"0.0.422"),en.length=0;let on=[];for(let an of[...Ce,...Se]){if(!an)continue;if(!Uo(an.config))continue;if(fe===!0){on.push(an);continue}Ma(j,D,"inline hook definitions in Copilot config files","1.0.8");break}let sn=(an)=>an.filter((rn)=>!!rn&&on.includes(rn)).map((rn)=>rn.path);return{activeConfigPaths:[...sn(Ce),...Ie,...sn(Se),...en],repoInlineSources:Ce}}function qa(P){let O=[],D=Rm(P.environment,P.cwd,P.copilotCliVersion,O);if(D.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:D.disabledBy,configPaths:[D.disabledBy],errors:O.length>0?O:void 0};let j=Bt(P.environment),J=bn(j,"installed-plugins",...Ar),Y=Or(J),re=bn(j,"settings.json"),ie=Pn(re,vn),de=(Ie)=>tn(tn(Ie,"enabledPlugins"),Tn),fe=D.repoInlineSources.find((Ie)=>typeof de(Ie?.config)==="boolean"),we=fe??(ie.kind==="ok"?{path:re,config:ie.value}:void 0);if(Y&&!fe&&ie.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};let Ce=Y&&we!==void 0&&de(we.config)===!1;if(Ce&&D.activeConfigPaths.length===0)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:we.path,errors:[`${Tn} is installed but not enabled in Copilot CLI`]};let Se=Y&&!Ce;if(Se||D.activeConfigPaths.length>0){let Ie=D.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:Se?"plugin config":"hook config",configPath:Ie??(Se?J:void 0),configPaths:D.activeConfigPaths.length>0?D.activeConfigPaths:void 0,errors:O.length>0?O:void 0}}return{platform:"copilot-cli",status:"n/a",errors:O.length>0?O:void 0}}import{existsSync as Fm,readFileSync as Hm}from"node:fs";import{existsSync as Ba,mkdirSync as Im,readFileSync as $m}from"node:fs";import{dirname as Om,join as Dm}from"node:path";import{existsSync as Em,renameSync as _m,statSync as Tm,writeFileSync as Am}from"node:fs";function cn(P,O){let D=`${P}.${process.pid}.tmp`;Am(D,O,Em(P)?{mode:Tm(P).mode&511}:{}),_m(D,P)}var xn=Object.fromEntries(Ht.map((P)=>[P.id,`npx -y cc-safety-net hook ${P.flags[1]}`]));var Vt=xn.cursor,Va=30;function Lr(P){return Dm(P.home,".cursor","hooks.json")}function Yn(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function qo(){return{command:Vt,timeout:Va,failClosed:!0}}function Dr(P){return Yn(P)&&P.command===Vt}function Lm(P){return Object.keys(P).length===3&&P.command===Vt&&P.timeout===Va&&P.failClosed===!0}function Nm(P){try{return JSON.parse($m(P,"utf-8"))}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${P}: ${O.message}`);throw O}}function Ja(P){let O=Nm(P);if(!Yn(O))throw Error(`Cursor hooks config ${P} must be a JSON object`);if(O.version!==1)throw Error(`Cursor hooks config ${P} must set "version": 1`);if(O.hooks!==void 0&&!Yn(O.hooks))throw Error(`Cursor hooks config ${P} "hooks" must be an object`);let D=Yn(O.hooks)?O.hooks.preToolUse:void 0;if(D!==void 0&&!Array.isArray(D))throw Error(`Cursor hooks config ${P} "hooks.preToolUse" must be an array`);return O}function Wa(P){let O=Yn(P.hooks)?P.hooks.preToolUse:void 0;return Array.isArray(O)?O:[]}function jm(P){if(!P.some(Dr))return[...P,qo()];return P.reduce((O,D)=>{if(!Dr(D))return O.result.push(D),O;if(!O.inserted)O.result.push(qo()),O.inserted=!0;return O},{result:[],inserted:!1}).result}function Ka(P,O,D){let j=Yn(O.hooks)?O.hooks:{},J={...O,hooks:{...j,preToolUse:D}};cn(P,`${JSON.stringify(J,null,2)}
34
- `)}function za(P){let O=Lr(P);if(!Ba(O))return Im(Om(O),{recursive:!0}),cn(O,`${JSON.stringify({version:1,hooks:{preToolUse:[qo()]}},null,2)}
35
- `),{path:O,alreadyInstalled:!1};let D=Ja(O),j=Wa(D),J=j.filter(Dr);if(Yn(D.hooks)&&Array.isArray(D.hooks.preToolUse)&&J.length===1&&J[0]!==void 0&&Lm(J[0]))return{path:O,alreadyInstalled:!0};return Ka(O,D,jm(j)),{path:O,alreadyInstalled:!1}}function Ya(P){let O=Lr(P);if(!Ba(O))return{path:O,alreadyInstalled:!1};let D=Ja(O),j=Wa(D),J=j.filter((Y)=>!Dr(Y));if(J.length===j.length)return{path:O,alreadyInstalled:!1};return Ka(O,D,J),{path:O,alreadyInstalled:!0}}function Mm(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];let O=P.hooks;if(!O||typeof O!=="object"||Array.isArray(O))return[];let D=O.preToolUse;if(!Array.isArray(D))return[];return D.filter((j)=>!!j&&typeof j==="object"&&!Array.isArray(j)&&j.command===Vt)}function Um(P){let O=[];if(P.length>1)O.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let D=P[0];if(D&&D.failClosed!==!0)O.push('Managed hook is missing "failClosed": true; reinstall to repair');if(D&&D.timeout!==30)O.push('Managed hook "timeout" is not 30; reinstall to repair');return O}function Za(P){let O=Lr(P.environment);if(!Fm(O))return{platform:"cursor",status:"n/a",configPath:O};let D;try{D=JSON.parse(Hm(O,"utf-8"))}catch(Y){return{platform:"cursor",status:"n/a",configPath:O,errors:[`Failed to parse Cursor hooks config ${O}: ${Y instanceof Error?Y.message:String(Y)}`]}}let j=Mm(D);if(j.length===0)return{platform:"cursor",status:"n/a",configPath:O};let J=Um(j);return{platform:"cursor",status:"configured",method:"hook config",configPath:O,errors:J.length>0?J:void 0}}import{readdirSync as Gm}from"node:fs";import{join as Bo,resolve as qm}from"node:path";var Vo="cc-safety-net";function Jo(P){let O=P.env.get("DSH_HOME");return Bo(O?.trim()?qm(Nn(O,P.home)):Bo(P.home,".dsh"),"profiles")}function Xa(P){let O=Jo(P),D=dn(O)?.isDirectory()?Gm(O,{withFileTypes:!0}).filter((J)=>J.isDirectory()&&J.name!=="node_modules").map((J)=>{let Y=Bo(O,J.name,"package.json");return{name:J.name,configPath:Y,manifest:Pn(Y)}}):[];return{installed:D.flatMap((J)=>{if(J.manifest.kind!=="ok")return[];let Y=J.manifest.value;if(tn(tn(Y,"dependencies"),Vo)===void 0)return[];let re=tn(tn(tn(Y,"dsh"),"profile"),"bundles");return[{name:J.name,configPath:J.configPath,enabled:Array.isArray(re)&&re.includes(Vo)}]}),unreadable:D.some((J)=>J.manifest.kind==="unreadable")}}function Wo(P){return Xa(P).installed}function Qa(P){let O=Xa(P.environment),D=O.installed.filter((Y)=>Y.enabled),j=O.installed.filter((Y)=>!Y.enabled),J=j.map((Y)=>`${Vo} is installed in the ${Y.name} profile but its bundle is disabled`);if(D.length>0)return{platform:"deepseek-harness",status:"configured",method:"dsh bundle",configPaths:D.map((Y)=>Y.configPath),...J.length>0?{errors:J}:{}};if(j.length>0)return{platform:"deepseek-harness",status:"disabled",method:"dsh bundle",configPaths:j.map((Y)=>Y.configPath),errors:J};return O.unreadable?{platform:"deepseek-harness",status:"not-inspected"}:{platform:"deepseek-harness",status:"n/a"}}import{existsSync as zm}from"node:fs";import{existsSync as tl,mkdirSync as Bm,readFileSync as Vm}from"node:fs";import{dirname as Jm,join as Yo}from"node:path";function Ko(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function zo(P,O){return Ko(P)&&P.command===O}function el(P,O){return Ko(P)&&Array.isArray(P.hooks)&&P.hooks.some((D)=>zo(D,O))}function Zn(P,O){return{hooks:[{type:"command",command:P,timeout:O}]}}function jn(P,O){return P.flatMap((D)=>{if(!Ko(D)||!Array.isArray(D.hooks))return[D];let j=D.hooks.filter((J)=>!zo(J,O));if(j.length===D.hooks.length)return[D];return j.length===0?[]:[{...D,hooks:j}]})}function Et(P,O,D){let j=P.filter((J)=>el(J,O));return j.length===1&&JSON.stringify(j[0])===JSON.stringify(Zn(O,D))}function _t(P,O){return P.find((D)=>el(D,O))}function Tt(P,O,D){let j=Array.isArray(P.hooks)?P.hooks.find((J)=>zo(J,O)):void 0;return[...P.matcher===void 0||P.matcher===""||P.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...j?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...j?.timeout===D?[]:[`Managed hook "timeout" is not ${D}; reinstall to repair`]]}var Xn=xn.devin,Nr=30,Wm={config:{},hooks:{},preToolUse:[]};function jr(P,O=process.platform){let D=O==="win32"?P.env.get("APPDATA")||Yo(P.home,"AppData","Roaming"):P.env.get("XDG_CONFIG_HOME")||Yo(P.home,".config");return Yo(D,"devin","config.json")}function nl(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Km(P){try{return{ok:!0,value:JSON.parse(vn(Vm(P,"utf-8")))}}catch(O){return{ok:!1,message:O instanceof Error?O.message:String(O)}}}function Zo(P){let O=Km(P);if(!O.ok)return`Failed to parse Devin CLI config ${P}: ${O.message}`;let D=O.value;if(!nl(D))return`Devin CLI config ${P} must be a JSON object`;let j=D.hooks===void 0?{}:D.hooks;if(!nl(j))return`Devin CLI config ${P} "hooks" must be an object`;let J=j.PreToolUse===void 0?[]:j.PreToolUse;if(!Array.isArray(J))return`Devin CLI config ${P} "hooks.PreToolUse" must be an array`;return{config:D,hooks:j,preToolUse:J}}function rl(P){let O=Zo(P);if(typeof O==="string")throw Error(O);return O}function ol(P,O,D){let j={...O.config,hooks:{...O.hooks,PreToolUse:D}};cn(P,`${JSON.stringify(j,null,2)}
36
- `)}function il(P){let O=jr(P),D=tl(O)?rl(O):Wm;if(Et(D.preToolUse,Xn,Nr))return{path:O,alreadyInstalled:!0};return Bm(Jm(O),{recursive:!0}),ol(O,D,[...jn(D.preToolUse,Xn),Zn(Xn,Nr)]),{path:O,alreadyInstalled:!1}}function sl(P){let O=jr(P);if(!tl(O))return{path:O,alreadyInstalled:!1};let D=rl(O),j=jn(D.preToolUse,Xn);if(JSON.stringify(j)===JSON.stringify(D.preToolUse))return{path:O,alreadyInstalled:!1};return ol(O,D,j),{path:O,alreadyInstalled:!0}}function al(P){let O=jr(P.environment);if(!zm(O))return{platform:"devin",status:"n/a",configPath:O};let D=Zo(O);if(typeof D==="string")return{platform:"devin",status:"n/a",configPath:O,errors:[D]};let j=_t(D.preToolUse,Xn);if(!j)return{platform:"devin",status:"n/a",configPath:O};let J=Tt(j,Xn,Nr);return{platform:"devin",status:"configured",method:"hook config",configPath:O,errors:J.length>0?J:void 0}}import{existsSync as ng,readFileSync as tg}from"node:fs";import{existsSync as Fr,mkdirSync as Ym,readFileSync as Zm,rmSync as Xm}from"node:fs";import{dirname as Qm,join as ll}from"node:path";var Qn=xn.droid,Hr=30;function Mr(P){return ll(P.home,".factory","hooks.json")}function cl(P){return ll(P.home,".factory","settings.json")}function Xo(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function dl(P){try{return JSON.parse(Zm(P,"utf-8"))}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Factory Droid hooks config ${P}: ${O.message}`);throw O}}function ul(P){let O=dl(P);if(!Xo(O))throw Error(`Factory Droid hooks config ${P} must be a JSON object`);if(O.PreToolUse===void 0||Array.isArray(O.PreToolUse))return O;throw Error(`Factory Droid hooks config ${P} "PreToolUse" must be an array`)}function eg(P){if(!Fr(P))return{};let O=dl(P);return Xo(O)&&Xo(O.hooks)?O.hooks:{}}function pl(P){return Array.isArray(P.PreToolUse)?P.PreToolUse:[]}function fl(P,O,D){cn(P,`${JSON.stringify({...O,PreToolUse:D},null,2)}
37
- `)}function ml(P){let O=Mr(P),D=Fr(O),j=D?ul(O):eg(cl(P)),J=pl(j);if(D&&Et(J,Qn,Hr))return{path:O,alreadyInstalled:!0};return Ym(Qm(O),{recursive:!0}),fl(O,j,[...jn(J,Qn),Zn(Qn,Hr)]),{path:O,alreadyInstalled:!1}}function gl(P){let O=Mr(P);if(!Fr(O))return{path:O,alreadyInstalled:!1};let D=ul(O),j=pl(D),J=jn(j,Qn);if(JSON.stringify(J)===JSON.stringify(j))return{path:O,alreadyInstalled:!1};let Y=Fr(cl(P));if(J.length===0&&Object.keys(D).length===1&&!Y)return Xm(O),{path:O,alreadyInstalled:!0};return fl(O,D,J),{path:O,alreadyInstalled:!0}}function yl(P){let O=Mr(P.environment);if(!ng(O))return{platform:"droid",status:"n/a",configPath:O};let D;try{D=JSON.parse(tg(O,"utf-8"))}catch(re){return{platform:"droid",status:"n/a",configPath:O,errors:[`Failed to parse Factory Droid hooks config ${O}: ${re instanceof Error?re.message:String(re)}`]}}let j=typeof D==="object"&&D!==null&&"PreToolUse"in D?D.PreToolUse:void 0,J=_t(Array.isArray(j)?j:[],Qn);if(!J)return{platform:"droid",status:"n/a",configPath:O};let Y=[...J.commandRegex===void 0||J.commandRegex===""?[]:['Managed hook has a "commandRegex" that narrows coverage; reinstall to repair'],...Tt(J,Qn,Hr)];return{platform:"droid",status:"configured",method:"hook config",configPath:O,errors:Y.length>0?Y:void 0}}import{existsSync as rg}from"node:fs";import{join as Qo}from"node:path";var ei="gemini-safety-net";function ni(P){let O=Qo(P.home,".gemini","extensions"),D=Qo(O,ei);if(!rg(D))return{platform:"gemini-cli",status:"n/a"};let j=Qo(O,"extension-enablement.json"),J=Pn(j);if(J.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let Y=J.kind==="ok"?tn(tn(J.value,ei),"overrides"):void 0;if(Array.isArray(Y)&&Y.some((ie)=>typeof ie==="string"&&ie.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:j,errors:[`${ei} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:D}}function hl(P){return ni(P.environment)}import{existsSync as ag,readFileSync as lg}from"node:fs";import{existsSync as bl,mkdirSync as og,readFileSync as wl,rmSync as ig}from"node:fs";import{dirname as sg,join as vl}from"node:path";var rt=xn["grok-build"],Gr=30,ti=Zn(rt,Gr);function qr(P){return vl(P.env.get("GROK_HOME")??vl(P.home,".grok"),"hooks","cc-safety-net.json")}function Br(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function kl(P){try{let O=JSON.parse(P);return Br(O)?O:null}catch{return null}}function xl(P){let O=Br(P.hooks)?P.hooks.PreToolUse:void 0;return Array.isArray(O)?O:[]}function Ur(P,O,D){let j=Br(O.hooks)?O.hooks:{};cn(P,`${JSON.stringify({...O,hooks:{...j,PreToolUse:D}},null,2)}
38
- `)}function Cl(P){let O=qr(P);if(!bl(O))return og(sg(O),{recursive:!0}),Ur(O,{},[ti]),{path:O,alreadyInstalled:!1};let D=kl(wl(O,"utf-8"));if(!D)return Ur(O,{},[ti]),{path:O,alreadyInstalled:!1};let j=xl(D);if(Et(j,rt,Gr))return{path:O,alreadyInstalled:!0};return Ur(O,D,[...jn(j,rt),ti]),{path:O,alreadyInstalled:!1}}function Sl(P){let O=qr(P);if(!bl(O))return{path:O,alreadyInstalled:!1};let D=kl(wl(O,"utf-8"));if(!D)return{path:O,alreadyInstalled:!1};let j=xl(D),J=jn(j,rt);if(JSON.stringify(J)===JSON.stringify(j))return{path:O,alreadyInstalled:!1};let Y=Br(D.hooks)?D.hooks:{};if(J.length===0&&Object.keys(D).length===1&&Object.keys(Y).length===1)return ig(O),{path:O,alreadyInstalled:!0};return Ur(O,D,J),{path:O,alreadyInstalled:!0}}function Pl(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function Rl(P){let O=qr(P.environment);if(!ag(O))return{platform:"grok-build",status:"n/a",configPath:O};let D;try{D=JSON.parse(lg(O,"utf-8"))}catch(re){return{platform:"grok-build",status:"n/a",configPath:O,errors:[`Failed to parse Grok Build hooks config ${O}: ${re instanceof Error?re.message:String(re)}`]}}let j=Pl(D)&&Pl(D.hooks)?D.hooks.PreToolUse:void 0,J=_t(Array.isArray(j)?j:[],rt);if(!J)return{platform:"grok-build",status:"n/a",configPath:O};let Y=Tt(J,rt,Gr);return{platform:"grok-build",status:"configured",method:"hook config",configPath:O,errors:Y.length>0?Y:void 0}}import{readFileSync as Ll}from"node:fs";import{join as Nl}from"node:path";var Rn="cc-safety-net",ri="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",cg=30;function El(P){return`${ri}
32
+ `,j-1),Y=J!==-1&&/^\s*$/.test(P.slice(J+1,j))?J:j;return`${P.slice(0,Y)}${P.slice(O.end)}`}function qo(P,O){if(P.startsWith("//",O)){let D=P.indexOf(`
33
+ `,O+2);return D===-1?P.length:D+1}if(P.startsWith("/*",O)){let D=P.indexOf("*/",O+2);return D===-1?P.length:D+2}return O}function Fa(P,O){let D=O;while(D<P.length){if(/\s/.test(P[D]??"")){D++;continue}let j=qo(P,D);if(j===D)return D;D=j}return D}function Ga(P,O,D){let j=0,J=0;while(J<P.length){let Y=qo(P,J);if(Y!==J){J=Y;continue}if(P[J]==='"'){let re=Ha(P,J,D.stringError);if(j===1&&JSON.parse(P.slice(J,re))===O){let ie=Fa(P,re),de=Fa(P,ie+1);if(P[ie]===":"&&P[de]==="[")return{start:de,end:Bo(P,de,{skipComment:qo,...D})}}J=re;continue}if(P[J]==="{"||P[J]==="[")j++;if(P[J]==="}"||P[J]==="]")j--;J++}return}var An="cc-safety-net@cc-marketplace",Dr=["cc-marketplace","cc-safety-net"],qa=["_direct","copilot-safety-net"],Ba=["cc-marketplace","safety-net"],Va="safety-net@cc-marketplace";function Lr(P,O){let D=O.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${D}([^a-z0-9-]|$)`,"m").test(P??"")}function Ja(P){return Lr(P,"cc-safety-net@cc-marketplace")}function Ka(P){return Lr(P,"cc-marketplace")}function Wa(P){return Lr(P,"copilot-safety-net")}function za(P){return Lr(P,"safety-net@cc-marketplace")}function Nr(P){if(!P?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(P)}function Za(P,O){if(!P)return null;let D=P.match(/(\d+)\.(\d+)\.(\d+)/);if(!D)return null;let j=[Number(D[1]),Number(D[2]),Number(D[3])];for(let J=0;J<O.length;J++){let Y=j[J]??0,re=O[J]??0;if(Y!==re)return Y>re}return!0}function Im(P){return Za(P,[0,0,422])}function $m(P){return Za(P,[1,0,8])}function Vt(P){return P.env.get("COPILOT_HOME")||bn(P.home,".copilot")}function Vo(P){return(P.hooks?.preToolUse??[]).some((D)=>{if(D.type!==void 0&&D.type!=="command")return!1;return Nr(D.command)||Nr(D.bash)||Nr(D.powershell)||Nr(D.exec&&[D.exec,...D.args??[]].join(" "))})}function Bt(P){return P===void 0||typeof P==="string"}function Om(P){return P===void 0||Array.isArray(P)&&P.every((O)=>typeof O==="string")}function Dm(P){if(!P||typeof P!=="object"||Array.isArray(P))return!1;let O=P;if(O.disableAllHooks!==void 0&&typeof O.disableAllHooks!=="boolean")return!1;if(O.hooks===void 0)return!0;if(!O.hooks||typeof O.hooks!=="object"||Array.isArray(O.hooks))return!1;let D=O.hooks.preToolUse;if(D===void 0)return!0;return Array.isArray(D)&&D.every((j)=>j!==null&&typeof j==="object"&&!Array.isArray(j)&&Bt(j.type)&&Bt(j.command)&&Bt(j.bash)&&Bt(j.powershell)&&Bt(j.exec)&&Om(j.args))}function Jo(P,O){try{let D=JSON.parse(vn(Tm(P,"utf-8")));if(!Dm(D)){O?.push(`Invalid hook config ${P}: hooks.preToolUse must be an array of hook objects`);return}return D}catch(D){O?.push(`Failed to parse ${P}: ${D instanceof Error?D.message:String(D)}`);return}}function Xa(P,O){try{return Am(P).filter((D)=>D.endsWith(".json")).sort((D,j)=>D.localeCompare(j))}catch(D){return O?.push(`Failed to read ${P}: ${D instanceof Error?D.message:String(D)}`),[]}}function Lm(P,O){if(!jr(P))return[];let D=[];for(let j of Xa(P,O)){let J=bn(P,j),Y=Jo(J,O);if(Y&&Vo(Y))D.push(J)}return D}function Rt(P,O){if(!jr(P))return;let D=Jo(P,O);if(!D)return;return{path:P,config:D}}function Ya(P,O,D,j){if(O){P.push(`GitHub Copilot CLI ${O} does not support ${D}; requires ${j}+`);return}P.push(`GitHub Copilot CLI version unavailable; skipping ${D} because it requires ${j}+`)}function Nm(P){for(let O of P){if(O?.config.disableAllHooks===!0)return O.path;if(O?.config.disableAllHooks===!1)return}return}function jm(P,O,D,j){let J=Vt(P),Y=bn(O,".github","hooks"),re=bn(J,"hooks"),ie=bn(O,".github","copilot"),de=bn(O,".claude"),fe=$m(D),we=fe===!0?j:void 0,Ce=[Rt(bn(ie,"settings.local.json"),we),Rt(bn(ie,"settings.json"),we),Rt(bn(de,"settings.local.json"),we),Rt(bn(de,"settings.json"),we)],Se=[Rt(bn(J,"settings.json"),we),Rt(bn(J,"config.json"),we)];if(fe!==!1){let an=Nm([...Ce,...Se]);if(an){if(fe===null)j.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${an} as active`);return{activeConfigPaths:[],repoInlineSources:Ce,disabledBy:an}}}let Ie=Lm(Y,j),Ee=Im(D),Ve=Ee===!0?j:void 0,Me=jr(re)?Xa(re,Ve):[],en=[];for(let an of Me){let rn=bn(re,an),fn=Jo(rn,Ve);if(fn&&Vo(fn))en.push(rn)}if(Ee!==!0&&en.length>0)Ya(j,D,`user hook files in ${re}`,"0.0.422"),en.length=0;let on=[];for(let an of[...Ce,...Se]){if(!an)continue;if(!Vo(an.config))continue;if(fe===!0){on.push(an);continue}Ya(j,D,"inline hook definitions in Copilot config files","1.0.8");break}let sn=(an)=>an.filter((rn)=>!!rn&&on.includes(rn)).map((rn)=>rn.path);return{activeConfigPaths:[...sn(Ce),...Ie,...sn(Se),...en],repoInlineSources:Ce}}function Qa(P){let O=[],D=jm(P.environment,P.cwd,P.copilotCliVersion,O);if(D.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:D.disabledBy,configPaths:[D.disabledBy],errors:O.length>0?O:void 0};let j=Vt(P.environment),J=bn(j,"installed-plugins",...Dr),Y=jr(J),re=bn(j,"settings.json"),ie=xn(re,vn),de=(Ie)=>tn(tn(Ie,"enabledPlugins"),An),fe=D.repoInlineSources.find((Ie)=>typeof de(Ie?.config)==="boolean"),we=fe??(ie.kind==="ok"?{path:re,config:ie.value}:void 0);if(Y&&!fe&&ie.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};let Ce=Y&&we!==void 0&&de(we.config)===!1;if(Ce&&D.activeConfigPaths.length===0)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:we.path,errors:[`${An} is installed but not enabled in Copilot CLI`]};let Se=Y&&!Ce;if(Se||D.activeConfigPaths.length>0){let Ie=D.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:Se?"plugin config":"hook config",configPath:Ie??(Se?J:void 0),configPaths:D.activeConfigPaths.length>0?D.activeConfigPaths:void 0,errors:O.length>0?O:void 0}}return{platform:"copilot-cli",status:"n/a",errors:O.length>0?O:void 0}}import{existsSync as ei,readdirSync as Zm,readFileSync as Xm}from"node:fs";import{join as Qo}from"node:path";import{existsSync as Zo,mkdirSync as Bm,readFileSync as Vm,rmSync as Jm}from"node:fs";import{dirname as Km,join as Fr}from"node:path";import{existsSync as Fm,renameSync as Hm,statSync as Mm,writeFileSync as Um}from"node:fs";function cn(P,O){let D=`${P}.${process.pid}.tmp`;Um(D,O,Fm(P)?{mode:Mm(P).mode&511}:{}),Hm(D,P)}import{spawn as Gm}from"node:child_process";function qm(P){return P.join(" ")}function Ko(P,O,D){return[`Failed to run ${qm(P)}${O===null?"":` (exit ${O})`}.`,D.trim()].filter(Boolean).join(`
34
+ `)}function Wo(P){let O={stdout:"",stderr:""};return P.stdout.setEncoding("utf-8"),P.stderr.setEncoding("utf-8"),P.stdout.on("data",(D)=>{O.stdout+=D}),P.stderr.on("data",(D)=>{O.stderr+=D}),O}function gn(P,O){return new Promise((D,j)=>{let J=zn([...P],process.env),Y=Gm(J.cmd,J.args,{stdio:["ignore","pipe","pipe"]}),re=Wo(Y),ie=()=>[re.stdout,re.stderr].filter(Boolean).join(`
35
+ `),de=O?.timeoutMs??120000,fe=setTimeout(()=>{Y.kill(),j(Error(Ko(P,null,`Timed out after ${de}ms.
36
+ ${ie()}`.trim())))},de);Y.on("error",(we)=>{clearTimeout(fe),j(Error(Ko(P,null,`${we.message}
37
+ ${ie()}`.trim())))}),Y.on("close",(we)=>{if(clearTimeout(fe),we!==0){j(Error(Ko(P,we,ie())));return}D(O?.stdoutOnly?re.stdout:ie())})})}async function zo(P){for(let O of P)await gn(O)}async function el(P){for(let O of P)try{await gn(O)}catch(D){console.warn(D instanceof Error?D.message:String(D))}}var Cn=Object.fromEntries(Ht.map((P)=>[P.id,`npx -y cc-safety-net hook ${P.flags[1]}`]));var Kt=Cn.cursor,nl=30;function Mr(P){return Fr(P.home,".cursor","hooks.json")}var Jt="cc-safety-net";function Xo(P){let O=Fr(P.home,".cursor","plugins");return{cache:Fr(O,"cache",Jt),marketplaceClone:Fr(O,"marketplaces","github.com","kenryu42","cc-safety-net")}}async function tl(P){let O=Object.values(Xo(P));if(!O.some((j)=>Zo(j)))return;let D="No marketplace matches";return await gn(["cursor-agent","plugin","marketplace","remove",Jt]).catch((j)=>{if(!(j instanceof Error&&j.message.includes(D)))throw j}),O.forEach((j)=>Jm(j,{recursive:!0,force:!0})),[`Removed the ${Jt} marketplace from your Cursor account.`,"If /plugins in cursor-agent still lists CC Safety Net as installed, uninstall it there."].join(`
38
+ `)}function Yn(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function Yo(){return{command:Kt,timeout:nl,failClosed:!0}}function Hr(P){return Yn(P)&&P.command===Kt}function Wm(P){return Object.keys(P).length===3&&P.command===Kt&&P.timeout===nl&&P.failClosed===!0}function zm(P){try{return JSON.parse(Vm(P,"utf-8"))}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${P}: ${O.message}`);throw O}}function rl(P){let O=zm(P);if(!Yn(O))throw Error(`Cursor hooks config ${P} must be a JSON object`);if(O.version!==1)throw Error(`Cursor hooks config ${P} must set "version": 1`);if(O.hooks!==void 0&&!Yn(O.hooks))throw Error(`Cursor hooks config ${P} "hooks" must be an object`);let D=Yn(O.hooks)?O.hooks.preToolUse:void 0;if(D!==void 0&&!Array.isArray(D))throw Error(`Cursor hooks config ${P} "hooks.preToolUse" must be an array`);return O}function ol(P){let O=Yn(P.hooks)?P.hooks.preToolUse:void 0;return Array.isArray(O)?O:[]}function Ym(P){if(!P.some(Hr))return[...P,Yo()];return P.reduce((O,D)=>{if(!Hr(D))return O.result.push(D),O;if(!O.inserted)O.result.push(Yo()),O.inserted=!0;return O},{result:[],inserted:!1}).result}function il(P,O,D){let j=Yn(O.hooks)?O.hooks:{},J={...O,hooks:{...j,preToolUse:D}};cn(P,`${JSON.stringify(J,null,2)}
39
+ `)}function sl(P){let O=Mr(P);if(!Zo(O))return Bm(Km(O),{recursive:!0}),cn(O,`${JSON.stringify({version:1,hooks:{preToolUse:[Yo()]}},null,2)}
40
+ `),{path:O,alreadyInstalled:!1};let D=rl(O),j=ol(D),J=j.filter(Hr);if(Yn(D.hooks)&&Array.isArray(D.hooks.preToolUse)&&J.length===1&&J[0]!==void 0&&Wm(J[0]))return{path:O,alreadyInstalled:!0};return il(O,D,Ym(j)),{path:O,alreadyInstalled:!1}}function al(P){let O=Mr(P);if(!Zo(O))return{path:O,alreadyInstalled:!1};let D=rl(O),j=ol(D),J=j.filter((Y)=>!Hr(Y));if(J.length===j.length)return{path:O,alreadyInstalled:!1};return il(O,D,J),{path:O,alreadyInstalled:!0}}function Qm(P){if(!P||typeof P!=="object"||Array.isArray(P))return[];let O=P.hooks;if(!O||typeof O!=="object"||Array.isArray(O))return[];let D=O.preToolUse;if(!Array.isArray(D))return[];return D.filter((j)=>!!j&&typeof j==="object"&&!Array.isArray(j)&&j.command===Kt)}function eg(P){let O=[];if(P.length>1)O.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let D=P[0];if(D&&D.failClosed!==!0)O.push('Managed hook is missing "failClosed": true; reinstall to repair');if(D&&D.timeout!==30)O.push('Managed hook "timeout" is not 30; reinstall to repair');return O}var Ur="Claude Code plugin",ni="Cursor plugin";function ng(P){let O=Qo(Xo(P).cache,Jt);if(!ei(O))return{};try{return{version:Zm(O).map((D)=>Qo(O,D)).find((D)=>ei(Qo(D,".cache-complete")))}}catch{return{unreadable:O}}}function tg(P,O){if(O){let J=["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:ni,configPath:O,duplicate:`The Cursor plugin also runs this check, so every tool call is checked twice. ${J} 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:`${J} If /plugins in cursor-agent does not list CC Safety Net as installed, run \`cc-safety-net install --cursor\`.`}}let D=Da(P);if(!D)return;let j="Cursor runs the Claude Code plugin only while it imports Claude Code plugins, which doctor cannot check.";return{method:Ur,configPath:D,duplicate:`The Claude Code plugin also runs this check in Cursor, so every tool call is checked twice. ${j} If Cursor runs it, run \`cc-safety-net uninstall --cursor\` to remove this hook.`,alone:`${j} If it stops, run \`cc-safety-net install --cursor\`.`}}function ll(P){let O=rg(P),D=ng(P.environment);if(D.unreadable)return O.status==="configured"?{...O,errors:[...O.errors??[],`Cannot read ${D.unreadable}, so doctor cannot tell whether the Cursor plugin also runs this check.`]}:{platform:"cursor",status:"not-inspected"};let j=tg(P.environment,D.version);if(!j)return O;if(O.status==="configured")return{...O,errors:[...O.errors??[],j.duplicate]};return{platform:"cursor",status:"configured",method:j.method,configPath:j.configPath,errors:[...O.errors??[],j.alone]}}function rg(P){let O=Mr(P.environment);if(!ei(O))return{platform:"cursor",status:"n/a",configPath:O};let D;try{D=JSON.parse(Xm(O,"utf-8"))}catch(Y){return{platform:"cursor",status:"n/a",configPath:O,errors:[`Failed to parse Cursor hooks config ${O}: ${Y instanceof Error?Y.message:String(Y)}`]}}let j=Qm(D);if(j.length===0)return{platform:"cursor",status:"n/a",configPath:O};let J=eg(j);return{platform:"cursor",status:"configured",method:"hook config",configPath:O,errors:J.length>0?J:void 0}}import{readdirSync as og}from"node:fs";import{join as ti,resolve as ig}from"node:path";var ri="cc-safety-net";function oi(P){let O=P.env.get("DSH_HOME");return ti(O?.trim()?ig(Nn(O,P.home)):ti(P.home,".dsh"),"profiles")}function cl(P){let O=oi(P),D=dn(O)?.isDirectory()?og(O,{withFileTypes:!0}).filter((J)=>J.isDirectory()&&J.name!=="node_modules").map((J)=>{let Y=ti(O,J.name,"package.json");return{name:J.name,configPath:Y,manifest:xn(Y)}}):[];return{installed:D.flatMap((J)=>{if(J.manifest.kind!=="ok")return[];let Y=J.manifest.value;if(tn(tn(Y,"dependencies"),ri)===void 0)return[];let re=tn(tn(tn(Y,"dsh"),"profile"),"bundles");return[{name:J.name,configPath:J.configPath,enabled:Array.isArray(re)&&re.includes(ri)}]}),unreadable:D.some((J)=>J.manifest.kind==="unreadable")}}function ii(P){return cl(P).installed}function dl(P){let O=cl(P.environment),D=O.installed.filter((Y)=>Y.enabled),j=O.installed.filter((Y)=>!Y.enabled),J=j.map((Y)=>`${ri} is installed in the ${Y.name} profile but its bundle is disabled`);if(D.length>0)return{platform:"deepseek-harness",status:"configured",method:"dsh bundle",configPaths:D.map((Y)=>Y.configPath),...J.length>0?{errors:J}:{}};if(j.length>0)return{platform:"deepseek-harness",status:"disabled",method:"dsh bundle",configPaths:j.map((Y)=>Y.configPath),errors:J};return O.unreadable?{platform:"deepseek-harness",status:"not-inspected"}:{platform:"deepseek-harness",status:"n/a"}}import{existsSync as ug}from"node:fs";import{existsSync as fl,mkdirSync as sg,readFileSync as ag}from"node:fs";import{dirname as lg,join as li}from"node:path";function si(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function ai(P,O){return si(P)&&P.command===O}function ul(P,O){return si(P)&&Array.isArray(P.hooks)&&P.hooks.some((D)=>ai(D,O))}function Zn(P,O){return{hooks:[{type:"command",command:P,timeout:O}]}}function jn(P,O){return P.flatMap((D)=>{if(!si(D)||!Array.isArray(D.hooks))return[D];let j=D.hooks.filter((J)=>!ai(J,O));if(j.length===D.hooks.length)return[D];return j.length===0?[]:[{...D,hooks:j}]})}function Et(P,O,D){let j=P.filter((J)=>ul(J,O));return j.length===1&&JSON.stringify(j[0])===JSON.stringify(Zn(O,D))}function _t(P,O){return P.find((D)=>ul(D,O))}function At(P,O,D){let j=Array.isArray(P.hooks)?P.hooks.find((J)=>ai(J,O)):void 0;return[...P.matcher===void 0||P.matcher===""||P.matcher==="*"?[]:['Managed hook has a "matcher" that narrows coverage; reinstall to repair'],...j?.type==="command"?[]:['Managed hook "type" is not "command"; reinstall to repair'],...j?.timeout===D?[]:[`Managed hook "timeout" is not ${D}; reinstall to repair`]]}var Xn=Cn.devin,Gr=30,cg={config:{},hooks:{},preToolUse:[]};function qr(P,O=process.platform){let D=O==="win32"?P.env.get("APPDATA")||li(P.home,"AppData","Roaming"):P.env.get("XDG_CONFIG_HOME")||li(P.home,".config");return li(D,"devin","config.json")}function pl(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function dg(P){try{return{ok:!0,value:JSON.parse(vn(ag(P,"utf-8")))}}catch(O){return{ok:!1,message:O instanceof Error?O.message:String(O)}}}function ci(P){let O=dg(P);if(!O.ok)return`Failed to parse Devin CLI config ${P}: ${O.message}`;let D=O.value;if(!pl(D))return`Devin CLI config ${P} must be a JSON object`;let j=D.hooks===void 0?{}:D.hooks;if(!pl(j))return`Devin CLI config ${P} "hooks" must be an object`;let J=j.PreToolUse===void 0?[]:j.PreToolUse;if(!Array.isArray(J))return`Devin CLI config ${P} "hooks.PreToolUse" must be an array`;return{config:D,hooks:j,preToolUse:J}}function ml(P){let O=ci(P);if(typeof O==="string")throw Error(O);return O}function gl(P,O,D){let j={...O.config,hooks:{...O.hooks,PreToolUse:D}};cn(P,`${JSON.stringify(j,null,2)}
41
+ `)}function yl(P){let O=qr(P),D=fl(O)?ml(O):cg;if(Et(D.preToolUse,Xn,Gr))return{path:O,alreadyInstalled:!0};return sg(lg(O),{recursive:!0}),gl(O,D,[...jn(D.preToolUse,Xn),Zn(Xn,Gr)]),{path:O,alreadyInstalled:!1}}function hl(P){let O=qr(P);if(!fl(O))return{path:O,alreadyInstalled:!1};let D=ml(O),j=jn(D.preToolUse,Xn);if(JSON.stringify(j)===JSON.stringify(D.preToolUse))return{path:O,alreadyInstalled:!1};return gl(O,D,j),{path:O,alreadyInstalled:!0}}function vl(P){let O=qr(P.environment);if(!ug(O))return{platform:"devin",status:"n/a",configPath:O};let D=ci(O);if(typeof D==="string")return{platform:"devin",status:"n/a",configPath:O,errors:[D]};let j=_t(D.preToolUse,Xn);if(!j)return{platform:"devin",status:"n/a",configPath:O};let J=At(j,Xn,Gr);return{platform:"devin",status:"configured",method:"hook config",configPath:O,errors:J.length>0?J:void 0}}import{existsSync as hg,readFileSync as vg}from"node:fs";import{existsSync as Br,mkdirSync as pg,readFileSync as fg,rmSync as mg}from"node:fs";import{dirname as gg,join as bl}from"node:path";var Qn=Cn.droid,Vr=30;function Jr(P){return bl(P.home,".factory","hooks.json")}function wl(P){return bl(P.home,".factory","settings.json")}function di(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function kl(P){try{return JSON.parse(fg(P,"utf-8"))}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Factory Droid hooks config ${P}: ${O.message}`);throw O}}function xl(P){let O=kl(P);if(!di(O))throw Error(`Factory Droid hooks config ${P} must be a JSON object`);if(O.PreToolUse===void 0||Array.isArray(O.PreToolUse))return O;throw Error(`Factory Droid hooks config ${P} "PreToolUse" must be an array`)}function yg(P){if(!Br(P))return{};let O=kl(P);return di(O)&&di(O.hooks)?O.hooks:{}}function Cl(P){return Array.isArray(P.PreToolUse)?P.PreToolUse:[]}function Sl(P,O,D){cn(P,`${JSON.stringify({...O,PreToolUse:D},null,2)}
42
+ `)}function Pl(P){let O=Jr(P),D=Br(O),j=D?xl(O):yg(wl(P)),J=Cl(j);if(D&&Et(J,Qn,Vr))return{path:O,alreadyInstalled:!0};return pg(gg(O),{recursive:!0}),Sl(O,j,[...jn(J,Qn),Zn(Qn,Vr)]),{path:O,alreadyInstalled:!1}}function Rl(P){let O=Jr(P);if(!Br(O))return{path:O,alreadyInstalled:!1};let D=xl(O),j=Cl(D),J=jn(j,Qn);if(JSON.stringify(J)===JSON.stringify(j))return{path:O,alreadyInstalled:!1};let Y=Br(wl(P));if(J.length===0&&Object.keys(D).length===1&&!Y)return mg(O),{path:O,alreadyInstalled:!0};return Sl(O,D,J),{path:O,alreadyInstalled:!0}}function El(P){let O=Jr(P.environment);if(!hg(O))return{platform:"droid",status:"n/a",configPath:O};let D;try{D=JSON.parse(vg(O,"utf-8"))}catch(re){return{platform:"droid",status:"n/a",configPath:O,errors:[`Failed to parse Factory Droid hooks config ${O}: ${re instanceof Error?re.message:String(re)}`]}}let j=typeof D==="object"&&D!==null&&"PreToolUse"in D?D.PreToolUse:void 0,J=_t(Array.isArray(j)?j:[],Qn);if(!J)return{platform:"droid",status:"n/a",configPath:O};let Y=[...J.commandRegex===void 0||J.commandRegex===""?[]:['Managed hook has a "commandRegex" that narrows coverage; reinstall to repair'],...At(J,Qn,Vr)];return{platform:"droid",status:"configured",method:"hook config",configPath:O,errors:Y.length>0?Y:void 0}}import{existsSync as bg}from"node:fs";import{join as ui}from"node:path";var pi="gemini-safety-net";function fi(P){let O=ui(P.home,".gemini","extensions"),D=ui(O,pi);if(!bg(D))return{platform:"gemini-cli",status:"n/a"};let j=ui(O,"extension-enablement.json"),J=xn(j);if(J.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let Y=J.kind==="ok"?tn(tn(J.value,pi),"overrides"):void 0;if(Array.isArray(Y)&&Y.some((ie)=>typeof ie==="string"&&ie.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:j,errors:[`${pi} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:D}}function _l(P){return fi(P.environment)}import{existsSync as Cg,readFileSync as Sg}from"node:fs";import{existsSync as Tl,mkdirSync as wg,readFileSync as Il,rmSync as kg}from"node:fs";import{dirname as xg,join as Al}from"node:path";var rt=Cn["grok-build"],Wr=30,mi=Zn(rt,Wr);function zr(P){return Al(P.env.get("GROK_HOME")??Al(P.home,".grok"),"hooks","cc-safety-net.json")}function Yr(P){return typeof P==="object"&&P!==null&&!Array.isArray(P)}function $l(P){try{let O=JSON.parse(P);return Yr(O)?O:null}catch{return null}}function Ol(P){let O=Yr(P.hooks)?P.hooks.PreToolUse:void 0;return Array.isArray(O)?O:[]}function Kr(P,O,D){let j=Yr(O.hooks)?O.hooks:{};cn(P,`${JSON.stringify({...O,hooks:{...j,PreToolUse:D}},null,2)}
43
+ `)}function Dl(P){let O=zr(P);if(!Tl(O))return wg(xg(O),{recursive:!0}),Kr(O,{},[mi]),{path:O,alreadyInstalled:!1};let D=$l(Il(O,"utf-8"));if(!D)return Kr(O,{},[mi]),{path:O,alreadyInstalled:!1};let j=Ol(D);if(Et(j,rt,Wr))return{path:O,alreadyInstalled:!0};return Kr(O,D,[...jn(j,rt),mi]),{path:O,alreadyInstalled:!1}}function Ll(P){let O=zr(P);if(!Tl(O))return{path:O,alreadyInstalled:!1};let D=$l(Il(O,"utf-8"));if(!D)return{path:O,alreadyInstalled:!1};let j=Ol(D),J=jn(j,rt);if(JSON.stringify(J)===JSON.stringify(j))return{path:O,alreadyInstalled:!1};let Y=Yr(D.hooks)?D.hooks:{};if(J.length===0&&Object.keys(D).length===1&&Object.keys(Y).length===1)return kg(O),{path:O,alreadyInstalled:!0};return Kr(O,D,J),{path:O,alreadyInstalled:!0}}function Nl(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}function jl(P){let O=zr(P.environment);if(!Cg(O))return{platform:"grok-build",status:"n/a",configPath:O};let D;try{D=JSON.parse(Sg(O,"utf-8"))}catch(re){return{platform:"grok-build",status:"n/a",configPath:O,errors:[`Failed to parse Grok Build hooks config ${O}: ${re instanceof Error?re.message:String(re)}`]}}let j=Nl(D)&&Nl(D.hooks)?D.hooks.PreToolUse:void 0,J=_t(Array.isArray(j)?j:[],rt);if(!J)return{platform:"grok-build",status:"n/a",configPath:O};let Y=At(J,rt,Wr);return{platform:"grok-build",status:"configured",method:"hook config",configPath:O,errors:Y.length>0?Y:void 0}}import{readFileSync as Jl}from"node:fs";import{join as Kl}from"node:path";var Rn="cc-safety-net",gi="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent",Pg=30;function Fl(P){return`${gi}
39
44
  # version: ${P}
40
- `}function dg(P){return`${El(P)}name: ${Rn}
45
+ `}function Rg(P){return`${Fl(P)}name: ${Rn}
41
46
  version: "${P}"
42
47
  description: "Block destructive commands and secret-file access before Hermes runs a tool."
43
48
  author: "cc-safety-net"
44
49
  provides_hooks:
45
50
  - pre_tool_call
46
- `}function ug(P){return`${El(P)}"""CC Safety Net guard for Hermes Agent.
51
+ `}function Eg(P){return`${Fl(P)}"""CC Safety Net guard for Hermes Agent.
47
52
 
48
53
  Registers pre_tool_call and forwards the tool call to the packaged CC Safety Net
49
54
  adapter (cc-safety-net hook --hermes-agent) over JSON stdin. The adapter prints nothing
@@ -59,8 +64,8 @@ import subprocess
59
64
 
60
65
  HOOK_EVENT = "pre_tool_call"
61
66
  SUPPORTED_TOOLS = ("patch", "read_file", "terminal", "write_file")
62
- ANALYZER = [${xn["hermes-agent"].split(" ").map((O)=>`"${O}"`).join(", ")}]
63
- TIMEOUT_SECONDS = ${cg}
67
+ ANALYZER = [${Cn["hermes-agent"].split(" ").map((O)=>`"${O}"`).join(", ")}]
68
+ TIMEOUT_SECONDS = ${Pg}
64
69
 
65
70
 
66
71
  def _block(detail):
@@ -213,85 +218,82 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
213
218
 
214
219
  def register(ctx):
215
220
  ctx.register_hook("pre_tool_call", _pre_tool_call)
216
- `}function Jt(P){return[{name:"__init__.py",content:ug(P)},{name:"plugin.yaml",content:dg(P)}]}import{mkdirSync as pg,readdirSync as fg,readFileSync as _l,rmSync as oi}from"node:fs";import{basename as mg,dirname as gg,join as Fn}from"node:path";var yg="__pycache__",hg=/^[a-z0-9][a-z0-9_-]{0,63}$/;function vg(P){try{return _l(P,"utf-8").trim()}catch{return}}function ii(P){let O=P.env.get("HERMES_HOME")?.trim();if(O&&mg(gg(O))==="profiles")return O;let D=O||Fn(P.home,".hermes"),j=Fn(D,"active_profile"),J=vg(j),Y=J?.toLowerCase();if(!Y||Y==="default")return D;if(!hg.test(Y))throw Error(`Invalid Hermes profile name "${J}" in ${j}; run \`hermes profile use <name>\` with a valid profile.`);return Fn(D,"profiles",Y)}function si(P){return Fn(ii(P),"plugins",Rn)}function ai(P){return P.startsWith(ri)}function li(P,O){let D=si(P),j=dn(D);if(j&&(j.isSymbolicLink()||!j.isDirectory()))throw Error(`Refusing to ${O} ${D}: not a regular directory. Move or remove it and rerun ${O==="install"?"install":"uninstall"} --hermes-agent.`);return D}function Tl(P,O){let D=dn(P);if(!D)return;if(D.isSymbolicLink()||!D.isFile())throw Error(`Refusing to ${O} ${P}: not a regular file. Move or remove it.`);let j=_l(P,"utf-8");if(!ai(j))throw Error(`Refusing to ${O} unmanaged file at ${P}. Move or remove it.`);return j}function Al(P){let O=li(P,"install"),D=Jt(pn());if(D.map((J)=>Tl(Fn(O,J.name),"overwrite")).every((J,Y)=>J===D[Y]?.content))return{path:O,alreadyInstalled:!0};return pg(O,{recursive:!0}),D.forEach((J)=>{cn(Fn(O,J.name),J.content)}),{path:O,alreadyInstalled:!1}}function ci(P){let O=li(P,"remove");if(!dn(O))return[];return Jt(pn()).filter((D)=>Tl(Fn(O,D.name),"remove")!==void 0)}function Il(P){let O=li(P,"remove");if(!dn(O))return{path:O,alreadyInstalled:!1};let D=ci(P);if(D.forEach((j)=>{oi(Fn(O,j.name))}),oi(Fn(O,yg),{recursive:!0,force:!0}),fg(O).length===0)oi(O,{recursive:!0});return{path:O,alreadyInstalled:D.length>0}}var Wt="hermes-agent",$l=/^([^\s#][^:]*):/,bg=/^\s+([A-Za-z_][\w-]*):/,Ol=/^\s+-\s*(.*)$/;function wg(P){return P.trim().replace(/^(["'])(.*)\1$/,"$2")}function kg(P){let O=P.split(/\r?\n/),D=O.findIndex((Y)=>$l.exec(Y)?.[1]?.trim()==="plugins");if(D===-1)return[];let j=O.slice(D+1),J=j.findIndex((Y)=>$l.test(Y));return J===-1?j:j.slice(0,J)}function Dl(P,O){let D=kg(P),j=D.findIndex((re)=>bg.exec(re)?.[1]===O);if(j===-1)return[];let J=D.slice(j+1),Y=J.findIndex((re)=>!Ol.test(re));return(Y===-1?J:J.slice(0,Y)).map((re)=>wg(Ol.exec(re)?.[1]??""))}function xg(P){try{return Ll(Nl(ii(P),"config.yaml"),"utf-8")}catch{return}}function di(P){let O=xg(P)??"";return Dl(O,"enabled").includes(Rn)&&!Dl(O,"disabled").includes(Rn)}function jl(P){return/^# version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function Cg(P,O){let D=dn(P);if(!D)return{error:`${O.name} is missing from ${P}; run install --hermes-agent`};if(D.isSymbolicLink()||!D.isFile())return{error:`${P} is a symlink or not a regular file; move or remove it`};try{let j=Ll(P,"utf-8");if(!ai(j))return{error:`Unmanaged ${O.name} occupies ${P}; move or remove it`};if(jl(j)===pn()&&j!==O.content)return{error:`Modified ${O.name} occupies ${P}; run install --hermes-agent to restore it`};return{content:j}}catch(j){return{error:`Failed to read ${P}: ${j instanceof Error?j.message:String(j)}`}}}function Sg(P){try{return{path:si(P)}}catch(O){return{error:O instanceof Error?O.message:String(O)}}}function Fl(P){let O=Sg(P.environment);if("error"in O)return{platform:Wt,status:"n/a",errors:[O.error]};let D=O.path,j=Er(Wt,D);if(j)return j;let J=Jt(pn()).map((de)=>Cg(Nl(D,de.name),de)),Y=J.flatMap((de)=>("error"in de)?[de.error]:[]);if(Y.length>0)return{platform:Wt,status:"n/a",configPath:D,errors:Y};let re=J.some((de)=>("content"in de)&&jl(de.content)!==pn()),ie=re?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!di(P.environment))return{platform:Wt,status:"disabled",method:"plugin directory",configPath:D,errors:[`${Rn} is not enabled in Hermes; run \`hermes plugins enable ${Rn}\``,...ie]};return{platform:Wt,status:"configured",method:"plugin directory",configPath:D,errors:re?ie:void 0}}import{existsSync as Pg,readFileSync as Rg}from"node:fs";import{join as Hl}from"node:path";var Eg=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function _g(P){return Hl(P.env.get("KIMI_CODE_HOME")||Hl(P.home,".kimi-code"),"config.toml")}function Kt(P){let O=_g(P.environment);if(!Pg(O))return{platform:"kimi-code",status:"n/a",configPath:O};try{if(!Eg.test(Rg(O,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:O}}catch(D){return{platform:"kimi-code",status:"n/a",configPath:O,errors:[`Failed to read ${O}: ${D instanceof Error?D.message:String(D)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:O}}import{readFileSync as zl}from"node:fs";import{join as Yt}from"node:path";var un="cc-safety-net",Sn="index.js",At="openclaw.plugin.json",It="package.json";var Vr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as Ig,lstatSync as $g,readdirSync as Og,readFileSync as Dg}from"node:fs";import{dirname as Ul,join as qn}from"node:path";import{fileURLToPath as Lg}from"node:url";import{spawn as Tg}from"node:child_process";function Ag(P){return P.join(" ")}function ui(P,O,D){return[`Failed to run ${Ag(P)}${O===null?"":` (exit ${O})`}.`,D.trim()].filter(Boolean).join(`
217
- `)}function pi(P){let O={stdout:"",stderr:""};return P.stdout.setEncoding("utf-8"),P.stderr.setEncoding("utf-8"),P.stdout.on("data",(D)=>{O.stdout+=D}),P.stderr.on("data",(D)=>{O.stderr+=D}),O}function hn(P,O){return new Promise((D,j)=>{let J=zn([...P],process.env),Y=Tg(J.cmd,J.args,{stdio:["ignore","pipe","pipe"]}),re=pi(Y),ie=()=>[re.stdout,re.stderr].filter(Boolean).join(`
218
- `),de=O?.timeoutMs??120000,fe=setTimeout(()=>{Y.kill(),j(Error(ui(P,null,`Timed out after ${de}ms.
219
- ${ie()}`.trim())))},de);Y.on("error",(we)=>{clearTimeout(fe),j(Error(ui(P,null,`${we.message}
220
- ${ie()}`.trim())))}),Y.on("close",(we)=>{if(clearTimeout(fe),we!==0){j(Error(ui(P,we,ie())));return}D(O?.stdoutOnly?re.stdout:ie())})})}async function fi(P){for(let O of P)await hn(O)}async function Ml(P){for(let O of P)try{await hn(O)}catch(D){console.warn(D instanceof Error?D.message:String(D))}}var mi=qn("openclaw",un),it=`run \`openclaw plugins enable ${un}\``,Ng="config reload superseded by a newer runtime config source",jg=[Sn,At,It];function Gl(P){let O=P.env.get("OPENCLAW_HOME")?.trim();return O?Nn(O,P.home):P.home}function ql(P){let O=Gl(P),D=P.env.get("OPENCLAW_STATE_DIR")?.trim();if(D)return Nn(D,O);let j=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return j?Ul(Nn(j,O)):qn(O,".openclaw")}function Bl(P){let O=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return O?Nn(O,Gl(P)):qn(ql(P),"openclaw.json")}function zt(P){return qn(ql(P),"extensions",un)}function Fg(P){let O=Og(P);if(O.length===0)return!0;if(O.some((J)=>!jg.includes(J)))return!1;let D=qn(P,Sn),j=dn(D);return j!==void 0&&!j.isSymbolicLink()&&j.isFile()&&Dg(D,"utf-8").startsWith(Vr)}function gi(P){let O=zt(P),D=dn(O);if(!D)return;if(!D.isSymbolicLink()&&D.isDirectory()&&Fg(O))return;throw Error(`Refusing to modify ${O}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function Vl(){let P=Ul(Lg(import.meta.url));return[qn(P,mi),qn(P,"..",mi),qn(P,"..","..","..","dist",mi)]}function yi(P=Vl()){return P.find((O)=>Ig(O)&&$g(O).isDirectory())}function Hg(P=Vl()){let O=yi(P);if(!O)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return O}function Jl(P=Hg()){return[["openclaw","plugins","install",P,"--force","--accept-capabilities"]]}function Mg(P){let O=(()=>{try{return JSON.parse(P)}catch{return}})(),D=tn(tn(O,"plugin"),"status");return typeof D==="string"?D:void 0}async function Ug(){await hn(["openclaw","plugins","enable",un]).catch((P)=>{if(!(P instanceof Error&&P.message.includes(Ng)))throw P})}async function Wl(P){let O=async()=>Mg(await hn(["openclaw","plugins","inspect",un,"--runtime","--json"],{stdoutOnly:!0})),D=await O(),j=D==="disabled"&&P;if(j)await Ug();let J=j?await O():D;if(J==="loaded")return;throw Error(`${J===void 0?`The ${un} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:J==="disabled"?`OpenClaw reports the ${un} plugin with status "disabled"; ${it}.`:`OpenClaw reports the ${un} plugin with status "${J}".`} Run \`openclaw plugins inspect ${un} --runtime\` for details.`)}var Jr="openclaw";function $t(P,O){let D=Yt(P,O),j=dn(D);if(!j)return{error:`${O} is missing from ${D}; run install --openclaw`};if(j.isSymbolicLink()||!j.isFile())return{error:`${D} is a symlink or not a regular file; move or remove it`};try{return{content:zl(D,"utf-8")}}catch(J){return{error:`Failed to read ${D}: ${J instanceof Error?J.message:String(J)}`}}}function Yl(P){try{return JSON.parse(vn(P))}catch{return}}function Gg(P){let O=$t(P,At);if("error"in O)return O.error;if(tn(Yl(O.content),"id")===un)return;return`${Yt(P,At)} is not a valid ${un} manifest; run install --openclaw`}function qg(P){let O=$t(P,It);if("error"in O)return O.error;let D=tn(tn(Yl(O.content),"openclaw"),"extensions");if(Array.isArray(D)&&D.includes(`./${Sn}`))return;return`${Yt(P,It)} does not point OpenClaw at ${Sn}; run install --openclaw`}function Kl(P){return Array.isArray(P)?P.filter((O)=>typeof O==="string"):[]}function Bg(P){let O=Bl(P);if(!dn(O))return`${un} is not enabled; ${it}`;let D=(()=>{try{return JSON.parse(vn(zl(O,"utf-8")))}catch{return}})();if(D===void 0)return`Failed to read ${O}; fix it, then ${it}`;let j=tn(D,"plugins");if(tn(j,"enabled")===!1)return`plugins.enabled is false in ${O}; no OpenClaw plugin loads`;let J=tn(tn(tn(j,"entries"),un),"enabled");if(Kl(tn(j,"deny")).includes(un)||J===!1)return`${un} is disabled in ${O}; ${it}`;let Y=Kl(tn(j,"allow"));if(Y.length>0&&!Y.includes(un))return`plugins.allow in ${O} does not list ${un}; add it, then ${it}`;if(Y.includes(un)||J===!0)return;return`${un} is not enabled; ${it}`}function Zl(P){return/^\/\/ version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function Vg(P,O,D){if(D===void 0)return[];let j=$t(D,Sn);if(!(("content"in j)&&Zl(j.content)===O))return[];return[Sn,At,It].flatMap((Y)=>{let re=$t(P,Y),ie=$t(D,Y);if("error"in re||"error"in ie||re.content===ie.content)return[];return[`Modified ${Y} occupies ${Yt(P,Y)}; run install --openclaw to restore it`]})}function Xl(P){let O=zt(P.environment),D=Er(Jr,O);if(D)return D;let j=$t(O,Sn),Y=["error"in j?j.error:j.content.startsWith(Vr)?void 0:`Unmanaged ${Sn} occupies ${Yt(O,Sn)}; move or remove it`,Gg(O),qg(O)].filter((we)=>we!==void 0),re="content"in j?Zl(j.content):void 0,ie=Y.length>0?Y:Vg(O,re,yi());if(ie.length>0)return{platform:Jr,status:"n/a",configPath:O,errors:ie};let de=re===pn()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],fe=Bg(P.environment);if(fe)return{platform:Jr,status:"disabled",method:"plugin directory",configPath:O,errors:[fe,...de]};return{platform:Jr,status:"configured",method:"plugin directory",configPath:O,errors:de.length>0?de:void 0}}import{existsSync as ey,readFileSync as ny}from"node:fs";import{basename as ty}from"node:path";import{existsSync as Wr,readFileSync as hi,rmSync as Jg}from"node:fs";import{join as An}from"node:path";import{pathToFileURL as Wg}from"node:url";var Zt="cc-safety-net",pt=`${Zt}@latest`,vi=["opencode.json","opencode.jsonc"],Kg=60,zg=250,Ql="CCSafetyNetPlugin",Yg={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function ec(P){return An(P.env.get("XDG_CONFIG_HOME")||An(P.home,".config"),"opencode")}function bi(P){return P.env.get("OPENCODE_CONFIG_DIR")||ec(P)}function wi(P){return vi.map((O)=>An(bi(P),O))}function ki(P){return[...new Set([bi(P),ec(P)])].flatMap((O)=>vi.map((D)=>An(O,D)))}function nc(P){return An(P.env.get("XDG_CACHE_HOME")||An(P.home,".cache"),"opencode","packages",pt)}function tc(P){Jg(nc(P),{recursive:!0,force:!0})}async function rc(P){let O=(await hn(["opencode","--version"],{stdoutOnly:!0})).trim(),D=/^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(O),j=Number(D?.[1]),J=Number(D?.[2]),Y=Number(D?.[3]);if(!D||j!==1&&j!==2||j===1&&(J<18||J===18&&Y<29)||j===2&&J===0&&Y<6)throw Error(`OpenCode 1.18.29+ or 2.0.6+ is required; found ${O||"an unknown version"}.`);if(j===2){for(let re of wi(P)){if(!Wr(re))continue;let ie=Ci(hi(re,"utf-8"),re);if(["plugin","plugins"].some((fe)=>{let we=tn(ie,fe);return Array.isArray(we)&&we.some((Ce)=>Kr(Ce)&&(typeof Ce==="string"?Ce:tn(Ce,"package"))!==pt)}))throw Error(`Change the cc-safety-net package spec in ${re} to ${pt}, preserving its options, then retry. Adding another spec would create a duplicate plugin ID.`)}return{commands:[],afterInstall:async()=>{if((await hn(["opencode","plugin","add",pt],{stdoutOnly:!0})).includes("is already configured in"))await hn(["opencode","plugin","update",pt]);let ie=await sc();if(!/^cc-safety-net\s+\S+\s+cc-safety-net@latest\s*$/m.test(ie))throw Error("OpenCode did not load cc-safety-net from cc-safety-net@latest. Run `opencode plugin list` for details.");let de=["--param",`location[directory]=${process.cwd()}`];await hn(["opencode","api","integration.list",...de]);let fe=await hn(["opencode","api","plugin.list",...de],{stdoutOnly:!0}),we=xi(fe);if(we)throw Error(we);if(!oc(fe).some(ic))throw Error("OpenCode lists no active cc-safety-net for this directory. Run `opencode api plugin.list` for details.")}}}return tc(P),{commands:[["opencode","plugin","-g","-f",pt]],afterInstall:()=>Xg(P)}}function oc(P){return Zg(P).filter((O)=>tn(O,"id")===Zt||Kr(tn(tn(O,"source"),"target"))).map((O)=>tn(O,"state"))}function ic(P){return tn(P,"status")==="active"}function xi(P){let O=oc(P);if(O.some(ic))return;let D=O.find((j)=>tn(j,"status")==="failed");if(!D)return;return`OpenCode reports cc-safety-net failed: ${String(tn(D,"error")).split(`
221
- `)[0]}`}function Zg(P){if(!P)return[];try{let O=tn(JSON.parse(P),"data");return Array.isArray(O)?O:[]}catch{return[]}}async function sc(P=1){let O=await hn(["opencode","plugin","list"],{stdoutOnly:!0});if(/^cc-safety-net\s|\scc-safety-net@latest\s*$/m.test(O)||P===Kg)return O;return await new Promise((D)=>setTimeout(D,zg)),sc(P+1)}async function Xg(P){let O=An(nc(P),"node_modules",Zt),D=An(O,"package.json");if(!Wr(D))throw Error(`The OpenCode plugin cache at ${O} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${pt}\` for details.`);let j=tn(JSON.parse(hi(D,"utf-8")),"main");if(typeof j!=="string")throw Error(`The cached OpenCode plugin at ${O} declares no "main" entry.`);let J=An(O,j);if(typeof(await import(Wg(J).href))[Ql]==="function")return;throw Error(`The cached OpenCode plugin at ${J} does not export a callable ${Ql}, so OpenCode would load nothing and fail open.`)}function Ci(P,O){try{return JSON.parse(vn(P))}catch(D){if(D instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${O}: ${D.message}`);throw D}}function Kr(P){let O=typeof P==="string"?P:tn(P,"package");return typeof O==="string"&&(O===Zt||O.startsWith(`${Zt}@`))}function Si(P){return["plugin","plugins"].some((O)=>{let D=tn(P,O);return Array.isArray(D)&&D.some(Kr)})}function Qg(P,O){let j=["plugin","plugins"].flatMap((J)=>{let Y=$a(P,J,Yg);if(!Y)return[];let re=[],ie=0,de=Y.start+1,fe=P.slice(Y.start+1,Y.end).matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|[^"\s{}[\],/]+|[{}[\],]/g);for(let we of fe){if(we[0].startsWith("//")||we[0].startsWith("/*"))continue;let Ce=Y.start+1+we.index;if(ie===0)de=Ce;if(we[0]==="{"||we[0]==="[")ie++;if(we[0]==="}"||we[0]==="]")ie--;if(ie!==0||we[0]===",")continue;let Se=Ce+we[0].length;if(Kr(JSON.parse(vn(P.slice(de,Se)))))re.push({start:de,end:Se})}return re}).sort((J,Y)=>J.start-Y.start).reverse().reduce((J,Y)=>{let re=/^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*,/.exec(J.slice(Y.end));if(re?.[0].includes("/")){let ie=Y.end+re[0].length-1;return J.slice(0,Y.start)+J.slice(Y.end,ie)+J.slice(ie+1)}return Ia(J,Y)},P);return Ci(j,O),j}function ac(P){tc(P);let O=ki(P),D=O.find((Y)=>Wr(Y)),j=[],J=[];for(let Y of O){if(!Wr(Y))continue;try{let re=hi(Y,"utf-8");if(!Si(Ci(re,Y)))continue;cn(Y,Qg(re,Y)),J.push(Y)}catch(re){j.push(re instanceof Error?re.message:String(re))}}if(j.length>0)throw Error(j.join(`
222
- `));return{path:J[0]??D??An(bi(P),vi[0]),alreadyInstalled:J.length>0}}function Ot(P){let O=[];for(let D of P.openCodeVersion?.startsWith("2.")?wi(P.environment):ki(P.environment))if(ey(D))try{let j=ny(D,"utf-8"),J=vn(j),Y=JSON.parse(J);if(Si(Y)){let re=xi(P.openCodePluginListOutput);if(re)return{platform:"opencode",status:"disabled",method:"opencode api plugin.list",configPath:D,errors:[...O,re]};return{platform:"opencode",status:"configured",method:"plugin array",configPath:D,errors:O.length>0?O:void 0}}}catch(j){O.push(`Failed to parse ${ty(D)}: ${j instanceof Error?j.message:String(j)}`)}return{platform:"opencode",status:"n/a",errors:O.length>0?O:void 0}}import{join as lc}from"node:path";function Pi(P){let O=P.env.get("PI_CODING_AGENT_DIR");return lc(O?Nn(O,P.home):lc(P.home,".pi","agent"),"settings.json")}function Ri(P){if(typeof P!=="string")return!1;return P==="npm:cc-safety-net"||P.startsWith("npm:cc-safety-net@")}function cc(P){let O=Pi(P.environment),D=Pn(O);if(D.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(D.kind==="missing")return{platform:"pi",status:"n/a"};let j=tn(D.value,"packages");if(!Array.isArray(j))return{platform:"pi",status:"n/a"};let J=j.find((ie)=>Ri(typeof ie==="string"?ie:tn(ie,"source")));if(J===void 0)return{platform:"pi",status:"n/a"};let Y=tn(J,"extensions");if(Array.isArray(Y)&&Y.some((ie)=>typeof ie==="string"&&ie.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:O,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:O}}var ry={amp:ka,"antigravity-cli":xa,"claude-code":Pa,codex:Ea,"copilot-cli":qa,cursor:Za,"deepseek-harness":Qa,devin:al,droid:yl,"gemini-cli":hl,"grok-build":Rl,"hermes-agent":Fl,"kimi-code":Kt,openclaw:Xl,opencode:Ot,pi:cc};function Dt(P,O,D){let j={...D,cwd:O,environment:P};return fr.map((J)=>oy(ry[J](j)))}function oy(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 iy}from"node:path";var sy=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}]),ay=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),safety:Object.freeze({}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),ly={strict:!1,paranoidRm:!1,paranoidInterpreters:!1,worktreeMode:!1,effectiveLevel:"standard",capabilities:{fail_closed:{enabled:!1,source:"preset",sources:[]},paranoid_rm:{enabled:!1,source:"preset",sources:[]},paranoid_interpreters:{enabled:!1,source:"preset",sources:[]}}};function dc(P){let O=iy(P.tmpdir,"cc-safety-net-self-test"),D=sy.map((j)=>{let J=G(P,u("self-test",{command:j.command},{kind:"command",shell:"auto"},{configCwd:O,executionCwd:O},j.command),{guard:{dependencies:{loadPolicySnapshot:()=>ay,getModes:()=>ly,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),Y=j.expectBlocked?"blocked":"allowed",re=J.decision.kind==="deny"?"blocked":"allowed";return{command:j.command,description:j.description,expected:Y,actual:re,passed:Y===re,reason:J.decision.kind==="deny"?J.decision.reason:void 0,ruleId:J.decision.kind==="deny"?J.decision.ruleId:void 0}});return{passed:D.filter((j)=>j.passed).length,failed:D.filter((j)=>!j.passed).length,total:D.length,results:D}}function Ei(P){let O=gn({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},P);if(Dn(O.errors))return null;return{json:O.flags.json,skipUpdateCheck:O.flags.skipUpdateCheck}}async function uc(P,O={}){let D=await Ut(!O.json,()=>{let j=dy(P,O);return{ready:j,finish:()=>j}},()=>Mt(),{loadingMessage:"Checking system status…"});if(O.json)console.log(JSON.stringify(D,null,2));else uy(D);return D.engineSelfTest.failed>0||D.findings.some((j)=>j.severity==="error")?1:0}async function dy(P,O){let D=O.cwd??process.cwd(),j=await xr((Me)=>Ot({environment:P,cwd:D,openCodeVersion:Me}).status!=="n/a",void 0,D),J=Dt(P,D,{ampPluginListOutput:j.ampPluginListOutput,codexPluginListOutput:j.codexPluginListOutput,copilotCliVersion:j.versions["copilot-cli"],openCodeVersion:j.versions.opencode,openCodePluginListOutput:j.openCodePluginListOutput}),Y=js(P,D),re=Fs(P),ie=k(P,{cwd:D}),de=ie.policy,fe=T(de,P.env),we=q(de,fe.capabilities),Ce=hr(P,7),Se=ya(P,D),Ie=[vr(D),Ct(P)].filter((Me)=>cy(Me)),Ee=O.skipUpdateCheck?{currentVersion:pn(),latestVersion:null,updateAvailable:!1}:await Gn(),Ve={hooks:J,engineSelfTest:dc(P),userConfig:Y.userConfig,projectConfig:Y.projectConfig,configState:je(ie),effectiveRules:Y.effectiveRules,environment:re,effectiveSafety:{selectedPreset:de.safety.level??"standard",level:fe.effectiveLevel,capabilities:fe.capabilities,ruleOverrides:de.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(we).filter(([,Me])=>Me.source==="rule_override"&&Me.override==="off"&&Me.inheritedEnabled&&Me.changesInherited).map(([Me])=>Me),ruleCounts:{stored:Object.keys(de.destructiveCommandRuleOverrides).length,effective:Object.values(we).filter((Me)=>Me.changesInherited).length},...ie.policyScopes?{policyScopes:ie.policyScopes}:{}},...Se.length>0?{v2Leftovers:Se}:{},...Ie.length>0?{legacyConfigs:Ie}:{},posture:Xs(P,Y.userConfig.path),activity:Ce,update:Ee,system:j};return{...Ve,findings:Ms(Ve)}}function uy(P){console.log(),console.log(Gs(P.hooks)),console.log(),console.log(qs(P.engineSelfTest)),console.log(),console.log(Bs(P)),console.log(),console.log(Vs(P.environment)),console.log(),console.log(Js(P)),console.log(),console.log(Ws(P.findings)),console.log(),console.log(Ks(P.activity)),console.log(),console.log(Ys(P.system)),console.log(),console.log(zs(P.update)),console.log(Zs(P))}import{existsSync as py}from"node:fs";var fy=/^[A-Za-z0-9_@%+=:,./-]+$/,pc="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function _i(P){let O=gn({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},P);if(Dn(O.errors))return console.error(pc),console.error("Pass -- before a command that starts with dashes."),null;if(O.values.cwd!==void 0&&!py(O.values.cwd))return console.error(`Error: --cwd path does not exist: ${O.values.cwd}`),null;let D=O.positionals.length===1?O.positionals[0]:O.positionals.map((j)=>fy.test(j)?j:`'${j.replaceAll("'","'\\''")}'`).join(" ");if(!D)return console.error("Error: No command provided"),console.error(pc),null;return{json:O.flags.json,cwd:O.values.cwd,command:D}}function fc(P){if(P)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function mc(P,O){let j=O-18;return[`${P.dtl}${P.dh.repeat(O)}${P.dtr}`,`${P.dv} Command Analysis${" ".repeat(j)}${P.dv}`,`${P.dbl}${P.dh.repeat(O)}${P.dbr}`]}function Ti(P){return JSON.stringify(P)}function gc(P,O=0){return`[${P.map((j,J)=>Us(j,J,O)).join(",")}]`}function Xt(P,O,D=70){let j=P.split(" "),J=[],Y="";for(let re of j)if(Y&&Y.length+re.length+1>D)J.push(Y),Y=re;else Y=Y?`${Y} ${re}`:re;if(Y)J.push(Y);return J.map((re,ie)=>ie===0?re:`${O}${re}`)}function yc(P,O,D){let j=[];switch(P.type){case"parse":return null;case"env-strip":return j.push(""),j.push(`STEP ${O} ${D.h} Strip environment variables`),j.push(` Removed: ${P.envVars.map((J)=>`${J}=<redacted>`).join(", ")}`),j.push(` Tokens: ${Ti(P.output)}`),{lines:j,incrementStep:!0};case"leading-tokens-stripped":return j.push(""),j.push(`STEP ${O} ${D.h} Strip wrappers`),j.push(` Removed: ${P.removed.join(", ")}`),j.push(` Tokens: ${Ti(P.output)}`),{lines:j,incrementStep:!0};case"shell-wrapper":return j.push(""),j.push(`STEP ${O} ${D.h} Detect shell wrapper`),j.push(` Wrapper: ${P.wrapper} -c`),j.push(` Inner: ${P.innerCommand}`),{lines:j,incrementStep:!0};case"interpreter":{if(j.push(""),j.push(`STEP ${O} ${D.h} Detect interpreter`),j.push(` Interpreter: ${P.interpreter}`),j.push(` Code: ${P.codeArg}`),P.paranoidBlocked)j.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:j,incrementStep:!0}}case"busybox":return j.push(""),j.push(`STEP ${O} ${D.h} Busybox wrapper`),j.push(` Subcommand: ${P.subcommand}`),{lines:j,incrementStep:!0};case"transparent-wrapper":return j.push(""),j.push(`STEP ${O} ${D.h} Transparent wrapper`),j.push(` Wrapper: ${P.wrapper}`),j.push(` Tokens: ${Ti(P.output)}`),{lines:j,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(j.push(""),j.push(`STEP ${O} ${D.h} Match rules`),j.push(` Rule: ${P.rule}()`),P.matched)j.push(" Result: MATCHED");else j.push(" Result: No match");return{lines:j,incrementStep:!0}}case"worktree-relaxation":return j.push(""),j.push(`STEP ${O} ${D.h} Worktree relaxation`),j.push(` Mode: ${n.worktree.name}`),j.push(` Git cwd: ${P.gitCwd}`),j.push(" Result: Allowed local discard in linked worktree"),{lines:j,incrementStep:!0};case"temp-root-relaxation":return j.push(""),j.push(`STEP ${O} ${D.h} Temp-root relaxation`),j.push(` Git cwd: ${P.gitCwd}`),j.push(" Result: Allowed git discard in a temp-root repository"),{lines:j,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(P.embeddedCommandFound)return j.push(""),j.push(`STEP ${O} ${D.h} Fallback scan`),j.push(` Found: ${P.embeddedCommandFound}`),{lines:j,incrementStep:!0};return null}case"custom-rules-check":{if(P.rulesChecked){if(j.push(""),j.push(`STEP ${O} ${D.h} Custom rules`),P.matched)j.push(" Result: MATCHED");else j.push(" Result: No match");return{lines:j,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(P.matched)return j.push(""),j.push(`STEP ${O} ${D.h} Dangerous text check`),j.push(` Token: ${P.token}`),j.push(" Result: MATCHED"),{lines:j,incrementStep:!0};return null}case"strict-unparseable":return j.push(""),j.push(`STEP ${O} ${D.h} Strict mode check`),j.push(` Command: ${P.rawCommand}`),j.push(" Result: ✗ UNPARSEABLE"),{lines:j,incrementStep:!0};case"segment-skipped":return null;case"error":return j.push(""),j.push(`ERROR: ${P.message}`),{lines:j,incrementStep:!1};default:return P}}function Ai(P,O){let D=fc(O?.asciiOnly??!1),j=58,J=[],Y=1;J.push(...mc(D,58)),J.push("");let re=P.trace.steps.find((Ee)=>Ee.type==="error");if(re&&re.type==="error"){J.push("ERROR"),J.push(` ${re.message}`),J.push(""),J.push("RESULT"),J.push(` Status: ${P.result==="blocked"?nn.red("BLOCKED"):nn.green("ALLOWED")}`),J.push(""),J.push("CONFIG");let Ee=P.configSource??"none";return J.push(` Path: ${Ee}`),J.join(`
223
- `)}let ie=P.trace.steps.find((Ee)=>Ee.type==="parse");if(ie&&ie.type==="parse"){J.push("INPUT"),J.push(` ${ie.input}`),J.push(""),J.push(`STEP ${Y} ${D.h} Split shell commands`),Y++;for(let Ee=0;Ee<ie.segments.length;Ee++){let Ve=ie.segments[Ee];if(Ve){let Me=Math.random();J.push(` Segment ${Ee+1}: ${gc(Ve,Me)}`)}}}let de=P.trace.segments,fe=de.length>1;for(let Ee of de){if(fe){J.push("");let on="";if(ie&&ie.type==="parse"){let wo=ie.segments[Ee.index];if(wo)on=wo.join(" ")}let sn=54,an=on,rn=` Segment ${Ee.index+1}: `,fn=" ";if(on){if(rn.length+on.length+fn.length>sn){let Qu=sn-rn.length-fn.length;an=`${on.substring(0,Qu-1)}…`}}let On=on?`${rn}${an}${fn}`:` Segment ${Ee.index+1} `,Zu=on?`${rn}${nn.cyan(an)}${fn}`:On,fs=58-On.length,ms=Math.floor(fs/2),Xu=fs-ms;J.push(`${D.sh.repeat(ms)}${Zu}${D.sh.repeat(Xu)}`)}if(Ee.steps.find((on)=>on.type==="segment-skipped")){J.push(""),J.push(" (skipped — prior segment blocked)");continue}let Me=!1,en=!1;for(let on of Ee.steps){let sn=yc(on,Y,D);if(sn){if(en=!0,on.type==="recurse"){J.push("");let an=" RECURSING ",rn=58-an.length-4;J.push(` ${D.tl}${D.h}${an}${D.h.repeat(rn)}`),J.push(` ${D.v}`),Me=!0;continue}for(let an of sn.lines)if(Me)J.push(` ${D.v} ${an}`);else J.push(an);if(sn.incrementStep)Y++}}if(Me)J.push(` ${D.v}`),J.push(` ${D.bl}${D.h.repeat(56)}`);if(!en)J.push(""),J.push(` ${nn.green("✓")} Allowed (no matching rules)`)}if(J.push(""),J.push("RESULT"),P.result==="blocked"){if(J.push(` Status: ${nn.red("BLOCKED")}`),P.customRule){if(J.push(` Rule: ${P.customRule.id}`),P.customRule.rulebook)J.push(` Rulebook: ${P.customRule.rulebook.name} ${P.customRule.rulebook.version}`);if(P.customRule.source)J.push(` Source: ${P.customRule.source}`);if(P.customRule.override)J.push(` Override: reason ${P.customRule.override.reason}`)}if(P.reason){let Ee=Xt(P.reason," ");J.push(` Reason: ${Ee[0]}`);for(let Ve=1;Ve<Ee.length;Ve++)J.push(Ee[Ve]??"")}}else J.push(` Status: ${nn.green("ALLOWED")}`);J.push(""),J.push("CONFIG");let we=P.configSource??"none",Ce=P.configValid?"":" (invalid)";J.push(` Path: ${we}${Ce}`);let Se=P.safetyPresetScope;J.push(` Safety preset: ${P.selectedPreset??"standard"}${Se?` (${br(Se)})`:""}`),J.push(` Effective capabilities: ${P.effectiveLevel}`);let Ie=Object.entries(P.destructiveCommandRuleOverrides??{});if(J.push(` Rule customizations: ${Ie.length}`),P.ruleActivation)J.push(` Rule activation: ${P.ruleActivation.id} — ${P.ruleActivation.enabled?"on":"off"} via ${P.ruleActivation.source}`);return J.join(`
224
- `)}function Ii(P){return JSON.stringify(P,null,2)}import{resolve as vy}from"node:path";var my=["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 hc(P){let O=0,D={allocateSegment(){return O++},getNextSegmentIndex(){return O},recordGlobal(j){P.record({kind:"step",scope:"global",step:j})},recordSegment(j,J=D.currentSegmentIndex){if(J===void 0)return;P.record({kind:"step",scope:"segment",segmentIndex:J,step:j})}};return D}function vc(P={}){let O=[],D=P.maxEvents??512,j={maxTextLength:P.maxTextLength??2048,maxListLength:P.maxListLength??128,maxObjectProperties:P.maxObjectProperties??P.maxListLength??128,maxDepth:P.maxDepth??16},J,Y=new Set;return{record(re){if(J)return;if(!re||O.length>=D)return;try{O.push(Di(gy(re,j,Y)))}catch{}},finish(){if(J)return J;return J=Di({events:Object.freeze(O)}),J}}}function gy(P,O,D){if(P.kind!=="step")throw TypeError("invalid trace event");let{scope:j,step:J}=P;zr(J,D,O);let Y=$i(J,O,D);if(j==="global")return{kind:"step",scope:"global",step:Y};if(j!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:P.segmentIndex,step:Y}}function zr(P,O,D,j=0,J=new WeakSet){if(typeof P==="string"){let ie=P.slice(0,D.maxTextLength);if(!ze(ie))return;for(let de of nt(ie))for(let fe of de.match(/[^\s"'()$]+/g)??[])O.add(bc(fe));return}if(!P||typeof P!=="object"||j>=D.maxDepth||J.has(P))return;if(J.add(P),Array.isArray(P)){let ie=Math.min(P.length,D.maxListLength);for(let de=0;de<ie;de++)zr(P[de],O,D,j+1,J);return}let Y=0,re=new Set;for(let ie in P){if(!Object.hasOwn(P,ie))continue;if(Y>=D.maxObjectProperties)break;Y++,zr(ie,O,D);let de=Oi(ie,D,O);if(re.has(de))continue;re.add(de),zr(P[ie],O,D,j+1,J)}}function $i(P,O,D,j=0,J=new WeakSet){if(typeof P==="string")return Oi(P,O,D);if(!P||typeof P!=="object")return P;if(j>=O.maxDepth)return;if(J.has(P))return;if(J.add(P),Array.isArray(P)){let ie=[],de=Math.min(P.length,O.maxListLength);for(let fe=0;fe<de;fe++)ie.push($i(P[fe],O,D,j+1,J));return ie}let Y={},re=0;for(let ie in P){if(!Object.hasOwn(P,ie))continue;if(re>=O.maxObjectProperties)break;re++;let de=Oi(ie,O,D);if(Object.hasOwn(Y,de))continue;Object.defineProperty(Y,de,{value:$i(P[ie],O,D,j+1,J),enumerable:!0,configurable:!0,writable:!0})}return Y}function Oi(P,O,D){let j=P.slice(0,O.maxTextLength),J=ze(j)?Be(j):j,Y=D.size>0?hy(J,D):J;return(yy(Y)?Pe(Y):Y).slice(0,O.maxTextLength)}function yy(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&&my.some((O)=>P.includes(O))||P.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(P)}function hy(P,O){return P.replace(/[^\s"'()$]+/g,(D)=>O.has(bc(D))?"<redacted>":D)}function bc(P){let O=2166136261,D=2166136261;for(let j=0;j<P.length;j++)O=Math.imul(O^P.charCodeAt(j),16777619),D=Math.imul(D^P.charCodeAt(P.length-j-1),16777619);return`${O>>>0}:${D>>>0}:${P.length}`}function Di(P){if(P&&typeof P==="object"&&!Object.isFrozen(P)){for(let O of Object.values(P))Di(O);Object.freeze(P)}return P}function Qt(P,O={},D){let j=vy(O.cwd??process.cwd()),J=O.policySnapshot??k(D,{cwd:j,userConfigDir:O.userConfigDir}),Y=T(J.policy,D.env),re=Ue({policySnapshot:J,effectiveCapabilities:Y.capabilities,strict:Y.strict,paranoidRm:Y.paranoidRm,paranoidInterpreters:Y.paranoidInterpreters,worktreeMode:Y.worktreeMode}),ie={effectiveLevel:re.effectiveLevel,selectedPreset:J.policy.safety.level??"standard",...J.policyScopes?{safetyPresetScope:J.policyScopes.levelScope}:{},effectiveCapabilities:re.effectiveCapabilities,destructiveCommandRuleOverrides:J.policy.destructiveCommandRuleOverrides},{configSource:de,configValid:fe}=wy(D,{cwd:j,userConfigDir:O.userConfigDir});if(!P||!P.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:de,configValid:fe,...ie};let we=y(P,"auto");if(we.status==="limited")throw new b;let Ce=we.dialect==="powershell"?y(P,"posix"):we,Se=dt(Ce),Ie=vc(),Ee=hc(Ie);Ee.recordGlobal({type:"parse",input:P,segments:Se.map((On)=>[...On])});let Ve=u("Bash",{command:P},{kind:"command",shell:"auto"},{configCwd:j,executionCwd:j},P),Me=V(Ve,{environment:D,trace:Ee,dependencies:{loadPolicySnapshot:()=>J}}),en=Me.decision.kind==="deny"?Me.decision:null;if(en&&(Me.stage==="policy-protection"||Me.stage==="secret-protection"))return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:by(en),matched:!0,reason:en.reason}]}]},result:"blocked",reason:R(en.reason),segment:R(wc(en,P)),ruleId:R(en.ruleId),configSource:de,configValid:fe,...ie};let on=Ee.getNextSegmentIndex();if(en&&on>0&&on<Se.length)Ee.recordSegment({type:"segment-skipped",index:on,reason:"prior-segment-blocked"},on);let sn=Ie.finish(),an=en?.ruleId??ky(Ve,J,Y,D),rn=z.find((On)=>On.id===an&&On.activationCapability),fn=rn?re.policy.effectiveDestructiveCommandRules[rn.id]:void 0;return{trace:Cy(sn),result:en?"blocked":"allowed",reason:en?R(en.reason):void 0,segment:en?R(wc(en,P)):void 0,ruleId:en?R(en.ruleId):void 0,customRule:xy(Sy(en?.ruleId,J)),configSource:de,configValid:fe,...ie,...rn&&fn?{ruleActivation:{id:rn.id,...fn}}:{}}}function wc(P,O){return P.evidence?.segment??O}function by(P){if(P.reason===He)return"policy-protection:findPolicyConfigMutationTargetInSemanticFacts";if(P.reason===Ge)return"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts";if(P.reason===x)return"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts";return"secret-protection:findSensitiveTargetInSemanticFacts"}function wy(P,O){let D=_(O.cwd),j=W(P,O),J=X(P,{cwd:O.cwd,userConfigDir:O.userConfigDir});try{if(r(J.projectConfigTarget)!==null){if(Un(J.projectConfigTarget).errors.length===0)return{configSource:D,configValid:!0};return{configSource:D,configValid:!1}}}catch(Y){if(Y instanceof o)return{configSource:D,configValid:!1};throw Y}try{if(r(J.userConfigTarget)!==null){let Y=Un(J.userConfigTarget);return{configSource:j,configValid:Y.errors.length===0}}return{configSource:null,configValid:!0}}catch(Y){if(Y instanceof o)return{configSource:j,configValid:!1};throw Y}}function ky(P,O,D,j){let J=O.policy,Y=_e({...J,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...J.destructiveCommandRuleOverrides,...Object.fromEntries(z.flatMap((ie)=>ie.activationCapability?[[ie.id,"on"]]:[]))}},O.state==="degraded"?{diagnostics:O.diagnostics,reason:O.reason}:void 0),re=V(P,{environment:j,dependencies:{loadPolicySnapshot:()=>Y,getModes:()=>({...D,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return re.decision.kind==="deny"?re.decision.ruleId:void 0}function xy(P){if(!P)return;return{id:R(P.id),...P.rulebook?{rulebook:{name:R(P.rulebook.name),version:R(P.rulebook.version)}}:{},...P.source?{source:R(P.source)}:{},...P.override?{override:{type:"reason",reason:R(P.override.reason)}}:{}}}function Cy(P){let O=P.events.flatMap((j)=>j.kind==="step"&&j.scope==="global"?[j.step]:[]),D=new Map;for(let j of P.events){if(j.kind!=="step"||j.scope!=="segment")continue;let J=D.get(j.segmentIndex)??{index:j.segmentIndex,steps:[]};J.steps.push(j.step),D.set(j.segmentIndex,J)}return{steps:O,segments:[...D.values()]}}function Sy(P,O){let D=P?.replace(/^custom\./,"");if(!D||!O.policy.rules.some((j)=>j.name===D))return;return O.ruleMetadata[D]??Object.freeze({id:D})}function kc(P){return new Promise((O)=>{process.stdout.write(`${P}
225
- `,()=>O())})}async function xc(P,O){let D=_i(O);if(!D)return 1;try{let j=Qt(D.command,{cwd:D.cwd},P),J=!!process.env.NO_COLOR||!process.stdout.isTTY;return await kc(D.json?Ii(j):Ai(j,{asciiOnly:J})),0}catch(j){let J=Py(j instanceof p?j.cause:j);if(J===void 0)throw j;if(D.json)return await kc(JSON.stringify({error:J})),1;return console.error(J),1}}function Py(P){if(P instanceof b)return P.message;if(P instanceof f)return P.message;if(P instanceof s&&a[P.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var Cc="2.6.1",_n=" ",ft="cc-safety-net";function Sc(P){return P.argument?`${P.flags} ${P.argument}`:P.flags}function Ry(P){return Math.max(...P.map((O)=>Sc(O).length))}function Ey(P){return Math.max(...P.map((O)=>O.usage.length))}function _y(P){return Math.max(...P.map((O)=>`${ft} ${O.usage}`.length))}function Ty(P,O){let D=`${ft} ${P.usage}`;return`${_n}${D.padEnd(O+2)}${P.description}`}function In(P,O){return`${_n}${P.padEnd(Math.max(40,P.length+2))}${O}`}function Lt(P,O=console.log){let D=[];if(D.push(`${ft} ${P.name}`),D.push(""),D.push(`${_n}${P.description}`),D.push(""),D.push("USAGE:"),D.push(`${_n}${ft} ${P.usage}`),D.push(""),P.subcommands&&P.subcommands.length>0){D.push("SUBCOMMANDS:");let j=Ey(P.subcommands);for(let J of P.subcommands)D.push(`${_n}${J.usage.padEnd(j+2)}${J.description}`);D.push("")}if(P.options.length>0){D.push("OPTIONS:");let j=Ry(P.options);for(let J of P.options){let Y=Sc(J),re=J.default?`${J.description} (default: ${J.default})`:J.description;D.push(`${_n}${Y.padEnd(j+2)}${re}`)}D.push("")}if(P.examples&&P.examples.length>0){D.push("EXAMPLES:");for(let j of P.examples)D.push(`${_n}${j}`)}O(D.join(`
226
- `))}function Li(){let P=_y(gr),O=[];O.push(`${ft} v${Cc}`),O.push(""),O.push("Blocks destructive commands and secret access."),O.push(""),O.push("COMMANDS:");for(let D of gr)O.push(Ty(D,P));O.push(""),O.push("GLOBAL OPTIONS:"),O.push(`${_n}-h, --help Show help (use with command for command-specific help)`),O.push(`${_n}-V, --version Show version`),O.push(""),O.push("HELP:"),O.push(`${_n}${ft} help <command> Show help for a specific command`),O.push(`${_n}${ft} <command> --help Show help for a specific command`),O.push(""),O.push("ENVIRONMENT VARIABLES:"),O.push(In(`${n.level.name}=standard|strict|paranoid`,"Set session safety level")),O.push(In(`${n.worktree.name}=1`,"Allow local git discards in linked worktrees")),O.push(In(`${n.debug.name}=1`,"Print diagnostic messages to stderr")),O.push(In(`${n.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),O.push(In(`${n.projectTightenOnly.name}=1`,"Ignore project policy settings that weaken the user policy")),O.push(In("CC_SAFETY_NET_HOME","Override rule config home directory")),O.push(""),O.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),O.push(In(`${n.strict.name}=1`,"Force safety.overrides.fail_closed on")),O.push(In(`${n.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),O.push(In(`${n.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),O.push(In(`${n.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),O.push(""),O.push("Documentation: https://ccsafetynet.com/docs"),console.log(O.join(`
227
- `))}function Pc(){console.log(Cc)}function er(P,O=console.log){let D=yr(P);if(!D)return!1;if(D.name.toLowerCase()!==P.toLowerCase())return!1;return Lt(D,O),!0}import{existsSync as ro,readFileSync as Id}from"node:fs";import{join as to}from"node:path";import*as Bn from"node:readline";function Ay(P){return P==="install"?"Install":"Uninstall"}function Iy(P){return P==="install"?"Installing":"Uninstalling"}function $y(P){return P==="install"?"into":"from"}function _c(P){return P?.available===!0}function Oy(P,O){let D=new Set(O);return P.filter((j)=>D.has(j.target)).map((j)=>j.target)}function Rc(P,O,D){if(P.every((j)=>!j.available))return O;return Array.from({length:P.length},(j,J)=>J+1).map((j)=>(O+j*D+P.length)%P.length).find((j)=>_c(P[j]))}function Dy(P,O,D){if(D.ctrl&&D.name==="c")return"interrupt";if(D.name==="escape"||O==="q")return"abort";if(P==="install"&&(O==="u"||O==="U"))return"update";if(D.name==="up"||O==="k")return"up";if(D.name==="down"||O==="j")return"down";if(D.name==="space"||O===" ")return"toggle";if(D.name==="return"||D.name==="enter")return"confirm";return null}function Ly(P){return{cursor:P.findIndex((O)=>O.available),selected:[]}}function Ny(P,O,D){if(D==="confirm"||D==="update"||D==="abort"||D==="interrupt")return{state:P,done:D};if(D==="up")return{state:{...P,cursor:Rc(O,P.cursor,-1)}};if(D==="down")return{state:{...P,cursor:Rc(O,P.cursor,1)}};let j=O[P.cursor];if(!_c(j))return{state:P};let J=P.selected.includes(j.target)?P.selected.filter((Y)=>Y!==j.target):Oy(O,[...P.selected,j.target]);return{state:{...P,selected:J}}}var Tc="◉",Ac="◯",Ic=">",$c=" ";function jy(P,O,D){return["",`${Ay(P)} CC Safety Net ${$y(P)}:`,"",...O.map((j,J)=>{let Y=D.selected.includes(j.target),re=J===D.cursor,ie=Y?Tc:Ac,de=re?Ic:$c,fe=j.available?"":` (${j.unavailableReason??"not installed"})`,we=`${ie} ${j.label}${fe}`,Ce=!j.available?nn.dim(we):Y?nn.green(we):re?nn.bold(we):we;return`${de} ${Ce}`}),"",P==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":O.some((j)=>j.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${P}. q/Esc: close`].join(`
228
- `)}var Ec=["global-hook","plugin"];function Fy(P,O,D={}){let j=D.color!==!1?nn.bold:(Y)=>Y;return["","Install the Kimi Code integration as:","",...[`Global hook — ${O?"already installed; selecting it reports the current state":"write the hook into ~/.kimi-code/config.toml now"}`,"Native Kimi plugin — print the steps to run inside Kimi Code"].map((Y,re)=>{let ie=re===P,de=`${ie?Tc:Ac} ${Y}`;return`${ie?Ic:$c} ${ie?j(de):de}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
229
- `)}function Oc(P){let{input:O,output:D}=P;Bn.emitKeypressEvents(O);let j=O.isRaw===!0;O.setRawMode(!0),O.resume();let J=0,Y=()=>{if(J===0)return;Bn.moveCursor(D,0,-J),Bn.cursorTo(D,0),Bn.clearScreenDown(D)},re=()=>{Y();let ie=P.render();D.write(`${ie}
221
+ `}function Wt(P){return[{name:"__init__.py",content:Eg(P)},{name:"plugin.yaml",content:Rg(P)}]}import{mkdirSync as _g,readdirSync as Ag,readFileSync as Hl,rmSync as yi}from"node:fs";import{basename as Tg,dirname as Ig,join as Fn}from"node:path";var $g="__pycache__",Og=/^[a-z0-9][a-z0-9_-]{0,63}$/;function Dg(P){try{return Hl(P,"utf-8").trim()}catch{return}}function hi(P){let O=P.env.get("HERMES_HOME")?.trim();if(O&&Tg(Ig(O))==="profiles")return O;let D=O||Fn(P.home,".hermes"),j=Fn(D,"active_profile"),J=Dg(j),Y=J?.toLowerCase();if(!Y||Y==="default")return D;if(!Og.test(Y))throw Error(`Invalid Hermes profile name "${J}" in ${j}; run \`hermes profile use <name>\` with a valid profile.`);return Fn(D,"profiles",Y)}function vi(P){return Fn(hi(P),"plugins",Rn)}function bi(P){return P.startsWith(gi)}function wi(P,O){let D=vi(P),j=dn(D);if(j&&(j.isSymbolicLink()||!j.isDirectory()))throw Error(`Refusing to ${O} ${D}: not a regular directory. Move or remove it and rerun ${O==="install"?"install":"uninstall"} --hermes-agent.`);return D}function Ml(P,O){let D=dn(P);if(!D)return;if(D.isSymbolicLink()||!D.isFile())throw Error(`Refusing to ${O} ${P}: not a regular file. Move or remove it.`);let j=Hl(P,"utf-8");if(!bi(j))throw Error(`Refusing to ${O} unmanaged file at ${P}. Move or remove it.`);return j}function Ul(P){let O=wi(P,"install"),D=Wt(pn());if(D.map((J)=>Ml(Fn(O,J.name),"overwrite")).every((J,Y)=>J===D[Y]?.content))return{path:O,alreadyInstalled:!0};return _g(O,{recursive:!0}),D.forEach((J)=>{cn(Fn(O,J.name),J.content)}),{path:O,alreadyInstalled:!1}}function ki(P){let O=wi(P,"remove");if(!dn(O))return[];return Wt(pn()).filter((D)=>Ml(Fn(O,D.name),"remove")!==void 0)}function Gl(P){let O=wi(P,"remove");if(!dn(O))return{path:O,alreadyInstalled:!1};let D=ki(P);if(D.forEach((j)=>{yi(Fn(O,j.name))}),yi(Fn(O,$g),{recursive:!0,force:!0}),Ag(O).length===0)yi(O,{recursive:!0});return{path:O,alreadyInstalled:D.length>0}}var zt="hermes-agent",ql=/^([^\s#][^:]*):/,Lg=/^\s+([A-Za-z_][\w-]*):/,Bl=/^\s+-\s*(.*)$/;function Ng(P){return P.trim().replace(/^(["'])(.*)\1$/,"$2")}function jg(P){let O=P.split(/\r?\n/),D=O.findIndex((Y)=>ql.exec(Y)?.[1]?.trim()==="plugins");if(D===-1)return[];let j=O.slice(D+1),J=j.findIndex((Y)=>ql.test(Y));return J===-1?j:j.slice(0,J)}function Vl(P,O){let D=jg(P),j=D.findIndex((re)=>Lg.exec(re)?.[1]===O);if(j===-1)return[];let J=D.slice(j+1),Y=J.findIndex((re)=>!Bl.test(re));return(Y===-1?J:J.slice(0,Y)).map((re)=>Ng(Bl.exec(re)?.[1]??""))}function Fg(P){try{return Jl(Kl(hi(P),"config.yaml"),"utf-8")}catch{return}}function xi(P){let O=Fg(P)??"";return Vl(O,"enabled").includes(Rn)&&!Vl(O,"disabled").includes(Rn)}function Wl(P){return/^# version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function Hg(P,O){let D=dn(P);if(!D)return{error:`${O.name} is missing from ${P}; run install --hermes-agent`};if(D.isSymbolicLink()||!D.isFile())return{error:`${P} is a symlink or not a regular file; move or remove it`};try{let j=Jl(P,"utf-8");if(!bi(j))return{error:`Unmanaged ${O.name} occupies ${P}; move or remove it`};if(Wl(j)===pn()&&j!==O.content)return{error:`Modified ${O.name} occupies ${P}; run install --hermes-agent to restore it`};return{content:j}}catch(j){return{error:`Failed to read ${P}: ${j instanceof Error?j.message:String(j)}`}}}function Mg(P){try{return{path:vi(P)}}catch(O){return{error:O instanceof Error?O.message:String(O)}}}function zl(P){let O=Mg(P.environment);if("error"in O)return{platform:zt,status:"n/a",errors:[O.error]};let D=O.path,j=Ar(zt,D);if(j)return j;let J=Wt(pn()).map((de)=>Hg(Kl(D,de.name),de)),Y=J.flatMap((de)=>("error"in de)?[de.error]:[]);if(Y.length>0)return{platform:zt,status:"n/a",configPath:D,errors:Y};let re=J.some((de)=>("content"in de)&&Wl(de.content)!==pn()),ie=re?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!xi(P.environment))return{platform:zt,status:"disabled",method:"plugin directory",configPath:D,errors:[`${Rn} is not enabled in Hermes; run \`hermes plugins enable ${Rn}\``,...ie]};return{platform:zt,status:"configured",method:"plugin directory",configPath:D,errors:re?ie:void 0}}import{existsSync as Ug,readFileSync as Gg}from"node:fs";import{join as Yl}from"node:path";var qg=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function Bg(P){return Yl(P.env.get("KIMI_CODE_HOME")||Yl(P.home,".kimi-code"),"config.toml")}function Yt(P){let O=Bg(P.environment);if(!Ug(O))return{platform:"kimi-code",status:"n/a",configPath:O};try{if(!qg.test(Gg(O,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:O}}catch(D){return{platform:"kimi-code",status:"n/a",configPath:O,errors:[`Failed to read ${O}: ${D instanceof Error?D.message:String(D)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:O}}import{readFileSync as ic}from"node:fs";import{join as Xt}from"node:path";var un="cc-safety-net",Pn="index.js",Tt="openclaw.plugin.json",It="package.json";var Zr="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as Vg,lstatSync as Jg,readdirSync as Kg,readFileSync as Wg}from"node:fs";import{dirname as Zl,join as qn}from"node:path";import{fileURLToPath as zg}from"node:url";var Ci=qn("openclaw",un),it=`run \`openclaw plugins enable ${un}\``,Yg="config reload superseded by a newer runtime config source",Zg=[Pn,Tt,It];function Xl(P){let O=P.env.get("OPENCLAW_HOME")?.trim();return O?Nn(O,P.home):P.home}function Ql(P){let O=Xl(P),D=P.env.get("OPENCLAW_STATE_DIR")?.trim();if(D)return Nn(D,O);let j=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return j?Zl(Nn(j,O)):qn(O,".openclaw")}function ec(P){let O=P.env.get("OPENCLAW_CONFIG_PATH")?.trim();return O?Nn(O,Xl(P)):qn(Ql(P),"openclaw.json")}function Zt(P){return qn(Ql(P),"extensions",un)}function Xg(P){let O=Kg(P);if(O.length===0)return!0;if(O.some((J)=>!Zg.includes(J)))return!1;let D=qn(P,Pn),j=dn(D);return j!==void 0&&!j.isSymbolicLink()&&j.isFile()&&Wg(D,"utf-8").startsWith(Zr)}function Si(P){let O=Zt(P),D=dn(O);if(!D)return;if(!D.isSymbolicLink()&&D.isDirectory()&&Xg(O))return;throw Error(`Refusing to modify ${O}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function nc(){let P=Zl(zg(import.meta.url));return[qn(P,Ci),qn(P,"..",Ci),qn(P,"..","..","..","dist",Ci)]}function Pi(P=nc()){return P.find((O)=>Vg(O)&&Jg(O).isDirectory())}function Qg(P=nc()){let O=Pi(P);if(!O)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return O}function tc(P=Qg()){return[["openclaw","plugins","install",P,"--force","--accept-capabilities"]]}function ey(P){let O=(()=>{try{return JSON.parse(P)}catch{return}})(),D=tn(tn(O,"plugin"),"status");return typeof D==="string"?D:void 0}async function ny(){await gn(["openclaw","plugins","enable",un]).catch((P)=>{if(!(P instanceof Error&&P.message.includes(Yg)))throw P})}async function rc(P){let O=async()=>ey(await gn(["openclaw","plugins","inspect",un,"--runtime","--json"],{stdoutOnly:!0})),D=await O(),j=D==="disabled"&&P;if(j)await ny();let J=j?await O():D;if(J==="loaded")return;throw Error(`${J===void 0?`The ${un} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:J==="disabled"?`OpenClaw reports the ${un} plugin with status "disabled"; ${it}.`:`OpenClaw reports the ${un} plugin with status "${J}".`} Run \`openclaw plugins inspect ${un} --runtime\` for details.`)}var Xr="openclaw";function $t(P,O){let D=Xt(P,O),j=dn(D);if(!j)return{error:`${O} is missing from ${D}; run install --openclaw`};if(j.isSymbolicLink()||!j.isFile())return{error:`${D} is a symlink or not a regular file; move or remove it`};try{return{content:ic(D,"utf-8")}}catch(J){return{error:`Failed to read ${D}: ${J instanceof Error?J.message:String(J)}`}}}function sc(P){try{return JSON.parse(vn(P))}catch{return}}function ty(P){let O=$t(P,Tt);if("error"in O)return O.error;if(tn(sc(O.content),"id")===un)return;return`${Xt(P,Tt)} is not a valid ${un} manifest; run install --openclaw`}function ry(P){let O=$t(P,It);if("error"in O)return O.error;let D=tn(tn(sc(O.content),"openclaw"),"extensions");if(Array.isArray(D)&&D.includes(`./${Pn}`))return;return`${Xt(P,It)} does not point OpenClaw at ${Pn}; run install --openclaw`}function oc(P){return Array.isArray(P)?P.filter((O)=>typeof O==="string"):[]}function oy(P){let O=ec(P);if(!dn(O))return`${un} is not enabled; ${it}`;let D=(()=>{try{return JSON.parse(vn(ic(O,"utf-8")))}catch{return}})();if(D===void 0)return`Failed to read ${O}; fix it, then ${it}`;let j=tn(D,"plugins");if(tn(j,"enabled")===!1)return`plugins.enabled is false in ${O}; no OpenClaw plugin loads`;let J=tn(tn(tn(j,"entries"),un),"enabled");if(oc(tn(j,"deny")).includes(un)||J===!1)return`${un} is disabled in ${O}; ${it}`;let Y=oc(tn(j,"allow"));if(Y.length>0&&!Y.includes(un))return`plugins.allow in ${O} does not list ${un}; add it, then ${it}`;if(Y.includes(un)||J===!0)return;return`${un} is not enabled; ${it}`}function ac(P){return/^\/\/ version:\s*(.+)$/m.exec(P)?.[1]?.trim()}function iy(P,O,D){if(D===void 0)return[];let j=$t(D,Pn);if(!(("content"in j)&&ac(j.content)===O))return[];return[Pn,Tt,It].flatMap((Y)=>{let re=$t(P,Y),ie=$t(D,Y);if("error"in re||"error"in ie||re.content===ie.content)return[];return[`Modified ${Y} occupies ${Xt(P,Y)}; run install --openclaw to restore it`]})}function lc(P){let O=Zt(P.environment),D=Ar(Xr,O);if(D)return D;let j=$t(O,Pn),Y=["error"in j?j.error:j.content.startsWith(Zr)?void 0:`Unmanaged ${Pn} occupies ${Xt(O,Pn)}; move or remove it`,ty(O),ry(O)].filter((we)=>we!==void 0),re="content"in j?ac(j.content):void 0,ie=Y.length>0?Y:iy(O,re,Pi());if(ie.length>0)return{platform:Xr,status:"n/a",configPath:O,errors:ie};let de=re===pn()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],fe=oy(P.environment);if(fe)return{platform:Xr,status:"disabled",method:"plugin directory",configPath:O,errors:[fe,...de]};return{platform:Xr,status:"configured",method:"plugin directory",configPath:O,errors:de.length>0?de:void 0}}import{existsSync as my,readFileSync as gy}from"node:fs";import{basename as yy}from"node:path";import{existsSync as Qr,readFileSync as Ri,rmSync as sy}from"node:fs";import{join as Tn}from"node:path";import{pathToFileURL as ay}from"node:url";var Qt="cc-safety-net",pt=`${Qt}@latest`,Ei=["opencode.json","opencode.jsonc"],ly=60,cy=250,cc="CCSafetyNetPlugin",dy={stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"};function dc(P){return Tn(P.env.get("XDG_CONFIG_HOME")||Tn(P.home,".config"),"opencode")}function _i(P){return P.env.get("OPENCODE_CONFIG_DIR")||dc(P)}function Ai(P){return Ei.map((O)=>Tn(_i(P),O))}function Ti(P){return[...new Set([_i(P),dc(P)])].flatMap((O)=>Ei.map((D)=>Tn(O,D)))}function uc(P){return Tn(P.env.get("XDG_CACHE_HOME")||Tn(P.home,".cache"),"opencode","packages",pt)}function pc(P){sy(uc(P),{recursive:!0,force:!0})}async function fc(P){let O=(await gn(["opencode","--version"],{stdoutOnly:!0})).trim(),D=/^(?:opencode\s+)?v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(O),j=Number(D?.[1]),J=Number(D?.[2]),Y=Number(D?.[3]);if(!D||j!==1&&j!==2||j===1&&(J<18||J===18&&Y<29)||j===2&&J===0&&Y<6)throw Error(`OpenCode 1.18.29+ or 2.0.6+ is required; found ${O||"an unknown version"}.`);if(j===2){for(let re of Ai(P)){if(!Qr(re))continue;let ie=$i(Ri(re,"utf-8"),re);if(["plugin","plugins"].some((fe)=>{let we=tn(ie,fe);return Array.isArray(we)&&we.some((Ce)=>eo(Ce)&&(typeof Ce==="string"?Ce:tn(Ce,"package"))!==pt)}))throw Error(`Change the cc-safety-net package spec in ${re} to ${pt}, preserving its options, then retry. Adding another spec would create a duplicate plugin ID.`)}return{commands:[],afterInstall:async()=>{if((await gn(["opencode","plugin","add",pt],{stdoutOnly:!0})).includes("is already configured in"))await gn(["opencode","plugin","update",pt]);let ie=await yc();if(!/^cc-safety-net\s+\S+\s+cc-safety-net@latest\s*$/m.test(ie))throw Error("OpenCode did not load cc-safety-net from cc-safety-net@latest. Run `opencode plugin list` for details.");let de=["--param",`location[directory]=${process.cwd()}`];await gn(["opencode","api","integration.list",...de]);let fe=await gn(["opencode","api","plugin.list",...de],{stdoutOnly:!0}),we=Ii(fe);if(we)throw Error(we);if(!mc(fe).some(gc))throw Error("OpenCode lists no active cc-safety-net for this directory. Run `opencode api plugin.list` for details.")}}}return pc(P),{commands:[["opencode","plugin","-g","-f",pt]],afterInstall:()=>py(P)}}function mc(P){return uy(P).filter((O)=>tn(O,"id")===Qt||eo(tn(tn(O,"source"),"target"))).map((O)=>tn(O,"state"))}function gc(P){return tn(P,"status")==="active"}function Ii(P){let O=mc(P);if(O.some(gc))return;let D=O.find((j)=>tn(j,"status")==="failed");if(!D)return;return`OpenCode reports cc-safety-net failed: ${String(tn(D,"error")).split(`
222
+ `)[0]}`}function uy(P){if(!P)return[];try{let O=tn(JSON.parse(P),"data");return Array.isArray(O)?O:[]}catch{return[]}}async function yc(P=1){let O=await gn(["opencode","plugin","list"],{stdoutOnly:!0});if(/^cc-safety-net\s|\scc-safety-net@latest\s*$/m.test(O)||P===ly)return O;return await new Promise((D)=>setTimeout(D,cy)),yc(P+1)}async function py(P){let O=Tn(uc(P),"node_modules",Qt),D=Tn(O,"package.json");if(!Qr(D))throw Error(`The OpenCode plugin cache at ${O} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${pt}\` for details.`);let j=tn(JSON.parse(Ri(D,"utf-8")),"main");if(typeof j!=="string")throw Error(`The cached OpenCode plugin at ${O} declares no "main" entry.`);let J=Tn(O,j);if(typeof(await import(ay(J).href))[cc]==="function")return;throw Error(`The cached OpenCode plugin at ${J} does not export a callable ${cc}, so OpenCode would load nothing and fail open.`)}function $i(P,O){try{return JSON.parse(vn(P))}catch(D){if(D instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${O}: ${D.message}`);throw D}}function eo(P){let O=typeof P==="string"?P:tn(P,"package");return typeof O==="string"&&(O===Qt||O.startsWith(`${Qt}@`))}function Oi(P){return["plugin","plugins"].some((O)=>{let D=tn(P,O);return Array.isArray(D)&&D.some(eo)})}function fy(P,O){let j=["plugin","plugins"].flatMap((J)=>{let Y=Ga(P,J,dy);if(!Y)return[];let re=[],ie=0,de=Y.start+1,fe=P.slice(Y.start+1,Y.end).matchAll(/\/\/[^\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|[^"\s{}[\],/]+|[{}[\],]/g);for(let we of fe){if(we[0].startsWith("//")||we[0].startsWith("/*"))continue;let Ce=Y.start+1+we.index;if(ie===0)de=Ce;if(we[0]==="{"||we[0]==="[")ie++;if(we[0]==="}"||we[0]==="]")ie--;if(ie!==0||we[0]===",")continue;let Se=Ce+we[0].length;if(eo(JSON.parse(vn(P.slice(de,Se)))))re.push({start:de,end:Se})}return re}).sort((J,Y)=>J.start-Y.start).reverse().reduce((J,Y)=>{let re=/^(?:\s|\/\/[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)*,/.exec(J.slice(Y.end));if(re?.[0].includes("/")){let ie=Y.end+re[0].length-1;return J.slice(0,Y.start)+J.slice(Y.end,ie)+J.slice(ie+1)}return Ua(J,Y)},P);return $i(j,O),j}function hc(P){pc(P);let O=Ti(P),D=O.find((Y)=>Qr(Y)),j=[],J=[];for(let Y of O){if(!Qr(Y))continue;try{let re=Ri(Y,"utf-8");if(!Oi($i(re,Y)))continue;cn(Y,fy(re,Y)),J.push(Y)}catch(re){j.push(re instanceof Error?re.message:String(re))}}if(j.length>0)throw Error(j.join(`
223
+ `));return{path:J[0]??D??Tn(_i(P),Ei[0]),alreadyInstalled:J.length>0}}function Ot(P){let O=[];for(let D of P.openCodeVersion?.startsWith("2.")?Ai(P.environment):Ti(P.environment))if(my(D))try{let j=gy(D,"utf-8"),J=vn(j),Y=JSON.parse(J);if(Oi(Y)){let re=Ii(P.openCodePluginListOutput);if(re)return{platform:"opencode",status:"disabled",method:"opencode api plugin.list",configPath:D,errors:[...O,re]};return{platform:"opencode",status:"configured",method:"plugin array",configPath:D,errors:O.length>0?O:void 0}}}catch(j){O.push(`Failed to parse ${yy(D)}: ${j instanceof Error?j.message:String(j)}`)}return{platform:"opencode",status:"n/a",errors:O.length>0?O:void 0}}import{join as vc}from"node:path";function Di(P){let O=P.env.get("PI_CODING_AGENT_DIR");return vc(O?Nn(O,P.home):vc(P.home,".pi","agent"),"settings.json")}function Li(P){if(typeof P!=="string")return!1;return P==="npm:cc-safety-net"||P.startsWith("npm:cc-safety-net@")}function bc(P){let O=Di(P.environment),D=xn(O);if(D.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(D.kind==="missing")return{platform:"pi",status:"n/a"};let j=tn(D.value,"packages");if(!Array.isArray(j))return{platform:"pi",status:"n/a"};let J=j.find((ie)=>Li(typeof ie==="string"?ie:tn(ie,"source")));if(J===void 0)return{platform:"pi",status:"n/a"};let Y=tn(J,"extensions");if(Array.isArray(Y)&&Y.some((ie)=>typeof ie==="string"&&ie.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:O,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:O}}var hy={amp:Ia,"antigravity-cli":$a,"claude-code":La,codex:ja,"copilot-cli":Qa,cursor:ll,"deepseek-harness":dl,devin:vl,droid:El,"gemini-cli":_l,"grok-build":jl,"hermes-agent":zl,"kimi-code":Yt,openclaw:lc,opencode:Ot,pi:bc};function Dt(P,O,D){let j={...D,cwd:O,environment:P};return gr.map((J)=>vy(hy[J](j)))}function vy(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 by}from"node:path";var wy=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}]),ky=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),safety:Object.freeze({}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),xy={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 wc(P){let O=by(P.tmpdir,"cc-safety-net-self-test"),D=wy.map((j)=>{let J=G(P,u("self-test",{command:j.command},{kind:"command",shell:"auto"},{configCwd:O,executionCwd:O},j.command),{guard:{dependencies:{loadPolicySnapshot:()=>ky,getModes:()=>xy,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),Y=j.expectBlocked?"blocked":"allowed",re=J.decision.kind==="deny"?"blocked":"allowed";return{command:j.command,description:j.description,expected:Y,actual:re,passed:Y===re,reason:J.decision.kind==="deny"?J.decision.reason:void 0,ruleId:J.decision.kind==="deny"?J.decision.ruleId:void 0}});return{passed:D.filter((j)=>j.passed).length,failed:D.filter((j)=>!j.passed).length,total:D.length,results:D}}function Ni(P){let O=yn({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},P);if(Dn(O.errors))return null;return{json:O.flags.json,skipUpdateCheck:O.flags.skipUpdateCheck}}async function kc(P,O={}){let D=await Ut(!O.json,()=>{let j=Sy(P,O);return{ready:j,finish:()=>j}},()=>Mt(),{loadingMessage:"Checking system status…"});if(O.json)console.log(JSON.stringify(D,null,2));else Py(D);return D.engineSelfTest.failed>0||D.findings.some((j)=>j.severity==="error")?1:0}async function Sy(P,O){let D=O.cwd??process.cwd(),j=await Sr((Me)=>Ot({environment:P,cwd:D,openCodeVersion:Me}).status!=="n/a",void 0,D),J=Dt(P,D,{ampPluginListOutput:j.ampPluginListOutput,codexPluginListOutput:j.codexPluginListOutput,copilotCliVersion:j.versions["copilot-cli"],openCodeVersion:j.versions.opencode,openCodePluginListOutput:j.openCodePluginListOutput}),Y=Ks(P,D),re=Ws(P),ie=k(P,{cwd:D}),de=ie.policy,fe=T(de,P.env),we=q(de,fe.capabilities),Ce=br(P,7),Se=Ra(P,D),Ie=[wr(D),Ct(P)].filter((Me)=>Cy(Me)),Ee=O.skipUpdateCheck?{currentVersion:pn(),latestVersion:null,updateAvailable:!1}:await Gn(),Ve={hooks:J,engineSelfTest:wc(P),userConfig:Y.userConfig,projectConfig:Y.projectConfig,configState:je(ie),effectiveRules:Y.effectiveRules,environment:re,effectiveSafety:{selectedPreset:de.safety.level??"standard",level:fe.effectiveLevel,capabilities:fe.capabilities,ruleOverrides:de.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(we).filter(([,Me])=>Me.source==="rule_override"&&Me.override==="off"&&Me.inheritedEnabled&&Me.changesInherited).map(([Me])=>Me),ruleCounts:{stored:Object.keys(de.destructiveCommandRuleOverrides).length,effective:Object.values(we).filter((Me)=>Me.changesInherited).length},...ie.policyScopes?{policyScopes:ie.policyScopes}:{}},...Se.length>0?{v2Leftovers:Se}:{},...Ie.length>0?{legacyConfigs:Ie}:{},posture:la(P,Y.userConfig.path),activity:Ce,update:Ee,system:j};return{...Ve,findings:Ys(Ve)}}function Py(P){console.log(),console.log(Xs(P.hooks)),console.log(),console.log(Qs(P.engineSelfTest)),console.log(),console.log(ea(P)),console.log(),console.log(na(P.environment)),console.log(),console.log(ta(P)),console.log(),console.log(ra(P.findings)),console.log(),console.log(oa(P.activity)),console.log(),console.log(sa(P.system)),console.log(),console.log(ia(P.update)),console.log(aa(P))}import{existsSync as Ry}from"node:fs";var Ey=/^[A-Za-z0-9_@%+=:,./-]+$/,xc="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function ji(P){let O=yn({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},P);if(Dn(O.errors))return console.error(xc),console.error("Pass -- before a command that starts with dashes."),null;if(O.values.cwd!==void 0&&!Ry(O.values.cwd))return console.error(`Error: --cwd path does not exist: ${O.values.cwd}`),null;let D=O.positionals.length===1?O.positionals[0]:O.positionals.map((j)=>Ey.test(j)?j:`'${j.replaceAll("'","'\\''")}'`).join(" ");if(!D)return console.error("Error: No command provided"),console.error(xc),null;return{json:O.flags.json,cwd:O.values.cwd,command:D}}function Cc(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 Sc(P,O){let j=O-18;return[`${P.dtl}${P.dh.repeat(O)}${P.dtr}`,`${P.dv} Command Analysis${" ".repeat(j)}${P.dv}`,`${P.dbl}${P.dh.repeat(O)}${P.dbr}`]}function Fi(P){return JSON.stringify(P)}function Pc(P,O=0){return`[${P.map((j,J)=>Zs(j,J,O)).join(",")}]`}function er(P,O,D=70){let j=P.split(" "),J=[],Y="";for(let re of j)if(Y&&Y.length+re.length+1>D)J.push(Y),Y=re;else Y=Y?`${Y} ${re}`:re;if(Y)J.push(Y);return J.map((re,ie)=>ie===0?re:`${O}${re}`)}function Rc(P,O,D){let j=[];switch(P.type){case"parse":return null;case"env-strip":return j.push(""),j.push(`STEP ${O} ${D.h} Strip environment variables`),j.push(` Removed: ${P.envVars.map((J)=>`${J}=<redacted>`).join(", ")}`),j.push(` Tokens: ${Fi(P.output)}`),{lines:j,incrementStep:!0};case"leading-tokens-stripped":return j.push(""),j.push(`STEP ${O} ${D.h} Strip wrappers`),j.push(` Removed: ${P.removed.join(", ")}`),j.push(` Tokens: ${Fi(P.output)}`),{lines:j,incrementStep:!0};case"shell-wrapper":return j.push(""),j.push(`STEP ${O} ${D.h} Detect shell wrapper`),j.push(` Wrapper: ${P.wrapper} -c`),j.push(` Inner: ${P.innerCommand}`),{lines:j,incrementStep:!0};case"interpreter":{if(j.push(""),j.push(`STEP ${O} ${D.h} Detect interpreter`),j.push(` Interpreter: ${P.interpreter}`),j.push(` Code: ${P.codeArg}`),P.paranoidBlocked)j.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:j,incrementStep:!0}}case"busybox":return j.push(""),j.push(`STEP ${O} ${D.h} Busybox wrapper`),j.push(` Subcommand: ${P.subcommand}`),{lines:j,incrementStep:!0};case"transparent-wrapper":return j.push(""),j.push(`STEP ${O} ${D.h} Transparent wrapper`),j.push(` Wrapper: ${P.wrapper}`),j.push(` Tokens: ${Fi(P.output)}`),{lines:j,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(j.push(""),j.push(`STEP ${O} ${D.h} Match rules`),j.push(` Rule: ${P.rule}()`),P.matched)j.push(" Result: MATCHED");else j.push(" Result: No match");return{lines:j,incrementStep:!0}}case"worktree-relaxation":return j.push(""),j.push(`STEP ${O} ${D.h} Worktree relaxation`),j.push(` Mode: ${n.worktree.name}`),j.push(` Git cwd: ${P.gitCwd}`),j.push(" Result: Allowed local discard in linked worktree"),{lines:j,incrementStep:!0};case"temp-root-relaxation":return j.push(""),j.push(`STEP ${O} ${D.h} Temp-root relaxation`),j.push(` Git cwd: ${P.gitCwd}`),j.push(" Result: Allowed git discard in a temp-root repository"),{lines:j,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(P.embeddedCommandFound)return j.push(""),j.push(`STEP ${O} ${D.h} Fallback scan`),j.push(` Found: ${P.embeddedCommandFound}`),{lines:j,incrementStep:!0};return null}case"custom-rules-check":{if(P.rulesChecked){if(j.push(""),j.push(`STEP ${O} ${D.h} Custom rules`),P.matched)j.push(" Result: MATCHED");else j.push(" Result: No match");return{lines:j,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(P.matched)return j.push(""),j.push(`STEP ${O} ${D.h} Dangerous text check`),j.push(` Token: ${P.token}`),j.push(" Result: MATCHED"),{lines:j,incrementStep:!0};return null}case"strict-unparseable":return j.push(""),j.push(`STEP ${O} ${D.h} Strict mode check`),j.push(` Command: ${P.rawCommand}`),j.push(" Result: ✗ UNPARSEABLE"),{lines:j,incrementStep:!0};case"segment-skipped":return null;case"error":return j.push(""),j.push(`ERROR: ${P.message}`),{lines:j,incrementStep:!1};default:return P}}function Hi(P,O){let D=Cc(O?.asciiOnly??!1),j=58,J=[],Y=1;J.push(...Sc(D,58)),J.push("");let re=P.trace.steps.find((Ee)=>Ee.type==="error");if(re&&re.type==="error"){J.push("ERROR"),J.push(` ${re.message}`),J.push(""),J.push("RESULT"),J.push(` Status: ${P.result==="blocked"?nn.red("BLOCKED"):nn.green("ALLOWED")}`),J.push(""),J.push("CONFIG");let Ee=P.configSource??"none";return J.push(` Path: ${Ee}`),J.join(`
224
+ `)}let ie=P.trace.steps.find((Ee)=>Ee.type==="parse");if(ie&&ie.type==="parse"){J.push("INPUT"),J.push(` ${ie.input}`),J.push(""),J.push(`STEP ${Y} ${D.h} Split shell commands`),Y++;for(let Ee=0;Ee<ie.segments.length;Ee++){let Ve=ie.segments[Ee];if(Ve){let Me=Math.random();J.push(` Segment ${Ee+1}: ${Pc(Ve,Me)}`)}}}let de=P.trace.segments,fe=de.length>1;for(let Ee of de){if(fe){J.push("");let on="";if(ie&&ie.type==="parse"){let Ro=ie.segments[Ee.index];if(Ro)on=Ro.join(" ")}let sn=54,an=on,rn=` Segment ${Ee.index+1}: `,fn=" ";if(on){if(rn.length+on.length+fn.length>sn){let cp=sn-rn.length-fn.length;an=`${on.substring(0,cp-1)}…`}}let On=on?`${rn}${an}${fn}`:` Segment ${Ee.index+1} `,ap=on?`${rn}${nn.cyan(an)}${fn}`:On,xs=58-On.length,Cs=Math.floor(xs/2),lp=xs-Cs;J.push(`${D.sh.repeat(Cs)}${ap}${D.sh.repeat(lp)}`)}if(Ee.steps.find((on)=>on.type==="segment-skipped")){J.push(""),J.push(" (skipped — prior segment blocked)");continue}let Me=!1,en=!1;for(let on of Ee.steps){let sn=Rc(on,Y,D);if(sn){if(en=!0,on.type==="recurse"){J.push("");let an=" RECURSING ",rn=58-an.length-4;J.push(` ${D.tl}${D.h}${an}${D.h.repeat(rn)}`),J.push(` ${D.v}`),Me=!0;continue}for(let an of sn.lines)if(Me)J.push(` ${D.v} ${an}`);else J.push(an);if(sn.incrementStep)Y++}}if(Me)J.push(` ${D.v}`),J.push(` ${D.bl}${D.h.repeat(56)}`);if(!en)J.push(""),J.push(` ${nn.green("✓")} Allowed (no matching rules)`)}if(J.push(""),J.push("RESULT"),P.result==="blocked"){if(J.push(` Status: ${nn.red("BLOCKED")}`),P.customRule){if(J.push(` Rule: ${P.customRule.id}`),P.customRule.rulebook)J.push(` Rulebook: ${P.customRule.rulebook.name} ${P.customRule.rulebook.version}`);if(P.customRule.source)J.push(` Source: ${P.customRule.source}`);if(P.customRule.override)J.push(` Override: reason ${P.customRule.override.reason}`)}if(P.reason){let Ee=er(P.reason," ");J.push(` Reason: ${Ee[0]}`);for(let Ve=1;Ve<Ee.length;Ve++)J.push(Ee[Ve]??"")}}else J.push(` Status: ${nn.green("ALLOWED")}`);J.push(""),J.push("CONFIG");let we=P.configSource??"none",Ce=P.configValid?"":" (invalid)";J.push(` Path: ${we}${Ce}`);let Se=P.safetyPresetScope;J.push(` Safety preset: ${P.selectedPreset??"standard"}${Se?` (${kr(Se)})`:""}`),J.push(` Effective capabilities: ${P.effectiveLevel}`);let Ie=Object.entries(P.destructiveCommandRuleOverrides??{});if(J.push(` Rule customizations: ${Ie.length}`),P.ruleActivation)J.push(` Rule activation: ${P.ruleActivation.id} — ${P.ruleActivation.enabled?"on":"off"} via ${P.ruleActivation.source}`);return J.join(`
225
+ `)}function Mi(P){return JSON.stringify(P,null,2)}import{resolve as $y}from"node:path";var _y=["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 Ec(P){let O=0,D={allocateSegment(){return O++},getNextSegmentIndex(){return O},recordGlobal(j){P.record({kind:"step",scope:"global",step:j})},recordSegment(j,J=D.currentSegmentIndex){if(J===void 0)return;P.record({kind:"step",scope:"segment",segmentIndex:J,step:j})}};return D}function _c(P={}){let O=[],D=P.maxEvents??512,j={maxTextLength:P.maxTextLength??2048,maxListLength:P.maxListLength??128,maxObjectProperties:P.maxObjectProperties??P.maxListLength??128,maxDepth:P.maxDepth??16},J,Y=new Set;return{record(re){if(J)return;if(!re||O.length>=D)return;try{O.push(qi(Ay(re,j,Y)))}catch{}},finish(){if(J)return J;return J=qi({events:Object.freeze(O)}),J}}}function Ay(P,O,D){if(P.kind!=="step")throw TypeError("invalid trace event");let{scope:j,step:J}=P;no(J,D,O);let Y=Ui(J,O,D);if(j==="global")return{kind:"step",scope:"global",step:Y};if(j!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:P.segmentIndex,step:Y}}function no(P,O,D,j=0,J=new WeakSet){if(typeof P==="string"){let ie=P.slice(0,D.maxTextLength);if(!ze(ie))return;for(let de of nt(ie))for(let fe of de.match(/[^\s"'()$]+/g)??[])O.add(Ac(fe));return}if(!P||typeof P!=="object"||j>=D.maxDepth||J.has(P))return;if(J.add(P),Array.isArray(P)){let ie=Math.min(P.length,D.maxListLength);for(let de=0;de<ie;de++)no(P[de],O,D,j+1,J);return}let Y=0,re=new Set;for(let ie in P){if(!Object.hasOwn(P,ie))continue;if(Y>=D.maxObjectProperties)break;Y++,no(ie,O,D);let de=Gi(ie,D,O);if(re.has(de))continue;re.add(de),no(P[ie],O,D,j+1,J)}}function Ui(P,O,D,j=0,J=new WeakSet){if(typeof P==="string")return Gi(P,O,D);if(!P||typeof P!=="object")return P;if(j>=O.maxDepth)return;if(J.has(P))return;if(J.add(P),Array.isArray(P)){let ie=[],de=Math.min(P.length,O.maxListLength);for(let fe=0;fe<de;fe++)ie.push(Ui(P[fe],O,D,j+1,J));return ie}let Y={},re=0;for(let ie in P){if(!Object.hasOwn(P,ie))continue;if(re>=O.maxObjectProperties)break;re++;let de=Gi(ie,O,D);if(Object.hasOwn(Y,de))continue;Object.defineProperty(Y,de,{value:Ui(P[ie],O,D,j+1,J),enumerable:!0,configurable:!0,writable:!0})}return Y}function Gi(P,O,D){let j=P.slice(0,O.maxTextLength),J=ze(j)?Be(j):j,Y=D.size>0?Iy(J,D):J;return(Ty(Y)?Pe(Y):Y).slice(0,O.maxTextLength)}function Ty(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&&_y.some((O)=>P.includes(O))||P.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(P)}function Iy(P,O){return P.replace(/[^\s"'()$]+/g,(D)=>O.has(Ac(D))?"<redacted>":D)}function Ac(P){let O=2166136261,D=2166136261;for(let j=0;j<P.length;j++)O=Math.imul(O^P.charCodeAt(j),16777619),D=Math.imul(D^P.charCodeAt(P.length-j-1),16777619);return`${O>>>0}:${D>>>0}:${P.length}`}function qi(P){if(P&&typeof P==="object"&&!Object.isFrozen(P)){for(let O of Object.values(P))qi(O);Object.freeze(P)}return P}function nr(P,O={},D){let j=$y(O.cwd??process.cwd()),J=O.policySnapshot??k(D,{cwd:j,userConfigDir:O.userConfigDir}),Y=T(J.policy,D.env),re=Ue({policySnapshot:J,effectiveCapabilities:Y.capabilities,strict:Y.strict,paranoidRm:Y.paranoidRm,paranoidInterpreters:Y.paranoidInterpreters,worktreeMode:Y.worktreeMode}),ie={effectiveLevel:re.effectiveLevel,selectedPreset:J.policy.safety.level??"standard",...J.policyScopes?{safetyPresetScope:J.policyScopes.levelScope}:{},effectiveCapabilities:re.effectiveCapabilities,destructiveCommandRuleOverrides:J.policy.destructiveCommandRuleOverrides},{configSource:de,configValid:fe}=Dy(D,{cwd:j,userConfigDir:O.userConfigDir});if(!P||!P.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:de,configValid:fe,...ie};let we=y(P,"auto");if(we.status==="limited")throw new b;let Ce=we.dialect==="powershell"?y(P,"posix"):we,Se=dt(Ce),Ie=_c(),Ee=Ec(Ie);Ee.recordGlobal({type:"parse",input:P,segments:Se.map((On)=>[...On])});let Ve=u("Bash",{command:P},{kind:"command",shell:"auto"},{configCwd:j,executionCwd:j},P),Me=V(Ve,{environment:D,trace:Ee,dependencies:{loadPolicySnapshot:()=>J}}),en=Me.decision.kind==="deny"?Me.decision:null;if(en&&(Me.stage==="policy-protection"||Me.stage==="secret-protection"))return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:Oy(en),matched:!0,reason:en.reason}]}]},result:"blocked",reason:R(en.reason),segment:R(Tc(en,P)),ruleId:R(en.ruleId),configSource:de,configValid:fe,...ie};let on=Ee.getNextSegmentIndex();if(en&&on>0&&on<Se.length)Ee.recordSegment({type:"segment-skipped",index:on,reason:"prior-segment-blocked"},on);let sn=Ie.finish(),an=en?.ruleId??Ly(Ve,J,Y,D),rn=z.find((On)=>On.id===an&&On.activationCapability),fn=rn?re.policy.effectiveDestructiveCommandRules[rn.id]:void 0;return{trace:jy(sn),result:en?"blocked":"allowed",reason:en?R(en.reason):void 0,segment:en?R(Tc(en,P)):void 0,ruleId:en?R(en.ruleId):void 0,customRule:Ny(Fy(en?.ruleId,J)),configSource:de,configValid:fe,...ie,...rn&&fn?{ruleActivation:{id:rn.id,...fn}}:{}}}function Tc(P,O){return P.evidence?.segment??O}function Oy(P){if(P.reason===He)return"policy-protection:findPolicyConfigMutationTargetInSemanticFacts";if(P.reason===Ge)return"policy-apply-protection:findPolicyApplyInvocationInSemanticFacts";if(P.reason===x)return"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts";return"secret-protection:findSensitiveTargetInSemanticFacts"}function Dy(P,O){let D=_(O.cwd),j=W(P,O),J=X(P,{cwd:O.cwd,userConfigDir:O.userConfigDir});try{if(r(J.projectConfigTarget)!==null){if(Un(J.projectConfigTarget).errors.length===0)return{configSource:D,configValid:!0};return{configSource:D,configValid:!1}}}catch(Y){if(Y instanceof o)return{configSource:D,configValid:!1};throw Y}try{if(r(J.userConfigTarget)!==null){let Y=Un(J.userConfigTarget);return{configSource:j,configValid:Y.errors.length===0}}return{configSource:null,configValid:!0}}catch(Y){if(Y instanceof o)return{configSource:j,configValid:!1};throw Y}}function Ly(P,O,D,j){let J=O.policy,Y=_e({...J,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...J.destructiveCommandRuleOverrides,...Object.fromEntries(z.flatMap((ie)=>ie.activationCapability?[[ie.id,"on"]]:[]))}},O.state==="degraded"?{diagnostics:O.diagnostics,reason:O.reason}:void 0),re=V(P,{environment:j,dependencies:{loadPolicySnapshot:()=>Y,getModes:()=>({...D,strict:!0,paranoidRm:!0,paranoidInterpreters:!0}),findSensitiveTarget:()=>null}});return re.decision.kind==="deny"?re.decision.ruleId:void 0}function Ny(P){if(!P)return;return{id:R(P.id),...P.rulebook?{rulebook:{name:R(P.rulebook.name),version:R(P.rulebook.version)}}:{},...P.source?{source:R(P.source)}:{},...P.override?{override:{type:"reason",reason:R(P.override.reason)}}:{}}}function jy(P){let O=P.events.flatMap((j)=>j.kind==="step"&&j.scope==="global"?[j.step]:[]),D=new Map;for(let j of P.events){if(j.kind!=="step"||j.scope!=="segment")continue;let J=D.get(j.segmentIndex)??{index:j.segmentIndex,steps:[]};J.steps.push(j.step),D.set(j.segmentIndex,J)}return{steps:O,segments:[...D.values()]}}function Fy(P,O){let D=P?.replace(/^custom\./,"");if(!D||!O.policy.rules.some((j)=>j.name===D))return;return O.ruleMetadata[D]??Object.freeze({id:D})}function Ic(P){return new Promise((O)=>{process.stdout.write(`${P}
226
+ `,()=>O())})}async function $c(P,O){let D=ji(O);if(!D)return 1;try{let j=nr(D.command,{cwd:D.cwd},P),J=!!process.env.NO_COLOR||!process.stdout.isTTY;return await Ic(D.json?Mi(j):Hi(j,{asciiOnly:J})),0}catch(j){let J=Hy(j instanceof p?j.cause:j);if(J===void 0)throw j;if(D.json)return await Ic(JSON.stringify({error:J})),1;return console.error(J),1}}function Hy(P){if(P instanceof b)return P.message;if(P instanceof f)return P.message;if(P instanceof s&&a[P.kind].errorCode==="path-canonicalization-limit")return"Path canonicalization work limit exceeded.";return}var Oc="2.6.3",_n=" ",ft="cc-safety-net";function Dc(P){return P.argument?`${P.flags} ${P.argument}`:P.flags}function My(P){return Math.max(...P.map((O)=>Dc(O).length))}function Uy(P){return Math.max(...P.map((O)=>O.usage.length))}function Gy(P){return Math.max(...P.map((O)=>`${ft} ${O.usage}`.length))}function qy(P,O){let D=`${ft} ${P.usage}`;return`${_n}${D.padEnd(O+2)}${P.description}`}function In(P,O){return`${_n}${P.padEnd(Math.max(40,P.length+2))}${O}`}function Lt(P,O=console.log){let D=[];if(D.push(`${ft} ${P.name}`),D.push(""),D.push(`${_n}${P.description}`),D.push(""),D.push("USAGE:"),D.push(`${_n}${ft} ${P.usage}`),D.push(""),P.subcommands&&P.subcommands.length>0){D.push("SUBCOMMANDS:");let j=Uy(P.subcommands);for(let J of P.subcommands)D.push(`${_n}${J.usage.padEnd(j+2)}${J.description}`);D.push("")}if(P.options.length>0){D.push("OPTIONS:");let j=My(P.options);for(let J of P.options){let Y=Dc(J),re=J.default?`${J.description} (default: ${J.default})`:J.description;D.push(`${_n}${Y.padEnd(j+2)}${re}`)}D.push("")}if(P.examples&&P.examples.length>0){D.push("EXAMPLES:");for(let j of P.examples)D.push(`${_n}${j}`)}O(D.join(`
227
+ `))}function Bi(){let P=Gy(hr),O=[];O.push(`${ft} v${Oc}`),O.push(""),O.push("Blocks destructive commands and secret access."),O.push(""),O.push("COMMANDS:");for(let D of hr)O.push(qy(D,P));O.push(""),O.push("GLOBAL OPTIONS:"),O.push(`${_n}-h, --help Show help (use with command for command-specific help)`),O.push(`${_n}-V, --version Show version`),O.push(""),O.push("HELP:"),O.push(`${_n}${ft} help <command> Show help for a specific command`),O.push(`${_n}${ft} <command> --help Show help for a specific command`),O.push(""),O.push("ENVIRONMENT VARIABLES:"),O.push(In(`${n.level.name}=standard|strict|paranoid`,"Set session safety level")),O.push(In(`${n.worktree.name}=1`,"Allow local git discards in linked worktrees")),O.push(In(`${n.debug.name}=1`,"Print diagnostic messages to stderr")),O.push(In(`${n.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),O.push(In(`${n.projectTightenOnly.name}=1`,"Ignore project policy settings that weaken the user policy")),O.push(In("CC_SAFETY_NET_HOME","Override rule config home directory")),O.push(""),O.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),O.push(In(`${n.strict.name}=1`,"Force safety.overrides.fail_closed on")),O.push(In(`${n.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),O.push(In(`${n.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),O.push(In(`${n.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),O.push(""),O.push("Documentation: https://ccsafetynet.com/docs"),console.log(O.join(`
228
+ `))}function Lc(){console.log(Oc)}function tr(P,O=console.log){let D=vr(P);if(!D)return!1;if(D.name.toLowerCase()!==P.toLowerCase())return!1;return Lt(D,O),!0}import{existsSync as co,readFileSync as Ud}from"node:fs";import{join as lo}from"node:path";import*as Bn from"node:readline";function By(P){return P==="install"?"Install":"Uninstall"}function Vy(P){return P==="install"?"Installing":"Uninstalling"}function Jy(P){return P==="install"?"into":"from"}function Fc(P){return P?.available===!0}function Ky(P,O){let D=new Set(O);return P.filter((j)=>D.has(j.target)).map((j)=>j.target)}function Nc(P,O,D){if(P.every((j)=>!j.available))return O;return Array.from({length:P.length},(j,J)=>J+1).map((j)=>(O+j*D+P.length)%P.length).find((j)=>Fc(P[j]))}function Wy(P,O,D){if(D.ctrl&&D.name==="c")return"interrupt";if(D.name==="escape"||O==="q")return"abort";if(P==="install"&&(O==="u"||O==="U"))return"update";if(D.name==="up"||O==="k")return"up";if(D.name==="down"||O==="j")return"down";if(D.name==="space"||O===" ")return"toggle";if(D.name==="return"||D.name==="enter")return"confirm";return null}function zy(P){return{cursor:P.findIndex((O)=>O.available),selected:[]}}function Yy(P,O,D){if(D==="confirm"||D==="update"||D==="abort"||D==="interrupt")return{state:P,done:D};if(D==="up")return{state:{...P,cursor:Nc(O,P.cursor,-1)}};if(D==="down")return{state:{...P,cursor:Nc(O,P.cursor,1)}};let j=O[P.cursor];if(!Fc(j))return{state:P};let J=P.selected.includes(j.target)?P.selected.filter((Y)=>Y!==j.target):Ky(O,[...P.selected,j.target]);return{state:{...P,selected:J}}}var Hc="◉",Mc="◯",Uc=">",Gc=" ";function Zy(P,O,D){return["",`${By(P)} CC Safety Net ${Jy(P)}:`,"",...O.map((j,J)=>{let Y=D.selected.includes(j.target),re=J===D.cursor,ie=Y?Hc:Mc,de=re?Uc:Gc,fe=j.available?"":` (${j.unavailableReason??"not installed"})`,we=`${ie} ${j.label}${fe}`,Ce=!j.available?nn.dim(we):Y?nn.green(we):re?nn.bold(we):we;return`${de} ${Ce}`}),"",P==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":O.some((j)=>j.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${P}. q/Esc: close`].join(`
229
+ `)}var jc=["global-hook","plugin"];function Xy(P,O,D={}){let j=D.color!==!1?nn.bold:(Y)=>Y;return["","Install the Kimi Code integration as:","",...[`Global hook — ${O?"already installed; selecting it reports the current state":"write the hook into ~/.kimi-code/config.toml now"}`,"Native Kimi plugin — print the steps to run inside Kimi Code"].map((Y,re)=>{let ie=re===P,de=`${ie?Hc:Mc} ${Y}`;return`${ie?Uc:Gc} ${ie?j(de):de}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
230
+ `)}function qc(P){let{input:O,output:D}=P;Bn.emitKeypressEvents(O);let j=O.isRaw===!0;O.setRawMode(!0),O.resume();let J=0,Y=()=>{if(J===0)return;Bn.moveCursor(D,0,-J),Bn.cursorTo(D,0),Bn.clearScreenDown(D)},re=()=>{Y();let ie=P.render();D.write(`${ie}
230
231
  `),J=ie.split(`
231
- `).length};return new Promise((ie)=>{let de=(we)=>{O.off("keypress",fe),O.setRawMode(j),O.pause(),Y(),ie(we)};function fe(we,Ce){P.onKey(we,Ce,{finish:de,draw:re})}O.on("keypress",fe),re()})}function Dc(P={}){let O=0;return Oc({input:P.input??process.stdin,output:P.output??process.stdout,render:()=>Fy(O,P.globalHookInstalled===!0),onKey:(D,j,J)=>{if(j.ctrl&&j.name==="c"){J.finish(null),(P.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(j.name==="escape"||D==="q")return J.finish(null);if(j.name==="return"||j.name==="enter")return J.finish(Ec[O]);if(j.name==="up"||j.name==="down"||D==="k"||D==="j")O=(O+1)%Ec.length,J.draw()}})}function Ni(P=process.stdin,O=process.stdout){return Boolean(P.isTTY&&O.isTTY&&typeof P.setRawMode==="function")}function Lc(P,O,D={}){let j=D.output??process.stdout,J=Ly(O);return Oc({input:D.input??process.stdin,output:j,render:()=>jy(P,O,J),onKey:(Y,re,ie)=>{let de=Dy(P,Y,re);if(!de)return;let fe=Ny(J,O,de);if(J=fe.state,fe.done==="interrupt"){ie.finish(null),(D.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(fe.done==="abort")return ie.finish(null);if(fe.done==="update")return ie.finish("update");if(fe.done==="confirm"){if(J.selected.length===0){j.write("\x07"),ie.draw();return}ie.finish([...J.selected]),j.write(`${Iy(P)} selected integrations...
232
- `);return}ie.draw()}})}import{existsSync as Nc,lstatSync as My,mkdirSync as Uy,mkdtempSync as Gy,readdirSync as qy,readFileSync as jt,rmSync as Zr}from"node:fs";import{basename as By,dirname as Vy,join as Cn}from"node:path";import{fileURLToPath as Jy}from"node:url";var ji="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",mt="cc-safety-net",gt="cc-safety-net/index.ts";import{spawn as Hy}from"node:child_process";var Fi=(P,O)=>{let D=zn([...P],process.env);return new Promise((j)=>{let J=Hy(D.cmd,D.args,{cwd:O,stdio:["ignore","pipe","pipe"]}),Y=pi(J),re=!1,ie=setTimeout(()=>{re=!0,J.kill()},120000);J.on("error",(de)=>{clearTimeout(ie),j({status:null,errorCode:de.code,stdout:Y.stdout,stderr:[de.message,Y.stderr].filter(Boolean).join(`
233
- `)})}),J.on("close",(de)=>{clearTimeout(ie),j({status:re?null:de,errorCode:re?"ETIMEDOUT":void 0,stdout:Y.stdout,stderr:Y.stderr})})})};var Nt="cc-safety-net.ts",Hi=Cn("amp",gt);function Wy(P){return Cn(P.home,".config","amp","plugins","cc-safety-net.ts")}function Ky(){let P=Vy(Jy(import.meta.url)),O=Cn(P,Hi),D=Cn(P,"..",Hi),j=Cn(P,"..","..","..","dist",Hi);return[O,D,j]}function zy(P=Ky()){let O=P.find((D)=>Nc(D)&&My(D).isFile());if(!O)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return O}function jc(P){try{return JSON.parse(P)}catch{return}}function Xr(P){return P.subarray(0,Buffer.byteLength(ji)).toString("utf-8")===ji}async function nr(P,O,D){let j=await P(O,D);if(j.status===0)return j;throw Error([`Failed to run ${O.join(" ")}${j.status===null?"":` (exit ${j.status})`}.`,[j.stdout,j.stderr].filter(Boolean).join(`
232
+ `).length};return new Promise((ie)=>{let de=(we)=>{O.off("keypress",fe),O.setRawMode(j),O.pause(),Y(),ie(we)};function fe(we,Ce){P.onKey(we,Ce,{finish:de,draw:re})}O.on("keypress",fe),re()})}function Bc(P={}){let O=0;return qc({input:P.input??process.stdin,output:P.output??process.stdout,render:()=>Xy(O,P.globalHookInstalled===!0),onKey:(D,j,J)=>{if(j.ctrl&&j.name==="c"){J.finish(null),(P.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(j.name==="escape"||D==="q")return J.finish(null);if(j.name==="return"||j.name==="enter")return J.finish(jc[O]);if(j.name==="up"||j.name==="down"||D==="k"||D==="j")O=(O+1)%jc.length,J.draw()}})}function Vi(P=process.stdin,O=process.stdout){return Boolean(P.isTTY&&O.isTTY&&typeof P.setRawMode==="function")}function Vc(P,O,D={}){let j=D.output??process.stdout,J=zy(O);return qc({input:D.input??process.stdin,output:j,render:()=>Zy(P,O,J),onKey:(Y,re,ie)=>{let de=Wy(P,Y,re);if(!de)return;let fe=Yy(J,O,de);if(J=fe.state,fe.done==="interrupt"){ie.finish(null),(D.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(fe.done==="abort")return ie.finish(null);if(fe.done==="update")return ie.finish("update");if(fe.done==="confirm"){if(J.selected.length===0){j.write("\x07"),ie.draw();return}ie.finish([...J.selected]),j.write(`${Vy(P)} selected integrations...
233
+ `);return}ie.draw()}})}import{existsSync as Jc,lstatSync as eh,mkdirSync as nh,mkdtempSync as th,readdirSync as rh,readFileSync as jt,rmSync as ro}from"node:fs";import{basename as oh,dirname as ih,join as Sn}from"node:path";import{fileURLToPath as sh}from"node:url";var Ji="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",mt="cc-safety-net",gt="cc-safety-net/index.ts";import{spawn as Qy}from"node:child_process";var Ki=(P,O)=>{let D=zn([...P],process.env);return new Promise((j)=>{let J=Qy(D.cmd,D.args,{cwd:O,stdio:["ignore","pipe","pipe"]}),Y=Wo(J),re=!1,ie=setTimeout(()=>{re=!0,J.kill()},120000);J.on("error",(de)=>{clearTimeout(ie),j({status:null,errorCode:de.code,stdout:Y.stdout,stderr:[de.message,Y.stderr].filter(Boolean).join(`
234
+ `)})}),J.on("close",(de)=>{clearTimeout(ie),j({status:re?null:de,errorCode:re?"ETIMEDOUT":void 0,stdout:Y.stdout,stderr:Y.stderr})})})};var Nt="cc-safety-net.ts",Wi=Sn("amp",gt);function ah(P){return Sn(P.home,".config","amp","plugins","cc-safety-net.ts")}function lh(){let P=ih(sh(import.meta.url)),O=Sn(P,Wi),D=Sn(P,"..",Wi),j=Sn(P,"..","..","..","dist",Wi);return[O,D,j]}function ch(P=lh()){let O=P.find((D)=>Jc(D)&&eh(D).isFile());if(!O)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return O}function Kc(P){try{return JSON.parse(P)}catch{return}}function oo(P){return P.subarray(0,Buffer.byteLength(Ji)).toString("utf-8")===Ji}async function rr(P,O,D){let j=await P(O,D);if(j.status===0)return j;throw Error([`Failed to run ${O.join(" ")}${j.status===null?"":` (exit ${j.status})`}.`,[j.stdout,j.stderr].filter(Boolean).join(`
234
235
  `).trim()].filter(Boolean).join(`
235
- `))}async function Fc(P){let O=await P(["amp","plugins","repositories","--json"]);if(O.status===null)throw Error(`${O.errorCode==="ENOENT"?'Amp CLI not found. Install the amp CLI, sign in with "amp login", and rerun install --amp.':`amp plugins repositories --json did not finish (${O.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
236
+ `))}async function Wc(P){let O=await P(["amp","plugins","repositories","--json"]);if(O.status===null)throw Error(`${O.errorCode==="ENOENT"?'Amp CLI not found. Install the amp CLI, sign in with "amp login", and rerun install --amp.':`amp plugins repositories --json did not finish (${O.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
236
237
  ${O.stderr}`.trim());if(O.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${O.status}). Sign in with "amp login" and rerun install --amp.
237
238
  ${[O.stdout,O.stderr].filter(Boolean).join(`
238
- `)}`.trim());let D=jc(O.stdout),j=(Array.isArray(D)?D:[]).filter((J)=>tn(J,"scope")==="user"&&tn(J,"exists")===!0&&tn(J,"viewerCanWrite")===!0).map((J)=>tn(J,"cloneRef")).find((J)=>typeof J==="string"&&J.length>0);if(!j)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return j}async function Hc(P,O,D){let j=Gy(Cn(O.tmpdir,"cc-safety-net-amp-"));try{return await nr(P,["amp","clone","user-plugins",j]),await D(j)}finally{Zr(j,{recursive:!0,force:!0})}}function Mi(P){return`rerun ${P==="overwrite"?"install":"uninstall"} --amp`}function Mc(P,O,D){let j=Cn(P,O),J=dn(j);if(!J)return;if(J.isSymbolicLink()||!J.isFile())throw Error(`Refusing to ${D} ${O} in your Amp personal plugins repository: not a regular file. Remove it there and ${Mi(D)}.`);let Y=jt(j);if(Xr(Y))return Y;throw Error(`Refusing to ${D} unmanaged file ${O} in your Amp personal plugins repository. Remove it there and ${Mi(D)}.`)}function Uc(P,O){let D=Cn(P,mt),j=dn(D);if(!j)return;if(j.isSymbolicLink()||!j.isDirectory())throw Error(`Refusing to ${O} ${mt} in your Amp personal plugins repository: not a regular directory. Remove it there and ${Mi(O)}.`);return Mc(P,gt,O)}function Yy(P){let O=Cn(P,Nt),D=dn(O);if(!D||D.isSymbolicLink()||!D.isFile())return;let j=jt(O);return Xr(j)?j:void 0}async function Gc(P,O,D,j){if(await nr(P,D,O),(await nr(P,["git","status","--porcelain"],O)).stdout.trim()==="")return!1;return await nr(P,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",j],O),await nr(P,["git","push","origin","HEAD"],O),!0}function Yr(P,O){Zy(P,O),Xy(P,O)}function qc(P,O){if(O==="keep")return;throw Error(`Local Amp plugin ${P} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function Zy(P,O){let D=Wy(P),j=dn(D);if(!j)return;if(!j.isSymbolicLink()&&j.isFile()&&Xr(jt(D))){Zr(D);return}qc(D,O)}function Xy(P,O){let D=Cn(P.home,".config","amp","plugins",mt),j=dn(D);if(!j)return;if(!j.isSymbolicLink()&&j.isDirectory()&&Qy(D)){Zr(D,{recursive:!0});return}qc(D,O)}function Qy(P){let O=By(gt);if(qy(P).join("\x00")!==O)return!1;let D=Cn(P,O),j=dn(D);return!!j&&!j.isSymbolicLink()&&j.isFile()&&Xr(jt(D))}function eh(P){let O=l(P);if(!Nc(O))return"";let D=jc(jt(O,"utf-8"));if(!D||typeof D!=="object"||Array.isArray(D))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(E(D,P.home))};
239
- `}async function Bc(P,O=zy(),D=Fi){let j=Buffer.concat([jt(O),Buffer.from(eh(P),"utf-8")]),J=await Fc(D);return Hc(D,P,async(Y)=>{let re=`${J}/${mt}`,ie=Uc(Y,"overwrite"),de=Mc(Y,Nt,"overwrite");if(ie?.equals(j)&&!de)return Yr(P,"fail"),{path:re,alreadyInstalled:!0};if(Uy(Cn(Y,mt),{recursive:!0}),cn(Cn(Y,gt),j),de)Zr(Cn(Y,Nt));let fe=await Gc(D,Y,["git","add","--",gt,...de?[Nt]:[]],`chore: update cc-safety-net plugin to v${pn()}`);return Yr(P,"fail"),{path:re,alreadyInstalled:!fe}})}async function Vc(P,O=Fi){let D=await Fc(O);return Hc(O,P,async(j)=>{let J=Uc(j,"remove"),Y=Yy(j),re=`${D}/${Y&&!J?Nt:mt}`;if(!J&&!Y)return Yr(P,"keep"),{path:re,alreadyInstalled:!1};return await Gc(O,j,["git","rm","--",...J?[gt]:[],...Y?[Nt]:[]],`chore: remove cc-safety-net plugin v${pn()}`),Yr(P,"keep"),{path:re,alreadyInstalled:!0}})}import{existsSync as Jc,mkdirSync as nh,readFileSync as th}from"node:fs";import{dirname as rh}from"node:path";var Ui=xn["antigravity-cli"],yt="cc-safety-net";function ht(P){return Boolean(P)&&typeof P==="object"&&!Array.isArray(P)}function eo(){return{PreToolUse:[{hooks:[{type:"command",command:Ui,timeout:30}]}]}}function Wc(P){try{let O=JSON.parse(th(P,"utf-8"));if(!O||typeof O!=="object"||Array.isArray(O))throw Error("Antigravity hooks config must be a JSON object");return O}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${P}: ${O.message}`);throw O}}function Kc(P){let O=P[yt];if(O===void 0){let j=eo();return P[yt]=j,{definition:j,preToolUse:j.PreToolUse??[]}}if(!ht(O))throw Error(`Antigravity hooks config entry "${yt}" must be an object`);let D=Array.isArray(O.PreToolUse)?O.PreToolUse:[];return O.PreToolUse=D,{definition:O,preToolUse:D}}function zc(P){if(!Array.isArray(P.PreToolUse))return!1;return P.PreToolUse.some((O)=>ht(O)&&Array.isArray(O.hooks)&&O.hooks.some((D)=>ht(D)&&D.command===Ui))}function oh(P){return Object.values(P).some((O)=>ht(O)&&O.enabled!==!1&&zc(O))}function ih(P){if(P[yt]===void 0)return!1;let O=Kc(P);if(O.definition.enabled!==!1||!zc(O.definition))return!1;return O.definition.enabled=!0,!0}function sh(P){if(P[yt]===void 0){P[yt]=eo();return}let O=Kc(P);O.definition.enabled=!0,O.preToolUse.push(eo().PreToolUse?.[0]??{hooks:[]})}function ah(P){let O=!1;for(let D of Object.values(P)){if(!ht(D)||!Array.isArray(D.PreToolUse))continue;D.PreToolUse=D.PreToolUse.flatMap((j)=>{if(!ht(j)||!Array.isArray(j.hooks))return[j];let J=j.hooks.filter((Y)=>!ht(Y)||Y.command!==Ui);if(J.length!==j.hooks.length)O=!0;return J.length===0?[]:[{...j,hooks:J}]})}return O}function Qr(P,O){cn(P,`${JSON.stringify(O,null,2)}
240
- `)}function Yc(P){let O=Gt(P.home);if(nh(rh(O),{recursive:!0}),!Jc(O))return Qr(O,{[yt]:eo()}),{path:O,alreadyInstalled:!1};let D=Wc(O);if(oh(D))return{path:O,alreadyInstalled:!0};if(ih(D))return Qr(O,D),{path:O,alreadyInstalled:!1};return sh(D),Qr(O,D),{path:O,alreadyInstalled:!1}}function Zc(P){let O=Gt(P.home);if(!Jc(O))return{path:O,alreadyInstalled:!1};let D=Wc(O);if(!ah(D))return{path:O,alreadyInstalled:!1};return Qr(O,D),{path:O,alreadyInstalled:!0}}import{existsSync as Bi,readlinkSync as dh}from"node:fs";import{join as Vn}from"node:path";import{spawn as lh}from"node:child_process";var $n=En.map((P)=>({target:P.id,flag:P.flag,label:mn(P.id),probeCommand:P.probeCommand}));function Gi(P){let O=new Set(P);return $n.map((D)=>D.target).filter((D)=>O.has(D))}async function Xc(P,O){for(let D of P)await O(D)}var ch=5000;function tr(P,O=ch){return new Promise((D)=>{let j=zn([...P],process.env),J=lh(j.cmd,j.args,{env:process.env,stdio:"ignore"}),Y=!1,re=(de)=>{if(Y)return;Y=!0,clearTimeout(ie),D(de)},ie=setTimeout(()=>{J.kill(),re(!1)},O);J.on("error",()=>re(!1)),J.on("close",(de)=>re(de===0))})}function Qc(P=tr,O={}){let D=new Set(O.configuredTargets??[]);return Promise.all($n.map(async(j)=>({target:j.target,flag:j.flag,label:j.label,...nd(O.action,await P(j.probeCommand),D.has(j.target))})))}function ed(P,O){let D=new Set(O.configuredTargets??[]);return P.map((j)=>({...j,...nd(O.action,j.available,D.has(j.target))}))}function nd(P,O,D){if(P==="uninstall")return D?{available:!0}:{available:!1,unavailableReason:"not installed"};if(P==="install"&&D)return{available:!1,unavailableReason:"already installed"};if(!O)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}var Jn="cc-safety-net",id=["npx","-y","@deepseek-ai/dsh"],td="DeepSeek Harness",rd=["@deepseek-ai","dsh-desktop"],sd="Quit DeepSeek Harness Desktop, then run this command again: Desktop plugins can only change while it is closed.",qi=(P)=>`DeepSeek Harness Desktop is not in its default location, so ${P} ${Jn} from its Plugins page.`,ad=(P,O)=>Bi(Vn(Jo(P),O,"package.json"));function Vi(P,O){let D=O.platform??process.platform,j=ad(P,"desktop"),J=D==="darwin"?[Vn(P.home,"Applications"),O.systemApplications??"/Applications"].map((Y)=>Vn(Y,`${td}.app`,"Contents","Resources","runtime","cli","bin","dsh")):D==="win32"?[Vn(P.env.get("LOCALAPPDATA")||Vn(P.home,"AppData","Local"),"Programs",td,"resources","runtime","cli","bin","dsh.cmd")]:[];return{profile:j,cli:j?J.find((Y)=>Bi(Y)):void 0}}function ld(P,O=process.platform){if(O==="win32")return Bi(Vn(P.env.get("APPDATA")||Vn(P.home,"AppData","Roaming"),...rd,"lockfile"));let D=uh(Vn(P.home,"Library","Application Support",...rd,"SingletonLock")),j=Number(/-(\d+)$/.exec(D??"")?.[1]);return Number.isInteger(j)&&j>0&&ph(j)}function uh(P){try{return dh(P)}catch{return}}function ph(P){try{return process.kill(P,0),!0}catch(O){return O.code==="EPERM"}}async function cd(P,O={}){let D=Vi(P,O);if(D.cli&&ld(P,O.platform))throw Error(sd);let j=!D.cli||ad(P,"web")||await(O.probe??tr)(xo),J=[...D.cli?[{profile:"desktop",label:"Desktop",dsh:[D.cli]}]:[],...j?[{profile:"web",label:"web",dsh:id}]:[]];return{commands:J.map((Y)=>[...Y.dsh,"plugin","--profile",Y.profile,"add",`${Jn}@${pn()}`]),afterInstall:async()=>{let Y=new Set(Wo(P).filter((ie)=>ie.enabled).map((ie)=>ie.name)),re=J.filter((ie)=>!Y.has(ie.profile));if(re.length>0)throw Error(`DeepSeek Harness installed ${Jn} in the ${od(re)} but did not enable it. Enable it from the Plugins page.`)},message:[`Added ${Jn} to the DeepSeek Harness ${od(J)}.`,...D.profile&&!D.cli?[qi("add")]:[]].join(`
241
- `)}}function od(P){return`${P.map((O)=>O.label).join(" and ")} profile${P.length>1?"s":""}`}function dd(P,O={}){let D=new Set(Wo(P).map((Y)=>Y.name));if(!D.has("desktop")&&!D.has("web"))throw Error(`${Jn} is not installed in the DeepSeek Harness web or Desktop profile`);let j=D.has("desktop")?Vi(P,O).cli:void 0,J=D.has("desktop")&&!j;if(J&&!D.has("web"))throw Error(qi("remove"));if(j&&ld(P,O.platform))throw Error(sd);return{commands:[...j?[[j,"plugin","--profile","desktop","remove",Jn]]:[],...D.has("web")?[[...id,"plugin","--profile","web","remove",Jn]]:[]],...J?{afterUninstall:()=>{throw Error(`Removed ${Jn} from the DeepSeek Harness web profile, but ${qi("remove")}`)}}:{}}}function ud(P,O,D={}){let j=Vi(O,D).cli!==void 0;return P.map((J)=>J.target==="deepseek-harness"&&j?{...J,available:!0,unavailableReason:void 0}:J)}import{existsSync as fh,readdirSync as mh,rmSync as gh}from"node:fs";import{join as yh}from"node:path";function pd(P,O=process.platform,D){if(!fh(P))return;let j=O==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);mh(P).filter((J)=>J!==D&&j.test(J)).forEach((J)=>{gh(yh(P,J),{recursive:!0,force:!0})})}import{existsSync as fd,readdirSync as hh,rmSync as vh}from"node:fs";import{join as Ft}from"node:path";function no(P,O=process.platform){let D=Ft(P.env.get("npm_config_cache")||(O==="win32"?Ft(P.env.get("LOCALAPPDATA")||Ft(P.home,"AppData","Local"),"npm-cache"):Ft(P.home,".npm")),"_npx");if(!fd(D))return;hh(D).filter((j)=>fd(Ft(D,j,"node_modules","cc-safety-net"))).forEach((j)=>{vh(Ft(D,j),{recursive:!0,force:!0})})}import{existsSync as bd,mkdirSync as wh,readFileSync as wd}from"node:fs";import{dirname as kh,join as vd}from"node:path";function bh(P,O){if(P[O]!=="#")return O;let D=P.indexOf(`
242
- `,O+1);return D===-1?P.length:D+1}function Ji(P,O,D){let j=new RegExp(`^(\\s*)${O}\\s*=\\s*\\[`),J=0;for(let Y of P.split(`
243
- `)){if(/^\s*\[/.test(Y))return;let re=j.exec(Y);if(re){let ie=J+re[0].lastIndexOf("[");return{start:ie,end:Mo(P,ie,{skipComment:bh,...D})}}J+=Y.length+1}return}function md(P,O,D){let j=P.slice(0,O.end).trimEnd(),J=Aa(P,O.end),Y=J===""?" ":`${J} `,re=!j.endsWith("[")&&!j.endsWith(",");return`${j}${re?",":""}
244
- ${Y}${D}${P.slice(O.end)}`}function gd(P,O,D){let j=P.indexOf(D,O.start);if(j===-1||j>O.end)return P;return`${P.slice(0,j)}${P.slice(j+D.length).replace(/^\s*,/,"")}`}function yd(P,O){let D=new RegExp(`^\\s*${O}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),j=P.split(`
239
+ `)}`.trim());let D=Kc(O.stdout),j=(Array.isArray(D)?D:[]).filter((J)=>tn(J,"scope")==="user"&&tn(J,"exists")===!0&&tn(J,"viewerCanWrite")===!0).map((J)=>tn(J,"cloneRef")).find((J)=>typeof J==="string"&&J.length>0);if(!j)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return j}async function zc(P,O,D){let j=th(Sn(O.tmpdir,"cc-safety-net-amp-"));try{return await rr(P,["amp","clone","user-plugins",j]),await D(j)}finally{ro(j,{recursive:!0,force:!0})}}function zi(P){return`rerun ${P==="overwrite"?"install":"uninstall"} --amp`}function Yc(P,O,D){let j=Sn(P,O),J=dn(j);if(!J)return;if(J.isSymbolicLink()||!J.isFile())throw Error(`Refusing to ${D} ${O} in your Amp personal plugins repository: not a regular file. Remove it there and ${zi(D)}.`);let Y=jt(j);if(oo(Y))return Y;throw Error(`Refusing to ${D} unmanaged file ${O} in your Amp personal plugins repository. Remove it there and ${zi(D)}.`)}function Zc(P,O){let D=Sn(P,mt),j=dn(D);if(!j)return;if(j.isSymbolicLink()||!j.isDirectory())throw Error(`Refusing to ${O} ${mt} in your Amp personal plugins repository: not a regular directory. Remove it there and ${zi(O)}.`);return Yc(P,gt,O)}function dh(P){let O=Sn(P,Nt),D=dn(O);if(!D||D.isSymbolicLink()||!D.isFile())return;let j=jt(O);return oo(j)?j:void 0}async function Xc(P,O,D,j){if(await rr(P,D,O),(await rr(P,["git","status","--porcelain"],O)).stdout.trim()==="")return!1;return await rr(P,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",j],O),await rr(P,["git","push","origin","HEAD"],O),!0}function to(P,O){uh(P,O),ph(P,O)}function Qc(P,O){if(O==="keep")return;throw Error(`Local Amp plugin ${P} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function uh(P,O){let D=ah(P),j=dn(D);if(!j)return;if(!j.isSymbolicLink()&&j.isFile()&&oo(jt(D))){ro(D);return}Qc(D,O)}function ph(P,O){let D=Sn(P.home,".config","amp","plugins",mt),j=dn(D);if(!j)return;if(!j.isSymbolicLink()&&j.isDirectory()&&fh(D)){ro(D,{recursive:!0});return}Qc(D,O)}function fh(P){let O=oh(gt);if(rh(P).join("\x00")!==O)return!1;let D=Sn(P,O),j=dn(D);return!!j&&!j.isSymbolicLink()&&j.isFile()&&oo(jt(D))}function mh(P){let O=l(P);if(!Jc(O))return"";let D=Kc(jt(O,"utf-8"));if(!D||typeof D!=="object"||Array.isArray(D))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(E(D,P.home))};
240
+ `}async function ed(P,O=ch(),D=Ki){let j=Buffer.concat([jt(O),Buffer.from(mh(P),"utf-8")]),J=await Wc(D);return zc(D,P,async(Y)=>{let re=`${J}/${mt}`,ie=Zc(Y,"overwrite"),de=Yc(Y,Nt,"overwrite");if(ie?.equals(j)&&!de)return to(P,"fail"),{path:re,alreadyInstalled:!0};if(nh(Sn(Y,mt),{recursive:!0}),cn(Sn(Y,gt),j),de)ro(Sn(Y,Nt));let fe=await Xc(D,Y,["git","add","--",gt,...de?[Nt]:[]],`chore: update cc-safety-net plugin to v${pn()}`);return to(P,"fail"),{path:re,alreadyInstalled:!fe}})}async function nd(P,O=Ki){let D=await Wc(O);return zc(O,P,async(j)=>{let J=Zc(j,"remove"),Y=dh(j),re=`${D}/${Y&&!J?Nt:mt}`;if(!J&&!Y)return to(P,"keep"),{path:re,alreadyInstalled:!1};return await Xc(O,j,["git","rm","--",...J?[gt]:[],...Y?[Nt]:[]],`chore: remove cc-safety-net plugin v${pn()}`),to(P,"keep"),{path:re,alreadyInstalled:!0}})}import{existsSync as td,mkdirSync as gh,readFileSync as yh}from"node:fs";import{dirname as hh}from"node:path";var Yi=Cn["antigravity-cli"],yt="cc-safety-net";function ht(P){return Boolean(P)&&typeof P==="object"&&!Array.isArray(P)}function so(){return{PreToolUse:[{hooks:[{type:"command",command:Yi,timeout:30}]}]}}function rd(P){try{let O=JSON.parse(yh(P,"utf-8"));if(!O||typeof O!=="object"||Array.isArray(O))throw Error("Antigravity hooks config must be a JSON object");return O}catch(O){if(O instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${P}: ${O.message}`);throw O}}function od(P){let O=P[yt];if(O===void 0){let j=so();return P[yt]=j,{definition:j,preToolUse:j.PreToolUse??[]}}if(!ht(O))throw Error(`Antigravity hooks config entry "${yt}" must be an object`);let D=Array.isArray(O.PreToolUse)?O.PreToolUse:[];return O.PreToolUse=D,{definition:O,preToolUse:D}}function id(P){if(!Array.isArray(P.PreToolUse))return!1;return P.PreToolUse.some((O)=>ht(O)&&Array.isArray(O.hooks)&&O.hooks.some((D)=>ht(D)&&D.command===Yi))}function vh(P){return Object.values(P).some((O)=>ht(O)&&O.enabled!==!1&&id(O))}function bh(P){if(P[yt]===void 0)return!1;let O=od(P);if(O.definition.enabled!==!1||!id(O.definition))return!1;return O.definition.enabled=!0,!0}function wh(P){if(P[yt]===void 0){P[yt]=so();return}let O=od(P);O.definition.enabled=!0,O.preToolUse.push(so().PreToolUse?.[0]??{hooks:[]})}function kh(P){let O=!1;for(let D of Object.values(P)){if(!ht(D)||!Array.isArray(D.PreToolUse))continue;D.PreToolUse=D.PreToolUse.flatMap((j)=>{if(!ht(j)||!Array.isArray(j.hooks))return[j];let J=j.hooks.filter((Y)=>!ht(Y)||Y.command!==Yi);if(J.length!==j.hooks.length)O=!0;return J.length===0?[]:[{...j,hooks:J}]})}return O}function io(P,O){cn(P,`${JSON.stringify(O,null,2)}
241
+ `)}function sd(P){let O=Gt(P.home);if(gh(hh(O),{recursive:!0}),!td(O))return io(O,{[yt]:so()}),{path:O,alreadyInstalled:!1};let D=rd(O);if(vh(D))return{path:O,alreadyInstalled:!0};if(bh(D))return io(O,D),{path:O,alreadyInstalled:!1};return wh(D),io(O,D),{path:O,alreadyInstalled:!1}}function ad(P){let O=Gt(P.home);if(!td(O))return{path:O,alreadyInstalled:!1};let D=rd(O);if(!kh(D))return{path:O,alreadyInstalled:!1};return io(O,D),{path:O,alreadyInstalled:!0}}import{existsSync as Qi,readlinkSync as Sh}from"node:fs";import{join as Vn}from"node:path";import{spawn as xh}from"node:child_process";var $n=En.map((P)=>({target:P.id,flag:P.flag,label:mn(P.id),probeCommand:P.probeCommand}));function Zi(P){let O=new Set(P);return $n.map((D)=>D.target).filter((D)=>O.has(D))}async function ld(P,O){for(let D of P)await O(D)}var Ch=5000;function or(P,O=Ch){return new Promise((D)=>{let j=zn([...P],process.env),J=xh(j.cmd,j.args,{env:process.env,stdio:"ignore"}),Y=!1,re=(de)=>{if(Y)return;Y=!0,clearTimeout(ie),D(de)},ie=setTimeout(()=>{J.kill(),re(!1)},O);J.on("error",()=>re(!1)),J.on("close",(de)=>re(de===0))})}function cd(P=or,O={}){let D=new Set(O.configuredTargets??[]);return Promise.all($n.map(async(j)=>({target:j.target,flag:j.flag,label:j.label,...ud(O.action,await P(j.probeCommand)||j.target==="cursor"&&await P(Ls),D.has(j.target))})))}function dd(P,O){let D=new Set(O.configuredTargets??[]);return P.map((j)=>({...j,...ud(O.action,j.available,D.has(j.target))}))}function ud(P,O,D){if(P==="uninstall")return D?{available:!0}:{available:!1,unavailableReason:"not installed"};if(P==="install"&&D)return{available:!1,unavailableReason:"already installed"};if(!O)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}var Jn="cc-safety-net",gd=["npx","-y","@deepseek-ai/dsh"],pd="DeepSeek Harness",fd=["@deepseek-ai","dsh-desktop"],yd="Quit DeepSeek Harness Desktop, then run this command again: Desktop plugins can only change while it is closed.",Xi=(P)=>`DeepSeek Harness Desktop is not in its default location, so ${P} ${Jn} from its Plugins page.`,hd=(P,O)=>Qi(Vn(oi(P),O,"package.json"));function es(P,O){let D=O.platform??process.platform,j=hd(P,"desktop"),J=D==="darwin"?[Vn(P.home,"Applications"),O.systemApplications??"/Applications"].map((Y)=>Vn(Y,`${pd}.app`,"Contents","Resources","runtime","cli","bin","dsh")):D==="win32"?[Vn(P.env.get("LOCALAPPDATA")||Vn(P.home,"AppData","Local"),"Programs",pd,"resources","runtime","cli","bin","dsh.cmd")]:[];return{profile:j,cli:j?J.find((Y)=>Qi(Y)):void 0}}function vd(P,O=process.platform){if(O==="win32")return Qi(Vn(P.env.get("APPDATA")||Vn(P.home,"AppData","Roaming"),...fd,"lockfile"));let D=Ph(Vn(P.home,"Library","Application Support",...fd,"SingletonLock")),j=Number(/-(\d+)$/.exec(D??"")?.[1]);return Number.isInteger(j)&&j>0&&Rh(j)}function Ph(P){try{return Sh(P)}catch{return}}function Rh(P){try{return process.kill(P,0),!0}catch(O){return O.code==="EPERM"}}async function bd(P,O={}){let D=es(P,O);if(D.cli&&vd(P,O.platform))throw Error(yd);let j=!D.cli||hd(P,"web")||await(O.probe??or)(_o),J=[...D.cli?[{profile:"desktop",label:"Desktop",dsh:[D.cli]}]:[],...j?[{profile:"web",label:"web",dsh:gd}]:[]];return{commands:J.map((Y)=>[...Y.dsh,"plugin","--profile",Y.profile,"add",`${Jn}@${pn()}`]),afterInstall:async()=>{let Y=new Set(ii(P).filter((ie)=>ie.enabled).map((ie)=>ie.name)),re=J.filter((ie)=>!Y.has(ie.profile));if(re.length>0)throw Error(`DeepSeek Harness installed ${Jn} in the ${md(re)} but did not enable it. Enable it from the Plugins page.`)},message:[`Added ${Jn} to the DeepSeek Harness ${md(J)}.`,...D.profile&&!D.cli?[Xi("add")]:[]].join(`
242
+ `)}}function md(P){return`${P.map((O)=>O.label).join(" and ")} profile${P.length>1?"s":""}`}function wd(P,O={}){let D=new Set(ii(P).map((Y)=>Y.name));if(!D.has("desktop")&&!D.has("web"))throw Error(`${Jn} is not installed in the DeepSeek Harness web or Desktop profile`);let j=D.has("desktop")?es(P,O).cli:void 0,J=D.has("desktop")&&!j;if(J&&!D.has("web"))throw Error(Xi("remove"));if(j&&vd(P,O.platform))throw Error(yd);return{commands:[...j?[[j,"plugin","--profile","desktop","remove",Jn]]:[],...D.has("web")?[[...gd,"plugin","--profile","web","remove",Jn]]:[]],...J?{afterUninstall:()=>{throw Error(`Removed ${Jn} from the DeepSeek Harness web profile, but ${Xi("remove")}`)}}:{}}}function kd(P,O,D={}){let j=es(O,D).cli!==void 0;return P.map((J)=>J.target==="deepseek-harness"&&j?{...J,available:!0,unavailableReason:void 0}:J)}import{existsSync as Eh,readdirSync as _h,rmSync as Ah}from"node:fs";import{join as Th}from"node:path";function xd(P,O=process.platform,D){if(!Eh(P))return;let j=O==="win32"?/^bunx-\d+-cc-safety-net@/:new RegExp(`^bunx-${process.getuid?.()??0}-cc-safety-net@`);_h(P).filter((J)=>J!==D&&j.test(J)).forEach((J)=>{Ah(Th(P,J),{recursive:!0,force:!0})})}import{existsSync as Cd,readdirSync as Ih,rmSync as $h}from"node:fs";import{join as Ft}from"node:path";function ao(P,O=process.platform){let D=Ft(P.env.get("npm_config_cache")||(O==="win32"?Ft(P.env.get("LOCALAPPDATA")||Ft(P.home,"AppData","Local"),"npm-cache"):Ft(P.home,".npm")),"_npx");if(!Cd(D))return;Ih(D).filter((j)=>Cd(Ft(D,j,"node_modules","cc-safety-net"))).forEach((j)=>{$h(Ft(D,j),{recursive:!0,force:!0})})}import{existsSync as Ad,mkdirSync as Dh,readFileSync as Td}from"node:fs";import{dirname as Lh,join as _d}from"node:path";function Oh(P,O){if(P[O]!=="#")return O;let D=P.indexOf(`
243
+ `,O+1);return D===-1?P.length:D+1}function ns(P,O,D){let j=new RegExp(`^(\\s*)${O}\\s*=\\s*\\[`),J=0;for(let Y of P.split(`
244
+ `)){if(/^\s*\[/.test(Y))return;let re=j.exec(Y);if(re){let ie=J+re[0].lastIndexOf("[");return{start:ie,end:Bo(P,ie,{skipComment:Oh,...D})}}J+=Y.length+1}return}function Sd(P,O,D){let j=P.slice(0,O.end).trimEnd(),J=Ma(P,O.end),Y=J===""?" ":`${J} `,re=!j.endsWith("[")&&!j.endsWith(",");return`${j}${re?",":""}
245
+ ${Y}${D}${P.slice(O.end)}`}function Pd(P,O,D){let j=P.indexOf(D,O.start);if(j===-1||j>O.end)return P;return`${P.slice(0,j)}${P.slice(j+D.length).replace(/^\s*,/,"")}`}function Rd(P,O){let D=new RegExp(`^\\s*${O}\\s*=\\s*\\[\\s*]\\s*(?:#.*)?$`),j=P.split(`
245
246
  `),J=j.findIndex((ie)=>/^\s*\[/.test(ie)),Y=J===-1?j:j.slice(0,J),re=J===-1?[]:j.slice(J);return[...Y.filter((ie)=>!D.test(ie)),...re].join(`
246
- `)}function hd(P,O,D){let j=new RegExp(`^\\s*\\[\\[${O}]]\\s*$`,"m");return P.split(/(?=^\s*\[)/m).filter((J)=>!j.test(J)||!J.includes(D)).join("").trimEnd()}var rr=xn["kimi-code"],Wi=`[[hooks]]
247
+ `)}function Ed(P,O,D){let j=new RegExp(`^\\s*\\[\\[${O}]]\\s*$`,"m");return P.split(/(?=^\s*\[)/m).filter((J)=>!j.test(J)||!J.includes(D)).join("").trimEnd()}var ir=Cn["kimi-code"],ts=`[[hooks]]
247
248
  event = "PreToolUse"
248
- command = "${rr}"`,kd=`{ event = "PreToolUse", command = "${rr}" }`,xd={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function Cd(P){return vd(P.env.get("KIMI_CODE_HOME")??vd(P.home,".kimi-code"),"config.toml")}function xh(P){let O=Ji(P,"hooks",xd);if(O&&P.slice(O.start+1,O.end).trim())return md(P,O,kd);let D=yd(P,"hooks").trimEnd();if(D==="")return`${Wi}
249
+ command = "${ir}"`,Id=`{ event = "PreToolUse", command = "${ir}" }`,$d={stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"};function Od(P){return _d(P.env.get("KIMI_CODE_HOME")??_d(P.home,".kimi-code"),"config.toml")}function Nh(P){let O=ns(P,"hooks",$d);if(O&&P.slice(O.start+1,O.end).trim())return Sd(P,O,Id);let D=Rd(P,"hooks").trimEnd();if(D==="")return`${ts}
249
250
  `;return`${D}
250
251
 
251
- ${Wi}
252
- `}function Sd(P){let O=Cd(P);if(wh(kh(O),{recursive:!0}),!bd(O))return cn(O,`${Wi}
253
- `),{path:O,alreadyInstalled:!1};let D=wd(O,"utf-8");if(D.includes(rr))return{path:O,alreadyInstalled:!0};return cn(O,xh(D)),{path:O,alreadyInstalled:!1}}function Pd(P){let O=Cd(P);if(!bd(O))return{path:O,alreadyInstalled:!1};let D=wd(O,"utf-8");if(!D.includes(rr))return{path:O,alreadyInstalled:!1};let j=Ji(D,"hooks",xd),J=j?gd(D,j,kd):`${hd(D,"hooks",rr)}
254
- `;return cn(O,J),{path:O,alreadyInstalled:!0}}var Ki="safety-net@cc-marketplace",Rd=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),Ed=new Set(["antigravity-cli","cursor","devin","droid","grok-build","hermes-agent","kimi-code"]);function zi(P){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(P??"")}function $d(P){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(P??"")}function Ch(P){return/^Marketplace `cc-marketplace`\s*$/m.test(P??"")}var Od={"claude-code":{installCommands:(P)=>{let O=Tr(P,"cc-safety-net@cc-marketplace");return{commands:[...O?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...Fo(P).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Tr(P,Ki)?[["claude","plugin","uninstall",Ki]]:[],update:O}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(P,O)=>{let D=O??await hn(["codex","plugin","list"]),j=$d(D);return{commands:[j||Ch(D)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:zi(D)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:j}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:Ra},"copilot-cli":{installCommands:async()=>{let P=await hn(["copilot","plugin","list"]),O=[...Fa(P)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...Ha(P)?[["copilot","plugin","uninstall",La]]:[]];if(Na(P))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",Tn]],cleanupCommands:O,update:!0};return{commands:[ja(await hn(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",Tn]],cleanupCommands:O}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(P)=>{let O=ni(P);if(O.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(O.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:gi,installCommands:(P)=>{let O=!ro(to(zt(P),Sn));return{commands:Jl(),afterInstall:()=>Wl(O)}},uninstallCommands:[["openclaw","plugins","uninstall",un,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
255
- `)},opencode:{installCommands:rc},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]},"deepseek-harness":{installCommands:(P)=>cd(P),uninstallCommands:(P)=>dd(P)}};function Dd(P,O=(D)=>D){try{let D=JSON.parse(O(Id(P,"utf-8")));if(!D||typeof D!=="object"||Array.isArray(D))throw Error(`Settings file ${P} must be a JSON object`);return D}catch(D){if(D instanceof SyntaxError)throw Error(`Failed to parse ${P}: ${D.message}`);throw D}}function Sh(P){let O=to(Bt(P),"settings.json");if(!ro(O))return;let D=Dd(O,vn),j=D.enabledPlugins;if(!j||typeof j!=="object"||Array.isArray(j))return;if(j[Tn]!==!1)return;let J=Id(O,"utf-8"),Y=J.replace(new RegExp(`("${Tn}"\\s*:\\s*)false`),"$1true");return j[Tn]=!0,cn(O,Y!==J?Y:`${JSON.stringify(D,null,2)}
256
- `),`Enabled ${Tn} plugin in ${O}`}function Ph(P){let O=Pi(P);if(!ro(O))return;let D=Dd(O);if(!Array.isArray(D.packages))return;let j=D.packages.find((J)=>!!J&&typeof J==="object"&&!Array.isArray(J)&&Ri(J.source)&&("extensions"in J));if(!j)return;return delete j.extensions,cn(O,`${JSON.stringify(D,null,2)}
257
- `),`Enabled npm:cc-safety-net extensions in ${O}`}function _d(P,O){let D=gn({label:O,booleans:Object.fromEntries($n.map((Y)=>[Y.target,[Y.flag]]))},P),j=D.errors[0];if(j)throw Error(j);let J=$n.filter((Y)=>D.flags[Y.target]).map((Y)=>Y.target);if(J.length!==1)throw Error(`Choose exactly one ${O} target: ${$n.map((Y)=>Y.flag).join(", ")}`);return J[0]}async function Ld(P,O=St){let[D,j,J]=await Promise.all([O(["amp","plugins","list"],30000),O(["codex","plugin","list"],30000),O(["copilot","--binary-version"])]);return{codexPluginListOutput:j,hooks:Dt(P,process.cwd(),{ampPluginListOutput:D,codexPluginListOutput:j,copilotCliVersion:J})}}async function Rh(P,O,D=St){let j=await Ld(P,D);return j.hooks.filter((J)=>O==="install"?J.configured:J.detected||J.inspectionStatus==="not-inspected").filter((J)=>J.platform!=="codex"||!zi(j.codexPluginListOutput)||$d(j.codexPluginListOutput)).map((J)=>J.platform)}function Eh(P,O,D,j){if(D.length>0)return{finish:async()=>[_d(D,O)]};if(!j.selectTargets&&!Ni(j.input,j.output))return{finish:async()=>[_d(D,O)]};let J=j.detectConfiguredTargets??(()=>Rh(P,O,j.fetchVersion)),Y=Promise.all([Qc(j.probeTargets).then((re)=>ud(re,P)),J()]);return{ready:Y,finish:async()=>{let[re,ie]=await Y,de=ed(re,{action:O,configuredTargets:ie}),fe=j.selectTargets?await j.selectTargets(O,Ad(O,de)):await Lc(O,Ad(O,de),{input:j.input,output:j.output});if(fe==="update")return fe;if(!fe||fe.length===0)return null;return Gi(fe)}}}async function _h(P,O,D=!1,j){let J=Od[P];J.beforeInstall?.(O);let Y=typeof J.installCommands==="function"?await J.installCommands(O,j):{commands:J.installCommands};return await fi(Y.commands),await Ml(Y.cleanupCommands??[]),await Y.afterInstall?.(),[`${Y.update||D?"Updated":"Installed"} ${mn(P)} integration`,Y.message??J.postInstallMessage].filter(Boolean).join(`
258
- `)}async function Th(P,O){let D=Od[P];if(!D.uninstallCommands)throw Error(`${mn(P)} uninstall is not supported`);let j=typeof D.uninstallCommands==="function"?D.uninstallCommands(O):{commands:D.uninstallCommands};return await fi(j.commands),j.afterUninstall?.(),`Uninstalled ${mn(P)} integration`}function Ah(P){let O=ac(P);return O.alreadyInstalled?`Uninstalled OpenCode plugin from ${O.path}`:`OpenCode plugin not installed in ${O.path}`}var Nd={"antigravity-cli":{install:Yc,uninstall:Zc},cursor:{install:za,uninstall:Ya},devin:{install:il,uninstall:sl},droid:{install:ml,uninstall:gl},"grok-build":{install:Cl,uninstall:Sl},"kimi-code":{install:Sd,uninstall:Pd}};function Ih(P,O,D,j=!1){if(P==="install"&&!j)no(D);let J=Nd[O][P](D),Y=mn(O),re=P!=="install"?"Uninstalled":j?"Updated":"Installed";return P==="install"&&J.alreadyInstalled?j?`${Y} hook up to date in ${J.path}`:`${Y} hook already installed in ${J.path}`:P==="uninstall"&&!J.alreadyInstalled?`${Y} hook not installed in ${J.path}`:`${re} ${Y} hook ${P==="install"?"in":"from"} ${J.path}`}var jd={amp:{install:Bc,uninstall:Vc,restartNote:'Amp personal plugins apply to every Amp session, including Orb threads. Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:Al,uninstall:Il,afterInstall:async(P)=>{let O=di(P);return await hn(["hermes","plugins","enable",Rn,"--no-allow-tool-override"]),!O},beforeUninstall:async(P)=>{ci(P);try{await hn(["hermes","plugins","disable",Rn])}catch(O){console.warn(`${O instanceof Error?O.message:String(O)}
259
- Removing the plugin files anyway; ${Rn} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function $h(P,O,D,j=!1){let J=jd[O];if(P==="uninstall")await J.beforeUninstall?.(D);let Y=P==="install"?await J.install(D):await J.uninstall(D),re=P==="install"&&await J.afterInstall?.(D),ie=mn(O),de=!re&&(P==="install"&&Y.alreadyInstalled||P==="uninstall"&&!Y.alreadyInstalled);return[de?P==="install"?`${ie} plugin ${j?"up to date":"already installed"} at ${Y.path}`:`${ie} plugin not installed at ${Y.path}`:`${P!=="install"?"Uninstalled":j?"Updated":"Installed"} ${ie} plugin ${P==="install"?"at":"from"} ${Y.path}`,de?void 0:J.restartNote].filter(Boolean).join(`
260
- `)}var Oh={"copilot-cli":{afterInstall:Sh},"hermes-agent":{beforeInstall:(P,O)=>{if(!O)no(P)}},openclaw:{beforeUninstall:gi},pi:{afterInstall:Ph}};function Dh(P){return P in Nd}function Lh(P){return P in jd}var Td=["Install CC Safety Net as a native Kimi Code plugin:",""," 1. Start Kimi Code and run: /plugins install https://github.com/kenryu42/cc-safety-net"," Confirm the trust prompt; it defaults to cancel."," 2. Run /reload, or start a new session.","","Note: Kimi Code hooks are fail-open. When the hook process cannot start, crashes, or times","out, Kimi Code allows the tool call."].join(`
261
- `);function Nh(P){if(Kt({environment:P,cwd:process.cwd()}).status!=="configured")return Td;return[Td,"",nn.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
252
+ ${ts}
253
+ `}function Dd(P){let O=Od(P);if(Dh(Lh(O),{recursive:!0}),!Ad(O))return cn(O,`${ts}
254
+ `),{path:O,alreadyInstalled:!1};let D=Td(O,"utf-8");if(D.includes(ir))return{path:O,alreadyInstalled:!0};return cn(O,Nh(D)),{path:O,alreadyInstalled:!1}}function Ld(P){let O=Od(P);if(!Ad(O))return{path:O,alreadyInstalled:!1};let D=Td(O,"utf-8");if(!D.includes(ir))return{path:O,alreadyInstalled:!1};let j=ns(D,"hooks",$d),J=j?Pd(D,j,Id):`${Ed(D,"hooks",ir)}
255
+ `;return cn(O,J),{path:O,alreadyInstalled:!0}}var rs="safety-net@cc-marketplace",Nd=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),jd=new Set(["antigravity-cli","cursor","devin","droid","grok-build","hermes-agent","kimi-code"]);function os(P){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(P??"")}function Gd(P){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(P??"")}function jh(P){return/^Marketplace `cc-marketplace`\s*$/m.test(P??"")}var qd={"claude-code":{installCommands:(P)=>{let O=$r(P,"cc-safety-net@cc-marketplace");return{commands:[...O?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...Or(P).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:$r(P,rs)?[["claude","plugin","uninstall",rs]]:[],update:O}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(P,O)=>{let D=O??await gn(["codex","plugin","list"]),j=Gd(D);return{commands:[j||jh(D)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:os(D)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:j}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:Na},"copilot-cli":{installCommands:async()=>{let P=await gn(["copilot","plugin","list"]),O=[...Wa(P)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...za(P)?[["copilot","plugin","uninstall",Va]]:[]];if(Ja(P))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",An]],cleanupCommands:O,update:!0};return{commands:[Ka(await gn(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",An]],cleanupCommands:O}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(P)=>{let O=fi(P);if(O.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(O.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:Si,installCommands:(P)=>{let O=!co(lo(Zt(P),Pn));return{commands:tc(),afterInstall:()=>rc(O)}},uninstallCommands:[["openclaw","plugins","uninstall",un,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
256
+ `)},opencode:{installCommands:fc},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]},"deepseek-harness":{installCommands:(P)=>bd(P),uninstallCommands:(P)=>wd(P)}};function Bd(P,O=(D)=>D){try{let D=JSON.parse(O(Ud(P,"utf-8")));if(!D||typeof D!=="object"||Array.isArray(D))throw Error(`Settings file ${P} must be a JSON object`);return D}catch(D){if(D instanceof SyntaxError)throw Error(`Failed to parse ${P}: ${D.message}`);throw D}}function Fh(P){let O=lo(Vt(P),"settings.json");if(!co(O))return;let D=Bd(O,vn),j=D.enabledPlugins;if(!j||typeof j!=="object"||Array.isArray(j))return;if(j[An]!==!1)return;let J=Ud(O,"utf-8"),Y=J.replace(new RegExp(`("${An}"\\s*:\\s*)false`),"$1true");return j[An]=!0,cn(O,Y!==J?Y:`${JSON.stringify(D,null,2)}
257
+ `),`Enabled ${An} plugin in ${O}`}function Hh(P){let O=Di(P);if(!co(O))return;let D=Bd(O);if(!Array.isArray(D.packages))return;let j=D.packages.find((J)=>!!J&&typeof J==="object"&&!Array.isArray(J)&&Li(J.source)&&("extensions"in J));if(!j)return;return delete j.extensions,cn(O,`${JSON.stringify(D,null,2)}
258
+ `),`Enabled npm:cc-safety-net extensions in ${O}`}function Fd(P,O){let D=yn({label:O,booleans:Object.fromEntries($n.map((Y)=>[Y.target,[Y.flag]]))},P),j=D.errors[0];if(j)throw Error(j);let J=$n.filter((Y)=>D.flags[Y.target]).map((Y)=>Y.target);if(J.length!==1)throw Error(`Choose exactly one ${O} target: ${$n.map((Y)=>Y.flag).join(", ")}`);return J[0]}async function Vd(P,O=St){let[D,j,J]=await Promise.all([O(["amp","plugins","list"],30000),O(["codex","plugin","list"],30000),O(["copilot","--binary-version"])]);return{codexPluginListOutput:j,hooks:Dt(P,process.cwd(),{ampPluginListOutput:D,codexPluginListOutput:j,copilotCliVersion:J})}}async function Mh(P,O,D=St){let j=await Vd(P,D);return j.hooks.filter((J)=>O==="install"?J.configured:J.detected&&J.method!==Ur||J.inspectionStatus==="not-inspected").filter((J)=>J.platform!=="codex"||!os(j.codexPluginListOutput)||Gd(j.codexPluginListOutput)).map((J)=>J.platform)}function Uh(P,O,D,j){if(D.length>0)return{finish:async()=>[Fd(D,O)]};if(!j.selectTargets&&!Vi(j.input,j.output))return{finish:async()=>[Fd(D,O)]};let J=j.detectConfiguredTargets??(()=>Mh(P,O,j.fetchVersion)),Y=Promise.all([cd(j.probeTargets).then((re)=>kd(re,P)),J()]);return{ready:Y,finish:async()=>{let[re,ie]=await Y,de=dd(re,{action:O,configuredTargets:ie}),fe=j.selectTargets?await j.selectTargets(O,Md(O,de)):await Vc(O,Md(O,de),{input:j.input,output:j.output});if(fe==="update")return fe;if(!fe||fe.length===0)return null;return Zi(fe)}}}async function Gh(P,O,D=!1,j){let J=qd[P];J.beforeInstall?.(O);let Y=typeof J.installCommands==="function"?await J.installCommands(O,j):{commands:J.installCommands};return await zo(Y.commands),await el(Y.cleanupCommands??[]),await Y.afterInstall?.(),[`${Y.update||D?"Updated":"Installed"} ${mn(P)} integration`,Y.message??J.postInstallMessage].filter(Boolean).join(`
259
+ `)}async function qh(P,O){let D=qd[P];if(!D.uninstallCommands)throw Error(`${mn(P)} uninstall is not supported`);let j=typeof D.uninstallCommands==="function"?D.uninstallCommands(O):{commands:D.uninstallCommands};return await zo(j.commands),j.afterUninstall?.(),`Uninstalled ${mn(P)} integration`}function Bh(P){let O=hc(P);return O.alreadyInstalled?`Uninstalled OpenCode plugin from ${O.path}`:`OpenCode plugin not installed in ${O.path}`}var Jd={"antigravity-cli":{install:sd,uninstall:ad},cursor:{install:sl,uninstall:al},devin:{install:yl,uninstall:hl},droid:{install:Pl,uninstall:Rl},"grok-build":{install:Dl,uninstall:Ll},"kimi-code":{install:Dd,uninstall:Ld}};function Vh(P,O,D,j=!1){if(P==="install"&&!j)ao(D);let J=Jd[O][P](D),Y=mn(O),re=P!=="install"?"Uninstalled":j?"Updated":"Installed";return P==="install"&&J.alreadyInstalled?j?`${Y} hook up to date in ${J.path}`:`${Y} hook already installed in ${J.path}`:P==="uninstall"&&!J.alreadyInstalled?`${Y} hook not installed in ${J.path}`:`${re} ${Y} hook ${P==="install"?"in":"from"} ${J.path}`}var Kd={amp:{install:ed,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:Ul,uninstall:Gl,afterInstall:async(P)=>{let O=xi(P);return await gn(["hermes","plugins","enable",Rn,"--no-allow-tool-override"]),!O},beforeUninstall:async(P)=>{ki(P);try{await gn(["hermes","plugins","disable",Rn])}catch(O){console.warn(`${O instanceof Error?O.message:String(O)}
260
+ Removing the plugin files anyway; ${Rn} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function Jh(P,O,D,j=!1){let J=Kd[O];if(P==="uninstall")await J.beforeUninstall?.(D);let Y=P==="install"?await J.install(D):await J.uninstall(D),re=P==="install"&&await J.afterInstall?.(D),ie=mn(O),de=!re&&(P==="install"&&Y.alreadyInstalled||P==="uninstall"&&!Y.alreadyInstalled);return[de?P==="install"?`${ie} plugin ${j?"up to date":"already installed"} at ${Y.path}`:`${ie} plugin not installed at ${Y.path}`:`${P!=="install"?"Uninstalled":j?"Updated":"Installed"} ${ie} plugin ${P==="install"?"at":"from"} ${Y.path}`,de?void 0:J.restartNote].filter(Boolean).join(`
261
+ `)}var Kh={"copilot-cli":{afterInstall:Fh},cursor:{afterUninstall:tl},"hermes-agent":{beforeInstall:(P,O)=>{if(!O)ao(P)}},openclaw:{beforeUninstall:Si},pi:{afterInstall:Hh}};function Wh(P){return P in Jd}function zh(P){return P in Kd}var Hd=["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(`
262
+ `);function Yh(P){if(Yt({environment:P,cwd:process.cwd()}).status!=="configured")return Hd;return[Hd,"",nn.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
262
263
  `))].join(`
263
- `)}function Ad(P,O){return O.map((D)=>P==="install"&&D.target==="kimi-code"&&D.unavailableReason==="already installed"?{...D,available:!0,unavailableReason:void 0,label:`${D.label} (global hook installed)`}:D)}function jh(P,O){if(P.selectKimiInstallMethod)return P.selectKimiInstallMethod();if(!Ni(P.input,P.output))return Promise.resolve("global-hook");return Dc({input:P.input,output:P.output,globalHookInstalled:Kt({environment:O,cwd:process.cwd()}).status==="configured"})}async function Fd(P,O,D,j=!1,J){let Y=Oh[O];if(P==="install")Y?.beforeInstall?.(D,j);if(P==="uninstall")Y?.beforeUninstall?.(D);if(Dh(O))return Ih(P,O,D,j);if(Lh(O))return $h(P,O,D,j);if(P==="uninstall")return O==="opencode"?Ah(D):Th(O,D);return[await _h(O,D,j,J),await Y?.afterInstall?.(D)].filter(Boolean).join(`
264
- `)}function Fh(P){let O=gn({label:"update"},P).errors[0];if(O)throw Error(O)}async function Hh(P,O=St){let D=await Ld(P,O),j=to(Bt(P),"installed-plugins");return{targets:Gi([...D.hooks.filter((Y)=>Y.platform!=="copilot-cli"&&Y.detected).map((Y)=>Y.platform),...[Ar,Da,Oa].flatMap((Y)=>ro(to(j,...Y))?["copilot-cli"]:[]),...Tr(P,Ki)?["claude-code"]:[],...zi(D.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:D.codexPluginListOutput}}async function Mh(P){let O=c(),D=P.output??process.stdout,j=(P.scriptPath??process.argv[1]??"").split(/[\\/]/),J=j.find((Ie)=>/^bunx-\d+-/.test(Ie)),Y=J!==void 0||j.includes("_npx")?null:(P.checkLatestVersion??Gn)(),re=async()=>{let Ie=Y&&await Y;if(Ie?.updateAvailable)D.write(`
264
+ `)}function Md(P,O){return O.map((D)=>P==="install"&&D.target==="kimi-code"&&D.unavailableReason==="already installed"?{...D,available:!0,unavailableReason:void 0,label:`${D.label} (global hook installed)`}:D)}function Zh(P,O){if(P.selectKimiInstallMethod)return P.selectKimiInstallMethod();if(!Vi(P.input,P.output))return Promise.resolve("global-hook");return Bc({input:P.input,output:P.output,globalHookInstalled:Yt({environment:O,cwd:process.cwd()}).status==="configured"})}async function Wd(P,O,D,j=!1,J){let Y=Kh[O];if(P==="install")Y?.beforeInstall?.(D,j);if(P==="uninstall")Y?.beforeUninstall?.(D);if(Wh(O))return[Vh(P,O,D,j),P==="uninstall"?await Y?.afterUninstall?.(D):void 0].filter(Boolean).join(`
265
+ `);if(zh(O))return Jh(P,O,D,j);if(P==="uninstall")return O==="opencode"?Bh(D):qh(O,D);return[await Gh(O,D,j,J),await Y?.afterInstall?.(D)].filter(Boolean).join(`
266
+ `)}function Xh(P){let O=yn({label:"update"},P).errors[0];if(O)throw Error(O)}async function Qh(P,O=St){let D=await Vd(P,O),j=lo(Vt(P),"installed-plugins");return{targets:Zi([...D.hooks.filter((Y)=>Y.platform!=="copilot-cli"&&Y.detected&&Y.method!==Ur&&Y.method!==ni).map((Y)=>Y.platform),...[Dr,Ba,qa].flatMap((Y)=>co(lo(j,...Y))?["copilot-cli"]:[]),...$r(P,rs)?["claude-code"]:[],...os(D.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:D.codexPluginListOutput}}async function ev(P){let O=c(),D=P.output??process.stdout,j=(P.scriptPath??process.argv[1]??"").split(/[\\/]/),J=j.find((Ie)=>/^bunx-\d+-/.test(Ie)),Y=J!==void 0||j.includes("_npx")?null:(P.checkLatestVersion??Gn)(),re=async()=>{let Ie=Y&&await Y;if(Ie?.updateAvailable)D.write(`
265
267
  Update available: cc-safety-net ${Ie.currentVersion} → ${Ie.latestVersion}. Update this CLI with your package manager, e.g. \`npm i -g cc-safety-net@latest\` for a global install.
266
- `)},ie=Hh(O,P.fetchVersion??St).then(async(Ie)=>{let Ee=new Set(Ie.targets);return{targets:Ie.targets,codexPluginListOutput:Ie.codexPluginListOutput,available:new Map(await Promise.all($n.filter((Ve)=>Ee.has(Ve.target)&&Rd.has(Ve.target)).map(async(Ve)=>[Ve.target,await tr(Ve.probeCommand)])))}}),de=await Ut(P.showBanner??!0,()=>({ready:ie,finish:()=>ie}),()=>Mt({input:P.input??process.stdin,output:D}),{loadingMessage:"Checking installed integrations…",output:D}),fe=await Promise.resolve().then(()=>(pd(O.tmpdir,process.platform,J),null)).catch((Ie)=>or(Ie));if(de.targets.length===0){if(D.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),fe!==null)console.error(fe);return await re(),fe===null?0:1}let we=de.targets.some((Ie)=>Ed.has(Ie))?await Promise.resolve().then(()=>(no(O),null)).catch((Ie)=>or(Ie)):null,Ce=await Pr(Promise.all(de.targets.map((Ie)=>{if(Rd.has(Ie)&&!de.available.get(Ie))return Promise.resolve({message:`${mn(Ie)} not found; skipped`,failed:!1});if(we!==null&&Ed.has(Ie))return Promise.resolve({message:we,failed:!0});return Fd("install",Ie,O,!0,de.codexPluginListOutput).then((Ee)=>({message:Ee,failed:!1}),(Ee)=>({message:or(Ee),failed:!0}))})),{loadingMessage:`Updating ${de.targets.length} integration${de.targets.length===1?"":"s"}…`,output:D}),Se=fe===null?Ce:[...Ce,{message:fe,failed:!0}];return Se.forEach((Ie)=>Ie.failed?console.error(Ie.message):D.write(`${Ie.message}
267
- `)),await re(),Se.some((Ie)=>Ie.failed)?1:0}function Yi(P,O={}){return Promise.resolve().then(()=>Fh(P)).then(()=>Mh(O)).catch((D)=>(console.error(or(D)),1))}async function ir(P,O,D={}){try{let j=c(),J=await Ut(!0,()=>Eh(j,P,O,D),()=>Mt({input:D.input??process.stdin,output:D.output??process.stdout}),{loadingMessage:P==="install"?"Checking available integrations…":"Checking installed integrations…",output:D.output??process.stdout});if(!J)return(D.output??process.stdout).write(`Cancelled: nothing was ${P}ed.
268
- `),0;if(J==="update")return(D.runUpdate??(()=>Yi([],{fetchVersion:D.fetchVersion,input:D.input,output:D.output,showBanner:!1})))();let Y=D.output??process.stdout;return await Xc(J,async(re)=>{if(re==="kimi-code"&&P==="install"){let de=await jh(D,j);if(de===null){Y.write(`Cancelled: Kimi Code integration was not installed.
269
- `);return}if(de==="plugin"){Y.write(`${Nh(j)}
270
- `);return}}let ie=await Pr(Fd(P,re,j),{loadingMessage:`${P==="install"?"Installing":"Uninstalling"} ${mn(re)} integration…`,output:Y});Y.write(`${ie}
271
- `)}),0}catch(j){return console.error(or(j)),1}}function or(P){let O=P instanceof Error?P.message:String(P),D=typeof P==="object"&&P!==null&&"code"in P?P.code:null;if(D==="EACCES"||D==="EPERM")return`${O}
268
+ `)},ie=Qh(O,P.fetchVersion??St).then(async(Ie)=>{let Ee=new Set(Ie.targets);return{targets:Ie.targets,codexPluginListOutput:Ie.codexPluginListOutput,available:new Map(await Promise.all($n.filter((Ve)=>Ee.has(Ve.target)&&Nd.has(Ve.target)).map(async(Ve)=>[Ve.target,await or(Ve.probeCommand)])))}}),de=await Ut(P.showBanner??!0,()=>({ready:ie,finish:()=>ie}),()=>Mt({input:P.input??process.stdin,output:D}),{loadingMessage:"Checking installed integrations…",output:D}),fe=await Promise.resolve().then(()=>(xd(O.tmpdir,process.platform,J),null)).catch((Ie)=>sr(Ie));if(de.targets.length===0){if(D.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),fe!==null)console.error(fe);return await re(),fe===null?0:1}let we=de.targets.some((Ie)=>jd.has(Ie))?await Promise.resolve().then(()=>(ao(O),null)).catch((Ie)=>sr(Ie)):null,Ce=await Er(Promise.all(de.targets.map((Ie)=>{if(Nd.has(Ie)&&!de.available.get(Ie))return Promise.resolve({message:`${mn(Ie)} not found; skipped`,failed:!1});if(we!==null&&jd.has(Ie))return Promise.resolve({message:we,failed:!0});return Wd("install",Ie,O,!0,de.codexPluginListOutput).then((Ee)=>({message:Ee,failed:!1}),(Ee)=>({message:sr(Ee),failed:!0}))})),{loadingMessage:`Updating ${de.targets.length} integration${de.targets.length===1?"":"s"}…`,output:D}),Se=fe===null?Ce:[...Ce,{message:fe,failed:!0}];return Se.forEach((Ie)=>Ie.failed?console.error(Ie.message):D.write(`${Ie.message}
269
+ `)),await re(),Se.some((Ie)=>Ie.failed)?1:0}function is(P,O={}){return Promise.resolve().then(()=>Xh(P)).then(()=>ev(O)).catch((D)=>(console.error(sr(D)),1))}async function ar(P,O,D={}){try{let j=c(),J=await Ut(!0,()=>Uh(j,P,O,D),()=>Mt({input:D.input??process.stdin,output:D.output??process.stdout}),{loadingMessage:P==="install"?"Checking available integrations…":"Checking installed integrations…",output:D.output??process.stdout});if(!J)return(D.output??process.stdout).write(`Cancelled: nothing was ${P}ed.
270
+ `),0;if(J==="update")return(D.runUpdate??(()=>is([],{fetchVersion:D.fetchVersion,input:D.input,output:D.output,showBanner:!1})))();let Y=D.output??process.stdout;return await ld(J,async(re)=>{if(re==="kimi-code"&&P==="install"){let de=await Zh(D,j);if(de===null){Y.write(`Cancelled: Kimi Code integration was not installed.
271
+ `);return}if(de==="plugin"){Y.write(`${Yh(j)}
272
+ `);return}}let ie=await Er(Wd(P,re,j),{loadingMessage:`${P==="install"?"Installing":"Uninstalling"} ${mn(re)} integration…`,output:Y});Y.write(`${ie}
273
+ `)}),0}catch(j){return console.error(sr(j)),1}}function sr(P){let O=P instanceof Error?P.message:String(P),D=typeof P==="object"&&P!==null&&"code"in P?P.code:null;if(D==="EACCES"||D==="EPERM")return`${O}
272
274
  Check file permissions for the target config file and parent directory.`;if(D==="ENOENT")return`${O}
273
275
  Check that the target config path and parent directory exist.`;if(D==="ENOTDIR")return`${O}
274
- Check that every parent path component is a directory.`;return O}import{mkdirSync as Jh}from"node:fs";import{dirname as Wh}from"node:path";import{createInterface as Kh}from"node:readline";import{existsSync as Md,readFileSync as Uh}from"node:fs";function vt(P,O){let D=tt(P,O);return{policy:D.policy,errors:ce(Xe(D.issues,et,(j)=>j.kind==="custom")," "," ")}}function sr(P,O){return vt(P,O).errors}function Hd(P,O){return{"safety.level":P.safety.level,...Zi("safety.overrides",P.safety.overrides),"workflow.worktree_mode":String(P.workflow.worktree_mode),"destructive_command_protection.enabled":String(P.destructive_command_protection.enabled),...Zi("destructive_command_protection.overrides",P.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":Xi(P.destructive_command_protection.allow_paths),"secret_protection.enabled":String(P.secret_protection.enabled),...Zi("secret_protection.overrides",P.secret_protection.overrides),"secret_protection.deny_paths":Xi(P.secret_protection.deny_paths),"secret_protection.allow_paths":Xi(P.secret_protection.allow_paths),...O?{"audit.retention_days":String(P.audit.retention_days)}:{}}}function oo(P,O,D){let j=Hd(P,D),J=Hd(O,D);return[...new Set([...Object.keys(j),...Object.keys(J)])].flatMap((Y)=>j[Y]===J[Y]?[]:[{field:Y,before:j[Y],after:J[Y]}])}function ar(P,O){let D=l(P,O);if(!Md(D))return{baseline:E(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,P.home),diagnostics:[]};let j=bt(D),J=vt(j.value,P.home);return{baseline:J.policy,diagnostics:j.errors.length>0?j.errors:J.errors}}function bt(P){if(!Md(P))return{errors:[`${P}: file not found`]};try{return{value:JSON.parse(Uh(P,"utf-8")),errors:[]}}catch(O){let D=O instanceof Error?O.message:String(O);return{errors:[`${P}: ${O instanceof SyntaxError?`Invalid JSON: ${D}`:D}`]}}}function io(P,O){let D=Gh(P)?P:{};return{version:O.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((j)=>D[j]!==void 0).map((j)=>[j,D[j]]))}}function Zi(P,O){return Object.fromEntries(Object.entries(O).flatMap(([D,j])=>j===void 0?[]:[[`${P}.${D}`,String(j)]]))}function Xi(P){return P.length===0?"(none)":P.join(", ")}function Gh(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{chmodSync as qh,existsSync as Ud,mkdirSync as Bh,readFileSync as Gd}from"node:fs";import{dirname as Vh}from"node:path";function qd(P,O={}){let D=l(P,O);if(!Ud(D))return{path:D,exists:!1,raw:"",policy:F(),errors:[]};let j=Gd(D,"utf-8");if(!j.trim())return{path:D,exists:!0,raw:j,policy:F(),errors:["Config file is empty"]};try{let J=vt(JSON.parse(j),P.home);return{path:D,exists:!0,raw:j,policy:J.policy,errors:J.errors}}catch(J){return{path:D,exists:!0,raw:j,policy:F(),errors:[`Invalid JSON: ${J instanceof Error?J.message:String(J)}`]}}}function Hn(P,O,D={}){let j=l(P,D),J=vt(O,P.home);if(J.errors.length>0)return{path:j,policy:F(),errors:J.errors};let Y=J.policy;return Bh(Vh(j),{recursive:!0,mode:448}),g(se(j),`${JSON.stringify(Y,null,2)}
275
- `,384),qh(j,384),{path:j,policy:Y,errors:[]}}function Bd(P,O){let D=vt(O,P.home);if(D.errors.length>0)return{errors:D.errors};return{preview:Le(D.policy,P.env),errors:[]}}function Vd(P,O={}){let D=l(P,O);if(!Ud(D))return Hn(P,te,O);let j=Gd(D,"utf-8");if(!j.trim())return Hn(P,te,O);try{return Hn(P,E(JSON.parse(j),P.home),O)}catch{return Hn(P,te,O)}}var Jd=new Set(["check","apply"]),Wd="(unset)";async function zd(P,O,D={}){let j=gn({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},O),J=j.positionals[0],Y=[...j.errors,...J&&!Jd.has(J)?[`Unknown policy subcommand: ${J}`]:[],...J&&Jd.has(J)&&!j.positionals[1]?[`policy ${J} requires a file`]:[],...j.positionals.slice(2).map((Ve)=>`Unexpected policy argument: ${Ve}`)];if(Y.length>0){for(let Ve of Y)console.error(Ve);return 1}let re=j.positionals[1];if(!J||!re)return Lt(mr,console.error),1;let ie=D.cwd??process.cwd(),de=j.flags.global?l(P):h(ie);if(!j.flags.global&&L(P,{cwd:ie}))return console.error(`${de} is the user policy, not a project policy; use --global for the user scope, or run from a project directory`),1;let fe=bt(re),we=[...fe.errors,...sr(fe.value,P.home).map((Ve)=>`${re}: ${Ve}`),...!j.flags.global&&Zh(fe.value)&&fe.value.audit!==void 0?[`${re}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(we.length>0){for(let Ve of we)console.error(Ve);return 1}let Ce=E(fe.value,P.home);if(console.log(`Scope: ${j.flags.global?"user":"project"} (${de})`),console.log(`Proposal: ${re}`),j.flags.global)Kd(E(bt(de).value,P.home),Ce,!0);if(!j.flags.global){let Ve=ar(P).baseline;console.log("Effective policy (user + project merged):"),Kd(ee(Ve,ue(bt(de).value,P.home).policy).policy,ee(Ve,ue(fe.value,P.home).policy).policy,!1)}if(J==="check")return 0;let Se=D.input??process.stdin,Ie=D.output??process.stdout;if(!Se.isTTY||!Ie.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${re}${j.flags.global?" --global":""}`),1;if(!await zh(`Apply this policy to ${de}? [y/N] `,Se,Ie))return console.log("Cancelled; nothing was written."),0;return Yh(P,de,fe.value,Ce,j.flags.global),console.log(`Policy applied: ${de}`),0}function zh(P,O,D){let j=Kh({input:O,output:D,terminal:!1});return new Promise((J)=>{j.once("close",()=>J(!1)),j.question(P,(Y)=>{J(/^y(es)?$/i.test(Y.trim())),j.close()})})}function Yh(P,O,D,j,J){if(J){Hn(P,j);return}Jh(Wh(O),{recursive:!0}),wn(O,io(D,j))}function Kd(P,O,D){let j=oo(P,O,D);if(j.length===0){console.log("No changes.");return}console.log(`Changes (${j.length}):`);for(let J of j)console.log(` ${J.field}: ${J.before??Wd} -> ${J.after??Wd}`)}function Zh(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{join as db}from"node:path";var Yd="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Priority |\n|-------|-------------|---------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | Second |\n| GitHub source | Listed in a local `rule.json` | Vendored into the consumer's `<rulebook-name>/rulebook.json` by `rule add` | Source order |\n\nEvery rulebook is a live file: the runtime reads it on each tool call, so an edit applies to the next command with no publishing step.\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule verify` reports the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- `caffeinate`, `exec`, `nice`, `nohup`, `setsid`, `stdbuf`, `time`, and `timeout` are built-in transparent wrappers and need no configuration. Configure only other wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n\n## Rulebook Sources\n\n- Local sources are bare rulebook names such as `project-rules`; the rulebook file is `.cc-safety-net/rules/project-rules/rulebook.json`.\n- Run `cc-safety-net rule add owner/repo` to add every rulebook currently present on the repository's default branch.\n- Use `--only` to select one or more rulebooks while preserving their order: `cc-safety-net rule add owner/repo --only aws gcloud`.\n- Use `--ref` to select a branch, tag, or commit instead of the default branch: `cc-safety-net rule add owner/repo --ref v2 --only aws`.\n- GitHub sources are stored in canonical form as `owner/repo#ref/<rulebook-name>`. That form remains valid in `rule.json` and as direct CLI input.\n- GitHub refs may contain `/`-separated path segments, such as `feature/rulebook-v2`.\n- The GitHub source name, the repository directory name, and the rulebook `name` must match exactly.\n- Rulebook source strings must be unique in a config.\n\n## rulebook.json Schema\n\n```json\n{\n \"rulebook_version\": 1,\n \"name\": \"project-rules\",\n \"version\": \"1.0.0\",\n \"description\": \"Project-specific CC Safety Net rules.\",\n \"author\": \"project\",\n \"allowed_commands\": [\"docker\"],\n \"rules\": [\n {\n \"name\": \"block-docker-system-prune\",\n \"command\": \"docker\",\n \"subcommand\": \"system\",\n \"block_args\": [\"prune\"],\n \"reason\": \"Use targeted cleanup instead.\"\n }\n ],\n \"tests\": [\n {\n \"command\": \"docker system prune\",\n \"expect\": \"blocked\",\n \"rule\": \"block-docker-system-prune\"\n },\n {\n \"command\": \"docker ps\",\n \"expect\": \"allowed\"\n }\n ]\n}\n```\n\n### Rulebook Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `rulebook_version` | Yes | Must be `1` or `2` |\n| `name` | Yes | `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` |\n| `version` | Yes | Non-empty string |\n| `description` | No | Free text; not type-checked at runtime |\n| `author` | No | Free text; not type-checked at runtime |\n| `allowed_commands` | Yes | Unique command names matching `^[a-zA-Z][a-zA-Z0-9_-]*$` |\n| `rules` | Yes | Array of rule objects |\n| `tests` | No | Array of fixtures |\n\n### Rule Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Unique within the rulebook (case-insensitive); same pattern as rulebook `name` |\n| `command` | Yes | Must be listed in `allowed_commands`; basename only, not path |\n| `subcommand` | No | Same pattern as `command`; omit to match any subcommand |\n| `intent` | No | One of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain` |\n| `block_args` | Yes | Non-empty array of non-empty strings |\n| `reason` | Yes | Non-empty string, max 256 chars |\n\n### Rule Fields (`rulebook_version` 2)\n\nVersion 2 replaces `subcommand` and `block_args` with an exact-token `match` object. Version 1 rulebooks keep their fields and their behavior; a client that does not support version 2 rejects the rulebook instead of applying broader version 1 semantics.\n\n```json\n{\n \"name\": \"block-terraform-apply-destroy\",\n \"command\": \"terraform\",\n \"match\": {\n \"command_path\": [\"apply\"],\n \"any_args\": [\"-destroy\", \"--destroy\"]\n },\n \"reason\": \"Review a destroy plan first with 'terraform plan -destroy'.\",\n \"intent\": \"use_alternative\"\n}\n```\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Same as version 1 |\n| `command` | Yes | Same as version 1 |\n| `match.command_path` | Yes | Non-empty array of non-empty command words |\n| `match.any_args` | No | Non-empty array of unique non-empty argument tokens |\n| `match.exclude_args` | No | Non-empty array of unique non-empty argument tokens |\n| `intent` | No | Same as version 1 |\n| `reason` | Yes | Same as version 1 |\n\n### Matching Behavior (`rulebook_version` 2)\n\n- **Command**: Normalized to lowercase basename, as in version 1.\n- **Command path**: After recognized global options and their values are skipped, the next command words must equal `command_path` exactly. AWS, gcloud, and Azure CLI value-taking global options are built in; Terraform's `-chdir=dir` is `=`-joined and is skipped with its own token.\n- **Unrecognized options**: A token starting with `-` that is not a recognized global option is skipped without consuming a value, so an unlisted value-taking option with a separate value (`--newflag value`) makes the rule miss. This fails open deliberately; document such gaps in the rulebook.\n- **`any_args`**: At least one listed token must appear literally among the arguments.\n- **`exclude_args`**: Any listed token appearing literally among the arguments prevents the match, which is how a safe preview such as `aws s3 rm --dryrun` stays allowed.\n- **No short-option expansion**: Arguments compare as exact tokens, so list every accepted spelling (`\"-destroy\"` and `\"--destroy\"`).\n- **Literal and case-sensitive**: No regex, glob, or substring matching. The first matching rule wins.\n- Release channels are separate rules: `gcloud beta compute instances delete` needs its own `command_path`.\n\n### Test Fixture Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `command` | Yes | Non-empty shell command string |\n| `expect` | Yes | `\"blocked\"` or `\"allowed\"` |\n| `rule` | Required for blocked fixtures | Rule name expected to block the command |\n\nFixtures are optional documentation of intended behavior. Version 1 fixtures are shape-validated only. Version 2 fixtures are evaluated against the rulebook's own rules when a source is fetched by `rule add` or `rule update`, and by `rule verify`; a failing fixture rejects that source before it is written. Loading a rulebook does not re-evaluate fixtures. CC Safety Net never executes fixture commands; they are analyzer inputs only.\n\n## Matching Behavior\n\nThe subcommand, argument, and option rules below describe `rulebook_version` 1 rules; version 2 rules match as described in Matching Behavior (`rulebook_version` 2). Execution order and transparent wrappers apply to both.\n\n- **Command**: Normalized to lowercase basename with any trailing `.exe` removed (`/usr/bin/git` → `git`).\n- **Subcommand**: The first command token after recognized Git and Docker global options and their values; `--` ends option parsing. An unrecognized option without `=` may consume the following token as its value.\n- **Arguments**: Each `block_args` value is compared literally against every command token, including expanded short options. The command is blocked if **any** item matches.\n- **Short options**: Expanded (`-Ap` matches `-A`).\n- **Long options**: Exact match (`--all-files` does not match `--all`).\n- **Execution order**: Built-in rules first, then custom rulebooks. Custom rules only add restrictions.\n- **Transparent wrappers**: A configured wrapper such as `rtk` lets `rtk git commit` be analyzed as `git commit` only when `git` is protected by built-in analyzers or active custom rules. `rtk -- git commit` is also supported.\n\n## Workflow\n\n1. Run `cc-safety-net rule init` or create `rule.json` manually.\n2. Optionally run `cc-safety-net rule init --example` to create an inactive example rulebook.\n3. Use `cc-safety-net rule wrapper add rtk` for trusted transparent wrappers.\n4. Run `cc-safety-net rule add <source>` after creating or choosing a rulebook source; add `--only <rulebook...>` or `--ref <ref>` for repository selection. The command adds the selected sources and syncs them.\n5. Edit a local rulebook whenever you like: the edit is enforced on the next command, so there is nothing to run afterwards.\n6. Run `cc-safety-net rule update [source]` to re-fetch remote sources and rewrite the vendored copies; the command prints what changed. A source with an ordinary update failure keeps its vendored copy while the other selected sources still update. Resource-limit failures remain fatal for the whole update.\n7. Run `cc-safety-net rule verify` to validate config, local rulebooks, and shareable GitHub-source rulebook directories in the current repository (it does not fetch remote content).\n8. Run `cc-safety-net rule list` to inspect active rulebooks and transparent wrappers.\n\nA missing or invalid rulebook file makes that source inactive, and an unreadable or invalid `rule.json` makes every source in its scope inactive. Inactive sources stop applying their rules while other custom rules and all built-in protections stay active. Fix the file named in the diagnostic, or run `cc-safety-net rule update` when a remote source has not been vendored yet. Run `cc-safety-net status` to see degraded sources.\n";function so(P,O){if(!P.ok){nu(P);return}Qd(P,O)}function Xd(P,O,D){if(P.ok)console.log(D);if(!P.add){so(P,`Added rulebook source: ${O}`);return}if(!P.ok){nu(P);return}if(P.add.added.length>0)console.log(`Added ${P.add.added.length} ${P.add.added.length===1?"rulebook":"rulebooks"} from ${P.add.source} at ${P.add.ref}:`),P.add.added.forEach((j)=>{console.log(` - ${j}`)});if(P.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${P.add.source} at ${P.add.ref}: ${P.add.alreadyConfigured.join(", ")}`);if(P.add.commits.length>0)console.log(`Vendored at ${P.add.commits.map((j)=>j.slice(0,7)).join(", ")}.`);Qd(P,"Rule config updated.")}function Qd(P,O){for(let D of P.changes??[])console.log(D);console.log(O),console.log(""),Xh(P.entries)}function Xh(P){if(P.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${P.length}):`);for(let O of P)console.log(` - ${O.name} ${O.version} (${Qh(O.ruleCount)})`),console.log(` Source: ${O.spec}`)}function Qh(P){return`${P} ${P===1?"rule":"rules"}`}function eu(P){wt("Active sources",P.rulebooks,(O)=>[`[${O.source}] ${O.name} ${O.version}`,` Source: ${O.spec}`]),wt("Active rules",P.rules,(O)=>[`[${nv(P,O.name)}] ${O.name}`,...ev(O),` Reason: ${O.reason}`]),wt("Disabled rules",Zd(P,"off"),(O)=>[O.key]),wt("Reason overrides",Zd(P,"reason"),(O)=>[O.key,` Reason: ${O.value.reason}`]),wt("Transparent wrappers",P.transparent_wrappers,(O)=>[O]),wt("Issues",P.errors,(O)=>[O]),wt("Warnings",P.warnings,(O)=>[O])}function wt(P,O,D){if(O.length===0){console.log(`${P}: (none)`);return}console.log(`${P} (${O.length}):`);for(let j of O){let[J,...Y]=D(j);console.log(` - ${J}`);for(let re of Y)console.log(` ${re}`)}}function ev(P){if(!P.match)return[` Command: ${P.subcommand?`${P.command} ${P.subcommand}`:P.command}`,` Block args: ${P.block_args.join(", ")}`];return[` Command: ${[P.command,...P.match.command_path].join(" ")}`,...P.match.any_args?[` Any args: ${P.match.any_args.join(", ")}`]:[],...P.match.exclude_args?[` Exclude args: ${P.match.exclude_args.join(", ")}`]:[]]}function nv(P,O){return P.rulebooks.find((D)=>D.rules.includes(O))?.source??"project"}function Zd(P,O){return Object.entries({...P.userConfig?.overrides,...P.projectConfig?.overrides}).filter((D)=>{if(O==="off")return D[1]==="off";return!!D[1]&&typeof D[1]==="object"}).map(([D,j])=>({key:D,value:j}))}function nu(P){for(let O of P.errors)console.error(O)}import{dirname as Su,join as go}from"node:path";import{join as rs,resolve as fv}from"node:path";function Qi(P){let O=m(P);if(O.errors.length>0)return{ok:!1,result:{ok:!1,errors:O.errors,entries:[]}};return{ok:!0,config:O.config??ut}}function tu(P){wn(P,{version:1,rules:[],overrides:{},transparent_wrappers:[]})}function ru(P){wn(P,{rulebook_version:1,name:"example-rules",version:"1.0.0",description:"Project-specific CC Safety Net rules.",author:"project",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as uo}from"node:path";var tv="custom.";function ao(P){if(P.rulebook_version!==2)return[];let O=P.rules.map((D)=>({name:D.name,command:D.command,block_args:[],match:D.match,reason:D.reason,intent:D.intent}));return(P.tests??[]).flatMap((D,j)=>{let J=es(y(D.command));if(J.length===0)return[`tests[${j}]: could not parse fixture command: ${D.command}`];let Y=J.reduce((re,ie)=>re??A(ie,O)?.id.slice(tv.length),void 0);if(D.expect==="blocked"){if(Y===D.rule)return[];let re=Y?`"${Y}" matched first`:"no rule matched";return[`tests[${j}]: expected "${D.rule}" to block "${D.command}" but ${re}`]}return Y?[`tests[${j}]: expected "${D.command}" to be allowed but "${Y}" matched`]:[]})}function es(P){return P.nodes.flatMap((O)=>{if(O.kind==="group"||O.kind==="function")return es(O.body);if(O.kind!=="command")return[];let D=ve(ne(O.dialect,O.words)).words.map(t);return[...D.length>0?[D]:[],...O.nested.flatMap((j)=>es(j))]})}var lo=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function co(P={}){return{requests:0,responseBytes:0,maxRequests:P.maxRequests??lo.maxRequests,maxResponseBytes:P.maxResponseBytes??lo.maxResponseBytes}}function Mn(P){return{controller:new AbortController,budget:co(),resolveUrl:P}}function ou(P){return P instanceof Error&&P.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function iu(P){if(P.requests>=P.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.requests++}function su(P,O){if(O>P.maxResponseBytes-P.responseBytes)throw P.responseBytes+=O,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.responseBytes+=O}var cu=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function au(P,O,D=S(uo(uo(O)),"rules policy"),j=Mn()){if(w(P))return sv(P,j);return iv(P,O,D)}async function du(P,O,D,j,J,Y){if(!w(P))return au(P,O,D,j);let re=J?null:rv(P,O,D);if(re)return re;if(!J&&!Y)throw Error(`${P} is not vendored; run rule update ${P} to vendor it`);return au(P,O,D,j)}function rv(P,O,D=S(uo(uo(O)),"rules policy")){let j=N(P),J=M(O,j.name),Y=r(i(D,J));if(Y===null)return null;let re=le(ns(Y,`Invalid rulebook ${J}.`));if(re.name!==j.name)throw Error(`rulebook name "${re.name}" in ${J} must match "${j.name}"`);return{spec:P,rulebook:re,content:Y}}async function uu(P,O={}){if(!Z(P))throw Error(`Invalid GitHub repository source: ${P}`);let[D,j]=P.split("/");if(!D||!j)throw Error(`Invalid GitHub repository source: ${P}`);if(O.ref!==void 0&&!ae(O.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${O.ref}`);let J=O.operation??Mn(),Y=O.ref??await ov(D,j,P,J),re=await fu(D,j,Y,P,J),ie=await po(`https://api.github.com/repos/${D}/${j}/git/trees/${re}?recursive=1`,"tree",J),de=ie.response;if(!de.ok)throw Error(`Failed to inspect ${P}: GitHub tree returned ${de.status}`);let fe=JSON.parse(ie.content);if(!Array.isArray(fe?.tree))throw Error(`Failed to inspect ${P}: unexpected GitHub tree response`);let we=fe.tree,Ce=[...new Set(we.flatMap((Se)=>{if(!Se||typeof Se!=="object")return[];let Ie=Se;if(Ie.type!=="blob"||typeof Ie.path!=="string")return[];let Ee=Ie.path.match(ct);return Ee?.[1]?[Ee[1]]:[]}))].sort();if(Ce.length===0)throw Error(`No rulebooks found in ${P} under ${he}/`);return{source:P,owner:D,repo:j,ref:Y,commit:re,names:Ce}}async function ov(P,O,D,j){let J=await po(`https://api.github.com/repos/${P}/${O}`,"metadata",j),Y=J.response;if(!Y.ok)throw Error(`Failed to inspect ${D}: GitHub returned ${Y.status}`);let ie=JSON.parse(J.content)?.default_branch;if(typeof ie!=="string"||ie==="")throw Error(`Failed to inspect ${D}: missing default branch`);if(!ae(ie))throw Error(`GitHub returned an invalid default branch: ${ie}`);return ie}function iv(P,O,D){lt(P);let j=M(O,P),J=r(i(D,j));if(J===null)throw Error(`Rulebook source not found: ${P}`);let Y=pu(ns(J,"Invalid local rulebook source."));if(Y.name!==P)throw Error(`rulebook name "${Y.name}" must match local source "${P}"`);return{spec:P,rulebook:Y,content:J}}async function sv(P,O){let D=N(P),j=await fu(D.owner,D.repo,D.ref,P,O),J=await po(`https://raw.githubusercontent.com/${D.owner}/${D.repo}/${j}/${D.path}`,"raw",O),Y=J.response;if(!Y.ok)throw Error(`Failed to fetch ${P}: GitHub raw returned ${Y.status}`);let re=J.content,ie=pu(ns(re,"Invalid GitHub rulebook response."));if(ie.name!==D.name)throw Error(`rulebook name "${ie.name}" must match GitHub source "${D.name}"`);return{spec:P,rulebook:ie,content:re}}function pu(P){let O=le(P),D=ao(O);if(D.length>0)throw Error(D.join("; "));return O}function ns(P,O){try{return JSON.parse(P)}catch{throw Error(O)}}async function fu(P,O,D,j,J){let Y=await po(`https://api.github.com/repos/${P}/${O}/commits/${encodeURIComponent(D)}`,"commit",J),re=Y.response;if(!re.ok)throw Error(`Failed to resolve ${j}: GitHub returned ${re.status}`);let ie=JSON.parse(Y.content);if(typeof ie?.sha!=="string"||ie.sha==="")throw Error(`Failed to resolve commit for ${j}`);return ie.sha}async function av(P,O,D={}){if(D.signal?.aborted)throw D.signal.reason;let j=D.budget??co(),J=new AbortController,Y=()=>J.abort(D.signal?.reason);D.signal?.addEventListener("abort",Y,{once:!0});let re=!1,ie=setTimeout(()=>{if(J.signal.aborted)return;re=!0,J.abort()},D.timeoutMs??cu.timeoutMs);try{if(D.signal?.aborted)throw D.signal.reason;iu(j);let de=await fetch(P,{signal:J.signal,redirect:"error"});if(!de.ok)return mu(de),{response:de,content:""};return{response:de,content:await lv(de,O,j,()=>J.abort())}}catch(de){if(re)throw Error("GitHub request timed out",{cause:de});if(D.signal?.aborted)throw D.signal.reason;throw de}finally{clearTimeout(ie),D.signal?.removeEventListener("abort",Y)}}function po(P,O,D){return av(D.resolveUrl?.(P)??P,O,{budget:D.budget,signal:D.controller.signal})}async function lv(P,O,D=co(),j){let J=cu[`${O}Bytes`],Y=Number(P.headers.get("content-length"));if(Number.isFinite(Y)&&Y>J)throw mu(P),Error(`GitHub ${O} response exceeds ${J} bytes`);if(!P.body)return"";let re=P.body.getReader(),ie=[],de=0;while(!0){let fe=await re.read();if(fe.done)break;try{su(D,fe.value.byteLength)}catch(we){throw j?.(),lu(re),we}if(de+=fe.value.byteLength,de>J)throw j?.(),lu(re),Error(`GitHub ${O} response exceeds ${J} bytes`);ie.push(Buffer.from(fe.value))}return Buffer.concat(ie,de).toString("utf-8")}function mu(P){if(!P.body)return;gu(()=>P.body?.cancel())}function lu(P){gu(()=>P.cancel())}function gu(P){try{Promise.resolve(P()).catch(()=>{})}catch{}}var cv=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function yu(P,O){let D=bu(P.rules,O);if(D.length>0)return{ok:!0,specs:D};return vu(P.rules,O)}function hu(P,O){let D=bu(P,O);if(D.length>0)return{ok:!0,specs:D};let j=uv(P,O);if(j.length>0)return{ok:!0,specs:j};let J=pv(P,O);if(!J.ok)return J;if(J.specs.length>0)return{ok:!0,specs:J.specs};return vu(P,O)}function vu(P,O){let D=P.filter((j)=>ts(j)?.name===O);if(D.length===1)return{ok:!0,specs:D};return dv(O,D)}function dv(P,O){return{ok:!1,result:{ok:!1,errors:O.length===0?[`No configured rulebook matches ${P}`]:[`Ambiguous rulebook match ${P}: ${O.join(", ")}`],entries:[]}}}function bu(P,O){return P.filter((D)=>D===O)}function uv(P,O){let D=O.match(cv),j=D?.[1],J=D?.[2],Y=D?.[3];if(!j||!J||!Y||!ae(Y))return[];return wu(P,(re)=>re.owner===j&&re.repo===J&&re.ref===Y)}function pv(P,O){if(!Z(O))return{ok:!0,specs:[]};let[D,j]=O.split("/"),J=wu(P,(re)=>re.owner===D&&re.repo===j);if(new Set(J.map((re)=>ts(re)?.ref).filter((re)=>!!re)).size<2)return{ok:!0,specs:J};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${O}. Use an explicit ref:`,` cc-safety-net rule remove ${O}#<ref>`],entries:[]}}}function ts(P){try{return N(P)}catch{return null}}function wu(P,O){return P.filter((D)=>{let j=ts(D);return j?O(j):!1})}async function mo(P,O={}){let D=os(O);return mv(P,D,await fo(P,D,Mn()))}function mv(P,O,D){if(!D.ok)return D;let j=kn(P,O),J=[...new Set(B(j.configPath,j.filesystemScope))];if(J.length===0)return D;return{ok:!1,errors:J,entries:D.entries}}async function fo(P,O,D,j={},J=new Set,Y=new Set){try{let re=kn(P,O),ie=Qi(re.configTarget);if(!ie.ok)return ie.result;let de=ie.config,fe=O.only?yu(de,O.only):{ok:!0,specs:de.rules};if(!fe.ok)return fe.result;let we=new Set([...O.refresh?fe.specs:[],...J]),Ce=(rn)=>du(rn,re.configDir,re.filesystemScope,D,we.has(rn),!O.refresh||we.has(rn)),Se=await Pv(de.rules,O.refresh?(rn)=>Ce(rn).then((fn)=>({ok:!0,item:fn})).catch((fn)=>{if(ou(fn))throw fn;return{ok:!1,spec:rn,message:fn instanceof Error?fn.message:String(fn)}}):async(rn)=>({ok:!0,item:await Ce(rn)}),D),Ie=Se.filter((rn)=>!rn.ok),Ee=Se.filter((rn)=>rn.ok).map((rn)=>rn.item),Ve=Ee.flatMap((rn)=>gv(rn,de.rules)),Me=Ee.flatMap((rn)=>yv(rn,Y,re)),en=new Set([...Ve,...Me].map((rn)=>rn.spec)),on=[...Ie,...Ve,...Me],sn=[],an=vv(sn,()=>Ee.flatMap((rn)=>en.has(rn.spec)||on.length>0&&Y.has(rn.spec)?[]:hv(rn,re,j,sn)));return{ok:on.length===0,errors:on.map((rn)=>`Failed to update ${rn.spec}: ${rn.message}`),entries:Ee.map(wv),changes:an}}catch(re){return cr(re)}}function gv(P,O){if(!w(P.spec))return[];let D=Ne(P.spec),j=O.filter((J)=>J!==P.spec&&Ne(J).toLowerCase()===D.toLowerCase());if(j.length===0)return[];return[{ok:!1,spec:P.spec,message:`rulebook name "${D}" is also claimed by ${j.join(", ")}; rename one of them`}]}function yv(P,O,D){if(!O.has(P.spec)||!w(P.spec))return[];let j=M(D.configDir,P.rulebook.name),J=r(i(D.filesystemScope,j));if(J===null||J===P.content)return[];return[{ok:!1,spec:P.spec,message:`${j} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function hv(P,O,D,j){if(!w(P.spec))return[];let J=M(O.configDir,P.rulebook.name),Y=i(O.filesystemScope,J),re=r(Y);if(re===P.content)return[];return j?.push({target:Y,previous:re}),g(Y,P.content,void 0,D._testAfterPolicyRename),bv(P,re)}function vv(P,O){try{return O()}catch(D){for(let j of[...P].reverse()){if(j.previous===null){H(j.target);continue}g(j.target,j.previous)}throw D}}function bv(P,O){if(O===null)return[`Vendored ${P.spec} (${P.rulebook.version})`];let D=xe(O),j="problem"in D?null:D.rulebook,J=new Map(j?.rules.map((re)=>[re.name,JSON.stringify(re)])??[]),Y=new Set(P.rulebook.rules.map((re)=>re.name));return[`Updated ${P.spec} (${j?.version??"unreadable"} -> ${P.rulebook.version})`,...[...Y].filter((re)=>!J.has(re)).map((re)=>` + ${re}`),...[...J.keys()].filter((re)=>!Y.has(re)).map((re)=>` - ${re}`),...P.rulebook.rules.filter((re)=>{let ie=J.get(re.name);return ie!==void 0&&ie!==JSON.stringify(re)}).map((re)=>` ~ ${re.name}`)]}function wv(P){return{spec:P.spec,name:P.rulebook.name,version:P.rulebook.version,ruleCount:P.rulebook.rules.length}}async function ku(P,O,D={}){return kv(P,O,Ev(D),Mn())}async function kv(P,O,D,j,J={}){let Y=null,re=!1;try{let ie=kn(P,D),de=r(ie.configTarget);Y={target:ie.configTarget,content:de};let fe=Qi(ie.configTarget);if(!fe.ok)return fe.result;let we=fe.config,Ce=Z(O);xv(O,D,Ce);let Se=Ce?await uu(O,{ref:D.ref,operation:j}):null,Ie=Se?Cv(Se,D.rulebooks):[],Ee=Se?Ie.map((sn)=>Sv(we.rules,Se,sn)??`${O}#${Se.ref}/${sn}`):[O],Ve=Ee.filter((sn)=>!we.rules.includes(sn)),Me=[...we.rules,...Ve];if(Me.length>ye)return Rv();if(Me.length!==we.rules.length)re=!0,wn(ie.configTarget,{version:1,rules:Me,overrides:we.overrides??{},transparent_wrappers:we.transparent_wrappers??[]},void 0,J._testAfterPolicyRename);let en=await fo(P,D,j,J,new Set(Ve),new Set(Ve));if(!en.ok)lr(ie.configTarget,de);if(!en.ok||!Se)return en;let on=Ie.filter((sn,an)=>Ve.includes(Ee[an]??""));return{...en,add:{source:O,ref:Se.ref,selected:Ie,added:on,alreadyConfigured:Ie.filter((sn)=>!on.includes(sn)),commits:Ve.length>0?[Se.commit]:[]}}}catch(ie){if(re&&Y)try{lr(Y.target,Y.content)}catch(de){return cr(de)}return cr(ie)}}function xv(P,O,D){if(!D&&O.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!D&&O.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${P}`);if(O.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let j=O.rulebooks?.filter((J)=>!d.test(J))??[];if(j.length>0)throw Error(`Invalid rulebook names: ${j.join(", ")}`)}function Cv(P,O){let D=O?[...new Set(O)]:P.names,j=D.filter((J)=>!P.names.includes(J));if(j.length>0)throw Error(`Rulebooks not found in ${P.source} at ${P.ref}: ${j.join(", ")}
276
- Available rulebooks: ${P.names.join(", ")}`);return D}function Sv(P,O,D){let j=`${O.source}#${O.ref}/${D}`;if(P.includes(j))return j;let J=`${O.source}#${O.commit}/${D}`;return P.find((Y)=>Y===J)}async function Pv(P,O,D=Mn()){if(P.length>ye)throw Error(be);let j=[],J=0,Y,re=Array.from({length:Math.min(P.length,lo.concurrency)},async()=>{while(!Y){let ie=J;if(ie>=P.length)return;J++;try{j[ie]=await O(P[ie],ie,D.controller.signal)}catch(de){if(!Y)Y={value:de},J=P.length,D.controller.abort(de);return}}});if(await Promise.all(re),Y)throw Y.value;return j}function Rv(){return{ok:!1,errors:[be],entries:[]}}function os(P){return{cwd:P.cwd,userConfigDir:P.userConfigDir,userConfigPath:P.userConfigPath,projectConfigPath:P.projectConfigPath,global:P.global,only:P.only,refresh:P.refresh}}function Ev(P){return{...os(P),ref:P.ref,rulebooks:P.rulebooks}}function _v(P){return{...os(P),deleteSource:P.deleteSource}}async function xu(P,O,D={}){try{return await Tv(P,O,_v(D),{})}catch(j){return cr(j)}}async function Tv(P,O,D,j){let J=kn(P,D),Y=m(J.configTarget);if(Y.errors.length>0)return{ok:!1,errors:Y.errors,entries:[]};if(!Y.config)return{ok:!1,errors:[`No config found at ${J.configPath}`],entries:[]};let re=hu(Y.config.rules,O);if(!re.ok)return re.result;let ie=D.deleteSource?Av(J.configDir,re.specs,J.filesystemScope):{ok:!0,dirs:[]};if(!ie.ok)return ie.result;let de=r(J.configTarget);if(de===null)return cr(Error("Rules config is unavailable."));try{wn(J.configTarget,{version:1,rules:Y.config.rules.filter((Ce)=>!re.specs.includes(Ce)),overrides:Y.config.overrides??{},transparent_wrappers:Y.config.transparent_wrappers??[]},void 0,j._testAfterPolicyRename)}catch(Ce){throw lr(J.configTarget,de),Ce}let fe=await fo(P,D,Mn(),j);if(!fe.ok)return lr(J.configTarget,de),fe;let we=Iv(ie.dirs,j,J.filesystemScope);if(!we.ok){lr(J.configTarget,de);let Ce=await fo(P,D,Mn(),j);if(!Ce.ok)return{ok:!1,errors:[...we.result.errors,...Ce.errors],entries:Ce.entries};return we.result}return fe}function Av(P,O,D){let j=O.flatMap((ie)=>d.test(ie)?[]:["--delete-source can only delete local rulebook sources"]),J=O.map((ie)=>rs(P,ie)),Y=j.length>0?[]:J.flatMap((ie)=>Cu(ie,D)),re=[...j,...Y];return re.length>0?{ok:!1,result:{ok:!1,errors:re,entries:[]}}:{ok:!0,dirs:J}}function Cu(P,O){let D=fv(P),j=i(O,D),J=me(j);if(!J)return[`Local rulebook source directory not found: ${P}`];let Y=J.find((re)=>re.name==="rulebook.json");if(!Y)return[`Local rulebook source directory is missing rulebook.json: ${P}`];if(Y.kind!=="file")throw new o(O.label);if(r(i(O,rs(D,"rulebook.json"))),J.length>1)return[`Local rulebook source directory contains extra files: ${P}. delete manually if you really want to remove the directory.`];return[]}function Iv(P,O,D){let j=P.flatMap((J)=>{try{if(!me(i(D,J)))return[];let Y=Cu(J,D);if(Y.length>0)return Y;return $v(J,O,D),[]}catch(Y){return[`Failed to delete local rulebook source ${J}: ${Y instanceof Error?Y.message:String(Y)}`]}});return j.length>0?{ok:!1,result:{ok:!1,errors:j,entries:[]}}:{ok:!0}}function $v(P,O,D){if(O._testDeleteLocalSourceDir){O._testDeleteLocalSourceDir(P);return}H(i(D,rs(P,ge))),at(i(D,P))}function lr(P,O){if(O===null){H(P);return}g(P,O)}function cr(P){return{ok:!1,errors:[P instanceof Error?P.message:String(P)],entries:[]}}var Ov=".safety-net.json",Dv="~/.cc-safety-net/config.json";async function Eu(P,O){let D=L(P,{cwd:O.cwd});if(D)console.log(`Skipped the project scope: ${_(O.cwd)} is the user rule config, not a project rule config`);return[D||await Pu(P,{legacyPath:pa({cwd:O.cwd}),configPath:_(O.cwd),defaultRulebookName:"project-rules",migratedFrom:Ov,cleanup:O.cleanup,syncOptions:{cwd:O.cwd}}),await Pu(P,{legacyPath:Ct(P),configPath:W(P),defaultRulebookName:"user-rules",migratedFrom:Dv,cleanup:O.cleanup,syncOptions:{cwd:O.cwd,global:!0}})].every((J)=>J)?0:1}async function Pu(P,O){let D=kn(P,O.syncOptions),j=i(D.filesystemScope,O.legacyPath),J=r(j);if(J===null)return console.log(`No legacy config found at ${O.legacyPath}`),!0;let Y=Nv(J);if(!Y.ok){for(let Ie of Y.errors)console.error(Ie);return!1}let re=m(D.configTarget);if(re.errors.length>0){for(let Ie of re.errors)console.error(Ie);return!1}let ie=re.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},de=jv(Su(O.configPath),ie.rules,O.defaultRulebookName,O.migratedFrom,D.filesystemScope),fe=go(Su(O.configPath),de,"rulebook.json"),we=i(D.filesystemScope,fe),Ce=[Ru(D.configTarget),Ru(we)],Se=await Lv(P,O,D.configTarget,we,de,Y.config.rules,ie.rules.includes(de)?ie.rules:[...ie.rules,de],ie.overrides??{},ie.transparent_wrappers??[]);if(!Se.ok){Mv(Ce);for(let Ie of Se.errors)console.error(Ie);return!1}if(!O.cleanup)return console.log(`Migrated legacy config at ${O.legacyPath}. Legacy file is no longer used.`),!0;if(!Hv(D.configTarget,we,de,O.migratedFrom,Y.config.rules))return console.error(`Migration cleanup verification failed for ${O.legacyPath}`),!1;return H(j),console.log(`Deleted legacy config at ${O.legacyPath}`),!0}async function Lv(P,O,D,j,J,Y,re,ie,de){try{return wn(D,{version:1,rules:re,overrides:ie,transparent_wrappers:de}),wn(j,Fv(J,O.migratedFrom,Y)),await mo(P,O.syncOptions)}catch(fe){return{ok:!1,errors:[fe instanceof Error?fe.message:String(fe)]}}}function Nv(P){try{let O=JSON.parse(P),D=Ro(O);if(D.errors.length>0)return{ok:!1,errors:D.errors};return{ok:!0,config:{version:1,rules:O.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function jv(P,O,D,j,J){let Y=O.find((re)=>Uv(i(J,go(P,re,"rulebook.json")))===j);if(Y)return Y;if(r(i(J,go(P,D,"rulebook.json")))===null)return D;for(let re=2;;re++){let ie=`${D}-${re}`;if(r(i(J,go(P,ie,"rulebook.json")))===null)return ie}}function Fv(P,O,D){return{rulebook_version:1,name:P,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:O,allowed_commands:[...new Set(D.map((j)=>j.command))],rules:D,tests:D.map((j)=>({command:[j.command,j.subcommand,j.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:j.name}))}}function Hv(P,O,D,j,J){if(!m(P).config?.rules.includes(D))return!1;try{let re=r(O);if(re===null)return!1;let ie=JSON.parse(re);return ie.migrated_from===j&&JSON.stringify(ie.rules)===JSON.stringify(J)}catch{return!1}}function Ru(P){return{target:P,content:r(P)}}function Mv(P){for(let O of P){if(O.content===null){H(O.target);continue}g(O.target,O.content)}}function Uv(P){let O=r(P);if(O===null)return null;try{let D=JSON.parse(O);return typeof D.migrated_from==="string"?D.migrated_from:null}catch{return null}}import{mkdir as Gv,readFile as qv,writeFile as Bv}from"node:fs/promises";import{dirname as Vv,join as Jv}from"node:path";var Wv=86400000,Kv=604800000;async function Tu(P,O=Date.now()){if(P.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let D=We(P);if(!D)return null;let j=Jv(D,".cc-safety-net","update-check.json"),J=await zv(j,O);if(!J.lastCheck||O-J.lastCheck>Wv){let ie=await Gn();if(J.lastCheck=O,ie.latestVersion)J.latestVersion=ie.latestVersion;if(!await _u(j,J))return null;if(ie.error)return null}let Y=J.latestVersion,re=pn();if(!Y||!$o(Y,re))return null;if(J.notifiedVersion===Y&&J.notifiedAt!==void 0&&O-J.notifiedAt<Kv)return null;if(J.notifiedVersion=Y,J.notifiedAt=O,!await _u(j,J))return null;return`UPDATE_AVAILABLE: cc-safety-net v${Y} is available (running v${re}). Ask the user once whether to run \`npx -y cc-safety-net@latest update\`; continue the current task either way and do not raise this again.`}async function zv(P,O){let D=await qv(P,"utf8").then((Y)=>JSON.parse(Y)).catch(()=>{return});if(!D||typeof D!=="object"||Array.isArray(D))return{};let j=D,J=(Y)=>typeof Y==="number"&&Number.isFinite(Y)&&Y<=O?Y:void 0;return{lastCheck:J(j.lastCheck),latestVersion:typeof j.latestVersion==="string"?j.latestVersion:void 0,notifiedVersion:typeof j.notifiedVersion==="string"?j.notifiedVersion:void 0,notifiedAt:J(j.notifiedAt)}}async function _u(P,O){return Gv(Vv(P),{recursive:!0,mode:448}).then(()=>Bv(P,JSON.stringify(O),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as Yv,resolve as is}from"node:path";var Au="CC Safety Net Config",Zv="═".repeat(Au.length),Xv="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",Qv=new Set(["rule.json","rule.lock","cache"]);function Iu(P,O={}){try{return eb(P,O)}catch(D){if(D instanceof o)return console.error(D.message),1;throw D}}function eb(P,O){let D=O.cwd??process.cwd(),j=X(P,{cwd:D}),J=Ct(P),Y=vr(D),re=is(D,he),ie=i(j.userScope,J),de=i(j.projectScope,Y),fe=!1,we=!1,Ce=[],Se=[],Ie=nb(i(j.projectScope,re));if(rb(),r(j.userConfigTarget)!==null){let Ee=Un(j.userConfigTarget);if(Ee.errors.push(...B(j.userConfigPath,j.userScope)),Ce.push({scope:"User",path:j.userConfigPath,result:Ee,schema:"rules",target:j.userConfigTarget}),Ee.errors.length>0)fe=!0}if(r(ie)!==null)if(we=!0,r(j.userConfigTarget)!==null)Se.push(yo("user","cleanup"));else{let Ee=Eo(ie);if(Ce.push({scope:"User",path:J,result:Ee,schema:"legacy",inactive:!0,target:ie}),Se.push(yo("user",Ee.errors.length>0?"fix-or-delete":"migrate")),Ee.errors.length>0)fe=!0}if(r(j.projectConfigTarget)!==null){let Ee=Un(j.projectConfigTarget);if(Ee.errors.push(...B(j.projectConfigPath,j.projectScope)),Ce.push({scope:"Project",path:is(j.projectConfigPath),result:Ee,schema:"rules",target:j.projectConfigTarget}),Ee.errors.length>0)fe=!0;if(r(de)!==null)we=!0,Se.push(yo("project","cleanup"))}else if(r(de)!==null){we=!0,fe=!0;let Ee=Eo(de);Ce.push({scope:"Project",path:is(Y),result:Ee,schema:"legacy",inactive:!0,target:de}),Se.push(yo("project",Ee.errors.length>0?"fix-or-delete":"migrate"))}if(Ie?.result.errors.length)fe=!0;if(Ce.length===0&&!Ie)return console.log(`
277
- No config files found. Using built-in rules only.`),0;for(let Ee of Ce)if(Ee.inactive)ib(Ee.scope,Ee.path,Ee.result);else if(Ee.result.errors.length>0)sb(Ee.scope,Ee.path,Ee.result.errors);else{if(Ee.schema==="rules"&&cb(Ee.target))console.log(`
278
- Added $schema to ${Ee.scope.toLowerCase()} config.`);ob(Ee.scope,Ee.path,Ee.result,Ee.schema)}for(let Ee of Se)console.error(`
279
- ${nn.red(Ee)}`);if(Ie)if(Ie.result.errors.length>0)lb(Ie.path,Ie.result.errors);else ab(Ie.path,Ie.result);if(fe)return console.error(`
276
+ Check that every parent path component is a directory.`;return O}import{mkdirSync as sv}from"node:fs";import{dirname as av}from"node:path";import{createInterface as lv}from"node:readline";import{existsSync as Yd,readFileSync as nv}from"node:fs";function vt(P,O){let D=tt(P,O);return{policy:D.policy,errors:ce(Xe(D.issues,et,(j)=>j.kind==="custom")," "," ")}}function lr(P,O){return vt(P,O).errors}function zd(P,O){return{"safety.level":P.safety.level,...ss("safety.overrides",P.safety.overrides),"workflow.worktree_mode":String(P.workflow.worktree_mode),"destructive_command_protection.enabled":String(P.destructive_command_protection.enabled),...ss("destructive_command_protection.overrides",P.destructive_command_protection.overrides),"destructive_command_protection.allow_paths":as(P.destructive_command_protection.allow_paths),"secret_protection.enabled":String(P.secret_protection.enabled),...ss("secret_protection.overrides",P.secret_protection.overrides),"secret_protection.deny_paths":as(P.secret_protection.deny_paths),"secret_protection.allow_paths":as(P.secret_protection.allow_paths),...O?{"audit.retention_days":String(P.audit.retention_days)}:{}}}function uo(P,O,D){let j=zd(P,D),J=zd(O,D);return[...new Set([...Object.keys(j),...Object.keys(J)])].flatMap((Y)=>j[Y]===J[Y]?[]:[{field:Y,before:j[Y],after:J[Y]}])}function cr(P,O){let D=l(P,O);if(!Yd(D))return{baseline:E(globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__,P.home),diagnostics:[]};let j=bt(D),J=vt(j.value,P.home);return{baseline:J.policy,diagnostics:j.errors.length>0?j.errors:J.errors}}function bt(P){if(!Yd(P))return{errors:[`${P}: file not found`]};try{return{value:JSON.parse(nv(P,"utf-8")),errors:[]}}catch(O){let D=O instanceof Error?O.message:String(O);return{errors:[`${P}: ${O instanceof SyntaxError?`Invalid JSON: ${D}`:D}`]}}}function po(P,O){let D=tv(P)?P:{};return{version:O.version,...Object.fromEntries(["safety","workflow","destructive_command_protection","secret_protection"].filter((j)=>D[j]!==void 0).map((j)=>[j,D[j]]))}}function ss(P,O){return Object.fromEntries(Object.entries(O).flatMap(([D,j])=>j===void 0?[]:[[`${P}.${D}`,String(j)]]))}function as(P){return P.length===0?"(none)":P.join(", ")}function tv(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{chmodSync as rv,existsSync as Zd,mkdirSync as ov,readFileSync as Xd}from"node:fs";import{dirname as iv}from"node:path";function Qd(P,O={}){let D=l(P,O);if(!Zd(D))return{path:D,exists:!1,raw:"",policy:F(),errors:[]};let j=Xd(D,"utf-8");if(!j.trim())return{path:D,exists:!0,raw:j,policy:F(),errors:["Config file is empty"]};try{let J=vt(JSON.parse(j),P.home);return{path:D,exists:!0,raw:j,policy:J.policy,errors:J.errors}}catch(J){return{path:D,exists:!0,raw:j,policy:F(),errors:[`Invalid JSON: ${J instanceof Error?J.message:String(J)}`]}}}function Hn(P,O,D={}){let j=l(P,D),J=vt(O,P.home);if(J.errors.length>0)return{path:j,policy:F(),errors:J.errors};let Y=J.policy;return ov(iv(j),{recursive:!0,mode:448}),g(se(j),`${JSON.stringify(Y,null,2)}
277
+ `,384),rv(j,384),{path:j,policy:Y,errors:[]}}function eu(P,O){let D=vt(O,P.home);if(D.errors.length>0)return{errors:D.errors};return{preview:Le(D.policy,P.env),errors:[]}}function nu(P,O={}){let D=l(P,O);if(!Zd(D))return Hn(P,te,O);let j=Xd(D,"utf-8");if(!j.trim())return Hn(P,te,O);try{return Hn(P,E(JSON.parse(j),P.home),O)}catch{return Hn(P,te,O)}}var tu=new Set(["check","apply"]),ru="(unset)";async function iu(P,O,D={}){let j=yn({label:"policy",booleans:{global:["-g","--global"]},positionals:"list"},O),J=j.positionals[0],Y=[...j.errors,...J&&!tu.has(J)?[`Unknown policy subcommand: ${J}`]:[],...J&&tu.has(J)&&!j.positionals[1]?[`policy ${J} requires a file`]:[],...j.positionals.slice(2).map((Ve)=>`Unexpected policy argument: ${Ve}`)];if(Y.length>0){for(let Ve of Y)console.error(Ve);return 1}let re=j.positionals[1];if(!J||!re)return Lt(yr,console.error),1;let ie=D.cwd??process.cwd(),de=j.flags.global?l(P):h(ie);if(!j.flags.global&&L(P,{cwd:ie}))return console.error(`${de} is the user policy, not a project policy; use --global for the user scope, or run from a project directory`),1;let fe=bt(re),we=[...fe.errors,...lr(fe.value,P.home).map((Ve)=>`${re}: ${Ve}`),...!j.flags.global&&uv(fe.value)&&fe.value.audit!==void 0?[`${re}: audit settings are user scope only; remove the audit section from a project proposal`]:[]];if(we.length>0){for(let Ve of we)console.error(Ve);return 1}let Ce=E(fe.value,P.home);if(console.log(`Scope: ${j.flags.global?"user":"project"} (${de})`),console.log(`Proposal: ${re}`),j.flags.global)ou(E(bt(de).value,P.home),Ce,!0);if(!j.flags.global){let Ve=cr(P).baseline;console.log("Effective policy (user + project merged):"),ou(ee(Ve,ue(bt(de).value,P.home).policy).policy,ee(Ve,ue(fe.value,P.home).policy).policy,!1)}if(J==="check")return 0;let Se=D.input??process.stdin,Ie=D.output??process.stdout;if(!Se.isTTY||!Ie.isTTY)return console.error("policy apply confirms interactively; run this yourself in a terminal:"),console.error(` cc-safety-net policy apply ${re}${j.flags.global?" --global":""}`),1;if(!await cv(`Apply this policy to ${de}? [y/N] `,Se,Ie))return console.log("Cancelled; nothing was written."),0;return dv(P,de,fe.value,Ce,j.flags.global),console.log(`Policy applied: ${de}`),0}function cv(P,O,D){let j=lv({input:O,output:D,terminal:!1});return new Promise((J)=>{j.once("close",()=>J(!1)),j.question(P,(Y)=>{J(/^y(es)?$/i.test(Y.trim())),j.close()})})}function dv(P,O,D,j,J){if(J){Hn(P,j);return}sv(av(O),{recursive:!0}),wn(O,po(D,j))}function ou(P,O,D){let j=uo(P,O,D);if(j.length===0){console.log("No changes.");return}console.log(`Changes (${j.length}):`);for(let J of j)console.log(` ${J.field}: ${J.before??ru} -> ${J.after??ru}`)}function uv(P){return!!P&&typeof P==="object"&&!Array.isArray(P)}import{join as Sb}from"node:path";var su="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Priority |\n|-------|-------------|---------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | Second |\n| GitHub source | Listed in a local `rule.json` | Vendored into the consumer's `<rulebook-name>/rulebook.json` by `rule add` | Source order |\n\nEvery rulebook is a live file: the runtime reads it on each tool call, so an edit applies to the next command with no publishing step.\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule verify` reports the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- `caffeinate`, `exec`, `nice`, `nohup`, `setsid`, `stdbuf`, `time`, and `timeout` are built-in transparent wrappers and need no configuration. Configure only other wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n\n## Rulebook Sources\n\n- Local sources are bare rulebook names such as `project-rules`; the rulebook file is `.cc-safety-net/rules/project-rules/rulebook.json`.\n- Run `cc-safety-net rule add owner/repo` to add every rulebook currently present on the repository's default branch.\n- Use `--only` to select one or more rulebooks while preserving their order: `cc-safety-net rule add owner/repo --only aws gcloud`.\n- Use `--ref` to select a branch, tag, or commit instead of the default branch: `cc-safety-net rule add owner/repo --ref v2 --only aws`.\n- GitHub sources are stored in canonical form as `owner/repo#ref/<rulebook-name>`. That form remains valid in `rule.json` and as direct CLI input.\n- GitHub refs may contain `/`-separated path segments, such as `feature/rulebook-v2`.\n- The GitHub source name, the repository directory name, and the rulebook `name` must match exactly.\n- Rulebook source strings must be unique in a config.\n\n## rulebook.json Schema\n\n```json\n{\n \"rulebook_version\": 1,\n \"name\": \"project-rules\",\n \"version\": \"1.0.0\",\n \"description\": \"Project-specific CC Safety Net rules.\",\n \"author\": \"project\",\n \"allowed_commands\": [\"docker\"],\n \"rules\": [\n {\n \"name\": \"block-docker-system-prune\",\n \"command\": \"docker\",\n \"subcommand\": \"system\",\n \"block_args\": [\"prune\"],\n \"reason\": \"Use targeted cleanup instead.\"\n }\n ],\n \"tests\": [\n {\n \"command\": \"docker system prune\",\n \"expect\": \"blocked\",\n \"rule\": \"block-docker-system-prune\"\n },\n {\n \"command\": \"docker ps\",\n \"expect\": \"allowed\"\n }\n ]\n}\n```\n\n### Rulebook Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `rulebook_version` | Yes | Must be `1` or `2` |\n| `name` | Yes | `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` |\n| `version` | Yes | Non-empty string |\n| `description` | No | Free text; not type-checked at runtime |\n| `author` | No | Free text; not type-checked at runtime |\n| `allowed_commands` | Yes | Unique command names matching `^[a-zA-Z][a-zA-Z0-9_-]*$` |\n| `rules` | Yes | Array of rule objects |\n| `tests` | No | Array of fixtures |\n\n### Rule Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Unique within the rulebook (case-insensitive); same pattern as rulebook `name` |\n| `command` | Yes | Must be listed in `allowed_commands`; basename only, not path |\n| `subcommand` | No | Same pattern as `command`; omit to match any subcommand |\n| `intent` | No | One of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain` |\n| `block_args` | Yes | Non-empty array of non-empty strings |\n| `reason` | Yes | Non-empty string, max 256 chars |\n\n### Rule Fields (`rulebook_version` 2)\n\nVersion 2 replaces `subcommand` and `block_args` with an exact-token `match` object. Version 1 rulebooks keep their fields and their behavior; a client that does not support version 2 rejects the rulebook instead of applying broader version 1 semantics.\n\n```json\n{\n \"name\": \"block-terraform-apply-destroy\",\n \"command\": \"terraform\",\n \"match\": {\n \"command_path\": [\"apply\"],\n \"any_args\": [\"-destroy\", \"--destroy\"]\n },\n \"reason\": \"Review a destroy plan first with 'terraform plan -destroy'.\",\n \"intent\": \"use_alternative\"\n}\n```\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Same as version 1 |\n| `command` | Yes | Same as version 1 |\n| `match.command_path` | Yes | Non-empty array of non-empty command words |\n| `match.any_args` | No | Non-empty array of unique non-empty argument tokens |\n| `match.exclude_args` | No | Non-empty array of unique non-empty argument tokens |\n| `intent` | No | Same as version 1 |\n| `reason` | Yes | Same as version 1 |\n\n### Matching Behavior (`rulebook_version` 2)\n\n- **Command**: Normalized to lowercase basename, as in version 1.\n- **Command path**: After recognized global options and their values are skipped, the next command words must equal `command_path` exactly. AWS, gcloud, and Azure CLI value-taking global options are built in; Terraform's `-chdir=dir` is `=`-joined and is skipped with its own token.\n- **Unrecognized options**: A token starting with `-` that is not a recognized global option is skipped without consuming a value, so an unlisted value-taking option with a separate value (`--newflag value`) makes the rule miss. This fails open deliberately; document such gaps in the rulebook.\n- **`any_args`**: At least one listed token must appear literally among the arguments.\n- **`exclude_args`**: Any listed token appearing literally among the arguments prevents the match, which is how a safe preview such as `aws s3 rm --dryrun` stays allowed.\n- **No short-option expansion**: Arguments compare as exact tokens, so list every accepted spelling (`\"-destroy\"` and `\"--destroy\"`).\n- **Literal and case-sensitive**: No regex, glob, or substring matching. The first matching rule wins.\n- Release channels are separate rules: `gcloud beta compute instances delete` needs its own `command_path`.\n\n### Test Fixture Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `command` | Yes | Non-empty shell command string |\n| `expect` | Yes | `\"blocked\"` or `\"allowed\"` |\n| `rule` | Required for blocked fixtures | Rule name expected to block the command |\n\nFixtures are optional documentation of intended behavior. Version 1 fixtures are shape-validated only. Version 2 fixtures are evaluated against the rulebook's own rules when a source is fetched by `rule add` or `rule update`, and by `rule verify`; a failing fixture rejects that source before it is written. Loading a rulebook does not re-evaluate fixtures. CC Safety Net never executes fixture commands; they are analyzer inputs only.\n\n## Matching Behavior\n\nThe subcommand, argument, and option rules below describe `rulebook_version` 1 rules; version 2 rules match as described in Matching Behavior (`rulebook_version` 2). Execution order and transparent wrappers apply to both.\n\n- **Command**: Normalized to lowercase basename with any trailing `.exe` removed (`/usr/bin/git` → `git`).\n- **Subcommand**: The first command token after recognized Git and Docker global options and their values; `--` ends option parsing. An unrecognized option without `=` may consume the following token as its value.\n- **Arguments**: Each `block_args` value is compared literally against every command token, including expanded short options. The command is blocked if **any** item matches.\n- **Short options**: Expanded (`-Ap` matches `-A`).\n- **Long options**: Exact match (`--all-files` does not match `--all`).\n- **Execution order**: Built-in rules first, then custom rulebooks. Custom rules only add restrictions.\n- **Transparent wrappers**: A configured wrapper such as `rtk` lets `rtk git commit` be analyzed as `git commit` only when `git` is protected by built-in analyzers or active custom rules. `rtk -- git commit` is also supported.\n\n## Workflow\n\n1. Run `cc-safety-net rule init` or create `rule.json` manually.\n2. Optionally run `cc-safety-net rule init --example` to create an inactive example rulebook.\n3. Use `cc-safety-net rule wrapper add rtk` for trusted transparent wrappers.\n4. Run `cc-safety-net rule add <source>` after creating or choosing a rulebook source; add `--only <rulebook...>` or `--ref <ref>` for repository selection. The command adds the selected sources and syncs them.\n5. Edit a local rulebook whenever you like: the edit is enforced on the next command, so there is nothing to run afterwards.\n6. Run `cc-safety-net rule update [source]` to re-fetch remote sources and rewrite the vendored copies; the command prints what changed. A source with an ordinary update failure keeps its vendored copy while the other selected sources still update. Resource-limit failures remain fatal for the whole update.\n7. Run `cc-safety-net rule verify` to validate config, local rulebooks, and shareable GitHub-source rulebook directories in the current repository (it does not fetch remote content).\n8. Run `cc-safety-net rule list` to inspect active rulebooks and transparent wrappers.\n\nA missing or invalid rulebook file makes that source inactive, and an unreadable or invalid `rule.json` makes every source in its scope inactive. Inactive sources stop applying their rules while other custom rules and all built-in protections stay active. Fix the file named in the diagnostic, or run `cc-safety-net rule update` when a remote source has not been vendored yet. Run `cc-safety-net status` to see degraded sources.\n";function fo(P,O){if(!P.ok){uu(P);return}cu(P,O)}function lu(P,O,D){if(P.ok)console.log(D);if(!P.add){fo(P,`Added rulebook source: ${O}`);return}if(!P.ok){uu(P);return}if(P.add.added.length>0)console.log(`Added ${P.add.added.length} ${P.add.added.length===1?"rulebook":"rulebooks"} from ${P.add.source} at ${P.add.ref}:`),P.add.added.forEach((j)=>{console.log(` - ${j}`)});if(P.add.alreadyConfigured.length>0)console.log(`Rulebooks already configured from ${P.add.source} at ${P.add.ref}: ${P.add.alreadyConfigured.join(", ")}`);if(P.add.commits.length>0)console.log(`Vendored at ${P.add.commits.map((j)=>j.slice(0,7)).join(", ")}.`);cu(P,"Rule config updated.")}function cu(P,O){for(let D of P.changes??[])console.log(D);console.log(O),console.log(""),pv(P.entries)}function pv(P){if(P.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${P.length}):`);for(let O of P)console.log(` - ${O.name} ${O.version} (${fv(O.ruleCount)})`),console.log(` Source: ${O.spec}`)}function fv(P){return`${P} ${P===1?"rule":"rules"}`}function du(P){wt("Active sources",P.rulebooks,(O)=>[`[${O.source}] ${O.name} ${O.version}`,` Source: ${O.spec}`]),wt("Active rules",P.rules,(O)=>[`[${gv(P,O.name)}] ${O.name}`,...mv(O),` Reason: ${O.reason}`]),wt("Disabled rules",au(P,"off"),(O)=>[O.key]),wt("Reason overrides",au(P,"reason"),(O)=>[O.key,` Reason: ${O.value.reason}`]),wt("Transparent wrappers",P.transparent_wrappers,(O)=>[O]),wt("Issues",P.errors,(O)=>[O]),wt("Warnings",P.warnings,(O)=>[O])}function wt(P,O,D){if(O.length===0){console.log(`${P}: (none)`);return}console.log(`${P} (${O.length}):`);for(let j of O){let[J,...Y]=D(j);console.log(` - ${J}`);for(let re of Y)console.log(` ${re}`)}}function mv(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 gv(P,O){return P.rulebooks.find((D)=>D.rules.includes(O))?.source??"project"}function au(P,O){return Object.entries({...P.userConfig?.overrides,...P.projectConfig?.overrides}).filter((D)=>{if(O==="off")return D[1]==="off";return!!D[1]&&typeof D[1]==="object"}).map(([D,j])=>({key:D,value:j}))}function uu(P){for(let O of P.errors)console.error(O)}import{dirname as Du,join as ko}from"node:path";import{join as ps,resolve as Ev}from"node:path";function ls(P){let O=m(P);if(O.errors.length>0)return{ok:!1,result:{ok:!1,errors:O.errors,entries:[]}};return{ok:!0,config:O.config??ut}}function pu(P){wn(P,{version:1,rules:[],overrides:{},transparent_wrappers:[]})}function fu(P){wn(P,{rulebook_version:1,name:"example-rules",version:"1.0.0",description:"Project-specific CC Safety Net rules.",author:"project",allowed_commands:["docker"],rules:[{name:"block-docker-system-prune",command:"docker",subcommand:"system",block_args:["prune"],reason:"Use targeted cleanup instead."}],tests:[{command:"docker system prune",expect:"blocked",rule:"block-docker-system-prune"}]})}import{dirname as ho}from"node:path";var yv="custom.";function mo(P){if(P.rulebook_version!==2)return[];let O=P.rules.map((D)=>({name:D.name,command:D.command,block_args:[],match:D.match,reason:D.reason,intent:D.intent}));return(P.tests??[]).flatMap((D,j)=>{let J=cs(y(D.command));if(J.length===0)return[`tests[${j}]: could not parse fixture command: ${D.command}`];let Y=J.reduce((re,ie)=>re??A(ie,O)?.id.slice(yv.length),void 0);if(D.expect==="blocked"){if(Y===D.rule)return[];let re=Y?`"${Y}" matched first`:"no rule matched";return[`tests[${j}]: expected "${D.rule}" to block "${D.command}" but ${re}`]}return Y?[`tests[${j}]: expected "${D.command}" to be allowed but "${Y}" matched`]:[]})}function cs(P){return P.nodes.flatMap((O)=>{if(O.kind==="group"||O.kind==="function")return cs(O.body);if(O.kind!=="command")return[];let D=ve(ne(O.dialect,O.words)).words.map(t);return[...D.length>0?[D]:[],...O.nested.flatMap((j)=>cs(j))]})}var go=Object.freeze({concurrency:4,maxRequests:131,maxResponseBytes:67108864});function yo(P={}){return{requests:0,responseBytes:0,maxRequests:P.maxRequests??go.maxRequests,maxResponseBytes:P.maxResponseBytes??go.maxResponseBytes}}function Mn(P){return{controller:new AbortController,budget:yo(),resolveUrl:P}}function mu(P){return P instanceof Error&&P.message==="Rule synchronization exceeds CC Safety Net's safe resource limits."}function gu(P){if(P.requests>=P.maxRequests)throw Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.requests++}function yu(P,O){if(O>P.maxResponseBytes-P.responseBytes)throw P.responseBytes+=O,Error("Rule synchronization exceeds CC Safety Net's safe resource limits.");P.responseBytes+=O}var bu=Object.freeze({timeoutMs:15000,metadataBytes:524288,commitBytes:262144,treeBytes:16777216,rawBytes:4194304});async function hu(P,O,D=S(ho(ho(O)),"rules policy"),j=Mn()){if(w(P))return wv(P,j);return bv(P,O,D)}async function wu(P,O,D,j,J,Y){if(!w(P))return hu(P,O,D,j);let re=J?null:hv(P,O,D);if(re)return re;if(!J&&!Y)throw Error(`${P} is not vendored; run rule update ${P} to vendor it`);return hu(P,O,D,j)}function hv(P,O,D=S(ho(ho(O)),"rules policy")){let j=N(P),J=M(O,j.name),Y=r(i(D,J));if(Y===null)return null;let re=le(ds(Y,`Invalid rulebook ${J}.`));if(re.name!==j.name)throw Error(`rulebook name "${re.name}" in ${J} must match "${j.name}"`);return{spec:P,rulebook:re,content:Y}}async function ku(P,O={}){if(!Z(P))throw Error(`Invalid GitHub repository source: ${P}`);let[D,j]=P.split("/");if(!D||!j)throw Error(`Invalid GitHub repository source: ${P}`);if(O.ref!==void 0&&!ae(O.ref))throw Error(`GitHub rulebook refs must use valid path segments: ${O.ref}`);let J=O.operation??Mn(),Y=O.ref??await vv(D,j,P,J),re=await Cu(D,j,Y,P,J),ie=await vo(`https://api.github.com/repos/${D}/${j}/git/trees/${re}?recursive=1`,"tree",J),de=ie.response;if(!de.ok)throw Error(`Failed to inspect ${P}: GitHub tree returned ${de.status}`);let fe=JSON.parse(ie.content);if(!Array.isArray(fe?.tree))throw Error(`Failed to inspect ${P}: unexpected GitHub tree response`);let we=fe.tree,Ce=[...new Set(we.flatMap((Se)=>{if(!Se||typeof Se!=="object")return[];let Ie=Se;if(Ie.type!=="blob"||typeof Ie.path!=="string")return[];let Ee=Ie.path.match(ct);return Ee?.[1]?[Ee[1]]:[]}))].sort();if(Ce.length===0)throw Error(`No rulebooks found in ${P} under ${he}/`);return{source:P,owner:D,repo:j,ref:Y,commit:re,names:Ce}}async function vv(P,O,D,j){let J=await vo(`https://api.github.com/repos/${P}/${O}`,"metadata",j),Y=J.response;if(!Y.ok)throw Error(`Failed to inspect ${D}: GitHub returned ${Y.status}`);let ie=JSON.parse(J.content)?.default_branch;if(typeof ie!=="string"||ie==="")throw Error(`Failed to inspect ${D}: missing default branch`);if(!ae(ie))throw Error(`GitHub returned an invalid default branch: ${ie}`);return ie}function bv(P,O,D){lt(P);let j=M(O,P),J=r(i(D,j));if(J===null)throw Error(`Rulebook source not found: ${P}`);let Y=xu(ds(J,"Invalid local rulebook source."));if(Y.name!==P)throw Error(`rulebook name "${Y.name}" must match local source "${P}"`);return{spec:P,rulebook:Y,content:J}}async function wv(P,O){let D=N(P),j=await Cu(D.owner,D.repo,D.ref,P,O),J=await vo(`https://raw.githubusercontent.com/${D.owner}/${D.repo}/${j}/${D.path}`,"raw",O),Y=J.response;if(!Y.ok)throw Error(`Failed to fetch ${P}: GitHub raw returned ${Y.status}`);let re=J.content,ie=xu(ds(re,"Invalid GitHub rulebook response."));if(ie.name!==D.name)throw Error(`rulebook name "${ie.name}" must match GitHub source "${D.name}"`);return{spec:P,rulebook:ie,content:re}}function xu(P){let O=le(P),D=mo(O);if(D.length>0)throw Error(D.join("; "));return O}function ds(P,O){try{return JSON.parse(P)}catch{throw Error(O)}}async function Cu(P,O,D,j,J){let Y=await vo(`https://api.github.com/repos/${P}/${O}/commits/${encodeURIComponent(D)}`,"commit",J),re=Y.response;if(!re.ok)throw Error(`Failed to resolve ${j}: GitHub returned ${re.status}`);let ie=JSON.parse(Y.content);if(typeof ie?.sha!=="string"||ie.sha==="")throw Error(`Failed to resolve commit for ${j}`);return ie.sha}async function kv(P,O,D={}){if(D.signal?.aborted)throw D.signal.reason;let j=D.budget??yo(),J=new AbortController,Y=()=>J.abort(D.signal?.reason);D.signal?.addEventListener("abort",Y,{once:!0});let re=!1,ie=setTimeout(()=>{if(J.signal.aborted)return;re=!0,J.abort()},D.timeoutMs??bu.timeoutMs);try{if(D.signal?.aborted)throw D.signal.reason;gu(j);let de=await fetch(P,{signal:J.signal,redirect:"error"});if(!de.ok)return Su(de),{response:de,content:""};return{response:de,content:await xv(de,O,j,()=>J.abort())}}catch(de){if(re)throw Error("GitHub request timed out",{cause:de});if(D.signal?.aborted)throw D.signal.reason;throw de}finally{clearTimeout(ie),D.signal?.removeEventListener("abort",Y)}}function vo(P,O,D){return kv(D.resolveUrl?.(P)??P,O,{budget:D.budget,signal:D.controller.signal})}async function xv(P,O,D=yo(),j){let J=bu[`${O}Bytes`],Y=Number(P.headers.get("content-length"));if(Number.isFinite(Y)&&Y>J)throw Su(P),Error(`GitHub ${O} response exceeds ${J} bytes`);if(!P.body)return"";let re=P.body.getReader(),ie=[],de=0;while(!0){let fe=await re.read();if(fe.done)break;try{yu(D,fe.value.byteLength)}catch(we){throw j?.(),vu(re),we}if(de+=fe.value.byteLength,de>J)throw j?.(),vu(re),Error(`GitHub ${O} response exceeds ${J} bytes`);ie.push(Buffer.from(fe.value))}return Buffer.concat(ie,de).toString("utf-8")}function Su(P){if(!P.body)return;Pu(()=>P.body?.cancel())}function vu(P){Pu(()=>P.cancel())}function Pu(P){try{Promise.resolve(P()).catch(()=>{})}catch{}}var Cv=/^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(.+)$/;function Ru(P,O){let D=Au(P.rules,O);if(D.length>0)return{ok:!0,specs:D};return _u(P.rules,O)}function Eu(P,O){let D=Au(P,O);if(D.length>0)return{ok:!0,specs:D};let j=Pv(P,O);if(j.length>0)return{ok:!0,specs:j};let J=Rv(P,O);if(!J.ok)return J;if(J.specs.length>0)return{ok:!0,specs:J.specs};return _u(P,O)}function _u(P,O){let D=P.filter((j)=>us(j)?.name===O);if(D.length===1)return{ok:!0,specs:D};return Sv(O,D)}function Sv(P,O){return{ok:!1,result:{ok:!1,errors:O.length===0?[`No configured rulebook matches ${P}`]:[`Ambiguous rulebook match ${P}: ${O.join(", ")}`],entries:[]}}}function Au(P,O){return P.filter((D)=>D===O)}function Pv(P,O){let D=O.match(Cv),j=D?.[1],J=D?.[2],Y=D?.[3];if(!j||!J||!Y||!ae(Y))return[];return Tu(P,(re)=>re.owner===j&&re.repo===J&&re.ref===Y)}function Rv(P,O){if(!Z(O))return{ok:!0,specs:[]};let[D,j]=O.split("/"),J=Tu(P,(re)=>re.owner===D&&re.repo===j);if(new Set(J.map((re)=>us(re)?.ref).filter((re)=>!!re)).size<2)return{ok:!0,specs:J};return{ok:!1,result:{ok:!1,errors:[`Multiple refs are configured for ${O}. Use an explicit ref:`,` cc-safety-net rule remove ${O}#<ref>`],entries:[]}}}function us(P){try{return N(P)}catch{return null}}function Tu(P,O){return P.filter((D)=>{let j=us(D);return j?O(j):!1})}async function wo(P,O={}){let D=fs(O);return _v(P,D,await bo(P,D,Mn()))}function _v(P,O,D){if(!D.ok)return D;let j=kn(P,O),J=[...new Set(B(j.configPath,j.filesystemScope))];if(J.length===0)return D;return{ok:!1,errors:J,entries:D.entries}}async function bo(P,O,D,j={},J=new Set,Y=new Set){try{let re=kn(P,O),ie=ls(re.configTarget);if(!ie.ok)return ie.result;let de=ie.config,fe=O.only?Ru(de,O.only):{ok:!0,specs:de.rules};if(!fe.ok)return fe.result;let we=new Set([...O.refresh?fe.specs:[],...J]),Ce=(rn)=>wu(rn,re.configDir,re.filesystemScope,D,we.has(rn),!O.refresh||we.has(rn)),Se=await Hv(de.rules,O.refresh?(rn)=>Ce(rn).then((fn)=>({ok:!0,item:fn})).catch((fn)=>{if(mu(fn))throw fn;return{ok:!1,spec:rn,message:fn instanceof Error?fn.message:String(fn)}}):async(rn)=>({ok:!0,item:await Ce(rn)}),D),Ie=Se.filter((rn)=>!rn.ok),Ee=Se.filter((rn)=>rn.ok).map((rn)=>rn.item),Ve=Ee.flatMap((rn)=>Av(rn,de.rules)),Me=Ee.flatMap((rn)=>Tv(rn,Y,re)),en=new Set([...Ve,...Me].map((rn)=>rn.spec)),on=[...Ie,...Ve,...Me],sn=[],an=$v(sn,()=>Ee.flatMap((rn)=>en.has(rn.spec)||on.length>0&&Y.has(rn.spec)?[]:Iv(rn,re,j,sn)));return{ok:on.length===0,errors:on.map((rn)=>`Failed to update ${rn.spec}: ${rn.message}`),entries:Ee.map(Dv),changes:an}}catch(re){return ur(re)}}function Av(P,O){if(!w(P.spec))return[];let D=Ne(P.spec),j=O.filter((J)=>J!==P.spec&&Ne(J).toLowerCase()===D.toLowerCase());if(j.length===0)return[];return[{ok:!1,spec:P.spec,message:`rulebook name "${D}" is also claimed by ${j.join(", ")}; rename one of them`}]}function Tv(P,O,D){if(!O.has(P.spec)||!w(P.spec))return[];let j=M(D.configDir,P.rulebook.name),J=r(i(D.filesystemScope,j));if(J===null||J===P.content)return[];return[{ok:!1,spec:P.spec,message:`${j} already exists and no configured source claims it; remove or rename the file, then re-run rule add`}]}function Iv(P,O,D,j){if(!w(P.spec))return[];let J=M(O.configDir,P.rulebook.name),Y=i(O.filesystemScope,J),re=r(Y);if(re===P.content)return[];return j?.push({target:Y,previous:re}),g(Y,P.content,void 0,D._testAfterPolicyRename),Ov(P,re)}function $v(P,O){try{return O()}catch(D){for(let j of[...P].reverse()){if(j.previous===null){H(j.target);continue}g(j.target,j.previous)}throw D}}function Ov(P,O){if(O===null)return[`Vendored ${P.spec} (${P.rulebook.version})`];let D=xe(O),j="problem"in D?null:D.rulebook,J=new Map(j?.rules.map((re)=>[re.name,JSON.stringify(re)])??[]),Y=new Set(P.rulebook.rules.map((re)=>re.name));return[`Updated ${P.spec} (${j?.version??"unreadable"} -> ${P.rulebook.version})`,...[...Y].filter((re)=>!J.has(re)).map((re)=>` + ${re}`),...[...J.keys()].filter((re)=>!Y.has(re)).map((re)=>` - ${re}`),...P.rulebook.rules.filter((re)=>{let ie=J.get(re.name);return ie!==void 0&&ie!==JSON.stringify(re)}).map((re)=>` ~ ${re.name}`)]}function Dv(P){return{spec:P.spec,name:P.rulebook.name,version:P.rulebook.version,ruleCount:P.rulebook.rules.length}}async function Iu(P,O,D={}){return Lv(P,O,Uv(D),Mn())}async function Lv(P,O,D,j,J={}){let Y=null,re=!1;try{let ie=kn(P,D),de=r(ie.configTarget);Y={target:ie.configTarget,content:de};let fe=ls(ie.configTarget);if(!fe.ok)return fe.result;let we=fe.config,Ce=Z(O);Nv(O,D,Ce);let Se=Ce?await ku(O,{ref:D.ref,operation:j}):null,Ie=Se?jv(Se,D.rulebooks):[],Ee=Se?Ie.map((sn)=>Fv(we.rules,Se,sn)??`${O}#${Se.ref}/${sn}`):[O],Ve=Ee.filter((sn)=>!we.rules.includes(sn)),Me=[...we.rules,...Ve];if(Me.length>ye)return Mv();if(Me.length!==we.rules.length)re=!0,wn(ie.configTarget,{version:1,rules:Me,overrides:we.overrides??{},transparent_wrappers:we.transparent_wrappers??[]},void 0,J._testAfterPolicyRename);let en=await bo(P,D,j,J,new Set(Ve),new Set(Ve));if(!en.ok)dr(ie.configTarget,de);if(!en.ok||!Se)return en;let on=Ie.filter((sn,an)=>Ve.includes(Ee[an]??""));return{...en,add:{source:O,ref:Se.ref,selected:Ie,added:on,alreadyConfigured:Ie.filter((sn)=>!on.includes(sn)),commits:Ve.length>0?[Se.commit]:[]}}}catch(ie){if(re&&Y)try{dr(Y.target,Y.content)}catch(de){return ur(de)}return ur(ie)}}function Nv(P,O,D){if(!D&&O.rulebooks!==void 0)throw Error("--only can only select rulebooks from an owner/repo source");if(!D&&O.ref)throw Error(`--ref can only select a ref for an owner/repo source: ${P}`);if(O.rulebooks?.length===0)throw Error("--only requires at least one rulebook name");let j=O.rulebooks?.filter((J)=>!d.test(J))??[];if(j.length>0)throw Error(`Invalid rulebook names: ${j.join(", ")}`)}function jv(P,O){let D=O?[...new Set(O)]:P.names,j=D.filter((J)=>!P.names.includes(J));if(j.length>0)throw Error(`Rulebooks not found in ${P.source} at ${P.ref}: ${j.join(", ")}
278
+ Available rulebooks: ${P.names.join(", ")}`);return D}function Fv(P,O,D){let j=`${O.source}#${O.ref}/${D}`;if(P.includes(j))return j;let J=`${O.source}#${O.commit}/${D}`;return P.find((Y)=>Y===J)}async function Hv(P,O,D=Mn()){if(P.length>ye)throw Error(be);let j=[],J=0,Y,re=Array.from({length:Math.min(P.length,go.concurrency)},async()=>{while(!Y){let ie=J;if(ie>=P.length)return;J++;try{j[ie]=await O(P[ie],ie,D.controller.signal)}catch(de){if(!Y)Y={value:de},J=P.length,D.controller.abort(de);return}}});if(await Promise.all(re),Y)throw Y.value;return j}function Mv(){return{ok:!1,errors:[be],entries:[]}}function fs(P){return{cwd:P.cwd,userConfigDir:P.userConfigDir,userConfigPath:P.userConfigPath,projectConfigPath:P.projectConfigPath,global:P.global,only:P.only,refresh:P.refresh}}function Uv(P){return{...fs(P),ref:P.ref,rulebooks:P.rulebooks}}function Gv(P){return{...fs(P),deleteSource:P.deleteSource}}async function $u(P,O,D={}){try{return await qv(P,O,Gv(D),{})}catch(j){return ur(j)}}async function qv(P,O,D,j){let J=kn(P,D),Y=m(J.configTarget);if(Y.errors.length>0)return{ok:!1,errors:Y.errors,entries:[]};if(!Y.config)return{ok:!1,errors:[`No config found at ${J.configPath}`],entries:[]};let re=Eu(Y.config.rules,O);if(!re.ok)return re.result;let ie=D.deleteSource?Bv(J.configDir,re.specs,J.filesystemScope):{ok:!0,dirs:[]};if(!ie.ok)return ie.result;let de=r(J.configTarget);if(de===null)return ur(Error("Rules config is unavailable."));try{wn(J.configTarget,{version:1,rules:Y.config.rules.filter((Ce)=>!re.specs.includes(Ce)),overrides:Y.config.overrides??{},transparent_wrappers:Y.config.transparent_wrappers??[]},void 0,j._testAfterPolicyRename)}catch(Ce){throw dr(J.configTarget,de),Ce}let fe=await bo(P,D,Mn(),j);if(!fe.ok)return dr(J.configTarget,de),fe;let we=Vv(ie.dirs,j,J.filesystemScope);if(!we.ok){dr(J.configTarget,de);let Ce=await bo(P,D,Mn(),j);if(!Ce.ok)return{ok:!1,errors:[...we.result.errors,...Ce.errors],entries:Ce.entries};return we.result}return fe}function Bv(P,O,D){let j=O.flatMap((ie)=>d.test(ie)?[]:["--delete-source can only delete local rulebook sources"]),J=O.map((ie)=>ps(P,ie)),Y=j.length>0?[]:J.flatMap((ie)=>Ou(ie,D)),re=[...j,...Y];return re.length>0?{ok:!1,result:{ok:!1,errors:re,entries:[]}}:{ok:!0,dirs:J}}function Ou(P,O){let D=Ev(P),j=i(O,D),J=me(j);if(!J)return[`Local rulebook source directory not found: ${P}`];let Y=J.find((re)=>re.name==="rulebook.json");if(!Y)return[`Local rulebook source directory is missing rulebook.json: ${P}`];if(Y.kind!=="file")throw new o(O.label);if(r(i(O,ps(D,"rulebook.json"))),J.length>1)return[`Local rulebook source directory contains extra files: ${P}. delete manually if you really want to remove the directory.`];return[]}function Vv(P,O,D){let j=P.flatMap((J)=>{try{if(!me(i(D,J)))return[];let Y=Ou(J,D);if(Y.length>0)return Y;return Jv(J,O,D),[]}catch(Y){return[`Failed to delete local rulebook source ${J}: ${Y instanceof Error?Y.message:String(Y)}`]}});return j.length>0?{ok:!1,result:{ok:!1,errors:j,entries:[]}}:{ok:!0}}function Jv(P,O,D){if(O._testDeleteLocalSourceDir){O._testDeleteLocalSourceDir(P);return}H(i(D,ps(P,ge))),at(i(D,P))}function dr(P,O){if(O===null){H(P);return}g(P,O)}function ur(P){return{ok:!1,errors:[P instanceof Error?P.message:String(P)],entries:[]}}var Kv=".safety-net.json",Wv="~/.cc-safety-net/config.json";async function ju(P,O){let D=L(P,{cwd:O.cwd});if(D)console.log(`Skipped the project scope: ${_(O.cwd)} is the user rule config, not a project rule config`);return[D||await Lu(P,{legacyPath:xa({cwd:O.cwd}),configPath:_(O.cwd),defaultRulebookName:"project-rules",migratedFrom:Kv,cleanup:O.cleanup,syncOptions:{cwd:O.cwd}}),await Lu(P,{legacyPath:Ct(P),configPath:W(P),defaultRulebookName:"user-rules",migratedFrom:Wv,cleanup:O.cleanup,syncOptions:{cwd:O.cwd,global:!0}})].every((J)=>J)?0:1}async function Lu(P,O){let D=kn(P,O.syncOptions),j=i(D.filesystemScope,O.legacyPath),J=r(j);if(J===null)return console.log(`No legacy config found at ${O.legacyPath}`),!0;let Y=Yv(J);if(!Y.ok){for(let Ie of Y.errors)console.error(Ie);return!1}let re=m(D.configTarget);if(re.errors.length>0){for(let Ie of re.errors)console.error(Ie);return!1}let ie=re.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},de=Zv(Du(O.configPath),ie.rules,O.defaultRulebookName,O.migratedFrom,D.filesystemScope),fe=ko(Du(O.configPath),de,"rulebook.json"),we=i(D.filesystemScope,fe),Ce=[Nu(D.configTarget),Nu(we)],Se=await zv(P,O,D.configTarget,we,de,Y.config.rules,ie.rules.includes(de)?ie.rules:[...ie.rules,de],ie.overrides??{},ie.transparent_wrappers??[]);if(!Se.ok){eb(Ce);for(let Ie of Se.errors)console.error(Ie);return!1}if(!O.cleanup)return console.log(`Migrated legacy config at ${O.legacyPath}. Legacy file is no longer used.`),!0;if(!Qv(D.configTarget,we,de,O.migratedFrom,Y.config.rules))return console.error(`Migration cleanup verification failed for ${O.legacyPath}`),!1;return H(j),console.log(`Deleted legacy config at ${O.legacyPath}`),!0}async function zv(P,O,D,j,J,Y,re,ie,de){try{return wn(D,{version:1,rules:re,overrides:ie,transparent_wrappers:de}),wn(j,Xv(J,O.migratedFrom,Y)),await wo(P,O.syncOptions)}catch(fe){return{ok:!1,errors:[fe instanceof Error?fe.message:String(fe)]}}}function Yv(P){try{let O=JSON.parse(P),D=$o(O);if(D.errors.length>0)return{ok:!1,errors:D.errors};return{ok:!0,config:{version:1,rules:O.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function Zv(P,O,D,j,J){let Y=O.find((re)=>nb(i(J,ko(P,re,"rulebook.json")))===j);if(Y)return Y;if(r(i(J,ko(P,D,"rulebook.json")))===null)return D;for(let re=2;;re++){let ie=`${D}-${re}`;if(r(i(J,ko(P,ie,"rulebook.json")))===null)return ie}}function Xv(P,O,D){return{rulebook_version:1,name:P,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:O,allowed_commands:[...new Set(D.map((j)=>j.command))],rules:D,tests:D.map((j)=>({command:[j.command,j.subcommand,j.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:j.name}))}}function Qv(P,O,D,j,J){if(!m(P).config?.rules.includes(D))return!1;try{let re=r(O);if(re===null)return!1;let ie=JSON.parse(re);return ie.migrated_from===j&&JSON.stringify(ie.rules)===JSON.stringify(J)}catch{return!1}}function Nu(P){return{target:P,content:r(P)}}function eb(P){for(let O of P){if(O.content===null){H(O.target);continue}g(O.target,O.content)}}function nb(P){let O=r(P);if(O===null)return null;try{let D=JSON.parse(O);return typeof D.migrated_from==="string"?D.migrated_from:null}catch{return null}}import{mkdir as tb,readFile as rb,writeFile as ob}from"node:fs/promises";import{dirname as ib,join as sb}from"node:path";var ab=86400000,lb=604800000;async function Hu(P,O=Date.now()){if(P.env.get("CC_SAFETY_NET_NO_UPDATE_CHECK"))return null;let D=We(P);if(!D)return null;let j=sb(D,".cc-safety-net","update-check.json"),J=await cb(j,O);if(!J.lastCheck||O-J.lastCheck>ab){let ie=await Gn();if(J.lastCheck=O,ie.latestVersion)J.latestVersion=ie.latestVersion;if(!await Fu(j,J))return null;if(ie.error)return null}let Y=J.latestVersion,re=pn();if(!Y||!Fo(Y,re))return null;if(J.notifiedVersion===Y&&J.notifiedAt!==void 0&&O-J.notifiedAt<lb)return null;if(J.notifiedVersion=Y,J.notifiedAt=O,!await Fu(j,J))return null;return`UPDATE_AVAILABLE: cc-safety-net v${Y} is available (running v${re}). Ask the user once whether to run \`npx -y cc-safety-net@latest update\`; continue the current task either way and do not raise this again.`}async function cb(P,O){let D=await rb(P,"utf8").then((Y)=>JSON.parse(Y)).catch(()=>{return});if(!D||typeof D!=="object"||Array.isArray(D))return{};let j=D,J=(Y)=>typeof Y==="number"&&Number.isFinite(Y)&&Y<=O?Y:void 0;return{lastCheck:J(j.lastCheck),latestVersion:typeof j.latestVersion==="string"?j.latestVersion:void 0,notifiedVersion:typeof j.notifiedVersion==="string"?j.notifiedVersion:void 0,notifiedAt:J(j.notifiedAt)}}async function Fu(P,O){return tb(ib(P),{recursive:!0,mode:448}).then(()=>ob(P,JSON.stringify(O),{mode:384})).then(()=>!0).catch(()=>!1)}import{join as db,resolve as ms}from"node:path";var Mu="CC Safety Net Config",ub="═".repeat(Mu.length),pb="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",fb=new Set(["rule.json","rule.lock","cache"]);function Uu(P,O={}){try{return mb(P,O)}catch(D){if(D instanceof o)return console.error(D.message),1;throw D}}function mb(P,O){let D=O.cwd??process.cwd(),j=X(P,{cwd:D}),J=Ct(P),Y=wr(D),re=ms(D,he),ie=i(j.userScope,J),de=i(j.projectScope,Y),fe=!1,we=!1,Ce=[],Se=[],Ie=gb(i(j.projectScope,re));if(hb(),r(j.userConfigTarget)!==null){let Ee=Un(j.userConfigTarget);if(Ee.errors.push(...B(j.userConfigPath,j.userScope)),Ce.push({scope:"User",path:j.userConfigPath,result:Ee,schema:"rules",target:j.userConfigTarget}),Ee.errors.length>0)fe=!0}if(r(ie)!==null)if(we=!0,r(j.userConfigTarget)!==null)Se.push(xo("user","cleanup"));else{let Ee=Oo(ie);if(Ce.push({scope:"User",path:J,result:Ee,schema:"legacy",inactive:!0,target:ie}),Se.push(xo("user",Ee.errors.length>0?"fix-or-delete":"migrate")),Ee.errors.length>0)fe=!0}if(r(j.projectConfigTarget)!==null){let Ee=Un(j.projectConfigTarget);if(Ee.errors.push(...B(j.projectConfigPath,j.projectScope)),Ce.push({scope:"Project",path:ms(j.projectConfigPath),result:Ee,schema:"rules",target:j.projectConfigTarget}),Ee.errors.length>0)fe=!0;if(r(de)!==null)we=!0,Se.push(xo("project","cleanup"))}else if(r(de)!==null){we=!0,fe=!0;let Ee=Oo(de);Ce.push({scope:"Project",path:ms(Y),result:Ee,schema:"legacy",inactive:!0,target:de}),Se.push(xo("project",Ee.errors.length>0?"fix-or-delete":"migrate"))}if(Ie?.result.errors.length)fe=!0;if(Ce.length===0&&!Ie)return console.log(`
279
+ No config files found. Using built-in rules only.`),0;for(let Ee of Ce)if(Ee.inactive)bb(Ee.scope,Ee.path,Ee.result);else if(Ee.result.errors.length>0)wb(Ee.scope,Ee.path,Ee.result.errors);else{if(Ee.schema==="rules"&&Cb(Ee.target))console.log(`
280
+ Added $schema to ${Ee.scope.toLowerCase()} config.`);vb(Ee.scope,Ee.path,Ee.result,Ee.schema)}for(let Ee of Se)console.error(`
281
+ ${nn.red(Ee)}`);if(Ie)if(Ie.result.errors.length>0)xb(Ie.path,Ie.result.errors);else kb(Ie.path,Ie.result);if(fe)return console.error(`
280
282
  Config validation failed.`),1;return console.log(we?`
281
283
  Configs valid with warnings.`:`
282
- All configs valid.`),0}function yo(P,O){let D=`legacy ${P} config`;if(O==="cleanup")return`Warning: Legacy ${P} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(O==="migrate")return`Warning: Legacy ${P} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${P} config is no longer supported. Fix or delete the ${D}, then run \`npx -y cc-safety-net rule migrate\`.`}function nb(P){if(me(P)===null)return null;let O=tb(P);if(O.ruleNames.size===0&&O.errors.length===0)return null;return{path:P.path,result:O}}function tb(P){let O=[],D=new Set,j=(me(P)??[]).filter((J)=>!Qv.has(J.name)).sort((J,Y)=>J.name.localeCompare(Y.name));if(j.length===0)return{errors:O,ruleNames:D};for(let J of j){if(!d.test(J.name)){O.push(`rulebook directory names must match ${d}: ${J.name}`);continue}if(J.kind!=="directory"){O.push(`${J.name} must be a rulebook directory`);continue}let Y=i(P.scope,Yv(P.path,J.name,"rulebook.json")),re=r(Y);if(re===null){O.push(`${J.name}/rulebook.json is required`);continue}try{let ie;try{ie=JSON.parse(re)}catch{O.push(`${J.name}/rulebook.json: invalid JSON`);continue}let de=le(ie);if(de.name!==J.name){O.push(`rulebook name "${de.name}" must match folder "${J.name}"`);continue}let fe=ao(de);if(fe.length>0){O.push(...fe.map((we)=>`${J.name}/rulebook.json: ${we}`));continue}D.add(J.name)}catch(ie){O.push(ie instanceof Error?`${J.name}/rulebook.json: ${ie.message}`:`${J.name}/rulebook.json: ${String(ie)}`)}}return{errors:O,ruleNames:D}}function rb(){console.log(Au),console.log(Zv)}function ob(P,O,D,j){if(console.log(`
283
- ✓ ${P} config: ${O}`),console.log(` Schema: ${j==="rules"?"rulebook sources":"legacy inline rules"}`),D.ruleNames.size>0){console.log(` ${j==="rules"?"Sources":"Rules"}:`);let J=1;for(let Y of D.ruleNames)console.log(` ${J}. ${Y}`),J++}else console.log(` ${j==="rules"?"Sources":"Rules"}: (none)`)}function ib(P,O,D){if(console.error(`
284
- ✗ Legacy ${P.toLowerCase()} config: ${O}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),D.errors.length>0){console.error(" Errors:");let j=1;for(let J of D.errors)for(let Y of J.split("; "))console.error(` ${j}. ${Y}`),j++;return}if(D.ruleNames.size>0){console.error(" Rules:");let j=1;for(let J of D.ruleNames)console.error(` ${j}. ${J}`),j++;return}console.error(" Rules: (none)")}function sb(P,O,D){$u(`${P} config`,O,D)}function ab(P,O){console.log(`
285
- ✓ GitHub source rules: ${P}`),console.log(" Rulebooks:");let D=1;for(let j of O.ruleNames)console.log(` ${D}. ${j}`),D++}function lb(P,O){$u("GitHub source rules",P,O)}function $u(P,O,D){console.error(`
286
- ✗ ${P}: ${O}`),console.error(" Errors:");let j=1;for(let J of D)for(let Y of J.split("; "))console.error(` ${j}. ${Y}`),j++}function cb(P){try{let O=r(P);if(O===null)return!1;let D=JSON.parse(O);if(D.$schema)return!1;return g(P,JSON.stringify({$schema:Xv,...D},null,2)),!0}catch(O){if(O instanceof o)throw O;return!1}}var Ou=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),ub=new Set(["init","add","remove","update","sync","wrapper"]),pb=new Set(["add","remove","list"]),fb="cc-safety-net/rulebooks";async function Du(P,O){try{return await mb(P,O)}catch(D){if(D instanceof o)return console.error(D.message),1;throw D}}async function mb(P,O){let D=yb(O),j=D.help?gb(D.positionals):null;if(j)return Lt(j),0;if(D.errors.length>0){for(let fe of D.errors)console.error(fe);return 1}let J=D.positionals[0];if(!J)return Lt(xt,console.error),1;let Y=D.positionals[1],re={global:D.global},ie=process.cwd();if(!D.global&&ub.has(J)&&!(J==="wrapper"&&Y==="list")&&L(P,{cwd:ie}))return console.error(`${_(ie)} is the user rule config, not a project rule config; use --global for the user scope, or run from a project directory`),1;if(J==="init"){let fe=kn(P,re);wb(fe.configTarget);let we=db(fe.configDir,"example-rules","rulebook.json"),Ce=i(fe.filesystemScope,we);if(D.example&&r(Ce)===null)ru(Ce);let Se=B(fe.configPath,fe.filesystemScope);for(let Ie of Se)console.error(Ie);if(Se.length>0)return 1;return console.log("Rule config initialized."),0}if(J==="add"){let fe=Lu(D);if(!fe)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let we=kn(P,re),Ce=await ku(P,fe,{...re,ref:D.ref,rulebooks:D.only.length>0?D.only:void 0});return Xd(Ce,fe,`Scope: ${D.global?"user":"project"} (${we.configDir})`),Ce.ok?0:1}if(J==="remove"){if(!Y)return console.error("rule remove requires a source"),1;let fe=await xu(P,Y,{...re,deleteSource:D.deleteSource});return so(fe,`Removed rulebook source: ${Y}`),fe.ok?0:1}if(J==="update"){let fe=await mo(P,{...re,only:Y,refresh:!0});return so(fe,"Rule config updated."),fe.ok?0:1}if(J==="sync")return ga(P,{global:D.global});if(J==="list"){let fe=Q(P,{cwd:ie});return eu(fe),fe.errors.length>0?1:0}if(J==="wrapper")return kb(P,D);if(J==="migrate")return Eu(P,{cleanup:D.cleanup,cwd:ie});if(J==="doc"){console.log(Yd);let fe=await Tu(P);if(fe)console.error(fe);return 0}if(J==="verify")return Iu(P);return 1}function gb(P){if(P.length===0)return xt;let O=xt.subcommands.filter((j)=>j.usage.split(" ")[0]===P[0]);if(O.length===0)return null;if(P.length===1&&O.length>1)return{name:`rule ${P[0]}`,description:`Subcommands of rule ${P[0]}`,usage:`rule ${P[0]} <subcommand>`,subcommands:O,options:[]};let D=P.length===1?O[0]:O.find((j)=>j.usage.split(" ")[1]===P[1]);if(!D)return null;return{name:`rule ${P[0]}`,description:D.description,usage:`rule ${D.usage}`,options:P[0]==="add"?Co:[],examples:P[0]==="add"?So:void 0}}function yb(P){let O=gn({label:"rule",booleans:{global:["-g","--global"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},P),D={...O.flags,ref:O.values.ref,only:O.lists.only??[],help:O.help,positionals:O.positionals,errors:O.errors};return hb(D),D}function hb(P){let[O]=P.positionals;if(O&&!Ou.has(O))P.errors.push(`Unknown rule subcommand: ${O}`);if(P.deleteSource&&O!=="remove")if(O&&Ou.has(O))P.errors.push(`Unknown option for rule ${O}: --delete-source`);else P.errors.push("--delete-source is only valid with 'rule remove'");if(P.cleanup&&O!=="migrate")P.errors.push(dr(O,"--cleanup"));if(P.example&&O!=="init")P.errors.push(dr(O,"--example"));if(P.ref&&O!=="add")P.errors.push(dr(O,"--ref"));if(P.only.length>0&&O!=="add")P.errors.push(dr(O,"--only"));if(O==="add")vb(P);if(O==="migrate"){if(P.global)P.errors.push(dr(O,"--global"));if(P.positionals.length>1)P.errors.push(`Unexpected rule migrate argument: ${P.positionals[1]}`)}else if(O==="wrapper")bb(P);else if(P.positionals.length>2)P.errors.push(`Unexpected rule argument: ${P.positionals[2]}`);if(O==="list"&&P.global)P.errors.push("Unknown option for rule list: --global")}function Lu(P){if(P.positionals[1])return P.positionals[1];if(P.ref||P.only.length>0)return fb;return}function vb(P){let O=Lu(P);if(!O)return;if((P.ref||P.only.length>0)&&!Z(O)){if(P.ref)P.errors.push(`--ref can only select a ref for an owner/repo source: ${O}`);if(P.only.length>0)P.errors.push("--only can only select rulebooks from an owner/repo source");return}if(P.ref&&!ae(P.ref))P.errors.push(`--ref must use valid path segments: ${P.ref}`);let D=P.only.filter((j)=>!d.test(j));if(D.length>0)P.errors.push(`Invalid rulebook names: ${D.join(", ")}`)}function dr(P,O){return P?`Unknown option for rule ${P}: ${O}`:`Unknown option for rule: ${O}`}function bb(P){let O=P.positionals[1],D=P.positionals[2];if(!O){P.errors.push("rule wrapper requires add, remove, or list");return}if(!pb.has(O)){P.errors.push(`Unknown rule wrapper action: ${O}`);return}if(O==="list"){if(D)P.errors.push(`Unexpected rule wrapper argument: ${D}`);return}if(!D){P.errors.push(`rule wrapper ${O} requires a command`);return}if(P.positionals.length>3)P.errors.push(`Unexpected rule wrapper argument: ${P.positionals[3]}`)}function wb(P){if(r(P)===null){tu(P);return}let O=m(P);if(!O.config)return;wn(P,{version:1,rules:O.config.rules,overrides:O.config.overrides??{},transparent_wrappers:O.config.transparent_wrappers??[]})}async function kb(P,O){let D=O.positionals[1],j=O.positionals[2],J=kn(P,{global:O.global}).configTarget;if(D==="list"){let de=m(J);if(de.errors.length>0){for(let fe of de.errors)console.error(fe);return 1}return xb(de.config?.transparent_wrappers??[]),0}if(!j||!C.test(j))return console.error("transparent wrapper must match command pattern"),1;if(Ae(j))return console.error(`reserved command "${j}" cannot be a wrapper`),1;let Y=m(J);if(Y.errors.length>0){for(let de of Y.errors)console.error(de);return 1}let re=Y.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},ie=D==="add"?[...new Set([...re.transparent_wrappers??[],j])]:(re.transparent_wrappers??[]).filter((de)=>de!==j);return wn(J,{version:1,rules:re.rules,overrides:re.overrides??{},transparent_wrappers:ie}),console.log(D==="add"?`Added transparent wrapper: ${j}`:`Removed transparent wrapper: ${j}`),0}function xb(P){if(P.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${P.length}):`);for(let O of P)console.log(` - ${O}`)}import{sep as _b}from"node:path";import{existsSync as Cb,readFileSync as Sb}from"node:fs";import{join as Pb}from"node:path";async function Rb(P){if(P.isTTY)return null;return(await Ke(P).catch(()=>null))?.trim()||null}function Eb(P){let O=P.env.get("CLAUDE_SETTINGS_PATH");if(O)return O;return Pb(_r(P),"settings.json")}function ss(P){let O=Eb(P);if(!Cb(O))return!1;try{let D=Sb(O,"utf-8"),j=JSON.parse(D);if(!j.enabledPlugins)return!1;let J="cc-safety-net@cc-marketplace";if(!(J in j.enabledPlugins))return!1;return j.enabledPlugins[J]===!0}catch(D){if(v(n.debug,P.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${O}: ${D instanceof Error?D.message:String(D)}`);return!1}}async function as(P,O=process.stdin){let D=ss(P),j;if(!D)j="\uD83D\uDEE1️ CC Safety Net ❌";else{let Y=k(P,{cwd:process.cwd()}),re=Y.policy,ie=T(re,P.env),de=Object.values(q(re,ie.capabilities)).some((Ce)=>Ce.changesInherited),fe={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[de?"custom":ie.effectiveLevel],we=Y.policyScopes&&!Y.policyScopes.weakeningsIgnored&&Y.policyScopes.weakenings.length>0?"\uD83D\uDD3B":"";j=`\uD83D\uDEE1️ CC Safety Net ${fe}${ie.worktreeMode?"\uD83C\uDF33":""}${we}${Y.state==="degraded"?"⚠️":""}`}let J=await Rb(O);if(J&&!J.startsWith("{"))console.log(`${J} | ${j}`);else console.log(j)}function Nu(P){let O=k(P,{cwd:process.cwd()}),D=O.policy,j=T(D,P.env),J=!!process.env.NO_COLOR||!process.stdout.isTTY,Y=Math.min(process.stdout.columns||80,100),re=J?"ok":"✔",ie=J?"OFF":"✘",de=(Ve,Me)=>{let en=` ${Ve.padEnd(13)}${Me}`;return(en.length>Y?`${en.slice(0,Y-1)}…`:en).replaceAll(ie,nn.red(ie))},fe=Object.values(q(D,j.capabilities)).some((Ve)=>Ve.changesInherited),we=(Ve)=>Ve===P.home||Ve.startsWith(`${P.home}${_b}`)?`~${Ve.slice(P.home.length)}`:Ve,Ce={ready:nn.green,degraded:nn.yellow}[O.state],Se=O.policyScopes?.weakenings??[],Ie=[...ss(P)?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...O.diagnostics],Ee=J?"-":"·";console.log([`${J?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ce(O.state)}`,"",de("Protection",`destructive ${D.destructiveCommandProtectionEnabled?re:ie} secrets ${D.secretProtection.enabled?re:ie}`),de("Level",fe?`${j.effectiveLevel} (customised)`:j.effectiveLevel),de("Rules",D.rules.length===0?"none active":`${D.rules.length} active`),de("Policy",we(l(P))),...O.policyScopes?[de("Project",we(h(process.cwd())))]:[],...j.worktreeMode?[de("Worktree","relaxations active")]:[],"",...Se.length===0?[]:[O.policyScopes?.weakeningsIgnored?" Project policy (ignored)":" Project policy",...Se.flatMap((Ve)=>Xt(Ve," ",Y-6).map((Me,en)=>en===0?` ${Me}`:Me)),""],...Ie.length===0?[" Everything configured is active."]:[" Not active",...Ie.flatMap((Ve)=>Xt(Ve," ",Y-6).map((Me,en)=>en===0?` ${Ee} ${Me}`:Me)),""," Full report: cc-safety-net doctor"]].join(`
287
- `))}import{spawn as Wu}from"node:child_process";import{randomBytes as Fb}from"node:crypto";import{existsSync as Hb}from"node:fs";import{createServer as Mb}from"node:http";import{Writable as Ub}from"node:stream";var ho=500;function Tb(P){let O=P.filter((J)=>J.decision!=="allow"),D=P.filter((J)=>J.decision==="allow"),j=Math.min(O.length,Math.max(ho-D.length,Math.ceil(ho/2)));return[...O.slice(0,j),...D.slice(0,ho-j)]}function ju(P,O,D=U(P)){if(D)K(P,D);let j=(Me)=>new Date(Me.getFullYear(),Me.getMonth(),Me.getDate()).getTime(),J=j(new Date),Y=new Date(J);Y.setDate(Y.getDate()-(O-1));let re=Y.getTime(),ie=[],de={count:0};for(let Me of D?Wn(D,de):[])for(let en of kt(Me,de)){let on=new Date(en.ts).getTime();if(!Number.isFinite(on))continue;if(on>=re)ie.push(en)}ie.sort((Me,en)=>new Date(en.ts).getTime()-new Date(Me.ts).getTime());let fe=Array.from({length:O},()=>0),we=Array.from({length:O},()=>0),Ce={},Se={},Ie={},Ee=0,Ve=0;for(let Me of ie){let en=Me.agent||"unknown";Ce[en]=(Ce[en]??0)+1;let on=Math.round((J-j(new Date(Me.ts)))/86400000),sn=O-1-on,an=on>=0&&on<O;if(an)we[sn]=(we[sn]??0)+1;if(Me.decision!=="allow"){if(Ee++,Me.ruleId)Se[Me.ruleId]=(Se[Me.ruleId]??0)+1;let rn=ko(Me.segment||Me.command);if(rn)Ie[rn]=(Ie[rn]??0)+1;if(Me.failureStage)Ve++;if(an)fe[sn]=(fe[sn]??0)+1}}return{days:O,logsDir:D,homeDir:P.home,totalInWindow:ie.length,truncated:ie.length>ho,unreadable:de.count,counts:{blocked:Ee,allowed:ie.length-Ee,agents:Ce,blockedByDay:fe,analyzedByDay:we,rules:Se,commands:Ie,errors:Ve},entries:Tb(ie).sort((Me,en)=>new Date(en.ts).getTime()-new Date(Me.ts).getTime())}}import{spawn as Ab}from"node:child_process";import{existsSync as Ib,statSync as Fu}from"node:fs";import{delimiter as $b,join as Ob}from"node:path";var Db=120000,vo="Choose the project folder",Lb=`try
288
- return POSIX path of (choose folder with prompt "${vo}")
284
+ All configs valid.`),0}function xo(P,O){let D=`legacy ${P} config`;if(O==="cleanup")return`Warning: Legacy ${P} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(O==="migrate")return`Warning: Legacy ${P} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${P} config is no longer supported. Fix or delete the ${D}, then run \`npx -y cc-safety-net rule migrate\`.`}function gb(P){if(me(P)===null)return null;let O=yb(P);if(O.ruleNames.size===0&&O.errors.length===0)return null;return{path:P.path,result:O}}function yb(P){let O=[],D=new Set,j=(me(P)??[]).filter((J)=>!fb.has(J.name)).sort((J,Y)=>J.name.localeCompare(Y.name));if(j.length===0)return{errors:O,ruleNames:D};for(let J of j){if(!d.test(J.name)){O.push(`rulebook directory names must match ${d}: ${J.name}`);continue}if(J.kind!=="directory"){O.push(`${J.name} must be a rulebook directory`);continue}let Y=i(P.scope,db(P.path,J.name,"rulebook.json")),re=r(Y);if(re===null){O.push(`${J.name}/rulebook.json is required`);continue}try{let ie;try{ie=JSON.parse(re)}catch{O.push(`${J.name}/rulebook.json: invalid JSON`);continue}let de=le(ie);if(de.name!==J.name){O.push(`rulebook name "${de.name}" must match folder "${J.name}"`);continue}let fe=mo(de);if(fe.length>0){O.push(...fe.map((we)=>`${J.name}/rulebook.json: ${we}`));continue}D.add(J.name)}catch(ie){O.push(ie instanceof Error?`${J.name}/rulebook.json: ${ie.message}`:`${J.name}/rulebook.json: ${String(ie)}`)}}return{errors:O,ruleNames:D}}function hb(){console.log(Mu),console.log(ub)}function vb(P,O,D,j){if(console.log(`
285
+ ✓ ${P} config: ${O}`),console.log(` Schema: ${j==="rules"?"rulebook sources":"legacy inline rules"}`),D.ruleNames.size>0){console.log(` ${j==="rules"?"Sources":"Rules"}:`);let J=1;for(let Y of D.ruleNames)console.log(` ${J}. ${Y}`),J++}else console.log(` ${j==="rules"?"Sources":"Rules"}: (none)`)}function bb(P,O,D){if(console.error(`
286
+ ✗ Legacy ${P.toLowerCase()} config: ${O}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),D.errors.length>0){console.error(" Errors:");let j=1;for(let J of D.errors)for(let Y of J.split("; "))console.error(` ${j}. ${Y}`),j++;return}if(D.ruleNames.size>0){console.error(" Rules:");let j=1;for(let J of D.ruleNames)console.error(` ${j}. ${J}`),j++;return}console.error(" Rules: (none)")}function wb(P,O,D){Gu(`${P} config`,O,D)}function kb(P,O){console.log(`
287
+ ✓ GitHub source rules: ${P}`),console.log(" Rulebooks:");let D=1;for(let j of O.ruleNames)console.log(` ${D}. ${j}`),D++}function xb(P,O){Gu("GitHub source rules",P,O)}function Gu(P,O,D){console.error(`
288
+ ✗ ${P}: ${O}`),console.error(" Errors:");let j=1;for(let J of D)for(let Y of J.split("; "))console.error(` ${j}. ${Y}`),j++}function Cb(P){try{let O=r(P);if(O===null)return!1;let D=JSON.parse(O);if(D.$schema)return!1;return g(P,JSON.stringify({$schema:pb,...D},null,2)),!0}catch(O){if(O instanceof o)throw O;return!1}}var qu=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),Pb=new Set(["init","add","remove","update","sync","wrapper"]),Rb=new Set(["add","remove","list"]),Eb="cc-safety-net/rulebooks";async function Bu(P,O){try{return await _b(P,O)}catch(D){if(D instanceof o)return console.error(D.message),1;throw D}}async function _b(P,O){let D=Tb(O),j=D.help?Ab(D.positionals):null;if(j)return Lt(j),0;if(D.errors.length>0){for(let fe of D.errors)console.error(fe);return 1}let J=D.positionals[0];if(!J)return Lt(xt,console.error),1;let Y=D.positionals[1],re={global:D.global},ie=process.cwd();if(!D.global&&Pb.has(J)&&!(J==="wrapper"&&Y==="list")&&L(P,{cwd:ie}))return console.error(`${_(ie)} is the user rule config, not a project rule config; use --global for the user scope, or run from a project directory`),1;if(J==="init"){let fe=kn(P,re);Db(fe.configTarget);let we=Sb(fe.configDir,"example-rules","rulebook.json"),Ce=i(fe.filesystemScope,we);if(D.example&&r(Ce)===null)fu(Ce);let Se=B(fe.configPath,fe.filesystemScope);for(let Ie of Se)console.error(Ie);if(Se.length>0)return 1;return console.log("Rule config initialized."),0}if(J==="add"){let fe=Vu(D);if(!fe)return console.error("rule add requires a source (pass --only <rulebook...> to select from cc-safety-net/rulebooks)"),1;let we=kn(P,re),Ce=await Iu(P,fe,{...re,ref:D.ref,rulebooks:D.only.length>0?D.only:void 0});return lu(Ce,fe,`Scope: ${D.global?"user":"project"} (${we.configDir})`),Ce.ok?0:1}if(J==="remove"){if(!Y)return console.error("rule remove requires a source"),1;let fe=await $u(P,Y,{...re,deleteSource:D.deleteSource});return fo(fe,`Removed rulebook source: ${Y}`),fe.ok?0:1}if(J==="update"){let fe=await wo(P,{...re,only:Y,refresh:!0});return fo(fe,"Rule config updated."),fe.ok?0:1}if(J==="sync")return Pa(P,{global:D.global});if(J==="list"){let fe=Q(P,{cwd:ie});return du(fe),fe.errors.length>0?1:0}if(J==="wrapper")return Lb(P,D);if(J==="migrate")return ju(P,{cleanup:D.cleanup,cwd:ie});if(J==="doc"){console.log(su);let fe=await Hu(P);if(fe)console.error(fe);return 0}if(J==="verify")return Uu(P);return 1}function Ab(P){if(P.length===0)return xt;let O=xt.subcommands.filter((j)=>j.usage.split(" ")[0]===P[0]);if(O.length===0)return null;if(P.length===1&&O.length>1)return{name:`rule ${P[0]}`,description:`Subcommands of rule ${P[0]}`,usage:`rule ${P[0]} <subcommand>`,subcommands:O,options:[]};let D=P.length===1?O[0]:O.find((j)=>j.usage.split(" ")[1]===P[1]);if(!D)return null;return{name:`rule ${P[0]}`,description:D.description,usage:`rule ${D.usage}`,options:P[0]==="add"?Ao:[],examples:P[0]==="add"?To:void 0}}function Tb(P){let O=yn({label:"rule",booleans:{global:["-g","--global"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},values:{ref:["--ref"]},lists:{only:["--only"]},positionals:"list"},P),D={...O.flags,ref:O.values.ref,only:O.lists.only??[],help:O.help,positionals:O.positionals,errors:O.errors};return Ib(D),D}function Ib(P){let[O]=P.positionals;if(O&&!qu.has(O))P.errors.push(`Unknown rule subcommand: ${O}`);if(P.deleteSource&&O!=="remove")if(O&&qu.has(O))P.errors.push(`Unknown option for rule ${O}: --delete-source`);else P.errors.push("--delete-source is only valid with 'rule remove'");if(P.cleanup&&O!=="migrate")P.errors.push(pr(O,"--cleanup"));if(P.example&&O!=="init")P.errors.push(pr(O,"--example"));if(P.ref&&O!=="add")P.errors.push(pr(O,"--ref"));if(P.only.length>0&&O!=="add")P.errors.push(pr(O,"--only"));if(O==="add")$b(P);if(O==="migrate"){if(P.global)P.errors.push(pr(O,"--global"));if(P.positionals.length>1)P.errors.push(`Unexpected rule migrate argument: ${P.positionals[1]}`)}else if(O==="wrapper")Ob(P);else if(P.positionals.length>2)P.errors.push(`Unexpected rule argument: ${P.positionals[2]}`);if(O==="list"&&P.global)P.errors.push("Unknown option for rule list: --global")}function Vu(P){if(P.positionals[1])return P.positionals[1];if(P.ref||P.only.length>0)return Eb;return}function $b(P){let O=Vu(P);if(!O)return;if((P.ref||P.only.length>0)&&!Z(O)){if(P.ref)P.errors.push(`--ref can only select a ref for an owner/repo source: ${O}`);if(P.only.length>0)P.errors.push("--only can only select rulebooks from an owner/repo source");return}if(P.ref&&!ae(P.ref))P.errors.push(`--ref must use valid path segments: ${P.ref}`);let D=P.only.filter((j)=>!d.test(j));if(D.length>0)P.errors.push(`Invalid rulebook names: ${D.join(", ")}`)}function pr(P,O){return P?`Unknown option for rule ${P}: ${O}`:`Unknown option for rule: ${O}`}function Ob(P){let O=P.positionals[1],D=P.positionals[2];if(!O){P.errors.push("rule wrapper requires add, remove, or list");return}if(!Rb.has(O)){P.errors.push(`Unknown rule wrapper action: ${O}`);return}if(O==="list"){if(D)P.errors.push(`Unexpected rule wrapper argument: ${D}`);return}if(!D){P.errors.push(`rule wrapper ${O} requires a command`);return}if(P.positionals.length>3)P.errors.push(`Unexpected rule wrapper argument: ${P.positionals[3]}`)}function Db(P){if(r(P)===null){pu(P);return}let O=m(P);if(!O.config)return;wn(P,{version:1,rules:O.config.rules,overrides:O.config.overrides??{},transparent_wrappers:O.config.transparent_wrappers??[]})}async function Lb(P,O){let D=O.positionals[1],j=O.positionals[2],J=kn(P,{global:O.global}).configTarget;if(D==="list"){let de=m(J);if(de.errors.length>0){for(let fe of de.errors)console.error(fe);return 1}return Nb(de.config?.transparent_wrappers??[]),0}if(!j||!C.test(j))return console.error("transparent wrapper must match command pattern"),1;if(Ae(j))return console.error(`reserved command "${j}" cannot be a wrapper`),1;let Y=m(J);if(Y.errors.length>0){for(let de of Y.errors)console.error(de);return 1}let re=Y.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},ie=D==="add"?[...new Set([...re.transparent_wrappers??[],j])]:(re.transparent_wrappers??[]).filter((de)=>de!==j);return wn(J,{version:1,rules:re.rules,overrides:re.overrides??{},transparent_wrappers:ie}),console.log(D==="add"?`Added transparent wrapper: ${j}`:`Removed transparent wrapper: ${j}`),0}function Nb(P){if(P.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${P.length}):`);for(let O of P)console.log(` - ${O}`)}import{sep as Gb}from"node:path";import{existsSync as jb,readFileSync as Fb}from"node:fs";import{join as Hb}from"node:path";async function Mb(P){if(P.isTTY)return null;return(await Ke(P).catch(()=>null))?.trim()||null}function Ub(P){let O=P.env.get("CLAUDE_SETTINGS_PATH");if(O)return O;return Hb(Ir(P),"settings.json")}function gs(P){let O=Ub(P);if(!jb(O))return!1;try{let D=Fb(O,"utf-8"),j=JSON.parse(D);if(!j.enabledPlugins)return!1;let J="cc-safety-net@cc-marketplace";if(!(J in j.enabledPlugins))return!1;return j.enabledPlugins[J]===!0}catch(D){if(v(n.debug,P.env))console.error(`CC Safety Net debug: failed to read Claude settings: ${O}: ${D instanceof Error?D.message:String(D)}`);return!1}}async function ys(P,O=process.stdin){let D=gs(P),j;if(!D)j="\uD83D\uDEE1️ CC Safety Net ❌";else{let Y=k(P,{cwd:process.cwd()}),re=Y.policy,ie=T(re,P.env),de=Object.values(q(re,ie.capabilities)).some((Ce)=>Ce.changesInherited),fe={standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[de?"custom":ie.effectiveLevel],we=Y.policyScopes&&!Y.policyScopes.weakeningsIgnored&&Y.policyScopes.weakenings.length>0?"\uD83D\uDD3B":"";j=`\uD83D\uDEE1️ CC Safety Net ${fe}${ie.worktreeMode?"\uD83C\uDF33":""}${we}${Y.state==="degraded"?"⚠️":""}`}let J=await Mb(O);if(J&&!J.startsWith("{"))console.log(`${J} | ${j}`);else console.log(j)}function Ju(P){let O=k(P,{cwd:process.cwd()}),D=O.policy,j=T(D,P.env),J=!!process.env.NO_COLOR||!process.stdout.isTTY,Y=Math.min(process.stdout.columns||80,100),re=J?"ok":"✔",ie=J?"OFF":"✘",de=(Ve,Me)=>{let en=` ${Ve.padEnd(13)}${Me}`;return(en.length>Y?`${en.slice(0,Y-1)}…`:en).replaceAll(ie,nn.red(ie))},fe=Object.values(q(D,j.capabilities)).some((Ve)=>Ve.changesInherited),we=(Ve)=>Ve===P.home||Ve.startsWith(`${P.home}${Gb}`)?`~${Ve.slice(P.home.length)}`:Ve,Ce={ready:nn.green,degraded:nn.yellow}[O.state],Se=O.policyScopes?.weakenings??[],Ie=[...gs(P)?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...O.diagnostics],Ee=J?"-":"·";console.log([`${J?"":"\uD83D\uDEE1️ "}CC Safety Net — ${Ce(O.state)}`,"",de("Protection",`destructive ${D.destructiveCommandProtectionEnabled?re:ie} secrets ${D.secretProtection.enabled?re:ie}`),de("Level",fe?`${j.effectiveLevel} (customised)`:j.effectiveLevel),de("Rules",D.rules.length===0?"none active":`${D.rules.length} active`),de("Policy",we(l(P))),...O.policyScopes?[de("Project",we(h(process.cwd())))]:[],...j.worktreeMode?[de("Worktree","relaxations active")]:[],"",...Se.length===0?[]:[O.policyScopes?.weakeningsIgnored?" Project policy (ignored)":" Project policy",...Se.flatMap((Ve)=>er(Ve," ",Y-6).map((Me,en)=>en===0?` ${Me}`:Me)),""],...Ie.length===0?[" Everything configured is active."]:[" Not active",...Ie.flatMap((Ve)=>er(Ve," ",Y-6).map((Me,en)=>en===0?` ${Ee} ${Me}`:Me)),""," Full report: cc-safety-net doctor"]].join(`
289
+ `))}import{spawn as rp}from"node:child_process";import{randomBytes as Xb}from"node:crypto";import{existsSync as Qb}from"node:fs";import{createServer as ew}from"node:http";import{Writable as nw}from"node:stream";var Co=500;function qb(P){let O=P.filter((J)=>J.decision!=="allow"),D=P.filter((J)=>J.decision==="allow"),j=Math.min(O.length,Math.max(Co-D.length,Math.ceil(Co/2)));return[...O.slice(0,j),...D.slice(0,Co-j)]}function Ku(P,O,D=U(P)){if(D)K(P,D);let j=(Me)=>new Date(Me.getFullYear(),Me.getMonth(),Me.getDate()).getTime(),J=j(new Date),Y=new Date(J);Y.setDate(Y.getDate()-(O-1));let re=Y.getTime(),ie=[],de={count:0};for(let Me of D?Kn(D,de):[])for(let en of kt(Me,de)){let on=new Date(en.ts).getTime();if(!Number.isFinite(on))continue;if(on>=re)ie.push(en)}ie.sort((Me,en)=>new Date(en.ts).getTime()-new Date(Me.ts).getTime());let fe=Array.from({length:O},()=>0),we=Array.from({length:O},()=>0),Ce={},Se={},Ie={},Ee=0,Ve=0;for(let Me of ie){let en=Me.agent||"unknown";Ce[en]=(Ce[en]??0)+1;let on=Math.round((J-j(new Date(Me.ts)))/86400000),sn=O-1-on,an=on>=0&&on<O;if(an)we[sn]=(we[sn]??0)+1;if(Me.decision!=="allow"){if(Ee++,Me.ruleId)Se[Me.ruleId]=(Se[Me.ruleId]??0)+1;let rn=Eo(Me.segment||Me.command);if(rn)Ie[rn]=(Ie[rn]??0)+1;if(Me.failureStage)Ve++;if(an)fe[sn]=(fe[sn]??0)+1}}return{days:O,logsDir:D,homeDir:P.home,totalInWindow:ie.length,truncated:ie.length>Co,unreadable:de.count,counts:{blocked:Ee,allowed:ie.length-Ee,agents:Ce,blockedByDay:fe,analyzedByDay:we,rules:Se,commands:Ie,errors:Ve},entries:qb(ie).sort((Me,en)=>new Date(en.ts).getTime()-new Date(Me.ts).getTime())}}import{spawn as Bb}from"node:child_process";import{existsSync as Vb,statSync as Wu}from"node:fs";import{delimiter as Jb,join as Kb}from"node:path";var Wb=120000,So="Choose the project folder",zb=`try
290
+ return POSIX path of (choose folder with prompt "${So}")
289
291
  on error number -128
290
292
  return ""
291
- end try`,Nb=`Add-Type -AssemblyName System.Windows.Forms
293
+ end try`,Yb=`Add-Type -AssemblyName System.Windows.Forms
292
294
  $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
293
- $dialog.Description = '${vo}'
294
- if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,Hu=[{binary:"zenity",args:["--file-selection","--directory",`--title=${vo}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",vo]}],Mu=(P,O)=>(O.PATH??"").split($b).some((D)=>{if(D.length===0)return!1;try{let j=Fu(Ob(D,P));return j.isFile()&&(j.mode&73)!==0}catch{return!1}});function ls(P,O){if(P==="darwin"||P==="win32")return!0;if(P!=="linux")return!1;if(!O.DISPLAY&&!O.WAYLAND_DISPLAY)return!1;return Hu.some((D)=>Mu(D.binary,O))}function jb(P,O){if(P==="darwin")return{cmd:"osascript",args:["-e",Lb]};if(P==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",Nb]};let D=Hu.find((j)=>Mu(j.binary,O));return D?{cmd:D.binary,args:D.args}:null}function cs(P=process.platform,O=process.env){let D=jb(P,O);if(!D)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((j)=>{let J=Ab(D.cmd,D.args,{env:O,stdio:["ignore","pipe","pipe"]}),Y="",re=!1,ie=(fe)=>{if(re)return;re=!0,clearTimeout(de),j(fe)},de=setTimeout(()=>{J.kill(),ie({error:"The folder dialog timed out"})},Db);J.stdout.on("data",(fe)=>{Y+=fe.toString()}),J.on("error",()=>ie({error:`Could not open the folder dialog (${D.cmd})`})),J.on("close",()=>{let fe=Y.trim().replace(/\/+$/,"");if(!fe)return ie({cancelled:!0});if(!Ib(fe)||!Fu(fe).isDirectory())return ie({error:"That selection is not a folder on disk"});ie({path:fe})})})}var Uu=`<!doctype html>
295
+ $dialog.Description = '${So}'
296
+ if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,zu=[{binary:"zenity",args:["--file-selection","--directory",`--title=${So}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",So]}],Yu=(P,O)=>(O.PATH??"").split(Jb).some((D)=>{if(D.length===0)return!1;try{let j=Wu(Kb(D,P));return j.isFile()&&(j.mode&73)!==0}catch{return!1}});function hs(P,O){if(P==="darwin"||P==="win32")return!0;if(P!=="linux")return!1;if(!O.DISPLAY&&!O.WAYLAND_DISPLAY)return!1;return zu.some((D)=>Yu(D.binary,O))}function Zb(P,O){if(P==="darwin")return{cmd:"osascript",args:["-e",zb]};if(P==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",Yb]};let D=zu.find((j)=>Yu(j.binary,O));return D?{cmd:D.binary,args:D.args}:null}function vs(P=process.platform,O=process.env){let D=Zb(P,O);if(!D)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((j)=>{let J=Bb(D.cmd,D.args,{env:O,stdio:["ignore","pipe","pipe"]}),Y="",re=!1,ie=(fe)=>{if(re)return;re=!0,clearTimeout(de),j(fe)},de=setTimeout(()=>{J.kill(),ie({error:"The folder dialog timed out"})},Wb);J.stdout.on("data",(fe)=>{Y+=fe.toString()}),J.on("error",()=>ie({error:`Could not open the folder dialog (${D.cmd})`})),J.on("close",()=>{let fe=Y.trim().replace(/\/+$/,"");if(!fe)return ie({cancelled:!0});if(!Vb(fe)||!Wu(fe).isDirectory())return ie({error:"That selection is not a folder on disk"});ie({path:fe})})})}var Zu=`<!doctype html>
295
297
  <html lang="en">
296
298
  <head>
297
299
  <meta charset="utf-8">
@@ -5766,6 +5768,6 @@ loadPolicy().then((loaded) => {
5766
5768
  </script>
5767
5769
  </body>
5768
5770
  </html>
5769
- `;var Gu='<script id="ccsn-data" type="application/json">';function qu(P,O=Uu){return O.replace(Gu,()=>Gu+JSON.stringify({token:P}).replaceAll("<","\\u003c"))}var bo="kenryu42/cc-safety-net",Gb=`https://github.com/${bo}`,ps=1e4,qb=7,Bb="The project draft directory changed; reload the draft before applying.",Vb="audit settings are user scope only; remove the audit section from a project proposal";async function Ku(P,O={}){let D=gn({label:"gui",booleans:{noOpen:["--no-open"]}},P),j=O.log??console.log,J=O.error??console.error;if(D.errors.length>0){for(let re of D.errors)J(re);return J("Usage: cc-safety-net gui [--no-open]"),1}let Y=await Jb(c,O);if(j(`CC Safety Net policy GUI: ${Y.url}`),!D.flags.noOpen)try{await(O.openBrowser??rw)(Y.url)}catch(re){J(`Failed to open browser: ${re instanceof Error?re.message:String(re)}`),J(`Open this URL manually: ${Y.url}`)}if(O.keepAlive===!1)return await Y.close(),0;return await tw(Y),0}async function Jb(P,O={}){let D=Fb(24).toString("base64url"),j={dir:null,revision:0},J=Mb((ie,de)=>{Wb(P,ie,de,D,O,j)});await new Promise((ie,de)=>{J.once("error",de),J.listen(0,"127.0.0.1",()=>{J.off("error",de),ie()})});let re=`http://127.0.0.1:${J.address().port}`;return{origin:re,token:D,url:`${re}/?token=${encodeURIComponent(D)}`,close:()=>nw(J)}}async function Wb(P,O,D,j,J,Y){let re=P(),ie=new URL(O.url??"/","http://127.0.0.1");if(O.method==="GET"&&ie.pathname==="/favicon.ico"){D.writeHead(204,{"cache-control":"no-store"}),D.end();return}if(!Xb(O,ie,j)){ln(D,403,{error:"Forbidden"});return}if(O.method==="GET"&&ie.pathname==="/"){await Promise.resolve(J.buildDocument?.()).then((de)=>ew(D,qu(j,de)),(de)=>ln(D,500,{error:de instanceof Error?de.message:String(de)}));return}if(O.method==="GET"&&ie.pathname==="/api/policy"){let de=qd(re,J),fe=k(re,ds(J));ln(D,200,{...de,configState:je(fe),...fe.policyScopes?{projectPolicy:{path:h(J.cwd??process.cwd()),weakenings:fe.policyScopes.weakeningsIgnored?[]:fe.policyScopes.weakenings}}:{},destructiveCommandRules:z,secretPatterns:Qe,version:pn(),preview:de.errors.length>0?null:Le(de.policy,re.env)});return}if(O.method==="POST"&&ie.pathname==="/api/policy/preview"){let de=await ur(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=Bd(re,de.value);ln(D,fe.errors.length>0?400:200,fe);return}if(O.method==="POST"&&ie.pathname==="/api/policy/explain"){let de=await ur(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=de.value;if(fe===null||typeof fe.command!=="string"){ln(D,400,{errors:["command must be a string"]});return}let we=sr(fe.policy,re.home);if(we.length>0){ln(D,400,{errors:we});return}ln(D,200,Yb(re,fe.command,fe.policy,J));return}if(O.method==="POST"&&ie.pathname==="/api/policy"){let de=await ur(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=Hn(re,de.value,J);ln(D,fe.errors.length>0?400:200,fe);return}if(O.method==="POST"&&ie.pathname==="/api/reset"){ln(D,200,Hn(re,te,J));return}if(O.method==="POST"&&ie.pathname==="/api/repair"){ln(D,200,Vd(re,J));return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/choose-directory"){let de=await(J.chooseDirectory??cs)();if("path"in de)Y.dir=de.path,Y.revision+=1;ln(D,200,{cancelled:"cancelled"in de,..."error"in de?{error:de.error}:{}});return}if(O.method==="GET"&&ie.pathname==="/api/policy/project"){let de=zu(Y,J),fe=Yu(re,de,J),we=fe?{projection:{},diagnostics:[fe]}:Bu(de,re.home),Ce=ar(re,J);ln(D,200,{path:h(de),revision:Y.revision,baseline:Ce.baseline,userPolicyDiagnostics:Ce.diagnostics,projection:we.projection,projectionDiagnostics:we.diagnostics,canPickDirectory:ls(process.platform,process.env)});return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/diff"){let de=await Vu(re,O,D,Y,J);if(!de)return;let fe=Bu(de.dir,re.home),we=ar(re,J).baseline,Ce=ee(we,ue(de.proposal,re.home).policy);ln(D,200,{rows:oo(ee(we,fe.projection).policy,Ce.policy,!1),weakenings:Ce.weakenings,existingFileDiagnostics:fe.diagnostics});return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/apply"){let de=await Vu(re,O,D,Y,J);if(!de)return;let fe=zb(de.dir,de.proposal,re.home);ln(D,fe.errors.length>0?500:200,fe);return}if(O.method==="GET"&&ie.pathname==="/api/activity"){let de=oe(re,J),fe=Zb(ie.searchParams.get("days"),de);if(fe===null){ln(D,400,{error:`days must be an integer between 1 and ${de}`});return}ln(D,200,ju(re,fe,J.activityLogsDir));return}if(O.method==="POST"&&ie.pathname==="/api/rules/choose-directory"){ln(D,200,await cs());return}if(O.method==="GET"&&ie.pathname==="/api/rules"){let de=Q(re,ds(J)),fe=new Map(de.rules.map((we)=>[we.name,we]));ln(D,200,{projectPath:J.cwd??process.cwd(),canPickDirectory:ls(process.platform,process.env),rulebooks:de.rulebooks.map((we)=>({source:we.source,spec:we.spec,name:we.name,version:we.version,rules:we.rules.flatMap((Ce)=>{let Se=fe.get(Ce);if(!Se)return[];return[{name:Se.name,command:Se.command,subcommand:Se.subcommand,block_args:Se.block_args,reason:Se.reason}]})})),errors:de.errors,warnings:de.warnings});return}if(O.method==="GET"&&ie.pathname==="/api/star/context"){ln(D,200,await(J.fetchStarContext??(()=>cw(re,{logsDir:J.activityLogsDir})))());return}if(O.method==="POST"&&ie.pathname==="/api/star"){let de=await(J.starRepo??ow)();ln(D,200,de.ok?{ok:!0}:{ok:!1,fallbackUrl:Gb});return}if(O.method==="GET"&&ie.pathname==="/api/integrations"){ln(D,200,await(J.fetchIntegrations??(()=>iw(re)))());return}if(O.method==="GET"&&ie.pathname==="/api/health"){ln(D,200,await(J.fetchHealth??aw)());return}if(O.method==="POST"&&(ie.pathname==="/api/install"||ie.pathname==="/api/uninstall")){let de=await ur(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=de.value?.target;if(typeof fe!=="string"||!$n.some((Ce)=>Ce.target===fe)){ln(D,400,{error:"unknown target"});return}let we=ie.pathname==="/api/install"?"install":"uninstall";ln(D,200,await(J.runIntegration??lw)(we,fe));return}ln(D,404,{error:"Not found"})}function ds(P){return{...P,cwd:P.cwd??process.cwd()}}function zu(P,O){return P.dir??O.cwd??process.cwd()}function Yu(P,O,D){if(!L(P,{...D,cwd:O}))return null;return`${h(O)} is the user policy, not a project policy; choose a project directory, or run the GUI from one`}function Bu(P,O){let D=h(P),j=Hb(D)?bt(D):{value:void 0,errors:[]},J=ue(j.value,O);return{projection:J.policy,diagnostics:[...j.errors,...J.diagnostics]}}async function Vu(P,O,D,j,J){let Y=zu(j,J),re=j.revision,ie=await ur(O);if(!ie.ok)return ln(D,ie.status,{errors:[ie.error]}),null;let de=ie.value;if(typeof de?.revision!=="number")return ln(D,400,{errors:["revision must be a number"]}),null;if(de.revision!==re)return ln(D,409,{errors:[Bb]}),null;let fe=Yu(P,Y,J);if(fe)return ln(D,400,{errors:[fe]}),null;let we=Kb(de.proposal,P.home);if(we.length>0)return ln(D,400,{errors:we}),null;return{dir:Y,proposal:de.proposal}}function Kb(P,O){let D=sr(P,O);if(D.length>0)return D;return P?.audit===void 0?[]:[Vb]}function zb(P,O,D){let j=h(P),J=io(O,E(O,D));try{return g(i(S(P,"project policy"),j),`${JSON.stringify(J,null,2)}
5770
- `),{path:j,errors:[]}}catch(Y){return{path:j,errors:[Y instanceof Error?Y.message:String(Y)]}}}function Yb(P,O,D,j){let J=E(D,P.home),Y=k(P,ds(j)),re=_e({rules:Y.policy.rules,transparentWrappers:Y.policy.transparentWrappers,safety:$e(J.safety),worktreeMode:J.workflow.worktree_mode,destructiveCommandProtectionEnabled:J.destructive_command_protection.enabled,destructiveCommandRuleOverrides:J.destructive_command_protection.overrides,destructiveCommandAllowPaths:J.destructive_command_protection.allow_paths,secretProtection:{enabled:J.secret_protection.enabled,disabledRules:Fe(J.secret_protection.overrides),denyPaths:J.secret_protection.deny_paths,allowPaths:J.secret_protection.allow_paths}});return Qt(O,{policySnapshot:re,cwd:j.cwd,userConfigDir:j.userConfigDir},P)}function Zb(P,O){if(P===null)return Math.min(qb,O);let D=Number(P);if(!Number.isInteger(D)||D<1||D>O)return null;return D}function Xb(P,O,D){if(O.searchParams.get("token")!==D)return!1;if(P.method!=="POST")return!0;return P.headers["x-cc-safety-net-token"]===D}var Qb=1048576;async function ur(P){let O=[],D=0;for await(let j of P){let J=j;if(D+=J.byteLength,D>Qb)return{ok:!1,status:413,error:"Request body is too large"};O.push(J)}try{return{ok:!0,value:JSON.parse(Buffer.concat(O).toString("utf-8")||"{}")}}catch(j){return{ok:!1,status:400,error:`Invalid JSON: ${j instanceof Error?j.message:String(j)}`}}}function ew(P,O){P.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),P.end(O)}function ln(P,O,D){P.writeHead(O,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),P.end(JSON.stringify(D))}function nw(P){return new Promise((O,D)=>{P.close((j)=>j?D(j):O())})}function tw(P){return new Promise((O)=>{let D=()=>{process.off("SIGINT",j),process.off("SIGTERM",j)},j=()=>{D(),P.close().then(O)};process.once("SIGINT",j),process.once("SIGTERM",j)})}function rw(P){let O=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",D=process.platform==="win32"?["/c","start","",P]:[P];return new Promise((j,J)=>{let Y=Wu(O,D,{detached:!0,stdio:"ignore"}),re=(de)=>{Y.off("spawn",ie),J(de)},ie=()=>{Y.off("error",re),Y.unref(),j()};Y.once("error",re),Y.once("spawn",ie)})}async function ow(P="gh",O=ps){return{ok:await us(P,["api","-X","PUT",`/user/starred/${bo}`],O)===0}}async function iw(P,O={}){let D=await xr((J)=>Ot({environment:P,cwd:process.cwd(),openCodeVersion:J}).status!=="n/a",O.fetcher),j=sw(P,D);return{targets:En.map((J)=>{let Y=j.find((re)=>re.platform===J.id);return{target:J.id,label:mn(J.id),version:D.versions[J.id]??null,status:Y?.configured?"active":Y?.detected?"disabled":Y?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:D.version,nodeVersion:D.nodeVersion,platform:D.platform}}}function sw(P,O){return Dt(P,process.cwd(),{ampPluginListOutput:O.ampPluginListOutput,codexPluginListOutput:O.codexPluginListOutput,copilotCliVersion:O.versions["copilot-cli"],openCodeVersion:O.versions.opencode,openCodePluginListOutput:O.openCodePluginListOutput})}async function aw(P={}){let O=await(P.checkUpdates??Gn)();return{update:{latestVersion:O.latestVersion??null,updateAvailable:O.updateAvailable}}}var Ju=Promise.resolve();function lw(P,O,D={}){let j=async()=>{let Y=[],{log:re,error:ie}=console;console.log=(...de)=>Y.push(de.map(String).join(" ")),console.error=console.log;try{return{ok:await ir(P,[],{selectTargets:async()=>[O],output:new Ub({write(fe,we,Ce){Y.push(String(fe).replace(/\n$/,"")),Ce()}}),...D})===0,output:Y.join(`
5771
- `)}}finally{console.log=re,console.error=ie}},J=Ju.then(j);return Ju=J.then(()=>{return},()=>{return}),J}async function cw(P,O={}){let[D,j,J]=await Promise.all([dw(O.command),uw(O.fetchRepo),Promise.resolve(hr(P,oe(P),O.logsDir).totalBlocked)]);return{starred:D,starCount:j,blockedTotal:J}}async function dw(P="gh",O=ps){if(await us(P,["auth","status"],O)!==0)return null;let D=await us(P,["api",`/user/starred/${bo}`],O);if(D===0)return!0;if(D===null)return null;return!1}function us(P,O,D){return new Promise((j)=>{let J=Wu(P,O,{stdio:"ignore",windowsHide:!0}),Y=!1,re=setTimeout(()=>{J.kill(),ie(null)},D),ie=(de)=>{if(Y)return;Y=!0,clearTimeout(re),j(de)};J.once("error",()=>ie(null)),J.once("close",ie)})}async function uw(P=fetch){try{let O=await P(`https://api.github.com/repos/${bo}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(ps)});if(!O.ok)return null;let D=await O.json();return typeof D.stargazers_count==="number"?D.stargazers_count:null}catch{return null}}function pw(P){if(P[0]!=="help")return!1;let O=P[1];if(!O)Li(),process.exit(0);if(er(O))process.exit(0);console.error(`Unknown command: ${O}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var fw={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),er("hook",console.error),process.exit(1)},install:async(P)=>{process.exit(await ir("install",P))},update:async(P)=>{process.exit(await Yi(P))},uninstall:async(P)=>{process.exit(await ir("uninstall",P))},rule:async(P)=>{process.exit(await Du(c(),P))},policy:async(P)=>{process.exit(await zd(c(),P))},status:async(P)=>{if(Dn(gn({label:"status"},P).errors))process.exit(1);Nu(c())},statusline:async(P)=>{let O=gn({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},P);if(O.errors.length===0&&O.flags.claudeCode){await as(c());return}if(Dn(O.errors),!O.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");er("statusline",console.error),process.exit(1)},doctor:async(P)=>{let O=Ei(P);if(!O)process.exit(1);let D=await uc(c(),{json:O.json,skipUpdateCheck:O.skipUpdateCheck});process.exit(D)},logs:async(P)=>{process.exit(await ws(c(),P))},gui:async(P)=>{process.exit(await Ku(P))},explain:async(P)=>{process.exit(await xc(c(),P))}};async function mw(P){let O=gn({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},P);if(pw(P))return;let D=P[0],j=D?yr(D):void 0;if(O.help&&j&&j.name!=="rule")er(j.name),process.exit(0);if(!D||O.help&&!j)Li(),process.exit(0);if(O.flags.version)Pc(),process.exit(0);if(j){await fw[j.name](P.slice(1));return}if(D==="--statusline"){await as(c());return}console.error(D.startsWith("-")?`Unknown option: ${D}`:`Unknown command: ${D}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{mw as runCli};
5771
+ `;var Xu='<script id="ccsn-data" type="application/json">';function Qu(P,O=Zu){return O.replace(Xu,()=>Xu+JSON.stringify({token:P}).replaceAll("<","\\u003c"))}var Po="kenryu42/cc-safety-net",tw=`https://github.com/${Po}`,ks=1e4,rw=7,ow="The project draft directory changed; reload the draft before applying.",iw="audit settings are user scope only; remove the audit section from a project proposal";async function op(P,O={}){let D=yn({label:"gui",booleans:{noOpen:["--no-open"]}},P),j=O.log??console.log,J=O.error??console.error;if(D.errors.length>0){for(let re of D.errors)J(re);return J("Usage: cc-safety-net gui [--no-open]"),1}let Y=await sw(c,O);if(j(`CC Safety Net policy GUI: ${Y.url}`),!D.flags.noOpen)try{await(O.openBrowser??hw)(Y.url)}catch(re){J(`Failed to open browser: ${re instanceof Error?re.message:String(re)}`),J(`Open this URL manually: ${Y.url}`)}if(O.keepAlive===!1)return await Y.close(),0;return await yw(Y),0}async function sw(P,O={}){let D=Xb(24).toString("base64url"),j={dir:null,revision:0},J=ew((ie,de)=>{aw(P,ie,de,D,O,j)});await new Promise((ie,de)=>{J.once("error",de),J.listen(0,"127.0.0.1",()=>{J.off("error",de),ie()})});let re=`http://127.0.0.1:${J.address().port}`;return{origin:re,token:D,url:`${re}/?token=${encodeURIComponent(D)}`,close:()=>gw(J)}}async function aw(P,O,D,j,J,Y){let re=P(),ie=new URL(O.url??"/","http://127.0.0.1");if(O.method==="GET"&&ie.pathname==="/favicon.ico"){D.writeHead(204,{"cache-control":"no-store"}),D.end();return}if(!pw(O,ie,j)){ln(D,403,{error:"Forbidden"});return}if(O.method==="GET"&&ie.pathname==="/"){await Promise.resolve(J.buildDocument?.()).then((de)=>mw(D,Qu(j,de)),(de)=>ln(D,500,{error:de instanceof Error?de.message:String(de)}));return}if(O.method==="GET"&&ie.pathname==="/api/policy"){let de=Qd(re,J),fe=k(re,bs(J));ln(D,200,{...de,configState:je(fe),...fe.policyScopes?{projectPolicy:{path:h(J.cwd??process.cwd()),weakenings:fe.policyScopes.weakeningsIgnored?[]:fe.policyScopes.weakenings}}:{},destructiveCommandRules:z,secretPatterns:Qe,version:pn(),preview:de.errors.length>0?null:Le(de.policy,re.env)});return}if(O.method==="POST"&&ie.pathname==="/api/policy/preview"){let de=await fr(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=eu(re,de.value);ln(D,fe.errors.length>0?400:200,fe);return}if(O.method==="POST"&&ie.pathname==="/api/policy/explain"){let de=await fr(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=de.value;if(fe===null||typeof fe.command!=="string"){ln(D,400,{errors:["command must be a string"]});return}let we=lr(fe.policy,re.home);if(we.length>0){ln(D,400,{errors:we});return}ln(D,200,dw(re,fe.command,fe.policy,J));return}if(O.method==="POST"&&ie.pathname==="/api/policy"){let de=await fr(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=Hn(re,de.value,J);ln(D,fe.errors.length>0?400:200,fe);return}if(O.method==="POST"&&ie.pathname==="/api/reset"){ln(D,200,Hn(re,te,J));return}if(O.method==="POST"&&ie.pathname==="/api/repair"){ln(D,200,nu(re,J));return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/choose-directory"){let de=await(J.chooseDirectory??vs)();if("path"in de)Y.dir=de.path,Y.revision+=1;ln(D,200,{cancelled:"cancelled"in de,..."error"in de?{error:de.error}:{}});return}if(O.method==="GET"&&ie.pathname==="/api/policy/project"){let de=ip(Y,J),fe=sp(re,de,J),we=fe?{projection:{},diagnostics:[fe]}:ep(de,re.home),Ce=cr(re,J);ln(D,200,{path:h(de),revision:Y.revision,baseline:Ce.baseline,userPolicyDiagnostics:Ce.diagnostics,projection:we.projection,projectionDiagnostics:we.diagnostics,canPickDirectory:hs(process.platform,process.env)});return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/diff"){let de=await np(re,O,D,Y,J);if(!de)return;let fe=ep(de.dir,re.home),we=cr(re,J).baseline,Ce=ee(we,ue(de.proposal,re.home).policy);ln(D,200,{rows:uo(ee(we,fe.projection).policy,Ce.policy,!1),weakenings:Ce.weakenings,existingFileDiagnostics:fe.diagnostics});return}if(O.method==="POST"&&ie.pathname==="/api/policy/project/apply"){let de=await np(re,O,D,Y,J);if(!de)return;let fe=cw(de.dir,de.proposal,re.home);ln(D,fe.errors.length>0?500:200,fe);return}if(O.method==="GET"&&ie.pathname==="/api/activity"){let de=oe(re,J),fe=uw(ie.searchParams.get("days"),de);if(fe===null){ln(D,400,{error:`days must be an integer between 1 and ${de}`});return}ln(D,200,Ku(re,fe,J.activityLogsDir));return}if(O.method==="POST"&&ie.pathname==="/api/rules/choose-directory"){ln(D,200,await vs());return}if(O.method==="GET"&&ie.pathname==="/api/rules"){let de=Q(re,bs(J)),fe=new Map(de.rules.map((we)=>[we.name,we]));ln(D,200,{projectPath:J.cwd??process.cwd(),canPickDirectory:hs(process.platform,process.env),rulebooks:de.rulebooks.map((we)=>({source:we.source,spec:we.spec,name:we.name,version:we.version,rules:we.rules.flatMap((Ce)=>{let Se=fe.get(Ce);if(!Se)return[];return[{name:Se.name,command:Se.command,subcommand:Se.subcommand,block_args:Se.block_args,reason:Se.reason}]})})),errors:de.errors,warnings:de.warnings});return}if(O.method==="GET"&&ie.pathname==="/api/star/context"){ln(D,200,await(J.fetchStarContext??(()=>Cw(re,{logsDir:J.activityLogsDir})))());return}if(O.method==="POST"&&ie.pathname==="/api/star"){let de=await(J.starRepo??vw)();ln(D,200,de.ok?{ok:!0}:{ok:!1,fallbackUrl:tw});return}if(O.method==="GET"&&ie.pathname==="/api/integrations"){ln(D,200,await(J.fetchIntegrations??(()=>bw(re)))());return}if(O.method==="GET"&&ie.pathname==="/api/health"){ln(D,200,await(J.fetchHealth??kw)());return}if(O.method==="POST"&&(ie.pathname==="/api/install"||ie.pathname==="/api/uninstall")){let de=await fr(O);if(!de.ok){ln(D,de.status,{errors:[de.error]});return}let fe=de.value?.target;if(typeof fe!=="string"||!$n.some((Ce)=>Ce.target===fe)){ln(D,400,{error:"unknown target"});return}let we=ie.pathname==="/api/install"?"install":"uninstall";ln(D,200,await(J.runIntegration??xw)(we,fe));return}ln(D,404,{error:"Not found"})}function bs(P){return{...P,cwd:P.cwd??process.cwd()}}function ip(P,O){return P.dir??O.cwd??process.cwd()}function sp(P,O,D){if(!L(P,{...D,cwd:O}))return null;return`${h(O)} is the user policy, not a project policy; choose a project directory, or run the GUI from one`}function ep(P,O){let D=h(P),j=Qb(D)?bt(D):{value:void 0,errors:[]},J=ue(j.value,O);return{projection:J.policy,diagnostics:[...j.errors,...J.diagnostics]}}async function np(P,O,D,j,J){let Y=ip(j,J),re=j.revision,ie=await fr(O);if(!ie.ok)return ln(D,ie.status,{errors:[ie.error]}),null;let de=ie.value;if(typeof de?.revision!=="number")return ln(D,400,{errors:["revision must be a number"]}),null;if(de.revision!==re)return ln(D,409,{errors:[ow]}),null;let fe=sp(P,Y,J);if(fe)return ln(D,400,{errors:[fe]}),null;let we=lw(de.proposal,P.home);if(we.length>0)return ln(D,400,{errors:we}),null;return{dir:Y,proposal:de.proposal}}function lw(P,O){let D=lr(P,O);if(D.length>0)return D;return P?.audit===void 0?[]:[iw]}function cw(P,O,D){let j=h(P),J=po(O,E(O,D));try{return g(i(S(P,"project policy"),j),`${JSON.stringify(J,null,2)}
5772
+ `),{path:j,errors:[]}}catch(Y){return{path:j,errors:[Y instanceof Error?Y.message:String(Y)]}}}function dw(P,O,D,j){let J=E(D,P.home),Y=k(P,bs(j)),re=_e({rules:Y.policy.rules,transparentWrappers:Y.policy.transparentWrappers,safety:$e(J.safety),worktreeMode:J.workflow.worktree_mode,destructiveCommandProtectionEnabled:J.destructive_command_protection.enabled,destructiveCommandRuleOverrides:J.destructive_command_protection.overrides,destructiveCommandAllowPaths:J.destructive_command_protection.allow_paths,secretProtection:{enabled:J.secret_protection.enabled,disabledRules:Fe(J.secret_protection.overrides),denyPaths:J.secret_protection.deny_paths,allowPaths:J.secret_protection.allow_paths}});return nr(O,{policySnapshot:re,cwd:j.cwd,userConfigDir:j.userConfigDir},P)}function uw(P,O){if(P===null)return Math.min(rw,O);let D=Number(P);if(!Number.isInteger(D)||D<1||D>O)return null;return D}function pw(P,O,D){if(O.searchParams.get("token")!==D)return!1;if(P.method!=="POST")return!0;return P.headers["x-cc-safety-net-token"]===D}var fw=1048576;async function fr(P){let O=[],D=0;for await(let j of P){let J=j;if(D+=J.byteLength,D>fw)return{ok:!1,status:413,error:"Request body is too large"};O.push(J)}try{return{ok:!0,value:JSON.parse(Buffer.concat(O).toString("utf-8")||"{}")}}catch(j){return{ok:!1,status:400,error:`Invalid JSON: ${j instanceof Error?j.message:String(j)}`}}}function mw(P,O){P.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),P.end(O)}function ln(P,O,D){P.writeHead(O,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),P.end(JSON.stringify(D))}function gw(P){return new Promise((O,D)=>{P.close((j)=>j?D(j):O())})}function yw(P){return new Promise((O)=>{let D=()=>{process.off("SIGINT",j),process.off("SIGTERM",j)},j=()=>{D(),P.close().then(O)};process.once("SIGINT",j),process.once("SIGTERM",j)})}function hw(P){let O=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",D=process.platform==="win32"?["/c","start","",P]:[P];return new Promise((j,J)=>{let Y=rp(O,D,{detached:!0,stdio:"ignore"}),re=(de)=>{Y.off("spawn",ie),J(de)},ie=()=>{Y.off("error",re),Y.unref(),j()};Y.once("error",re),Y.once("spawn",ie)})}async function vw(P="gh",O=ks){return{ok:await ws(P,["api","-X","PUT",`/user/starred/${Po}`],O)===0}}async function bw(P,O={}){let D=await Sr((J)=>Ot({environment:P,cwd:process.cwd(),openCodeVersion:J}).status!=="n/a",O.fetcher),j=ww(P,D);return{targets:En.map((J)=>{let Y=j.find((re)=>re.platform===J.id);return{target:J.id,label:mn(J.id),version:D.versions[J.id]??null,status:Y?.configured?"active":Y?.detected?"disabled":Y?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:D.version,nodeVersion:D.nodeVersion,platform:D.platform}}}function ww(P,O){return Dt(P,process.cwd(),{ampPluginListOutput:O.ampPluginListOutput,codexPluginListOutput:O.codexPluginListOutput,copilotCliVersion:O.versions["copilot-cli"],openCodeVersion:O.versions.opencode,openCodePluginListOutput:O.openCodePluginListOutput})}async function kw(P={}){let O=await(P.checkUpdates??Gn)();return{update:{latestVersion:O.latestVersion??null,updateAvailable:O.updateAvailable}}}var tp=Promise.resolve();function xw(P,O,D={}){let j=async()=>{let Y=[],{log:re,error:ie}=console;console.log=(...de)=>Y.push(de.map(String).join(" ")),console.error=console.log;try{return{ok:await ar(P,[],{selectTargets:async()=>[O],output:new nw({write(fe,we,Ce){Y.push(String(fe).replace(/\n$/,"")),Ce()}}),...D})===0,output:Y.join(`
5773
+ `)}}finally{console.log=re,console.error=ie}},J=tp.then(j);return tp=J.then(()=>{return},()=>{return}),J}async function Cw(P,O={}){let[D,j,J]=await Promise.all([Sw(O.command),Pw(O.fetchRepo),Promise.resolve(br(P,oe(P),O.logsDir).totalBlocked)]);return{starred:D,starCount:j,blockedTotal:J}}async function Sw(P="gh",O=ks){if(await ws(P,["auth","status"],O)!==0)return null;let D=await ws(P,["api",`/user/starred/${Po}`],O);if(D===0)return!0;if(D===null)return null;return!1}function ws(P,O,D){return new Promise((j)=>{let J=rp(P,O,{stdio:"ignore",windowsHide:!0}),Y=!1,re=setTimeout(()=>{J.kill(),ie(null)},D),ie=(de)=>{if(Y)return;Y=!0,clearTimeout(re),j(de)};J.once("error",()=>ie(null)),J.once("close",ie)})}async function Pw(P=fetch){try{let O=await P(`https://api.github.com/repos/${Po}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(ks)});if(!O.ok)return null;let D=await O.json();return typeof D.stargazers_count==="number"?D.stargazers_count:null}catch{return null}}function Rw(P){if(P[0]!=="help")return!1;let O=P[1];if(!O)Bi(),process.exit(0);if(tr(O))process.exit(0);console.error(`Unknown command: ${O}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var Ew={hook:async()=>{console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),tr("hook",console.error),process.exit(1)},install:async(P)=>{process.exit(await ar("install",P))},update:async(P)=>{process.exit(await is(P))},uninstall:async(P)=>{process.exit(await ar("uninstall",P))},rule:async(P)=>{process.exit(await Bu(c(),P))},policy:async(P)=>{process.exit(await iu(c(),P))},status:async(P)=>{if(Dn(yn({label:"status"},P).errors))process.exit(1);Ju(c())},statusline:async(P)=>{let O=yn({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},P);if(O.errors.length===0&&O.flags.claudeCode){await ys(c());return}if(Dn(O.errors),!O.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");tr("statusline",console.error),process.exit(1)},doctor:async(P)=>{let O=Ni(P);if(!O)process.exit(1);let D=await kc(c(),{json:O.json,skipUpdateCheck:O.skipUpdateCheck});process.exit(D)},logs:async(P)=>{process.exit(await As(c(),P))},gui:async(P)=>{process.exit(await op(P))},explain:async(P)=>{process.exit(await $c(c(),P))}};async function _w(P){let O=yn({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},P);if(Rw(P))return;let D=P[0],j=D?vr(D):void 0;if(O.help&&j&&j.name!=="rule")tr(j.name),process.exit(0);if(!D||O.help&&!j)Bi(),process.exit(0);if(O.flags.version)Lc(),process.exit(0);if(j){await Ew[j.name](P.slice(1));return}if(D==="--statusline"){await ys(c());return}console.error(D.startsWith("-")?`Unknown option: ${D}`:`Unknown command: ${D}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}export{_w as runCli};