@rulemetric/cli 0.12.5 → 0.12.7
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/chunk-2TJ7Q2OU.js +1 -0
- package/dist/{chunk-VEFLUZH5.js → chunk-3DZD322E.js} +1 -1
- package/dist/{chunk-A5P3RCPI.js → chunk-5N5S3NKS.js} +1 -1
- package/dist/{chunk-RUTWW6N6.js → chunk-C6GLNE6X.js} +1 -1
- package/dist/{chunk-2MD5QLYF.js → chunk-CPDMJGTC.js} +1 -1
- package/dist/{chunk-Y3BYR4M7.js → chunk-DCH3QWB7.js} +1 -1
- package/dist/chunk-EVD5A3VI.js +1 -0
- package/dist/{chunk-7PWPWJXC.js → chunk-FUYR7CFD.js} +1 -1
- package/dist/{chunk-R6MCQNSH.js → chunk-INSKP5ED.js} +1 -1
- package/dist/{chunk-EHNPJJIH.js → chunk-NVABG3AO.js} +1 -1
- package/dist/chunk-OZQNSELV.js +31 -0
- package/dist/{chunk-GCLTMV7V.js → chunk-PVPYLKB3.js} +1 -1
- package/dist/{chunk-YXNAGHHQ.js → chunk-RLEMDKQ4.js} +1 -1
- package/dist/chunk-TYFEWLYZ.js +2 -0
- package/dist/{chunk-BXFDEQCX.js → chunk-UKOI2Q4J.js} +1 -1
- package/dist/chunk-UUFCTEBT.js +1 -0
- package/dist/chunk-VS5ROGDP.js +1 -0
- package/dist/{chunk-2DWUGAJ4.js → chunk-WO6MS654.js} +1 -1
- package/dist/commands/diagnostics.js +1 -1
- package/dist/commands/evals/agent.js +1 -1
- package/dist/commands/evals/refine-cases.js +1 -1
- package/dist/commands/gateway/ensure.js +1 -1
- package/dist/commands/hooks/install.js +1 -1
- package/dist/commands/hooks/uninstall.js +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/commands/suggestions/accept.js +1 -1
- package/dist/commands/suggestions/undo.js +1 -1
- package/dist/lib/agent-loop.js +1 -1
- package/dist/lib/antigravity-capture-status.js +1 -0
- package/dist/lib/claude-hook-timeouts.js +1 -0
- package/dist/lib/editor-proxy-pins.js +1 -1
- package/dist/lib/evolution-enrolment.js +1 -1
- package/dist/lib/hooks-config.js +1 -1
- package/dist/lib/instructions/acceptance/accept-hook.js +1 -1
- package/dist/lib/instructions/acceptance/hook-install.js +1 -1
- package/dist/lib/instructions/acceptance/reverse-applications.js +1 -1
- package/dist/lib/instructions/acceptance/suggestion-accept.js +1 -1
- package/dist/lib/jobs/handlers/cron-auto-accept-suggestions.js +1 -1
- package/dist/lib/jobs/handlers/cron-instruction-evolution.js +1 -1
- package/dist/lib/jobs/handlers/cron-refine-cases.js +1 -1
- package/dist/lib/jobs/handlers/process-insights.js +1 -1
- package/dist/lib/mac-sleep-log.js +1 -0
- package/dist/lib/machine-pause-detector.js +1 -0
- package/dist/lib/manual-tasks.js +1 -1
- package/dist/lib/refine-cases.js +1 -1
- package/dist/lib/setup-steps.js +1 -1
- package/oclif.manifest.json +326 -326
- package/package.json +8 -8
- package/dist/chunk-3QXRLIGC.js +0 -31
- package/dist/chunk-7R3WWD7V.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as n}from"./chunk-ZLLER3HP.js";import{existsSync as a,readFileSync as u}from"node:fs";import{homedir as c}from"node:os";import{join as s}from"node:path";function i(t){if(!a(t))return!1;try{let r=JSON.parse(u(t,"utf-8"));return!!r&&typeof r=="object"&&"rulemetric"in r}catch{return!1}}n(i,"hasRulemetricBlock");function g(t,r=c()){let e=s(t,".agents","hooks.json"),o=s(r,".gemini","config","hooks.json");return{workspace:i(e)?e:null,user:i(o)?o:null}}n(g,"antigravityCaptureStatus");export{g as a};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as v}from"./chunk-
|
|
1
|
+
import{c as v}from"./chunk-CPDMJGTC.js";import{e as h,f}from"./chunk-UGACB66X.js";import{q as m,r as u}from"./chunk-WMIUFMDI.js";import{a as c}from"./chunk-ZLLER3HP.js";import*as i from"node:fs";import*as d from"node:path";var g=new Set(m);async function $(t){let{applications:l}=await h(`/api/recommendation-applications?instructionId=${encodeURIComponent(t.instructionId)}&projectPath=${encodeURIComponent(t.projectPath)}&limit=200`),r=l.filter(e=>g.has(e.status)&&e.inverse),s=[];for(let e of u(r.map(n=>({...n,appliedAt:n.appliedAt})))){let n=e.inverse;if(n.kind==="delete-paths"){let p=y(t.dir,n.paths);s.push({applicationId:e.id,target:e.targetPath,reversed:p.removed,drifted:!1,reason:p.reason}),(p.removed||p.alreadyGone)&&await f(`/api/recommendation-applications/${encodeURIComponent(e.id)}/transition`,{status:"reverted"});continue}if(n.kind!=="remove-hook-entry"){s.push({applicationId:e.id,target:e.targetPath,reversed:!1,drifted:!1,reason:`no reverser for inverse kind '${n.kind}' \u2014 recorded, not reversed`});continue}let o=v({dir:t.dir,inverse:n});s.push({applicationId:e.id,target:e.targetPath,reversed:o.removed,drifted:o.drifted,reason:o.reason}),(o.removed||o.code==="not-present")&&await f(`/api/recommendation-applications/${encodeURIComponent(e.id)}/transition`,{status:"reverted"})}return s}c($,"reverseApplications");function y(t,l){let r=d.resolve(t),s=!1,e=0;for(let n of l){let o=d.resolve(r,n);if(o===r||!o.startsWith(r+d.sep))return{removed:!1,alreadyGone:!1,reason:`refused: ${n} does not resolve to a path inside the project`};if(!i.existsSync(o)&&!I(o)){e+=1;continue}try{i.rmSync(o,{recursive:!0,force:!0}),s=!0;let a=d.dirname(o);a.startsWith(r+d.sep)&&i.readdirSync(a).length===0&&i.rmdirSync(a)}catch(a){return{removed:!1,alreadyGone:!1,reason:`could not remove ${n}: ${a instanceof Error?a.message:String(a)}`}}}return!s&&e===l.length?{removed:!1,alreadyGone:!0,reason:"already removed"}:{removed:s,alreadyGone:!1}}c(y,"deletePaths");function I(t){try{return i.lstatSync(t).isSymbolicLink()}catch{return!1}}c(I,"isSymlink");function b(t){let l=t.name??t.instructionId,r=[],s=t.reversals.filter(e=>e.reversed);if(t.stripped)r.push(`Removed ${l} from CLAUDE.md.`);else if(s.length>0)for(let e of s)r.push(`Removed ${l} from ${e.target}.`),e.drifted&&r.push(" (that file had changed since it was installed; only the recorded entry was removed)");else r.push(`CLAUDE.md was not modified \u2014 no rulemetric-managed block for ${t.instructionId} was found in this directory.`);for(let e of t.reversals.filter(n=>!n.reversed))r.push(`Still installed in ${e.target}: ${e.reason??"the recorded inverse did not apply"}`);return t.dismissalError?(r.push(`Could not record the dismissal: ${t.dismissalError}`),r.push(s.length>0?' What was removed above stays removed \u2014 only the "stop proposing this" record failed.':" Nothing was removed, and the dismissal was not recorded either."),r.push(" This proposal may be suggested again. Re-run this command to retry."),r):(r.push("It will not be proposed again for 30 days."),r.push("Turn auto-adoption off entirely: rulemetric suggestions auto --off"),r)}c(b,"describeUndo");export{$ as a,y as b,b as c};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as t,e as E}from"./chunk-
|
|
1
|
+
import{b as t,e as E}from"./chunk-FUYR7CFD.js";import{a as r}from"./chunk-ZLLER3HP.js";function s(o=10,_=t){for(let e=1;e<=o;e++)if(E(e,o,_).feasible)return e;return o}r(s,"minFeasibleLiveCases");var S=s(),A=3;export{s as a,S as b,A as c};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d as $}from"./chunk-
|
|
1
|
+
import{d as $}from"./chunk-RLEMDKQ4.js";import{e as b}from"./chunk-UGACB66X.js";import{a as g}from"./chunk-ZLLER3HP.js";import{existsSync as k,statSync as A}from"node:fs";async function v(y,h){let s=g(n=>h?.logger?.info?.(n)??console.log(n),"log"),{projectPath:o}=y,r=`[cron_auto_accept_suggestions] ${o}`;if(!o)return{skipped:"no-project-path"};if(!k(o)||!A(o).isDirectory())return s(`${r}: project directory no longer exists on this machine \u2014 skipping`),{skipped:"project-path-missing"};let e=await b(`/api/instruction-suggestions/auto-acceptable?projectPath=${encodeURIComponent(o)}`);if(!e.consent.allowed)return s(`${r}: ${e.consent.reason??"no consent"} (${e.consent.source})`),{skipped:"no-consent",reason:e.consent.reason};for(let n of e.refused)s(`${r}: refused "${n.name}" \u2014 ${n.reason}`);if(e.eligible.length===0)return s(`${r}: nothing to adopt`+(e.budget?` (rules ${e.budget.used}/${e.budget.max}`+(e.budget.skillsUsed!==void 0?`, skills ${e.budget.skillsUsed}`+(e.budget.skillsMax==null?" (uncapped)":`/${e.budget.skillsMax}`):"")+` used in ${e.budget.windowDays}d)`:"")),{skipped:"nothing-eligible",refused:e.refused.length,adopted:0};let i=0,f=0,a=0,l=0,d=0,u=0,c=0,m=[];for(let n of e.eligible)try{let t=await $({suggestionId:n.id,dir:o,projectPath:o,actor:"auto"});if(t.action==="added")i+=1,m.push(t.name),n.type==="skill"&&(f+=1),s(`${r}: adopted ${n.type==="skill"?"skill":"rule"} "${t.name}" (score ${n.score.toFixed(2)})`);else if(t.action==="redundant"){t.partialOverlap?d+=1:l+=1;for(let p of t.messages)s(`${r}: ${p}`)}else if(t.action==="unresolvable-reference"){u+=1;for(let p of t.messages)s(`${r}: ${p}`)}else a+=1,s(`${r}: "${t.name}" was already in CLAUDE.md`)}catch(t){c+=1,s(`${r}: failed to adopt "${n.name}" \u2014 ${t instanceof Error?t.message:String(t)}`)}return s(`${r}: ${i} adopted, ${a} already present, ${l} already covered in other words, ${d} refused for partial overlap, ${u} refused for naming files this project does not have, ${c} failed, ${e.refused.length} refused upstream. Undo any of them with \`rulemetric suggestions undo <instruction-id>\`.`),{adopted:i,skills:f,alreadyPresent:a,redundant:l,partialOverlaps:d,unresolvableReferences:u,failed:c,refused:e.refused.length,names:m}}g(v,"cronAutoAcceptSuggestions");export{v as a};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{f as k,k as b}from"./chunk-
|
|
1
|
+
import{f as k,k as b}from"./chunk-OZQNSELV.js";import{m as v,s as f,u as y}from"./chunk-WMIUFMDI.js";import{a as o}from"./chunk-ZLLER3HP.js";import{createHash as D}from"node:crypto";import{existsSync as d,readFileSync as H,writeFileSync as O,mkdirSync as I}from"node:fs";import{delimiter as R,dirname as j,join as m,resolve as w}from"node:path";function P(e){return b(m(e,".claude"),!1)}o(P,"adoptedHookSettingsPath");function B(e){return D("sha256").update(e).digest("hex")}o(B,"sha256");function h(e){return B(d(e)?H(e,"utf-8"):"")}o(h,"fileHash");function x(e){if(!d(e))return{settings:{}};let t=H(e,"utf-8");try{let n=JSON.parse(t);return!n||typeof n!="object"||Array.isArray(n)?{unreadable:!0}:{settings:n}}catch{return{unreadable:!0}}}o(x,"readSettings");function p(e,t){let n=e.hooks;if(!n||typeof n!="object")return[];let r=n[t];return Array.isArray(r)?r:[]}o(p,"hookBlocks");function A(e,t){return p(e,t).flatMap(n=>(n?.hooks??[]).map(r=>r?.command).filter(r=>typeof r=="string"))}o(A,"commandsFor");function W(e){let t=P(e.dir);if(!t.endsWith("settings.local.json"))return{status:"refused",reason:`refusing to write ${t}: adopted hooks are machine-local and only ever land in settings.local.json`};let n=x(t);if("unreadable"in n)return{status:"refused",reason:`${t} exists but is not readable as JSON. Nothing was written \u2014 installing would mean replacing a settings file this command could not read.`};let r=n.settings,s=y(e.spec.command,e.instructionId),a=h(t),l=o((g,S)=>({kind:"remove-hook-entry",file:f,event:e.spec.event,command:s,backupPath:S,hashAtWrite:g}),"inverseFor");if(A(r,e.spec.event).includes(s))return{status:"already-present",target:f,command:s,inverse:l(a,`${t}.bak`),beforeHash:a};let c={...e.spec.matcher?{matcher:e.spec.matcher}:{},hooks:[{type:"command",command:s}]},u=r.hooks&&typeof r.hooks=="object"?r.hooks:{};u[e.spec.event]=[...p(r,e.spec.event),c],r.hooks=u;let{backupPath:i}=k(t,r);return i||(i=`${t}.bak`,I(j(i),{recursive:!0}),O(i,`{}
|
|
2
2
|
`)),{status:"installed",target:f,command:s,inverse:l(h(t),i),beforeHash:a}}o(W,"installHook");function _(e){let t=w(e.dir,e.inverse.file);if(!d(t))return{removed:!1,drifted:!0,code:"file-missing",reason:`${e.inverse.file} no longer exists`};let n=x(t);if("unreadable"in n)return{removed:!1,drifted:!0,code:"unreadable",reason:`${e.inverse.file} is not readable as JSON; refusing to rewrite it`};let r=n.settings,s=h(t)!==e.inverse.hashAtWrite,a=A(r,e.inverse.event).filter(i=>i===e.inverse.command);if(a.length===0)return{removed:!1,drifted:s,code:"not-present",reason:"the recorded entry is no longer present \u2014 nothing to remove"};if(a.length>1)return{removed:!1,drifted:s,code:"ambiguous",reason:`${a.length} entries carry this exact command; refusing to guess which one this artifact installed`};let l=p(r,e.inverse.event).map(i=>({...i,hooks:(i?.hooks??[]).filter(g=>g?.command!==e.inverse.command)})).filter(i=>(i.hooks??[]).length>0),c=r.hooks;l.length===0?delete c[e.inverse.event]:c[e.inverse.event]=l,Object.keys(c).length===0&&delete r.hooks;let{backupPath:u}=k(t,r);return{removed:!0,drifted:s,backupPath:u}}o(_,"uninstallHook");function K(e){return(process.env.PATH??"").split(R).filter(Boolean).some(n=>d(m(n,e)))}o(K,"commandOnPath");function $(e,t){return d(m(e,".agents","skills",t))||d(m(e,".claude","skills",t))}o($,"skillInstalled");function z(e,t){let n={satisfied:[],missing:[],unverifiable:[]};for(let r of t){let s=v(r);if(!s)continue;let[a,...l]=s.split(":"),c=l.join(":").trim();if(!c){n.unverifiable.push(s);continue}a==="cmd"?(K(c)?n.satisfied:n.missing).push(s):a==="skill"?($(e,c)?n.satisfied:n.missing).push(s):a==="file"?(d(w(e,c))?n.satisfied:n.missing).push(s):n.unverifiable.push(s)}return n}o(z,"checkDependencies");export{P as a,W as b,_ as c,z as d};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{e as d}from"./chunk-QWCEZEDO.js";import{d as g}from"./chunk-NF2BIEAF.js";import{a as R,g as v,h as T,j as I,m as C}from"./chunk-
|
|
1
|
+
import{e as d}from"./chunk-QWCEZEDO.js";import{d as g}from"./chunk-NF2BIEAF.js";import{a as R,g as v,h as T,j as I,m as C}from"./chunk-OZQNSELV.js";import{e as _}from"./chunk-UGACB66X.js";import{g as m,l as k}from"./chunk-PZNWH4VQ.js";import{a as i}from"./chunk-ZLLER3HP.js";import{execSync as j}from"node:child_process";import{existsSync as p,readFileSync as y}from"node:fs";import{homedir as f}from"node:os";import{join as a}from"node:path";var P=["install","auth","hooks","worker"],O=["judge"],M=[...P,...O];function $(){return{projectPath:process.cwd(),configDir:k()}}i($,"defaultContext");var A=a(f(),".mitmproxy","mitmproxy-ca-cert.pem");function S(e){if(!e)return"";if(e.length<=8)return"*".repeat(e.length);let t=e.slice(0,4),n=e.slice(-4);return`${t}${"*".repeat(Math.max(4,e.length-8))}${n}`}i(S,"maskToken");function te(e,t){let n=e===null?[]:e.replace(/\n$/,"").split(`
|
|
2
2
|
`),o=t===null?[]:t.replace(/\n$/,"").split(`
|
|
3
3
|
`),s=[],u=Math.max(n.length,o.length);for(let c=0;c<u;c++){let l=n[c],r=o[c];l===r?s.push(` ${l}`):(l!==void 0&&s.push(`-${l}`),r!==void 0&&s.push(`+${r}`))}return s.join(`
|
|
4
4
|
`)}i(te,"renderDiff");function x(e,t){let n=a(e,"env");if(!p(n))return null;try{let s=y(n,"utf-8").match(new RegExp(`^${t}=(.+)$`,"m"));return s?s[1]:null}catch{return null}}i(x,"readEnvValue");async function b(){if(!m())return!1;try{return(await Promise.race([_("/api/setup/status"),new Promise((t,n)=>setTimeout(()=>n(new Error("setup/status timeout")),2500))]))?.workerActive===!0}catch{return!1}}i(b,"workerActive");function E(e,t){let n=a(e,".claude",t),o={},s=null;if(p(n))try{s=y(n,"utf-8").replace(/\n$/,""),o=JSON.parse(s)}catch{o={}}return{settings:o,before:s}}i(E,"readProjectSettings");function D(e){let{settings:t,before:n}=E(e,"settings.local.json");return v(t),{before:n,after:JSON.stringify(t,null,2)}}i(D,"projectHooksSettings");function N(e){let{settings:t,before:n}=E(e,"settings.local.json"),o={...t.env??{}};return o.HTTPS_PROXY=`http://localhost:${d}`,o.NO_PROXY=I,o.NODE_EXTRA_CA_CERTS=A,{before:n,after:JSON.stringify({...t,env:o},null,2)}}i(N,"projectProxyEnvSettings");function U(e){let{settings:t,before:n}=E(e,"settings.json");if(n===null)return null;let{removed:o}=C(t,d);return o?{before:n,after:JSON.stringify(t,null,2)}:null}i(U,"projectSharedSettingsMigration");var Y=a(f(),"Library","LaunchAgents","com.rulemetric.worker.plist"),G=a(f(),".config","systemd","user","rulemetric-worker.service");function h(e){j(e,{stdio:"inherit"})}i(h,"runCommand");var L=[{id:"install",title:"Install the CLI",command:"npm install -g @rulemetric/cli",async detect(){return m()||await b()},async plan(){return{id:"install",title:"Install the CLI",command:"npm install -g @rulemetric/cli",artifacts:[{path:"npm install -g @rulemetric/cli",kind:"command",before:null,after:"rulemetric --version # verifies the binary is on PATH"}]}},async apply(){h("npm install -g @rulemetric/cli")}},{id:"auth",title:"Authenticate",command:"rulemetric auth login",async detect(){return m()},async plan(e){let t=a(e.configDir,"env"),n=null;if(p(t))try{n=X(y(t,"utf-8"))}catch{n="(unreadable)"}let o=x(e.configDir,"RULEMETRIC_ACCESS_TOKEN"),u=[`RULEMETRIC_ACCESS_TOKEN=${S(o||"<token-from-login>")}`],c=x(e.configDir,"RULEMETRIC_API_KEY");c&&u.push(`RULEMETRIC_API_KEY=${S(c)}`);let l=process.env.RULEMETRIC_API_URL;l&&u.push(`RULEMETRIC_API_URL=${l}`);let r=u.join(`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as X}from"./chunk-2KJAM2NG.js";import{b as Y}from"./chunk-IEQDLURA.js";import{d as z,e as Z}from"./chunk-UUFCTEBT.js";import{a as V}from"./chunk-ZYGBABMZ.js";import{a as $}from"./chunk-5OX6YKTR.js";import{a as C}from"./chunk-MJ5H7RDK.js";import{a as L}from"./chunk-W67DO5PT.js";import{a as N}from"./chunk-WO6MS654.js";import{a as F}from"./chunk-UTAETY5Z.js";import{b as x}from"./chunk-E4RGYYBC.js";import{a as B}from"./chunk-O65AQZYB.js";import{a as O}from"./chunk-ARC4Q3GL.js";import{b as D}from"./chunk-5RBLIVBF.js";import{a as G}from"./chunk-GRPUY2EZ.js";import{a as P}from"./chunk-UXB6DRR7.js";import{a as q}from"./chunk-INSKP5ED.js";import{a as J}from"./chunk-UA5GEVGW.js";import{a as R}from"./chunk-PZS55PW2.js";import{a as Q}from"./chunk-AKXGUQ5B.js";import{e as H}from"./chunk-Z4YVOVMM.js";import{b as W}from"./chunk-NKJTNGXR.js";import{a as K}from"./chunk-C6GLNE6X.js";import{a as U}from"./chunk-S2SKT5PV.js";import{l as M}from"./chunk-FUYR7CFD.js";import{d as T}from"./chunk-NF2BIEAF.js";import{b as S,e as A,f as k}from"./chunk-UGACB66X.js";import{a as s}from"./chunk-ZLLER3HP.js";var y=null,b=null,oe={process_eval:L,process_insights:N,process_launch:x,process_send_message:V,process_conversation:C,process_session_goal:$,distill_memories:W,memory_ab:B,process_run_cleanup:O,cron_refine_cases:q,cron_retire_unused_skills:Q,cron_reconcile_attribution:P,cron_suggest_instructions:H,cron_refresh_skills:R,cron_refresh_pricing:J,cron_eval_autorun:U,cron_auto_accept_suggestions:K,cron_instruction_training:G,cron_instruction_evolution:M,process_judge_review:F},j=Object.keys(oe),ae=new Set([]);function ie(e=process.env){return e.DATABASE_URL?j:j.filter(n=>!ae.has(n))}s(ie,"availableCapabilities");var le=3e4,ce=3e4,de=3e4,ee=500,ne=1e4,ue=`thin-agent-${process.pid}`,E=null;function me(e,n,r,c){let i;try{let l=T();i={claude:l.claudeBin!=null,codex:l.codexBin!=null,codexModel:l.codexConfiguredModel}}catch{}let g=s(l=>k("/api/workers/heartbeat",{workerType:"cli-worker",clientName:ue,clientVersion:c,workerVersion:"0.1.0",currentJobId:null,inFlightCount:0,lastError:null,status:l,metadata:{capabilities:e,mode:"thin-agent",llmEngines:i,machine:y?.summary()}}).then(u=>{let d=u?.advisory;d&&d.message!==E?(E=d.message,a(r,{event:"worker_advisory",code:d.code,message:d.message})):d||(E=null)}).catch(u=>{a(r,{event:"presence_heartbeat_error",error:u instanceof Error?u.message:String(u)})}),"send");g("alive");let f=setInterval(()=>g("alive"),de),o=null,m=s(()=>o||(clearInterval(f),o=Promise.race([g("shutting_down"),new Promise(l=>setTimeout(l,2e3).unref())]),o),"sayGoodbye");return n.addEventListener("abort",()=>{m()},{once:!0}),{shutdown:m}}s(me,"startPresenceHeartbeat");function a(e,n){try{e(JSON.stringify({ts:new Date().toISOString(),...n}))}catch{e(`[agent-loop] log_error event=${n.event}`)}}s(a,"structuredLog");function re(e,n){return n.aborted?Promise.resolve(!1):e<=0?Promise.resolve(!0):new Promise(r=>{let c=setTimeout(()=>{n.removeEventListener("abort",i),r(!0)},e),i=s(()=>{clearTimeout(c),n.removeEventListener("abort",i),r(!1)},"onAbort");n.addEventListener("abort",i,{once:!0})})}s(re,"abortableSleep");async function ge(e,n){let r=`capabilities=${encodeURIComponent(e.join(","))}&waitMs=${n}`,c=await A(`/api/work/next?${r}`);return c==null||typeof c=="string"?null:c}s(ge,"pollForWork");function pe(e,n){return{logger:{info:s(r=>n(r),"info"),warn:s(r=>n(r),"warn"),error:s(r=>n(r),"error")},job:{attempts:e}}}s(pe,"makeHelpers");async function _e(e,n,r){let c=oe[e.kind],i=Date.now();if(a(r,{event:"claim",jobId:e.id,kind:e.kind,attempts:e.attempts}),!c){let o=`unknown kind: ${e.kind}`;a(r,{event:"fail",jobId:e.id,kind:e.kind,terminal:!0,error:o}),await k(`/api/work/${e.id}/fail`,{leaseToken:e.leaseToken,error:o,terminal:!0}).catch(()=>{});return}let g=s(()=>{a(r,{event:"heartbeat",jobId:e.id}),k(`/api/work/${e.id}/heartbeat`,{leaseToken:e.leaseToken}).catch(o=>{a(r,{event:"heartbeat_error",jobId:e.id,error:o instanceof Error?o.message:String(o)})})},"beat"),f=setInterval(g,n);b={jobId:e.id,beat:g};try{let o=pe(e.attempts,r),m=await c(e.payload,o)??{};clearInterval(f),a(r,{event:"complete",jobId:e.id,kind:e.kind,durationMs:Date.now()-i}),await k(`/api/work/${e.id}/complete`,{leaseToken:e.leaseToken,result:m})}catch(o){clearInterval(f);let m=D(o),l=Z(y?.pausesSince(i)??[]),u=o instanceof Error?o.message:String(o),d=l?`${l}; ${u}`:u;a(r,{event:"fail",jobId:e.id,kind:e.kind,durationMs:Date.now()-i,terminal:m,error:d,...l?{pausedDuringJob:!0}:{}}),await k(`/api/work/${e.id}/fail`,{leaseToken:e.leaseToken,error:d,terminal:m}).catch(p=>{a(r,{event:"fail_post_error",jobId:e.id,error:p instanceof Error?p.message:String(p)})})}finally{b=null}}s(_e,"runOne");var te=new Set(["process_eval","process_conversation","process_insights","process_session_goal","distill_memories","memory_ab","cron_suggest_instructions","cron_eval_autorun","cron_instruction_evolution","process_judge_review"]);async function Je(e){let n=e.log??(()=>{}),r=e.pollWaitMs??le,c=e.heartbeatIntervalMs??ce,i=e.capabilities??ie();a(n,{event:"agent_start",capabilities:i,pollWaitMs:r,heartbeatIntervalMs:c});try{let t=Y();t.removed.length>0&&a(n,{event:"eval_worktrees_swept",removed:t.removed.length})}catch(t){a(n,{event:"eval_worktree_sweep_failed",error:t instanceof Error?t.message:String(t)})}y=z({signal:e.signal,onPause:s(t=>{a(n,{event:"machine_pause",...t,jobId:b?.jobId??null}),b?.beat()},"onPause")});let g=me(i,e.signal,n,e.version);X({signal:e.signal,log:n}).catch(t=>{a(n,{event:"tt_heartbeat_fatal",error:t instanceof Error?t.message:String(t)})});let f=5*6e4,o=0,m=s(()=>{if(!e.readInstalledVersion||!e.version)return!1;let t=Date.now();if(t-o<f)return!1;o=t;let w=e.readInstalledVersion();return!!(w&&w!==e.version)},"versionDrifted"),l=new AbortController,u=l.signal;e.signal.aborted?l.abort():e.signal.addEventListener("abort",()=>l.abort(),{once:!0});let d=s(async(t,w)=>{let _=ee;for(;!u.aborted;){if(m()){a(n,{event:"agent_version_drift",bootVersion:e.version,installedVersion:e.readInstalledVersion?.()??null}),l.abort(),e.onVersionDrift?.();break}let I=null;try{I=await ge([...w],r)}catch(v){let se=v instanceof S?v.statusCode:void 0;if(a(n,{event:"poll_error",lane:t,status:se,error:v instanceof Error?v.message:String(v)}),!await re(_,u))break;_=Math.min(_*2,ne);continue}if(!I){if(a(n,{event:"poll_204",lane:t}),!await re(_,u))break;_=Math.min(_*2,ne);continue}_=ee,await _e(I,c,n)}},"runLane"),p=i.filter(t=>te.has(t)),h=i.filter(t=>!te.has(t));p.length>0&&h.length>0?(a(n,{event:"agent_lanes",heavy:p.length,fast:h.length}),await Promise.all([d("heavy",p),d("fast",h)])):await d("single",i),await g.shutdown(),a(n,{event:"agent_stop"})}s(Je,"runAgentLoop");export{oe as a,j as b,ie as c,ge as d,Je as e};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as Re}from"./chunk-M7QSC64D.js";import{i as Ae}from"./chunk-DPCAPIQB.js";import{a as Pe,b as ye,c as ve,d as ke,e as ee,f as Ce}from"./chunk-W23MESHM.js";import{b as ce,i as ue,j as pe,k as de,l as ge,m as me,n as fe}from"./chunk-LB24UKHZ.js";import{c as we}from"./chunk-G7V4ZZZ3.js";import{d as he,e as be,g as $e}from"./chunk-PWTTCSQA.js";import{d as se,e as Z,f as le}from"./chunk-VBXL7XO7.js";import{e as P,f as K}from"./chunk-UGACB66X.js";import{a as u}from"./chunk-ZLLER3HP.js";import{createHash as We}from"node:crypto";import{existsSync as Ee,readFileSync as Se,writeFileSync as Ne}from"node:fs";var W=u(a=>We("sha256").update(a).digest("hex"),"sha256"),Ie=1.3,te=4,Le=20;function Fe(a,i){if(!a.configured||i<=0)return te;let t=Math.ceil(a.minPairs*Ie/i);return Math.min(Le,Math.max(te,t))}u(Fe,"passCapFor");function je(a,i=10,t=te){if(a<=0)return{passes:0,expectedPairs:0,feasible:!1,reason:"no live cases"};let l=Math.ceil(i*Ie),e=Math.min(t,Math.ceil(l/a)),r=e*a;return r<i?{passes:e,expectedPairs:r,feasible:!1,reason:`${a} live case(s) x ${t} passes = ${a*t} pairs at best, below the ${i} a controlled verdict requires \u2014 add cases rather than replaying these`}:{passes:e,expectedPairs:r,feasible:!0}}u(je,"planPasses");var Ue=60,qe=u(a=>typeof a=="object"&&a!==null&&typeof a.withScore=="number"&&typeof a.withoutScore=="number","isPair");function Ge(a,i,t){let l=[...a].sort((e,r)=>Date.parse(r.createdAt)-Date.parse(e.createdAt));for(let e of l){if(e.applied)continue;let r=e.gates?.accumulation;if(!r||typeof r!="object"||r.priorContentHash!==i||r.targetPairs!==t||typeof r.candidateContentHash!="string"||!Array.isArray(r.pairs))continue;let o=r.pairs.filter(qe);if(o.length===r.pairs.length&&!(o.length>=t))return{promotionId:e.id,candidateContentHash:r.candidateContentHash,pairs:o,runs:typeof r.runs=="number"?r.runs:1}}return null}u(Ge,"findOpenAccumulation");var Be=5,xe=u(a=>Array.isArray(a)?a.filter(i=>typeof i=="string"):[],"stringList"),j=u(a=>typeof a=="number"&&Number.isFinite(a)?a:null,"finite");function Xe(a,i,t=Be){let l=[...a].filter(o=>o.fromContentHash===i).sort((o,g)=>Date.parse(g.createdAt)-Date.parse(o.createdAt)),e=[],r=new Set;for(let o of l){let g=o.toContentHash??o.id;if(r.has(g))continue;r.add(g);let y=o.verdict??null,S=j(y?.delta),x=j(y?.ci?.lower),H=j(y?.ci?.upper),C=j(y?.nWith),ne=y?.sufficient===!0&&S!=null&&x!=null&&H!=null&&C!=null?{delta:S,ciLower:x,ciUpper:H,nPairs:C}:null;if(e.push({decision:typeof o.decision=="string"?o.decision:"unknown",applied:o.applied===!0,at:typeof o.createdAt=="string"?o.createdAt:"",rationale:typeof o.proposalRationale=="string"?o.proposalRationale:"",touched:xe(o.touchedSections),refusals:xe(o.refusals),measured:ne}),e.length>=t)break}return e}u(Xe,"summarisePriorDecisions");function ze(a,i){let t=i.accumulate??(a.autoEvolveAccumulate===!0||a.autoEvolveAccumulate==="true"),l=i.accumulateTargetPairs??a.autoEvolveAccumulateTarget,e=typeof l=="string"?Number.parseInt(l,10):l,r=typeof e=="number"&&Number.isInteger(e)&&e>0?e:Ue;return{enabled:t,targetPairs:r}}u(ze,"readAccumulateConfig");function Qe(a){let i=a.accumulateEnabled&&a.pairCount<a.targetPairs;return{apply:a.consented&&!i,peeking:i}}u(Qe,"resolveApply");async function it(a,i){let t=u(n=>i?.logger?.info?.(n)??console.log(n),"log"),{evalTargetId:l}=a,e=`[cron_instruction_evolution] ${l}`,r=await P(`/api/eval-targets/${l}`),o=r.metadata??{},g=null,y=!1;if(r.name.startsWith("/")&&Ee(r.name))try{if(g=Se(r.name,"utf8"),g!==r.content){let n=await K(`/api/eval-targets/${l}/sync-content`,{content:g});y=n.synced,t(`${e}: target content drifted from disk by ${Math.abs(g.length-r.content.length)} chars \u2014 synced to disk truth (v${n.version}). Prior verdicts against the old text dissolve via content-hash keying.`),r={...r,content:g,version:n.version}}}catch(n){t(`${e}: disk sync failed (${n instanceof Error?n.message:String(n)}) \u2014 measuring the stored snapshot`)}let S=!1;try{S=(await P("/api/settings/evolution-account")).paused}catch(n){t(`${e}: could not read the account switch (${n instanceof Error?n.message:String(n)}) \u2014 pausing to be safe`),S=!0}if(S)return t(`${e}: PAUSED for the whole account (profiles.evolution_paused) \u2014 no model budget spent.`),{skipped:"paused-account"};if(pe(o))return t(`${e}: PAUSED (metadata.autoEvolvePaused) \u2014 no model budget spent. Opt-in is intact.`),{skipped:"paused"};let x=Re(r);if(x)return t(`${e}: ${x.reason}`),x;let H=a.apply??(o.autoEvolveApply===!0||o.autoEvolveApply==="true"),C=Ve(o);if(C==null){if(H)return t(`${e}: refusing \u2014 metadata.immutableSections is unset. Set it (use [] to explicitly protect nothing) before letting the loop edit this target unattended.`),{skipped:"immutable-sections-unset"};t(`${e}: metadata.immutableSections unset \u2014 measure-only cycle proceeds with [] (nothing protected). Writing still requires setting it explicitly.`),C=[]}let $=(await P(`/api/eval-targets/${l}/evals`)).filter(n=>!n.retiredAt);if($.length===0)return{skipped:"no-live-cases"};let N=ue(o);N.note&&t(`${e}: ${N.note}`);let v=je($.length,N.minPairs,Fe(N,$.length));if(!v.feasible)return t(`${e}: cannot reach a sufficient verdict \u2014 ${v.reason}`),{skipped:"cannot-reach-min-n",reason:v.reason};let He=de({liveCases:$.length,passes:v.passes});t(`${e}: budget for this run \u2014 ${fe(He)}`);let U=await P(`/api/eval-targets/${l}/judge-calibration`);if(!U.powerCheck.adequate){let n=(U.powerCheck.reasons??[]).join("; ");return t(`${e}: not adequately powered, skipping before spending budget \u2014 ${n}`),{skipped:"not-adequate",reason:n}}let re=le,_e=Date.now()-re*24*60*60*1e3,q=await P(`/api/eval-targets/${l}/promotions?limit=200`),ae=q.promotions.filter(n=>n.applied&&Date.parse(n.createdAt)>=_e).length;if(ae>=Z)return t(`${e}: change budget looks exhausted (${ae}/${Z} applied in ${re}d), skipping before spending budget`),{skipped:"budget-exhausted"};try{let n=await P("/api/usage/current-limits"),c=we({limits:n,now:new Date});if(!c.ok)return t(`${e}: deferring before spending budget \u2014 ${c.reason}`),{skipped:"quota-exhausted",reason:c.reason}}catch(n){t(`${e}: quota unknown (${n instanceof Error?n.message:String(n)}) \u2014 proceeding`)}let L=se();if(!L.green)return t(`${e}: A/A canary is RED \u2014 halting. ${L.failures.join(" | ")}`),{skipped:"canary-red",reason:L.failures.join(" | ")};let G=r.content,D=W(G),p=ze(o,a),k=p.enabled?Ge(q.promotions,D,p.targetPairs):null,m,F,w=[],_=0,B=ce,f=k?null:ye(o,D);if(f){m=f.content,F="",B=0;try{w=await ke({evalTargetId:l,candidateContentHash:f.hash})}catch(n){return t(`${e}: could not rebuild banked pairs (${n instanceof Error?n.message:String(n)})`),{skipped:"resume-read-failed",reason:f.hash}}t(`${e}: resuming interrupted cycle \u2014 ${w.length}/${f.plannedPairs} pair(s) rebuilt from eval_runs, no proposal call spent`)}else if(k){let n=await P(`/api/promotions/${k.promotionId}`);if(W(n.toContent)!==k.candidateContentHash)return t(`${e}: stored candidate does not match its recorded hash \u2014 refusing to continue`),{skipped:"accumulation-hash-mismatch",reason:k.promotionId};m=n.toContent,F=n.proposalRationale??"",w=k.pairs,_=k.runs,B=0,t(`${e}: continuing accumulation ${k.promotionId} \u2014 ${w.length}/${p.targetPairs} pair(s) carried from ${_} prior run(s)`)}else{let n=U.caseDiscrimination?.cases??[],c=[];if(r.name.startsWith("/")){let s=r.name.slice(0,r.name.lastIndexOf("/"));try{let b=await P(`/api/insights/evidence?projectPath=${encodeURIComponent(s)}`);b.analyzedAt&&(c=[...b.friction.map(Y=>`Real-session friction (insights, ${b.analyzedAt.slice(0,10)}): ${Y}`),...b.whatWorks.map(Y=>`Working well in real sessions \u2014 do not break: ${Y}`)],c.length>0&&t(`${e}: proposer sees ${b.friction.length} friction + ${b.whatWorks.length} what-works item(s) from insights`))}catch(b){t(`${e}: insights evidence unavailable (${b instanceof Error?b.message:String(b)}) \u2014 proposing without it`)}}let T=[];try{T=Xe(q.promotions,D)}catch(s){t(`${e}: could not summarise prior decisions (${s instanceof Error?s.message:String(s)}) \u2014 proposing without them`)}T.length>0&&t(`${e}: proposer sees ${T.length} prior decision(s) against this exact body (${T.map(s=>`${s.decision}${s.measured?"/measured":""}`).join(", ")})`);let M=await Ae({currentContent:r.content,targetType:r.type,targetName:r.name,immutableSections:C,evidence:{nonDiscriminating:n.filter(s=>!s.discriminating).map(s=>`${s.name??s.assertion??"unnamed"} \u2014 ${s.note}`),weakest:n.filter(s=>s.discriminating&&s.withPassRate<s.withoutPassRate).map(s=>({name:s.name??s.assertion??"unnamed",withPassRate:s.withPassRate,withoutPassRate:s.withoutPassRate})),priorDecisions:T,notes:c}});if(!M.ok)return t(`${e}: no usable proposal \u2014 ${M.reason}`),{skipped:"no-proposal",reason:M.reason};m=M.proposal.candidateContent,F=M.proposal.rationale}let I=f?ve({plannedPairs:f.plannedPairs||v.expectedPairs,carriedPairs:w.length,liveCases:$.length}):v.passes;t(`${e}: measuring ${$.length} case(s) x ${I} pass(es) = up to ${$.length*I} pairs, candidate vs prior version`+(f?` (resumed; ${w.length} pair(s) already banked)`:""));let A=[],X=[],Oe=Date.now(),oe=0,z=0;for(let n=1;n<=I;n++){let c=await $e({cases:$,candidateContent:m,priorVersionContent:G,concurrency:a.concurrency??2,runNumber:n,opts:{targetId:l,targetVersion:r.version??1,iteration:1,timeout:a.timeout??24e4,model:a.model,graderModel:a.graderModel,skipGrading:!1,targetType:r.type,targetName:r.name,candidateContentHash:W(m)},onLog:t});if(A.push(...c.pairs),X.push(...c.results),oe+=c.completed,z+=c.failed,t(`${e}: pass ${n}/${I} \u2014 ${c.pairs.length} pair(s), running total ${A.length}`),c.abortedForQuota){t(`${e}: stopping after pass ${n}/${I} \u2014 ${c.abortedForQuota}. Remaining passes would spend against an exhausted account.`);break}}let R=[...w,...A],O=he(X),Q=A.length>0,d=ge({runs:X,plannedPairs:v.expectedPairs,usablePairs:A.length,verdictPairs:Q?R.length:A.length,proposalCalls:B,passes:I,liveCases:$.length,wallMs:Date.now()-Oe});if(t(`${e}: ${oe} completed, ${z} failed, ${A.length} usable pair(s) \u2014 spent ~${d.modelCalls} model calls (${d.proposalCalls} proposal + ${d.executorCalls} executor + >=${d.graderCalls} grader) in ${(d.wallMs/6e4).toFixed(1)} min`+(Q?`; the ${d.verdictPairs} pair(s) behind this verdict resolve +/-${me(d.mde)} at 80% power`:"")),!Q)return{skipped:O.infrastructureFailed?"infrastructure-failure":"no-pairs",reason:O.infrastructureFailed?`${O.infrastructureFailed} run(s) never executed (${O.summary.describe()}) \u2014 the environment failed, not the target`:`${z} run(s) failed or were ungradeable`,cost:d};let V=be({pairs:R.length,minPairs:10,accounting:O});if(V.kind==="infrastructure-incomplete")return t(`${e}: not posting a verdict \u2014 ${V.reason}`),await ee({evalTargetId:l,meta:o,blob:Ce({content:m,hash:W(m),priorHash:D,plannedPairs:f?.plannedPairs||v.expectedPairs,now:new Date}),log:t,tag:e}),{skipped:"infrastructure-incomplete",reason:V.reason,cost:d};p.enabled&&t(`${e}: accumulated ${R.length}/${p.targetPairs} pair(s) over ${_+1} run(s) on one candidate`);let ie=H,{apply:Te,peeking:Me}=Qe({consented:ie,accumulateEnabled:p.enabled,pairCount:R.length,targetPairs:p.targetPairs});ie&&Me&&t(`${e}: interim readout at ${R.length}/${p.targetPairs} pairs \u2014 recording the decision but not acting until the target is reached`);let h=await K(`/api/eval-targets/${l}/promotions`,{candidateContent:m,proposalSource:"llm",proposalRationale:F,pairs:R,canaryGreen:L.green,measuredAgainstContentHash:D,immutableSections:C,apply:Te,measurementCost:d,...p.enabled?{accumulation:{candidateContentHash:W(m),priorContentHash:D,targetPairs:p.targetPairs,carriedPairs:w.length,runs:_+1}}:{}});t(`${e}: ${h.decision}${h.applied?" (APPLIED)":""} \u2014 ${h.rationale}`+(h.refusals.length>0?` | refusals: ${h.refusals.join("; ")}`:"")),(f||o[Pe])&&await ee({evalTargetId:l,meta:o,blob:null,log:t,tag:e});let J=!1,E;if(h.applied&&r.name.startsWith("/"))try{Ee(r.name)?Se(r.name,"utf8")!==G?E="file changed since measurement started \u2014 refusing to clobber; next cycle re-syncs":(Ne(r.name,m,"utf8"),J=!0):E="file no longer exists on disk",t(J?`${e}: measured improvement written to ${r.name} (undo: git checkout -- ${r.name})`:`${e}: NOT written to disk \u2014 ${E}`)}catch(n){E=n instanceof Error?n.message:String(n),t(`${e}: disk write-back failed \u2014 ${E}. The eval target is updated; the file is not.`)}return{decision:h.decision,applied:h.applied,nPairs:R.length,promotionId:h.id,cost:d,diskSynced:y,...h.applied?{fileWritten:J,...E?{fileWriteSkipped:E}:{}}:{},...p.enabled?{carriedPairs:w.length,accumulationRuns:_+1}:{}}}u(it,"cronInstructionEvolution");function Ve(a){let i=a.immutableSections;return i==null||!Array.isArray(i)?null:i.filter(t=>typeof t=="string")}u(Ve,"readImmutableSections");export{Ie as a,te as b,Le as c,Fe as d,je as e,Ue as f,Ge as g,Be as h,Xe as i,ze as j,Qe as k,it as l,Ve as m};
|
|
1
|
+
import{a as Re}from"./chunk-M7QSC64D.js";import{i as Ae}from"./chunk-DPCAPIQB.js";import{c as we}from"./chunk-G7V4ZZZ3.js";import{a as Pe,b as ye,c as ve,d as ke,e as ee,f as Ce}from"./chunk-W23MESHM.js";import{b as ce,i as ue,j as pe,k as de,l as ge,m as me,n as fe}from"./chunk-LB24UKHZ.js";import{d as he,e as be,g as $e}from"./chunk-PWTTCSQA.js";import{d as se,e as Z,f as le}from"./chunk-VBXL7XO7.js";import{e as P,f as K}from"./chunk-UGACB66X.js";import{a as u}from"./chunk-ZLLER3HP.js";import{createHash as We}from"node:crypto";import{existsSync as Ee,readFileSync as Se,writeFileSync as Ne}from"node:fs";var W=u(a=>We("sha256").update(a).digest("hex"),"sha256"),Ie=1.3,te=4,Le=20;function Fe(a,i){if(!a.configured||i<=0)return te;let t=Math.ceil(a.minPairs*Ie/i);return Math.min(Le,Math.max(te,t))}u(Fe,"passCapFor");function je(a,i=10,t=te){if(a<=0)return{passes:0,expectedPairs:0,feasible:!1,reason:"no live cases"};let l=Math.ceil(i*Ie),e=Math.min(t,Math.ceil(l/a)),r=e*a;return r<i?{passes:e,expectedPairs:r,feasible:!1,reason:`${a} live case(s) x ${t} passes = ${a*t} pairs at best, below the ${i} a controlled verdict requires \u2014 add cases rather than replaying these`}:{passes:e,expectedPairs:r,feasible:!0}}u(je,"planPasses");var Ue=60,qe=u(a=>typeof a=="object"&&a!==null&&typeof a.withScore=="number"&&typeof a.withoutScore=="number","isPair");function Ge(a,i,t){let l=[...a].sort((e,r)=>Date.parse(r.createdAt)-Date.parse(e.createdAt));for(let e of l){if(e.applied)continue;let r=e.gates?.accumulation;if(!r||typeof r!="object"||r.priorContentHash!==i||r.targetPairs!==t||typeof r.candidateContentHash!="string"||!Array.isArray(r.pairs))continue;let o=r.pairs.filter(qe);if(o.length===r.pairs.length&&!(o.length>=t))return{promotionId:e.id,candidateContentHash:r.candidateContentHash,pairs:o,runs:typeof r.runs=="number"?r.runs:1}}return null}u(Ge,"findOpenAccumulation");var Be=5,xe=u(a=>Array.isArray(a)?a.filter(i=>typeof i=="string"):[],"stringList"),j=u(a=>typeof a=="number"&&Number.isFinite(a)?a:null,"finite");function Xe(a,i,t=Be){let l=[...a].filter(o=>o.fromContentHash===i).sort((o,g)=>Date.parse(g.createdAt)-Date.parse(o.createdAt)),e=[],r=new Set;for(let o of l){let g=o.toContentHash??o.id;if(r.has(g))continue;r.add(g);let y=o.verdict??null,S=j(y?.delta),x=j(y?.ci?.lower),H=j(y?.ci?.upper),C=j(y?.nWith),ne=y?.sufficient===!0&&S!=null&&x!=null&&H!=null&&C!=null?{delta:S,ciLower:x,ciUpper:H,nPairs:C}:null;if(e.push({decision:typeof o.decision=="string"?o.decision:"unknown",applied:o.applied===!0,at:typeof o.createdAt=="string"?o.createdAt:"",rationale:typeof o.proposalRationale=="string"?o.proposalRationale:"",touched:xe(o.touchedSections),refusals:xe(o.refusals),measured:ne}),e.length>=t)break}return e}u(Xe,"summarisePriorDecisions");function ze(a,i){let t=i.accumulate??(a.autoEvolveAccumulate===!0||a.autoEvolveAccumulate==="true"),l=i.accumulateTargetPairs??a.autoEvolveAccumulateTarget,e=typeof l=="string"?Number.parseInt(l,10):l,r=typeof e=="number"&&Number.isInteger(e)&&e>0?e:Ue;return{enabled:t,targetPairs:r}}u(ze,"readAccumulateConfig");function Qe(a){let i=a.accumulateEnabled&&a.pairCount<a.targetPairs;return{apply:a.consented&&!i,peeking:i}}u(Qe,"resolveApply");async function it(a,i){let t=u(n=>i?.logger?.info?.(n)??console.log(n),"log"),{evalTargetId:l}=a,e=`[cron_instruction_evolution] ${l}`,r=await P(`/api/eval-targets/${l}`),o=r.metadata??{},g=null,y=!1;if(r.name.startsWith("/")&&Ee(r.name))try{if(g=Se(r.name,"utf8"),g!==r.content){let n=await K(`/api/eval-targets/${l}/sync-content`,{content:g});y=n.synced,t(`${e}: target content drifted from disk by ${Math.abs(g.length-r.content.length)} chars \u2014 synced to disk truth (v${n.version}). Prior verdicts against the old text dissolve via content-hash keying.`),r={...r,content:g,version:n.version}}}catch(n){t(`${e}: disk sync failed (${n instanceof Error?n.message:String(n)}) \u2014 measuring the stored snapshot`)}let S=!1;try{S=(await P("/api/settings/evolution-account")).paused}catch(n){t(`${e}: could not read the account switch (${n instanceof Error?n.message:String(n)}) \u2014 pausing to be safe`),S=!0}if(S)return t(`${e}: PAUSED for the whole account (profiles.evolution_paused) \u2014 no model budget spent.`),{skipped:"paused-account"};if(pe(o))return t(`${e}: PAUSED (metadata.autoEvolvePaused) \u2014 no model budget spent. Opt-in is intact.`),{skipped:"paused"};let x=Re(r);if(x)return t(`${e}: ${x.reason}`),x;let H=a.apply??(o.autoEvolveApply===!0||o.autoEvolveApply==="true"),C=Ve(o);if(C==null){if(H)return t(`${e}: refusing \u2014 metadata.immutableSections is unset. Set it (use [] to explicitly protect nothing) before letting the loop edit this target unattended.`),{skipped:"immutable-sections-unset"};t(`${e}: metadata.immutableSections unset \u2014 measure-only cycle proceeds with [] (nothing protected). Writing still requires setting it explicitly.`),C=[]}let $=(await P(`/api/eval-targets/${l}/evals`)).filter(n=>!n.retiredAt);if($.length===0)return{skipped:"no-live-cases"};let N=ue(o);N.note&&t(`${e}: ${N.note}`);let v=je($.length,N.minPairs,Fe(N,$.length));if(!v.feasible)return t(`${e}: cannot reach a sufficient verdict \u2014 ${v.reason}`),{skipped:"cannot-reach-min-n",reason:v.reason};let He=de({liveCases:$.length,passes:v.passes});t(`${e}: budget for this run \u2014 ${fe(He)}`);let U=await P(`/api/eval-targets/${l}/judge-calibration`);if(!U.powerCheck.adequate){let n=(U.powerCheck.reasons??[]).join("; ");return t(`${e}: not adequately powered, skipping before spending budget \u2014 ${n}`),{skipped:"not-adequate",reason:n}}let re=le,_e=Date.now()-re*24*60*60*1e3,q=await P(`/api/eval-targets/${l}/promotions?limit=200`),ae=q.promotions.filter(n=>n.applied&&Date.parse(n.createdAt)>=_e).length;if(ae>=Z)return t(`${e}: change budget looks exhausted (${ae}/${Z} applied in ${re}d), skipping before spending budget`),{skipped:"budget-exhausted"};try{let n=await P("/api/usage/current-limits"),c=we({limits:n,now:new Date});if(!c.ok)return t(`${e}: deferring before spending budget \u2014 ${c.reason}`),{skipped:"quota-exhausted",reason:c.reason}}catch(n){t(`${e}: quota unknown (${n instanceof Error?n.message:String(n)}) \u2014 proceeding`)}let L=se();if(!L.green)return t(`${e}: A/A canary is RED \u2014 halting. ${L.failures.join(" | ")}`),{skipped:"canary-red",reason:L.failures.join(" | ")};let G=r.content,D=W(G),p=ze(o,a),k=p.enabled?Ge(q.promotions,D,p.targetPairs):null,m,F,w=[],_=0,B=ce,f=k?null:ye(o,D);if(f){m=f.content,F="",B=0;try{w=await ke({evalTargetId:l,candidateContentHash:f.hash})}catch(n){return t(`${e}: could not rebuild banked pairs (${n instanceof Error?n.message:String(n)})`),{skipped:"resume-read-failed",reason:f.hash}}t(`${e}: resuming interrupted cycle \u2014 ${w.length}/${f.plannedPairs} pair(s) rebuilt from eval_runs, no proposal call spent`)}else if(k){let n=await P(`/api/promotions/${k.promotionId}`);if(W(n.toContent)!==k.candidateContentHash)return t(`${e}: stored candidate does not match its recorded hash \u2014 refusing to continue`),{skipped:"accumulation-hash-mismatch",reason:k.promotionId};m=n.toContent,F=n.proposalRationale??"",w=k.pairs,_=k.runs,B=0,t(`${e}: continuing accumulation ${k.promotionId} \u2014 ${w.length}/${p.targetPairs} pair(s) carried from ${_} prior run(s)`)}else{let n=U.caseDiscrimination?.cases??[],c=[];if(r.name.startsWith("/")){let s=r.name.slice(0,r.name.lastIndexOf("/"));try{let b=await P(`/api/insights/evidence?projectPath=${encodeURIComponent(s)}`);b.analyzedAt&&(c=[...b.friction.map(Y=>`Real-session friction (insights, ${b.analyzedAt.slice(0,10)}): ${Y}`),...b.whatWorks.map(Y=>`Working well in real sessions \u2014 do not break: ${Y}`)],c.length>0&&t(`${e}: proposer sees ${b.friction.length} friction + ${b.whatWorks.length} what-works item(s) from insights`))}catch(b){t(`${e}: insights evidence unavailable (${b instanceof Error?b.message:String(b)}) \u2014 proposing without it`)}}let T=[];try{T=Xe(q.promotions,D)}catch(s){t(`${e}: could not summarise prior decisions (${s instanceof Error?s.message:String(s)}) \u2014 proposing without them`)}T.length>0&&t(`${e}: proposer sees ${T.length} prior decision(s) against this exact body (${T.map(s=>`${s.decision}${s.measured?"/measured":""}`).join(", ")})`);let M=await Ae({currentContent:r.content,targetType:r.type,targetName:r.name,immutableSections:C,evidence:{nonDiscriminating:n.filter(s=>!s.discriminating).map(s=>`${s.name??s.assertion??"unnamed"} \u2014 ${s.note}`),weakest:n.filter(s=>s.discriminating&&s.withPassRate<s.withoutPassRate).map(s=>({name:s.name??s.assertion??"unnamed",withPassRate:s.withPassRate,withoutPassRate:s.withoutPassRate})),priorDecisions:T,notes:c}});if(!M.ok)return t(`${e}: no usable proposal \u2014 ${M.reason}`),{skipped:"no-proposal",reason:M.reason};m=M.proposal.candidateContent,F=M.proposal.rationale}let I=f?ve({plannedPairs:f.plannedPairs||v.expectedPairs,carriedPairs:w.length,liveCases:$.length}):v.passes;t(`${e}: measuring ${$.length} case(s) x ${I} pass(es) = up to ${$.length*I} pairs, candidate vs prior version`+(f?` (resumed; ${w.length} pair(s) already banked)`:""));let A=[],X=[],Oe=Date.now(),oe=0,z=0;for(let n=1;n<=I;n++){let c=await $e({cases:$,candidateContent:m,priorVersionContent:G,concurrency:a.concurrency??2,runNumber:n,opts:{targetId:l,targetVersion:r.version??1,iteration:1,timeout:a.timeout??24e4,model:a.model,graderModel:a.graderModel,skipGrading:!1,targetType:r.type,targetName:r.name,candidateContentHash:W(m)},onLog:t});if(A.push(...c.pairs),X.push(...c.results),oe+=c.completed,z+=c.failed,t(`${e}: pass ${n}/${I} \u2014 ${c.pairs.length} pair(s), running total ${A.length}`),c.abortedForQuota){t(`${e}: stopping after pass ${n}/${I} \u2014 ${c.abortedForQuota}. Remaining passes would spend against an exhausted account.`);break}}let R=[...w,...A],O=he(X),Q=A.length>0,d=ge({runs:X,plannedPairs:v.expectedPairs,usablePairs:A.length,verdictPairs:Q?R.length:A.length,proposalCalls:B,passes:I,liveCases:$.length,wallMs:Date.now()-Oe});if(t(`${e}: ${oe} completed, ${z} failed, ${A.length} usable pair(s) \u2014 spent ~${d.modelCalls} model calls (${d.proposalCalls} proposal + ${d.executorCalls} executor + >=${d.graderCalls} grader) in ${(d.wallMs/6e4).toFixed(1)} min`+(Q?`; the ${d.verdictPairs} pair(s) behind this verdict resolve +/-${me(d.mde)} at 80% power`:"")),!Q)return{skipped:O.infrastructureFailed?"infrastructure-failure":"no-pairs",reason:O.infrastructureFailed?`${O.infrastructureFailed} run(s) never executed (${O.summary.describe()}) \u2014 the environment failed, not the target`:`${z} run(s) failed or were ungradeable`,cost:d};let V=be({pairs:R.length,minPairs:10,accounting:O});if(V.kind==="infrastructure-incomplete")return t(`${e}: not posting a verdict \u2014 ${V.reason}`),await ee({evalTargetId:l,meta:o,blob:Ce({content:m,hash:W(m),priorHash:D,plannedPairs:f?.plannedPairs||v.expectedPairs,now:new Date}),log:t,tag:e}),{skipped:"infrastructure-incomplete",reason:V.reason,cost:d};p.enabled&&t(`${e}: accumulated ${R.length}/${p.targetPairs} pair(s) over ${_+1} run(s) on one candidate`);let ie=H,{apply:Te,peeking:Me}=Qe({consented:ie,accumulateEnabled:p.enabled,pairCount:R.length,targetPairs:p.targetPairs});ie&&Me&&t(`${e}: interim readout at ${R.length}/${p.targetPairs} pairs \u2014 recording the decision but not acting until the target is reached`);let h=await K(`/api/eval-targets/${l}/promotions`,{candidateContent:m,proposalSource:"llm",proposalRationale:F,pairs:R,canaryGreen:L.green,measuredAgainstContentHash:D,immutableSections:C,apply:Te,measurementCost:d,...p.enabled?{accumulation:{candidateContentHash:W(m),priorContentHash:D,targetPairs:p.targetPairs,carriedPairs:w.length,runs:_+1}}:{}});t(`${e}: ${h.decision}${h.applied?" (APPLIED)":""} \u2014 ${h.rationale}`+(h.refusals.length>0?` | refusals: ${h.refusals.join("; ")}`:"")),(f||o[Pe])&&await ee({evalTargetId:l,meta:o,blob:null,log:t,tag:e});let J=!1,E;if(h.applied&&r.name.startsWith("/"))try{Ee(r.name)?Se(r.name,"utf8")!==G?E="file changed since measurement started \u2014 refusing to clobber; next cycle re-syncs":(Ne(r.name,m,"utf8"),J=!0):E="file no longer exists on disk",t(J?`${e}: measured improvement written to ${r.name} (undo: git checkout -- ${r.name})`:`${e}: NOT written to disk \u2014 ${E}`)}catch(n){E=n instanceof Error?n.message:String(n),t(`${e}: disk write-back failed \u2014 ${E}. The eval target is updated; the file is not.`)}return{decision:h.decision,applied:h.applied,nPairs:R.length,promotionId:h.id,cost:d,diskSynced:y,...h.applied?{fileWritten:J,...E?{fileWriteSkipped:E}:{}}:{},...p.enabled?{carriedPairs:w.length,accumulationRuns:_+1}:{}}}u(it,"cronInstructionEvolution");function Ve(a){let i=a.immutableSections;return i==null||!Array.isArray(i)?null:i.filter(t=>typeof t=="string")}u(Ve,"readImmutableSections");export{Ie as a,te as b,Le as c,Fe as d,je as e,Ue as f,Ge as g,Be as h,Xe as i,ze as j,Qe as k,it as l,Ve as m};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as u,c as d}from"./chunk-
|
|
1
|
+
import{b as u,c as d}from"./chunk-UKOI2Q4J.js";import{b as g}from"./chunk-KJRMGTAO.js";import{e as m,f as p,h as l}from"./chunk-UGACB66X.js";import{a as s}from"./chunk-ZLLER3HP.js";async function x(f,R){let r=s(e=>R?.logger?.info?.(e)??console.log(e),"log"),{evalTargetId:n}=f,i=`[cron_refine_cases] ${n}`,t=await m(`/api/eval-targets/${n}`);if(!(t.metadata?.autoRefineCases===!0))return r(`${i} not opted in (metadata.autoRefineCases)`),{skipped:"not-opted-in",reason:`"${t.name}" has not opted into automatic case refinement. Set metadata.autoRefineCases=true to let the loop cull cases that carry no treatment signal, or run \`rulemetric evals refine-cases ${n}\` by hand.`,targetName:t.name};let C=await m(`/api/eval-targets/${n}/judge-calibration`),a=u(C.caseDiscrimination);if(a.refused)return r(`${i} ${a.refused}: ${a.summary}`),{skipped:a.refused,reason:a.summary,targetName:t.name};r(`${i} ${a.summary}`);let o=await d(a,{generate:s(e=>g({content:t.content,name:t.name,feedback:e}),"generate"),createCase:s(e=>p(`/api/eval-targets/${n}/evals`,{name:e.name,prompt:e.prompt,expectations:e.expectations}),"createCase"),retireCase:s(async(e,y)=>{await l(`/api/eval-targets/${n}/evals/${e}`,{retire:!0,retiredReason:y})},"retireCase"),log:r});r(`${i} ${o.summary}`);let{skipped:c,...$}=o;return{...$,targetName:t.name,...c?{skipped:c,reason:o.summary}:{}}}s(x,"cronRefineCases");export{x as a};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{A as u,D as d}from"./chunk-
|
|
1
|
+
import{A as u,D as d}from"./chunk-OZQNSELV.js";import{a as s}from"./chunk-ZLLER3HP.js";import{existsSync as l,readFileSync as p,unlinkSync as y,writeFileSync as a}from"node:fs";import{homedir as h}from"node:os";import{join as S}from"node:path";function f(){return{vscode:u(),cursor:d(),marker:S(h(),".config","rulemetric","editor-proxy-unpinned.json")}}s(f,"defaultEditorPinPaths");function m(r,t){return r===`http://localhost:${t}`||r===`http://127.0.0.1:${t}`}s(m,"isOurProxyValue");function c(r){if(!l(r))return null;try{return JSON.parse(p(r,"utf-8"))}catch{return null}}s(c,"readSettings");function v(r,t=f()){let o=[];for(let e of["vscode","cursor"]){let n=t[e],i=c(n);if(!(!i||!m(i["http.proxy"],r))){delete i["http.proxy"],i["http.proxyStrictSSL"]===!1&&delete i["http.proxyStrictSSL"];try{a(n,JSON.stringify(i,null,2)+`
|
|
2
2
|
`),o.push(e)}catch{}}}if(o.length>0){let e=c(t.marker),n=[...new Set([...e?.editors??[],...o])];try{a(t.marker,JSON.stringify({editors:n,gatewayPort:r,unpinnedAt:new Date().toISOString()},null,2)+`
|
|
3
3
|
`)}catch{}}return o}s(v,"unpinEditorProxies");function A(r,t=f()){let o=c(t.marker);if(!o||!Array.isArray(o.editors))return[];let e=[];for(let n of o.editors)if(!(n!=="vscode"&&n!=="cursor"))try{r(n),e.push(n)}catch{}try{y(t.marker)}catch{}return e}s(A,"repinEditorProxies");export{f as a,v as b,A as c};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import{f as x}from"./chunk-HFGO5762.js";import{a as b}from"./chunk-VS5ROGDP.js";import{a as r}from"./chunk-ZLLER3HP.js";import{execSync as h}from"node:child_process";import{existsSync as c,mkdirSync as y,readFileSync as p,writeFileSync as a,unlinkSync as v,copyFileSync as N}from"node:fs";import{homedir as f}from"node:os";import{join as i,dirname as U}from"node:path";function Z(e,t=f()){let o=["claude_code"];return c(i(t,".codex"))&&o.push("codex"),c(i(e,".cursor"))&&o.push("cursor"),c(i(e,".github"))&&o.push("copilot_agent"),c(i(t,".gemini"))&&o.push("antigravity"),o}r(Z,"detectInstalledTools");function L(e){let t=e?`PATH="${e}:$PATH" `:"",o=r(n=>({command:`${t}rulemetric hooks run ${n}`}),"cmd");return{version:1,hooks:{sessionStart:[o("session-start")],beforeSubmitPrompt:[o("user-prompt")],afterFileEdit:[o("post-tool-use")],beforeShellExecution:[o("post-tool-use")],afterShellExecution:[o("post-tool-use")],beforeMCPExecution:[o("post-tool-use")],afterMCPExecution:[o("post-tool-use")],afterAgentResponse:[o("assistant-response")],stop:[o("post-tool-use")],sessionEnd:[o("session-end")]}}}r(L,"generateCursorHooksConfig");function B(e){let t=e?`PATH="${e}:$PATH" `:"",o=r(n=>({type:"command",bash:`${t}rulemetric hooks run ${n}`}),"cmd");return{version:1,hooks:{sessionStart:[o("session-start")],userPromptSubmitted:[o("user-prompt")],postToolUse:[o("post-tool-use")],sessionEnd:[o("session-end")]}}}r(B,"generateCopilotHooksConfig");function J(e){let t=e?`PATH="${e}:$PATH" `:"",o=r(n=>({type:"command",command:`${t}rulemetric hooks run ${n}`,timeout:b[n]}),"mk");return{SessionStart:[{hooks:[o("session-start")]}],UserPromptSubmit:[{hooks:[o("user-prompt")]}],PostToolUse:[{matcher:".*",hooks:[o("post-tool-use")]}],SessionEnd:[{hooks:[o("session-end")]}]}}r(J,"generateClaudeCodeHooksConfig");function D(e){if(!c(e))return{settings:{},recoveredBackup:null};let t=p(e,"utf-8");try{return{settings:JSON.parse(t),recoveredBackup:null}}catch{let o=`${e}.corrupt.bak`;return a(o,t),{settings:{},recoveredBackup:o}}}r(D,"readClaudeSettings");function C(e,t){y(U(e),{recursive:!0});let o=null;return c(e)&&(o=`${e}.bak`,N(e,o)),a(e,JSON.stringify(t,null,2)+`
|
|
2
|
+
`),{backupPath:o}}r(C,"writeClaudeSettingsWithBackup");function k(e){if(!c(e))return{};let t=p(e,"utf-8");try{return JSON.parse(t)}catch{try{a(`${e}.corrupt.bak`,t)}catch{}return null}}r(k,"readMergeableJson");function tt(e,t){let o=J(t),n=e.hooks??{};for(let[s,u]of Object.entries(o)){let l=n[s]??[];l.some(m=>m?.hooks?.some(d=>typeof d?.command=="string"&&d.command.includes("rulemetric")))||(n[s]=[...l,...u])}e.hooks=n}r(tt,"mergeClaudeCodeHooks");function et(e){if(!e.hooks||typeof e.hooks!="object")return!1;let t=e.hooks;return Object.values(t).some(o=>Array.isArray(o)&&o.some(n=>n?.hooks?.some(s=>typeof s?.command=="string"&&s.command.includes("rulemetric"))))}r(et,"hasRulemetricClaudeHooks");function X(e){if(!e.hooks||typeof e.hooks!="object")return!1;let t=e.hooks,o=0;for(let n of Object.keys(t)){let s=t[n];if(!Array.isArray(s))continue;let u=s.filter(l=>{let g=l?.hooks?.some(m=>typeof m?.command=="string"&&m.command.includes("rulemetric"));return g&&(o+=1),!g});u.length===0?delete t[n]:t[n]=u}return Object.keys(t).length===0&&delete e.hooks,o>0}r(X,"removeClaudeCodeHooks");var M="localhost,127.0.0.1,*.supabase.co,*.supabase.in";function ot(e,t){return i(e,t?"settings.json":"settings.local.json")}r(ot,"claudeSettingsInstallPath");function F(e,t){let o=e.env;if(!o||typeof o!="object")return!1;let n=!1,s=o.HTTPS_PROXY;(s===`http://localhost:${t}`||s===`http://127.0.0.1:${t}`)&&(delete o.HTTPS_PROXY,n=!0),o.NO_PROXY===M&&(delete o.NO_PROXY,n=!0);let u=o.NODE_EXTRA_CA_CERTS;return typeof u=="string"&&u.includes(".mitmproxy")&&u.endsWith("mitmproxy-ca-cert.pem")&&(delete o.NODE_EXTRA_CA_CERTS,n=!0),n&&Object.keys(o).length===0&&delete e.env,n}r(F,"removeRulemetricProxyEnv");function R(e,t){let o=X(e),n=F(e,t),s=x(e);return{removedHooks:o,removedProxyEnv:n,removedStatusline:s,removed:o||n||s}}r(R,"removeRulemetricMachineState");function nt(e,t){let o={migrated:!1,backupPath:null,removedHooks:!1,removedProxyEnv:!1,removedStatusline:!1,removed:!1};if(!c(e))return o;let n;try{n=JSON.parse(p(e,"utf-8"))}catch{return o}let s=R(n,t);if(!s.removed)return o;let{backupPath:u}=C(e,n);return{...s,migrated:!0,backupPath:u}}r(nt,"migrateSharedClaudeSettings");function rt(e,t){let o=[];for(let n of["settings.json","settings.local.json"]){let s=i(e,n);if(!c(s))continue;let{settings:u,recoveredBackup:l}=D(s),g=R(u,t);g.removed&&C(s,u),o.push({...g,configPath:s,fileName:n,recoveredBackup:l,changed:g.removed})}return o}r(rt,"cleanClaudeSettingsFiles");function A(e,t){if(!c(e))return null;let o=i(e,"hooks.json"),n=L(t),s=k(o);if(s===null)return null;let u=s,l={...u.hooks??{}},g=r(d=>typeof d=="object"&&d!==null&&"command"in d&&typeof d.command=="string"&&d.command.includes("rulemetric"),"isRulemetricHook");for(let[d,j]of Object.entries(n.hooks)){let _=(l[d]??[]).filter($=>!g($));l[d]=[..._,...j]}let m={version:u.version??n.version,hooks:l};return a(o,JSON.stringify(m,null,2)+`
|
|
3
|
+
`),o}r(A,"writeCursorHooksToDir");function st(e,t){return A(i(e,".cursor"),t)}r(st,"writeCursorHooks");function it(e,t=f()){let o=i(t,".cursor");return c(o)?A(o,e):null}r(it,"writeCursorUserHooks");function ut(e,t){let o=i(e,".github");if(!c(o))return null;let n=i(o,"hooks");y(n,{recursive:!0});let s=i(n,"rulemetric.json"),u=B(t);return a(s,JSON.stringify(u,null,2)+`
|
|
4
|
+
`),s}r(ut,"writeCopilotHooks");function H(e){if(!c(e))return!1;let t;try{t=JSON.parse(p(e,"utf-8"))}catch{return!1}if(!t.hooks)return!1;let o=!1;for(let[n,s]of Object.entries(t.hooks)){let u=s.filter(l=>{if(typeof l!="object"||l===null||!("command"in l))return!0;let g=l.command;return typeof g=="string"&&g.includes("rulemetric")?(o=!0,!1):!0});u.length===0?delete t.hooks[n]:t.hooks[n]=u}return o&&a(e,JSON.stringify(t,null,2)+`
|
|
5
|
+
`),o}r(H,"removeCursorHooksFromFile");function ct(e){return H(i(e,".cursor","hooks.json"))}r(ct,"removeCursorHooks");function lt(){return H(i(f(),".cursor","hooks.json"))}r(lt,"removeCursorUserHooks");function at(e,t,o){let n=i(e,".cursor");if(!c(n))return!1;let s=i(n,"settings.json"),u=k(s);return u===null?!1:(u["http.proxy"]=`http://localhost:${t}`,u["http.proxyStrictSSL"]=c(o),a(s,JSON.stringify(u,null,2)+`
|
|
6
|
+
`),!0)}r(at,"writeCursorProxyConfig");function gt(e,t,o){let n=i(e,".vscode");if(!c(n))return!1;let s=i(n,"settings.json"),u=k(s);if(u===null)return!1;u["http.proxy"]=`http://localhost:${t}`,u["http.proxyStrictSSL"]=c(o);let l=u["github.copilot.advanced"]??{};return l["debug.overrideProxyUrl"]=`http://localhost:${t}`,u["github.copilot.advanced"]=l,a(s,JSON.stringify(u,null,2)+`
|
|
7
|
+
`),!0}r(gt,"writeVSCodeProxyConfig");function ft(e){let t=i(e,".vscode","settings.json");if(!c(t))return!1;let o;try{o=JSON.parse(p(t,"utf-8"))}catch{return!1}let n=!1;o["http.proxy"]&&(delete o["http.proxy"],delete o["http.proxyStrictSSL"],n=!0);let s=o["github.copilot.advanced"];return s?.["debug.overrideProxyUrl"]&&(delete s["debug.overrideProxyUrl"],Object.keys(s).length===0&&delete o["github.copilot.advanced"],n=!0),n&&a(t,JSON.stringify(o,null,2)+`
|
|
8
|
+
`),n}r(ft,"removeVSCodeProxyConfig");function dt(e){let t=i(e,".github","hooks","rulemetric.json");return c(t)?(v(t),!0):!1}r(dt,"removeCopilotHooks");var P="com.rulemetric.env";function O(){return i(f(),"Library","LaunchAgents",`${P}.plist`)}r(O,"getLaunchAgentPath");function pt(e,t){if(process.platform!=="darwin")return!1;let o=`http://localhost:${e}`;try{h(`launchctl setenv HTTPS_PROXY ${o}`,{stdio:"pipe"}),c(t)&&h(`launchctl setenv NODE_EXTRA_CA_CERTS ${t}`,{stdio:"pipe"})}catch{return!1}let n=O(),s=i(f(),"Library","LaunchAgents");y(s,{recursive:!0});let u=c(t)?`launchctl setenv NODE_EXTRA_CA_CERTS ${t};`:"",l=`if nc -z -w 1 127.0.0.1 ${e} 2>/dev/null; then launchctl setenv HTTPS_PROXY ${o};${u} else launchctl unsetenv HTTPS_PROXY; launchctl unsetenv NODE_EXTRA_CA_CERTS; fi`,g=`<?xml version="1.0" encoding="UTF-8"?>
|
|
9
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
10
|
+
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
11
|
+
<plist version="1.0">
|
|
12
|
+
<dict>
|
|
13
|
+
<key>Label</key>
|
|
14
|
+
<string>${P}</string>
|
|
15
|
+
<key>ProgramArguments</key>
|
|
16
|
+
<array>
|
|
17
|
+
<string>/bin/sh</string>
|
|
18
|
+
<string>-c</string>
|
|
19
|
+
<string>${l}</string>
|
|
20
|
+
</array>
|
|
21
|
+
<key>RunAtLoad</key>
|
|
22
|
+
<true/>
|
|
23
|
+
</dict>
|
|
24
|
+
</plist>
|
|
25
|
+
`;return a(n,g),!0}r(pt,"installMacOSProxyEnv");function mt(){if(process.platform!=="darwin")return!1;let e=!1;try{h("launchctl unsetenv HTTPS_PROXY",{stdio:"pipe"}),h("launchctl unsetenv NODE_EXTRA_CA_CERTS",{stdio:"pipe"})}catch{}let t=O();return c(t)&&(v(t),e=!0),e}r(mt,"uninstallMacOSProxyEnv");function T(){return process.platform==="darwin"?i(f(),"Library","Application Support","Code","User","settings.json"):process.platform==="win32"?i(process.env.APPDATA??"","Code","User","settings.json"):i(f(),".config","Code","User","settings.json")}r(T,"getVSCodeUserSettingsPath");function kt(e){let t=T();if(!c(i(t,"..")))return!1;let o=k(t);return o===null||o["http.proxy"]&&!o["http.proxy"].includes("localhost")?!1:(o["http.proxy"]=`http://localhost:${e}`,o["http.proxyStrictSSL"]=!1,a(t,JSON.stringify(o,null,2)+`
|
|
26
|
+
`),!0)}r(kt,"writeVSCodeUserProxyConfig");function ht(){let e=T();if(!c(e))return!1;let t;try{t=JSON.parse(p(e,"utf-8"))}catch{return!1}return t["http.proxy"]?.includes("localhost")?(delete t["http.proxy"],delete t["http.proxyStrictSSL"],a(e,JSON.stringify(t,null,2)+`
|
|
27
|
+
`),!0):!1}r(ht,"removeVSCodeUserProxyConfig");function E(){return process.platform==="darwin"?i(f(),"Library","Application Support","Cursor","User","settings.json"):process.platform==="win32"?i(process.env.APPDATA??"","Cursor","User","settings.json"):i(f(),".config","Cursor","User","settings.json")}r(E,"getCursorUserSettingsPath");function yt(e){let t=E();if(!c(i(t,"..")))return!1;let o=k(t);return o===null||o["http.proxy"]&&!o["http.proxy"].includes("localhost")?!1:(o["http.proxy"]=`http://localhost:${e}`,o["http.proxyStrictSSL"]=!1,a(t,JSON.stringify(o,null,2)+`
|
|
28
|
+
`),!0)}r(yt,"writeCursorUserProxyConfig");function St(){let e=E();if(!c(e))return!1;let t;try{t=JSON.parse(p(e,"utf-8"))}catch{return!1}return t["http.proxy"]?.includes("localhost")?(delete t["http.proxy"],delete t["http.proxyStrictSSL"],a(e,JSON.stringify(t,null,2)+`
|
|
29
|
+
`),!0):!1}r(St,"removeCursorUserProxyConfig");function Y(){let e=process.execPath,t=process.argv[1];return t&&t.endsWith("run.js")?`${e} ${t}`:"rulemetric"}r(Y,"getRulemetricCommand");function I(){let e=Y(),t=r(o=>({type:"command",command:`RULEMETRIC_HOOK_TOOL=antigravity ${e} hooks run ${o}`,timeout:30}),"mk");return{rulemetric:{enabled:!0,SessionStart:[{hooks:[t("session-start")]}],PostToolUse:[{matcher:".*",hooks:[t("post-tool-use")]}],SessionEnd:[{hooks:[t("session-end")]}]}}}r(I,"generateAntigravityHooksConfig");function w(e){let t=i(e,"hooks.json"),o=k(t);if(o===null)return null;let n=I(),s={...o,rulemetric:n.rulemetric};return y(e,{recursive:!0}),a(t,JSON.stringify(s,null,2)+`
|
|
30
|
+
`),t}r(w,"writeAntigravityHooksToDir");function vt(e){return w(i(e,".agents"))}r(vt,"writeAntigravityHooks");function xt(e=f()){let t=i(e,".gemini");return c(t)?w(i(t,"config")):null}r(xt,"writeAntigravityUserHooks");function S(e){if(!c(e))return!1;let t;try{t=JSON.parse(p(e,"utf-8"))}catch{return!1}if(!("rulemetric"in t))return!1;if(delete t.rulemetric,Object.keys(t).length===0)try{v(e)}catch{}else a(e,JSON.stringify(t,null,2)+`
|
|
31
|
+
`);return!0}r(S,"removeAntigravityHooksFromFile");function bt(e){return S(i(e,".agents","hooks.json"))}r(bt,"removeAntigravityHooks");function Ct(){let e=S(i(f(),".gemini","config","hooks.json")),t=S(i(f(),".gemini","hooks.json"));return e||t}r(Ct,"removeAntigravityUserHooks");export{Z as a,L as b,B as c,J as d,D as e,C as f,tt as g,et as h,X as i,M as j,ot as k,F as l,R as m,nt as n,rt as o,st as p,it as q,ut as r,ct as s,lt as t,at as u,gt as v,ft as w,dt as x,pt as y,mt as z,T as A,kt as B,ht as C,E as D,yt as E,St as F,I as G,vt as H,xt as I,bt as J,Ct as K};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as I}from"./chunk-22ZDUL6H.js";import{b as A,c as l,d as b}from"./chunk-
|
|
1
|
+
import{a as I}from"./chunk-22ZDUL6H.js";import{b as A,c as l,d as b}from"./chunk-CPDMJGTC.js";import{f as k}from"./chunk-UGACB66X.js";import{n as f,o as g,p as u,v,w as $,x as y}from"./chunk-WMIUFMDI.js";import{a as c}from"./chunk-ZLLER3HP.js";import{randomUUID as P}from"node:crypto";async function H(s){let{applyMode:e="human",...r}=s;await k("/api/recommendation-applications",{...r,harness:"claude_code",applyMode:e,status:"applied",applyBatchId:P(),applySeq:0})}c(H,"recordApplication");async function M(s,e){let r=c(t=>({action:"manual-required",instructionId:e.id,name:e.name,fileModified:!1,messages:t}),"refuse");if(s.actor!=="human")return r([`Not installed: ${e.name} is a hook, and a hook is a command this machine runs unattended.`,"Installing one is always a human decision \u2014 the same refusal the API makes server-side.",` Review it: rulemetric suggestions accept ${s.suggestionId}`]);let n=y(e);if(!n.spec)return r([`Not installed: ${e.name} does not contain an installable hook spec.`,...n.problems.map(t=>` ${t.field}: ${t.message}`)]);if(n.problems.length>0)return r([`Not installed: ${e.name}'s hook spec is not fit to act on.`,...n.problems.map(t=>` ${t.field}: ${t.message}`)]);let w=u(e.frontmatter),i=v(n.spec,w??void 0),p=f(i);if(p.length>0)return r([`Not installed: ${e.name}'s artifact spec is not fit to act on.`,...p.map(t=>` ${t.field}: ${t.message}`)]);let o=b(s.dir,i.requires);if(o.missing.length>0)return r([`Not installed: ${e.name} needs ${o.missing.join(", ")}, which is not present here.`,"It is left unapplied rather than installed and broken \u2014 a hook whose command is missing still runs, and fails, on every matching event.","Accept it again once the dependency exists."]);let a=A({dir:s.dir,instructionId:e.id,spec:n.spec});if(a.status==="refused")return r([`Not installed: ${e.name}.`,` ${a.reason}`]);let m=g(i,a.inverse);if(m.length>0)return l({dir:s.dir,inverse:a.inverse}),r([`Not installed: ${e.name} was written and then rolled back \u2014 the actuator could not produce a valid inverse.`,...m.map(t=>` ${t.field}: ${t.message}`)]);try{await H({instructionId:e.id,projectPath:s.projectPath,targetPath:a.target,beforeHash:a.beforeHash,appliedHash:a.inverse.hashAtWrite,boundaryClass:i.boundaryClass,targets:i.targets,inverse:a.inverse,requires:i.requires,provides:i.provides})}catch(t){let h=l({dir:s.dir,inverse:a.inverse});return r([`Not installed: ${e.name} \u2014 the effect could not be recorded, so it was undone.`,` ${t instanceof Error?t.message:String(t)}`,h.removed?" The hook was removed; your settings are as they were.":` WARNING: the rollback did not complete (${h.reason??"unknown reason"}). Check ${a.target} for the entry tagged with ${e.id}.`])}await I(s.suggestionId,s.projectPath,e.id,s.actor);let d=a.status==="installed"?[`Accepted: installed a ${n.spec.event} hook into ${a.target}.`]:[`Already present: this hook is already installed in ${a.target}.`];for(let t of $(n.spec))d.push(` ${t}`);return o.unverifiable.length>0&&d.push(` unchecked: ${o.unverifiable.join(", ")} \u2014 this command cannot verify that namespace.`),d.push(`Undo with: rulemetric suggestions undo ${e.id}`),{action:a.status==="installed"?"added":"already-present",instructionId:e.id,name:e.name,fileModified:a.status==="installed",messages:d}}c(M,"acceptHook");export{H as a,M as b};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as R,b as T}from"./chunk-
|
|
1
|
+
import{a as R,b as T}from"./chunk-PVPYLKB3.js";import{a as p,b as y}from"./chunk-22ZDUL6H.js";import{a as $,b as w,e as U}from"./chunk-LJRE3LZ2.js";import{g as j,i as D,j as x}from"./chunk-UPFH72PF.js";import{e as I,f as P,i as C}from"./chunk-UGACB66X.js";import{B as S,C as b,o as k,z as A}from"./chunk-WMIUFMDI.js";import{a as u}from"./chunk-ZLLER3HP.js";import*as l from"node:fs";import*as m from"node:path";var O=new Set(["mcp","subagent","feature"]);function L(e,t,i){let a=m.join(e,"CLAUDE.md"),s=$(t),o=w(t),r=l.existsSync(a)?l.readFileSync(a,"utf8"):"";if(r.includes(s))return!1;let d=`${r.length>0&&!r.endsWith(`
|
|
2
2
|
`)?`
|
|
3
3
|
|
|
4
4
|
`:r.length>0?`
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as u}from"./chunk-ZLLER3HP.js";import{execFile as S}from"node:child_process";var k=/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [+-]\d{4})\s+(Sleep|Wake|DarkWake)[ ]{2,}\s*(.*)$/,m=/(\d+)\s+secs\s*$/;function f(e){let s=[];for(let r of e.split(`
|
|
2
|
+
`)){let t=k.exec(r.trimEnd());if(!t)continue;let[,o,l,a]=t,i=new Date(o.replace(" ","T").replace(/ ([+-]\d{2})(\d{2})$/,"$1:$2"));if(Number.isNaN(i.getTime()))continue;let c=l==="Sleep"?"sleep":l==="DarkWake"?"darkwake":"wake",p=m.exec(a),n=a.replace(m,"").replace(/\s+/g," ").trim(),d={kind:c,at:i,reason:n};p&&(d.seconds=Number(p[1])),s.push(d)}return s}u(f,"parsePmsetLog");function g(e,s,r=24){let t=s.getTime()-r*36e5,o=e.filter(n=>n.at.getTime()>=t),l=0,a=0,i=0,c=0,p=0;for(let n of o)n.kind==="sleep"?(l++,n.seconds!=null&&(p+=n.seconds,n.seconds>c&&(c=n.seconds))):n.kind==="darkwake"?a++:i++;return{windowHours:r,sleeps:l,darkWakes:a,fullWakes:i,longestSleepSec:c,totalSleepSec:p,recent:o.slice(-6)}}u(g,"summarizeSleep");function E(e=new Date,s=24,r=process.platform){return r!=="darwin"?Promise.resolve(null):new Promise(t=>{S("pmset",["-g","log"],{timeout:8e3,maxBuffer:64*1024*1024,encoding:"utf8"},(o,l)=>{if(o||!l)return t(null);try{t(g(f(l),e,s))}catch{t(null)}})})}u(E,"readMacSleepLog");function $(e){if(e.sleeps===0&&e.darkWakes===0)return`no sleep in the last ${e.windowHours}h`;let s=Math.round(e.longestSleepSec/60),r=Math.round(e.totalSleepSec/60),t=[`${e.sleeps} sleep${e.sleeps===1?"":"s"} in the last ${e.windowHours}h`];return e.totalSleepSec>0&&t.push(`${r}m asleep total, longest ${s}m`),e.darkWakes>0&&t.push(`${e.darkWakes} dark wake${e.darkWakes===1?"":"s"} (seconds-long maintenance wakes)`),t.join(", ")}u($,"formatSleepSummary");export{f as a,g as b,E as c,$ as d};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as m}from"./chunk-
|
|
1
|
+
import{b as m}from"./chunk-5N5S3NKS.js";import{a as g}from"./chunk-ZLLER3HP.js";var p=5;function b(t){let r=g((e,f)=>({retire:[],survivingCases:0,replacementsRequired:!1,refused:e,summary:f}),"none");if(!t||t.cases.length===0&&t.unpairedCases.length===0)return r("no-discrimination-data","No case-discrimination data yet \u2014 the target needs runs in BOTH cohorts before any case can be judged dead.");let c=[...t.cases.filter(e=>!e.discriminating).map(e=>({evalId:e.evalId,name:e.name,feedback:{name:e.name,withPassRate:e.withPassRate,withoutPassRate:e.withoutPassRate,reason:e.note}})),...t.unpairedCases.map(e=>({evalId:e.evalId,name:e.name,feedback:{name:e.name,withPassRate:e.withPassRate??0,withoutPassRate:e.withoutPassRate,reason:"runs in only one cohort (no with-vs-without comparison possible)"}}))];if(c.length===0)return r("all-discriminating","Every case discriminates \u2014 nothing to retire.");let s=new Map(t.cases.map(e=>[e.evalId,e.separation])),o=[...c].sort((e,f)=>(s.get(e.evalId)??-1)-(s.get(f.evalId)??-1)).slice(0,p),u=c.length-o.length,d=t.total+t.unpaired,l=d-o.length,i=l<m,n=`${o.length} of ${d} live case(s) carry no treatment signal`+(u>0?` (${u} more over the ${p}-per-run cap)`:"")+(i?`; retiring them leaves ${l}, below the ${m}-case evolution floor, so replacements must be generated first`:"");return{retire:o,survivingCases:l,replacementsRequired:i,refused:null,summary:n}}g(b,"planCaseRefinement");async function v(t,r){let h=r.log??(()=>{}),c=g((n,e)=>({retired:0,generated:0,skipped:n,summary:e,retiredNames:[],generatedNames:[]}),"empty");if(t.refused)return c(t.refused,t.summary);let s=await r.generate(t.retire.map(n=>n.feedback)),a=[];for(let n of s??[]){let e=await r.createCase(n);a.push(e.name),h(` + ${e.name} (${e.id})`)}let o=t.survivingCases+t.retire.length+a.length,u=Math.max(0,o-m),d=t.retire.slice(0,Math.min(t.retire.length,u)),l=t.retire.length-d.length;if(d.length===0)return{retired:0,generated:a.length,skipped:s===null?"no-llm-backend":"no-replacements-generated",summary:`${t.summary}. `+(s===null?"No local LLM backend available, so nothing was retired":`The generator produced ${a.length} usable replacement(s), not enough to retire anything`)+` \u2014 dropping below the ${m}-case floor would silently disenrol the target from the nightly loop.`,retiredNames:[],generatedNames:a};let i=[];for(let n of d)await r.retireCase(n.evalId,n.feedback.reason),i.push(n.name),h(` retired ${n.name}`);return{retired:i.length,generated:a.length,skipped:null,summary:`Retired ${i.length} non-discriminating case(s), added ${a.length} replacement(s)`+(l>0?`; held ${l} back to stay at the ${m}-case floor (they remain condemned and will be retired once replacements exist)`:"")+". The replacements have no runs yet \u2014 the next autorun batch builds their depth.",retiredNames:i,generatedNames:a}}g(v,"executeCaseRefinement");export{p as a,b,v as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as l}from"./chunk-ZLLER3HP.js";var k=5e3;function v(){let e=process.cpuUsage();return{wallMs:Date.now(),monoMs:Number(process.hrtime.bigint()/1000000n),cpuMs:(e.user+e.system)/1e3}}l(v,"takeClockSample");function P(e,n,u,o=5e3){let r=n.wallMs-e.wallMs,s=n.monoMs-e.monoMs,i=Math.max(0,n.cpuMs-e.cpuMs);if(r<u+o)return null;let a={detectedAt:new Date(n.wallMs).toISOString(),lastSeenAt:new Date(e.wallMs).toISOString(),wallGapMs:r,monoGapMs:s,cpuMs:i,expectedMs:u};return r-s>o?{kind:"suspend",evidence:"clock",...a}:{kind:i>r*.25?"stall":"suspend",evidence:"cpu",...a}}l(P,"classifyGap");var b=15e3,f=50;function w(e={}){let n=e.intervalMs??b,u=e.sample??v,o=e.setIntervalFn??setInterval,r=e.clearIntervalFn??clearInterval,s=u(),i=new Date(s.wallMs).toISOString(),a=[],p=0,d=0,m=0,M=o(l(()=>{let t=u(),c=P(s,t,n);if(s=t,!!c){c.kind==="suspend"?p++:d++,m+=c.wallGapMs-c.expectedMs,a.push(c),a.length>f&&a.shift();try{e.onPause?.(c)}catch{}}},"tick"),n);M.unref?.();let S=l(()=>r(M),"stop");return e.signal?.addEventListener("abort",S,{once:!0}),{summary:l(()=>{let t=a[a.length-1];return{suspends:p,stalls:d,pausedMs:m,lastPause:t?{kind:t.kind,evidence:t.evidence,detectedAt:t.detectedAt,lastSeenAt:t.lastSeenAt,wallGapMs:t.wallGapMs}:null,since:i}},"summary"),pausesSince:l(t=>a.filter(c=>new Date(c.detectedAt).getTime()>=t),"pausesSince"),stop:S}}l(w,"startPauseDetector");function A(e){if(e.length===0)return"";let n=e.reduce((s,i)=>s+i.wallGapMs,0),u=new Set(e.map(s=>s.kind==="suspend"?"machine suspended":"event loop stalled")),o=Math.round(n/6e4),r=o>=1?`${o}m`:`${Math.round(n/1e3)}s`;return`${[...u].join(" + ")} for ${r} during this job (${e.length} pause${e.length===1?"":"s"}, last resumed ${e[e.length-1].detectedAt})`}l(A,"describePauses");export{k as a,v as b,P as c,w as d,A as e};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s={"session-start":30,"user-prompt":15,"post-tool-use":15,"session-end":60};export{s as a};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as I}from"./chunk-5RBLIVBF.js";import{a as j,d as O}from"./chunk-3UKZJAFS.js";import{c as U}from"./chunk-FE2UWAIP.js";import{a as T,b as P,c as H,d as A}from"./chunk-SJKS3PYX.js";import{
|
|
1
|
+
import{a as I}from"./chunk-5RBLIVBF.js";import{a as W}from"./chunk-HQCPGDQE.js";import{a as j,d as O}from"./chunk-3UKZJAFS.js";import{c as U}from"./chunk-FE2UWAIP.js";import{a as T,b as P,c as H,d as A}from"./chunk-SJKS3PYX.js";import{c as x,d as L,f as S}from"./chunk-QBNLZJIR.js";import{e as _,f as J,h as d}from"./chunk-UGACB66X.js";import{a as z,b as F}from"./chunk-WMIUFMDI.js";import{a as f}from"./chunk-ZLLER3HP.js";var B=f((l,{limit:a,sort:n,eventTypes:s})=>_(`/api/sessions/${l}/events?limit=${a}&sort=${n}&eventType=${encodeURIComponent(s.join(","))}&hasContent=true`),"fetchTranscriptTurns");async function is(l,a){let{mirrorId:n,projectPath:s,projectId:r,config:g}=l,t=f(e=>a.logger.info(e),"log");if(g?.sessionId)return Y({mirrorId:n,sessionId:g.sessionId},t);t(`Processing insights job ${n}...`),await d(`/api/insights-jobs/${n}/progress`,{status:"running",progress:{step:"reading_data"}});try{let{repaired:e}=await J("/api/sessions/repair-analyzed-at",{});e>0&&t(` Repaired analyzed_at on ${e} orphan session(s).`)}catch(e){t(` Warning: analyzed_at repair failed: ${e instanceof Error?e.message:String(e)}`)}let p=20,w=200,v=15*6e4,D=3,C=Date.now()+v;if(L()!=="none"){let e=0,o=0;try{for(;e<w&&Date.now()<C;){let c=await _(`/api/sessions?needsFacets=true&graderVersion=${2}&limit=${p}&offset=${o}`);if(c.length===0)break;t(` Generating facets for ${c.length} un-analyzed sessions (drained ${e} so far)...`);for(let $=0;$<c.length&&!(e>=w||Date.now()>=C);$+=D){let R=c.slice($,$+D);await Promise.all(R.map(async m=>{if(!(e>=w||Date.now()>=C))try{let u=await O(q=>B(m.id,q));if(u.turnCount<2){e++,o++;return}let k=await S(A,u.text,4096);k&&typeof k.outcome=="string"?(await d(`/api/sessions/${m.id}/enrich`,{analysis:{source:"generated_facets",...k,graderVersion:2},...m.eventCount!=null?{analyzedEventCount:m.eventCount}:{},analyzedTurnCount:u.turnCount}),t(` Generated facets for session ${m.id} (${m.tool}, ${u.turnCount} turns)`)):o++,e++}catch(u){t(` Failed to generate facets for session ${m.id}: ${u instanceof Error?u.message:String(u)}`),e++,o++}}))}if(c.length<p)break}}catch(c){t(` Warning: facet generation failed after ${e} sessions: ${c instanceof Error?c.message:String(c)}`)}if(e>0){let c=Date.now()>=C?`time budget (${Math.round(v/6e4)}m)`:e>=w?`hard cap (${w})`:"queue empty";t(` Facet drain stopped on ${c} after ${e} session(s); the rest resume next run.`)}}let b=await K(s,r);if(!b)throw new I("No session data found \u2014 ensure sessions are captured and enriched.");t(` Found ${b.stats.sessions} sessions, generating recommendations...`);let E=await Z(s,t);E&&t(` Generator memory: ${E.split(`
|
|
2
2
|
`).length} lines of prior-advice context`);let i={},y=[],h=P.length+1;for(let e=0;e<P.length;e++){let o=P[e];t(` [${e+1}/${h}] Generating ${o.name}...`);try{await d(`/api/insights-jobs/${n}/progress`,{status:"running",progress:{step:o.name,current:e+1,total:h,partial:{...i}}})}catch(u){t(` Warning: progress update failed for ${o.name}: ${u instanceof Error?u.message:String(u)}`)}t(` Running LLM prompt for ${o.name}...`);let c=o.usesGeneratorMemory&&E?`${b.summary}
|
|
3
3
|
${E}`:b.summary,$=Date.now(),R=await S(o.prompt,c,o.maxTokens,{timeoutMs:o.timeoutMs}),m=Date.now()-$;R?(i[o.name]=R,t(` Got result for ${o.name} (${Math.round(m/1e3)}s)`)):(y.push(o.name),t(` No result for ${o.name} after ${Math.round(m/1e3)}s (budget ${Math.round((o.timeoutMs??12e4)/1e3)}s) \u2014 section DROPPED`))}t(` [${h}/${h}] Generating at_a_glance...`),await d(`/api/insights-jobs/${n}/progress`,{status:"running",progress:{step:"at_a_glance",current:h,total:h,partial:{...i}}});let V=[b.summary,i.what_works?`
|
|
4
4
|
## What Works
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as
|
|
1
|
+
import{c as q,d as K}from"../chunk-TYFEWLYZ.js";import{b as L,c as F}from"../chunk-V5U3E4BZ.js";import{a as J}from"../chunk-2TJ7Q2OU.js";import{e as O,f as _,g as M}from"../chunk-QWCEZEDO.js";import"../chunk-KKDHD4XA.js";import"../chunk-SZ62CP55.js";import{d as oe,e as ne}from"../chunk-FUYR7CFD.js";import"../chunk-M7QSC64D.js";import"../chunk-DPCAPIQB.js";import"../chunk-G7V4ZZZ3.js";import"../chunk-W23MESHM.js";import{i as z,j as Q,k as Z,m as ee,n as te}from"../chunk-LB24UKHZ.js";import"../chunk-PWTTCSQA.js";import{d as W}from"../chunk-NF2BIEAF.js";import{a as V}from"../chunk-OZQNSELV.js";import"../chunk-HFGO5762.js";import"../chunk-VS5ROGDP.js";import"../chunk-WTMJSL7R.js";import"../chunk-GN3ZHQ46.js";import"../chunk-U2NT5OSQ.js";import"../chunk-KGURGIZ2.js";import"../chunk-UPFH72PF.js";import"../chunk-BJSVATVJ.js";import"../chunk-CDY7TQFZ.js";import"../chunk-RIVEBBZC.js";import"../chunk-QBNLZJIR.js";import"../chunk-N7ODX6PO.js";import"../chunk-PJ3WHQ67.js";import"../chunk-VBXL7XO7.js";import"../chunk-TZA4HAVF.js";import{a as X,b as D,c as Y,f as j,g as G}from"../chunk-QXPYGN7I.js";import{a as B}from"../chunk-DSJNZWCZ.js";import"../chunk-IZTIYR5Q.js";import"../chunk-OOFGV7EX.js";import"../chunk-VYZKKSX4.js";import"../chunk-YSLKV4XC.js";import"../chunk-3AV3GTMP.js";import{a as U,e as y}from"../chunk-UGACB66X.js";import"../chunk-WMIUFMDI.js";import{a as N,g as v,l as x}from"../chunk-PZNWH4VQ.js";import{a as S}from"../chunk-ZLLER3HP.js";import{spawnSync as le}from"node:child_process";import{existsSync as ce,readFileSync as ue}from"node:fs";import{join as se}from"node:path";var I=class h extends B{static{S(this,"Diagnostics")}static description='Diagnose capture / proxy / connectivity problems (e.g. a client-side "502 Bad Gateway")';static examples=["<%= config.bin %> diagnostics"];baseUrl(){return process.env.RULEMETRIC_API_URL??N().apiUrl??U}async checkDirect(){let r=process.env.HTTPS_PROXY,i=process.env.HTTP_PROXY;delete process.env.HTTPS_PROXY,delete process.env.HTTP_PROXY;let s=new AbortController,l=setTimeout(()=>s.abort(),8e3);try{return(await globalThis.fetch(`${this.baseUrl()}/health`,{signal:s.signal})).ok}catch{return!1}finally{clearTimeout(l),r!==void 0&&(process.env.HTTPS_PROXY=r),i!==void 0&&(process.env.HTTP_PROXY=i)}}configuredProxy(){if(process.env.HTTPS_PROXY)return process.env.HTTPS_PROXY;for(let r of["settings.local.json","settings.json"]){let i=se(process.cwd(),".claude",r);if(ce(i))try{let s=JSON.parse(ue(i,"utf8"));if(s.env?.HTTPS_PROXY)return s.env.HTTPS_PROXY}catch{}}return null}checkThroughProxy(r){let i=le("curl",["-sS","-x",r,"--max-time","8","-o","/dev/null","-w","%{http_code}",`${this.baseUrl()}/health`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return i.error||typeof i.stdout!="string"?null:i.stdout.trim()==="200"}async run(){await this.parse(h);let r=process.version,i=this.configuredProxy(),s=i!=null,[l,m,d]=await Promise.all([this.checkDirect(),M(O),M(_)]),p=s&&i?this.checkThroughProxy(i):null,t=S((e,c,T)=>{let u=c===null?"\u2013":c?"[OK]":"[!!]";this.log(` ${u} ${e.padEnd(22)} ${T}`)},"line");this.log("RuleMetric diagnostics"),this.log(""),t("Node",!L(r),`${r}${L(r)?" (< 20.11 \u2014 breaks the bundled proxy)":""}`),t("API (direct)",l,`${this.baseUrl()}/health ${l?"reachable":"UNREACHABLE"}`),t("Authenticated",v(),v()?"yes":"no \u2014 run `rulemetric auth login`"),t("Proxy configured",s?!0:null,s?i:"no HTTPS_PROXY set"),s&&(t("Gateway :"+O,m,m?"listening":"NOT listening"),t("mitmproxy :"+_,d,d?"listening":"not listening (gateway should route direct)"),t("API (via proxy)",p,p===null?"inconclusive (curl unavailable)":p?"reachable":"FAILED \u2014 502/blocked through your proxy"));let a=W();t("claude CLI",a.claudeBin!=null,a.claudeBin??"not found \u2014 LLM features (grading, distill) will no-op"),t("codex CLI",a.codexBin!=null?!0:null,a.codexBin?`${a.codexBin}${a.codexConfiguredModel?` (model ${a.codexConfiguredModel})`:""}`:"not found \u2014 optional; enables the cross-vendor reviewer (evals validate-judge)");let o=null;if(v()&&l)try{o=await y("/api/workers/health")}catch{o=null}if(o){let e=o.worker;t("Worker",!!e.active,e.present?e.active?`online (last heartbeat ${e.ageSeconds??"?"}s ago${e.clientVersion?`, v${e.clientVersion}`:""})`:`NOT RUNNING \u2014 last heartbeat ${A(e.ageSeconds)} ago`:"never connected \u2014 no worker has ever reported in");let c=o.worker.engines;if(c!=null){let u=[c.claude&&"claude",c.codex&&"codex"].filter(Boolean);t("LLM engine",u.length>0,u.length>0?`${u.join(" + ")} available to the worker`:"NONE \u2014 the worker found no `claude` and no `codex`. LLM jobs will complete with empty output rather than failing.")}let T=o.pending.reduce((u,E)=>u+E.count,0);if(T>0){let u=o.verdict.stuck.reduce(($,k)=>$+k.count,0),E=o.verdict.unclaimable.reduce(($,k)=>$+k.count,0),R=(o.verdict.engineBlocked??[]).reduce(($,k)=>$+k.count,0);t("Job queue",u===0&&R===0,`${T} pending`+(u>0?` \u2014 ${u} waiting on this worker`:"")+(R>0?` \u2014 ${R} need a local LLM engine`:"")+(E>0?` \u2014 ${E} need a worker with DATABASE_URL`:""))}else t("Job queue",!0,"empty")}else v()&&l&&t("Worker",null,"could not read /workers/health (older API?)");let n=o?.worker.machine;if(n){let e=n.suspends+n.stalls,c=n.lastPause;t("Worker pauses",e===0?!0:null,e===0?`none since ${n.since} \u2014 no sleep or stall seen by the worker`:`${n.suspends} suspend${n.suspends===1?"":"s"}`+(n.stalls>0?` + ${n.stalls} event-loop stall${n.stalls===1?"":"s"}`:"")+` since ${n.since}, ${A(Math.round(n.pausedMs/1e3))} paused total`+(c?`; last: ${c.kind} of ${A(Math.round(c.wallGapMs/1e3))} ending ${c.detectedAt}`:"")+" \u2014 jobs in flight during a suspend lose their lease and are redone on wake")}let f=await q();if(f){t("Machine sleep (pmset)",f.sleeps===0?!0:null,K(f));for(let e of f.recent.slice(-3)){let c=e.seconds!=null?` (${A(e.seconds)})`:"";this.log(` \u21B3 ${e.at.toISOString()} ${e.kind}${c}: ${e.reason.slice(0,80)}`)}}let C=V(process.cwd()),g=await D({configDir:x()}),re=await Y({configDir:x()}),w=` \u2014 ${G(re)}`,b=J(process.cwd()),H=[b.user&&`user hooks (${b.user})`,b.workspace&&`workspace hooks (${b.workspace})`].filter(Boolean),ie={claude_code:`session hooks (+ proxy for instruction linking)${w}`,codex:`worker transcript sync of ~/.codex/sessions \u2014 ${j(g)}`,cursor:`user hooks (~/.cursor/hooks.json)${w}`,copilot_agent:`workspace hooks${w}`,antigravity:H.length>0?`${H.join(" + ")}${w}`:"NOT CAPTURED \u2014 no rulemetric block in ~/.gemini/config/hooks.json or .agents/hooks.json; run `rulemetric hooks install` (user hooks are on by default)"};this.log(""),this.log(" Capture coverage (agents found on this machine):");for(let e of C)this.log(` \u2022 ${e.padEnd(15)} ${ie[e]??"captured"}`);if(C.includes("codex"))if(g.error)this.log(` ! ${g.error}`);else if(g.mode==="allowlist")for(let e of g.roots)this.log(` \u21B3 ${e}`);else g.mode==="all"&&this.log(` \u21B3 scope it with ${se(x(),X)} ({"codex":{"roots":["/path/to/repo"]}}) or RULEMETRIC_CODEX_CAPTURE=off`);o&&!o.worker.active&&C.includes("codex")&&g.mode!=="off"&&this.log(" ! Codex capture runs INSIDE the worker \u2014 it is stopped while the worker is down."),v()&&l&&await this.reportEvolutionSpend();let P=F({nodeVersion:r,directApiOk:l,httpsProxySet:s,gatewayAlive:m,mitmproxyAlive:d,proxyPathOk:p});this.log("");let ae=P.severity==="ok"?"[OK]":P.severity==="warn"?"[!!]":"[XX]";this.log(`${ae} ${P.headline}`);for(let e of P.hints)this.log(` \u2022 ${e}`);if(o&&o.verdict.severity!=="ok"){let e=o.verdict.severity==="warn"?"[!!]":"[XX]";this.log(""),this.log(`${e} ${o.verdict.headline}`);for(let c of o.verdict.hints)this.log(` \u2022 ${c}`)}}async reportEvolutionSpend(){let r;try{r=await y("/api/eval-targets?type=instruction&limit=200")}catch{return}let i=r.filter(s=>{let l=s.metadata??{};return l.autoEvolveEnabled===!0||l.autoEvolveEnabled==="true"});if(i.length!==0){this.log(""),this.log(" Nightly instruction evolution (cron_instruction_evolution, 07:30 UTC):");for(let s of i){let l=s.metadata??{},m=Q(l),d=z(l);if(m){this.log(` \u2022 ${s.name} \u2014 PAUSED (metadata.autoEvolvePaused). Opt-in preserved.`),this.log(" \u21B3 resume: set autoEvolvePaused=false");continue}let p=null;try{p=(await y(`/api/eval-targets/${s.id}/evals`)).filter(a=>!a.retiredAt).length}catch{}if(this.log(` \u2022 ${s.name}`),p!=null){let t=ne(p,d.minPairs,oe(d,p));if(!t.feasible)this.log(` \u21B3 cannot reach a verdict \u2014 ${t.reason}`);else{let a=Z({liveCases:p,passes:t.passes});this.log(` \u21B3 each night: ${te(a)}`)}}this.log(` \u21B3 pairs budget ${d.minPairs}`+(d.configured?" (metadata.autoEvolvePairs)":" (default)")+` \xB7 writes ${l.autoEvolveApply===!0||l.autoEvolveApply==="true"?"ENABLED":"off (dry run)"}`),d.note&&this.log(` ! ${d.note}`);try{let t=await y(`/api/eval-targets/${s.id}/promotions?limit=1`),a=t.promotions[0];if(a){let n=a.gates?.cost,f=n?.modelCalls?`${n.modelCalls} model calls, ${n.usablePairs??"?"} usable pair(s)`+(n.mde!=null?`, resolved +/-${ee(n.mde)}`:"")+(n.wallMs?`, ${(n.wallMs/6e4).toFixed(0)} min`:""):"cost not recorded (decision predates cost tracking)";this.log(` \u21B3 last run ${new Date(a.createdAt).toISOString().slice(0,10)}: ${a.decision}${a.applied?" (APPLIED)":""} \u2014 ${f}`)}let o=t.counts??{};this.log(` \u21B3 lifetime: ${o.promote??0} promote / ${o.revert??0} revert / ${o.refuse??0} refuse`)}catch{}}this.log(" \u21B3 pause the spend: metadata.autoEvolvePaused=true (keeps the opt-in)")}}};function A(h){if(h===null)return"never";if(h<90)return`${Math.round(h)}s`;let r=Math.round(h/60);return r<90?`${r}m`:`${Math.round(r/60)}h`}S(A,"formatAge");export{I as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as C,b as L,c as D}from"../../chunk-GWDZNGUP.js";import{c as d}from"../../chunk-LUCVMLHV.js";import{e as I}from"../../chunk-
|
|
1
|
+
import{a as C,b as L,c as D}from"../../chunk-GWDZNGUP.js";import{c as d}from"../../chunk-LUCVMLHV.js";import{e as I}from"../../chunk-EVD5A3VI.js";import"../../chunk-2KJAM2NG.js";import"../../chunk-IEQDLURA.js";import"../../chunk-UUFCTEBT.js";import"../../chunk-ZYGBABMZ.js";import"../../chunk-5OX6YKTR.js";import"../../chunk-MJ5H7RDK.js";import"../../chunk-W67DO5PT.js";import"../../chunk-WO6MS654.js";import"../../chunk-UTAETY5Z.js";import"../../chunk-E4RGYYBC.js";import"../../chunk-O65AQZYB.js";import"../../chunk-ARC4Q3GL.js";import"../../chunk-RFISMWRW.js";import"../../chunk-5RBLIVBF.js";import"../../chunk-GRPUY2EZ.js";import"../../chunk-UXB6DRR7.js";import"../../chunk-INSKP5ED.js";import"../../chunk-UA5GEVGW.js";import"../../chunk-PZS55PW2.js";import"../../chunk-AKXGUQ5B.js";import"../../chunk-3ZHVP3KE.js";import"../../chunk-Z4YVOVMM.js";import"../../chunk-HOQPVOMF.js";import"../../chunk-NKJTNGXR.js";import"../../chunk-C6GLNE6X.js";import"../../chunk-S2SKT5PV.js";import"../../chunk-HQCPGDQE.js";import"../../chunk-3UKZJAFS.js";import"../../chunk-FE2UWAIP.js";import"../../chunk-SJKS3PYX.js";import"../../chunk-XFAFMYIP.js";import"../../chunk-5PM4E27L.js";import"../../chunk-GIRPEMTW.js";import"../../chunk-SIGZEQ3K.js";import"../../chunk-RLEMDKQ4.js";import"../../chunk-PVPYLKB3.js";import"../../chunk-22ZDUL6H.js";import"../../chunk-CPDMJGTC.js";import"../../chunk-E7XOYGL5.js";import"../../chunk-WCIX5KWG.js";import"../../chunk-LJRE3LZ2.js";import"../../chunk-UKOI2Q4J.js";import"../../chunk-5N5S3NKS.js";import"../../chunk-KJRMGTAO.js";import"../../chunk-MILLBGCB.js";import"../../chunk-6UEFCMR2.js";import"../../chunk-MODXEGCU.js";import"../../chunk-RBSEE2Z6.js";import"../../chunk-AFYZYXQ3.js";import"../../chunk-FUYR7CFD.js";import"../../chunk-M7QSC64D.js";import"../../chunk-DPCAPIQB.js";import"../../chunk-G7V4ZZZ3.js";import"../../chunk-W23MESHM.js";import"../../chunk-LB24UKHZ.js";import"../../chunk-PWTTCSQA.js";import"../../chunk-NF2BIEAF.js";import"../../chunk-OZQNSELV.js";import"../../chunk-HFGO5762.js";import"../../chunk-VS5ROGDP.js";import"../../chunk-WTMJSL7R.js";import"../../chunk-GN3ZHQ46.js";import"../../chunk-U2NT5OSQ.js";import"../../chunk-KGURGIZ2.js";import"../../chunk-UPFH72PF.js";import"../../chunk-BJSVATVJ.js";import"../../chunk-CDY7TQFZ.js";import"../../chunk-RIVEBBZC.js";import"../../chunk-QBNLZJIR.js";import"../../chunk-N7ODX6PO.js";import"../../chunk-PJ3WHQ67.js";import"../../chunk-VBXL7XO7.js";import"../../chunk-TZA4HAVF.js";import{b as k,f as h,h as A}from"../../chunk-QXPYGN7I.js";import{a as O}from"../../chunk-DSJNZWCZ.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-OOFGV7EX.js";import"../../chunk-VYZKKSX4.js";import"../../chunk-YSLKV4XC.js";import"../../chunk-3AV3GTMP.js";import{f as b}from"../../chunk-UGACB66X.js";import"../../chunk-WMIUFMDI.js";import{e as P,l as f}from"../../chunk-PZNWH4VQ.js";import{a as e}from"../../chunk-ZLLER3HP.js";import{trace as se,context as ie}from"@opentelemetry/api";import{NodeSDK as j}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as q}from"@opentelemetry/exporter-trace-otlp-http";import{BatchSpanProcessor as F,ConsoleSpanExporter as U,SimpleSpanProcessor as X}from"@opentelemetry/sdk-trace-node";import{Resource as B}from"@opentelemetry/resources";import{ATTR_SERVICE_NAME as H,ATTR_SERVICE_VERSION as K}from"@opentelemetry/semantic-conventions";function $(t){if(!t)return{};let r={};for(let n of t.split(",")){let s=n.indexOf("=");if(s===-1)continue;let i=n.slice(0,s).trim(),a=n.slice(s+1).trim();i&&(r[i]=a)}return r}e($,"parseOtlpHeaders");var p=null;function y(){return process.env.TELEMETRY_ENABLED!=="false"}e(y,"isTelemetryEnabled");function S(t){if(!y()||p!==null)return"off";let r=new B({[H]:t.serviceName,[K]:t.serviceVersion??"0.1.0"}),n=process.env.OTEL_EXPORTER_OTLP_ENDPOINT,s,i;if(n){let a=$(process.env.OTEL_EXPORTER_OTLP_HEADERS),l=new q({url:`${n}/v1/traces`,headers:a});i=new F(l),s="otlp"}else if(process.env.OTEL_SPAN_EXPORT==="none")i=void 0,s="silent";else{let a=new U;i=new X(a),s="console"}return p=new j({resource:r,spanProcessors:i?[i]:[]}),p.start(),s}e(S,"initTelemetry");async function m(){p&&(await p.shutdown(),p=null)}e(m,"shutdownTelemetry");import{SpanKind as he,SpanStatusCode as ye}from"@opentelemetry/api";import{trace as ve,context as we}from"@opentelemetry/api";import*as u from"@sentry/node";var E=!1;function T(t){if(E)return!1;let r=process.env.SENTRY_DSN;return r?(u.init({dsn:r,serverName:t.serviceName,environment:process.env.NODE_ENV??"development",tracesSampleRate:0}),E=!0,!0):!1}e(T,"initSentry");async function g(t){E&&await u.flush(t)}e(g,"flushSentry");import{existsSync as J,mkdirSync as W,readFileSync as R,unlinkSync as V,writeFileSync as M}from"node:fs";import{dirname as z,join as v}from"node:path";import{execFileSync as Q}from"node:child_process";var c=v(f(),"evals-agent.lock");function Z(t){try{return process.kill(t,0),!0}catch(r){return r.code==="EPERM"}}e(Z,"pidAlive");function ee(t){if(!Z(t))return!1;try{let r=Q("ps",["-p",String(t),"-o","command="],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]});return/run\.js\s+evals\s+agent|evals\s+agent/.test(r)}catch{return!0}}e(ee,"isLiveAgent");function te(){try{W(z(c),{recursive:!0})}catch{}for(let t=0;t<2;t++)try{return M(c,String(process.pid),{flag:"wx"}),{ok:!0}}catch(r){if(r.code!=="EEXIST")throw r;let n=0;try{n=Number(R(c,"utf-8").trim())}catch{}if(n&&n!==process.pid&&ee(n))return{ok:!1,holder:n};try{V(c)}catch{}}try{M(c,String(process.pid))}catch{}return{ok:!0}}e(te,"acquireAgentLock");function x(){try{J(c)&&Number(R(c,"utf-8").trim())===process.pid&&V(c)}catch{}}e(x,"releaseAgentLock");var w=class t extends O{static{e(this,"EvalAgentCommand")}static description="The worker daemon: long-polls /api/work/next, claims jobs, and runs them locally. Installed as a launchd service by `rulemetric service install`.";static examples=["<%= config.bin %> evals agent"];async run(){await this.parse(t),this.requireAuth();let r=te();if(!r.ok){this.log(`Another rulemetric evals agent is already running (pid ${r.holder}). Refusing to start a second instance.`);return}process.env.PG_APPLICATION_NAME||="rulemetric-agent",T({serviceName:"rulemetric-agent"})&&this.log("[sentry] error capture enabled");let s=S({serviceName:"rulemetric-agent"});s==="otlp"?this.log(`[otel] traces exporting to ${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}`):s==="console"?this.log("[otel] cron spans printing to stdout (set OTEL_EXPORTER_OTLP_ENDPOINT to ship to a backend)"):this.log("[otel] disabled (TELEMETRY_ENABLED=false)"),!P()&&!process.env.RULEMETRIC_API_KEY&&this.error("No auth token found. Run `rulemetric auth login` first."),this.log("Starting thin agent (Phase 4b parallel-run)..."),this.log(`Long-polling /api/work/next. Press Ctrl+C to stop.
|
|
2
2
|
`);let a=new AbortController,l=await k({configDir:f()});if(this.log(`[transcript-sync] Codex capture: ${h(l)}`),l.error)this.log(`[transcript-sync] WARNING: ${l.error}`);else if(l.mode==="allowlist")for(let o of l.roots)this.log(`[transcript-sync] \u2022 ${o}`);let G=new C({providers:[L(void 0,void 0,A({configDir:f(),onChange:e(o=>this.log(`[transcript-sync] Codex capture changed: ${h(o)}`),"onChange")}))],statePath:v(f(),"transcript-sync-state.json"),importTranscript:e(o=>b("/api/sessions/import",o),"importTranscript"),log:e(o=>this.log(`[transcript-sync] ${o}`),"log")});D(G,{signal:a.signal,log:e(o=>this.log(`[transcript-sync] ${o}`),"log")});let N=e(async o=>{this.log(`
|
|
3
3
|
[${o}] shutting down agent...`),a.abort(),await Promise.allSettled([g(2e3),m(),d()]),x(),process.exit(0)},"shutdown");process.on("SIGINT",()=>{N("SIGINT")}),process.on("SIGTERM",()=>{N("SIGTERM")});let _=!1;try{await I({signal:a.signal,log:e(o=>this.log(o),"log"),version:this.config.version,readInstalledVersion:e(()=>{try{return JSON.parse(R(v(this.config.root,"package.json"),"utf-8")).version??null}catch{return null}},"readInstalledVersion"),onVersionDrift:e(()=>{_=!0},"onVersionDrift")}),_&&(this.log("[upgrade] Installed CLI version changed \u2014 restarting worker onto the new code."),await Promise.allSettled([g(2e3),m(),d()]),x(),process.exit(1))}finally{x(),await d()}}};export{w as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{b as w,c as $}from"../../chunk-
|
|
1
|
+
import{b as w,c as $}from"../../chunk-UKOI2Q4J.js";import"../../chunk-5N5S3NKS.js";import{b as v}from"../../chunk-KJRMGTAO.js";import"../../chunk-FUYR7CFD.js";import"../../chunk-M7QSC64D.js";import"../../chunk-DPCAPIQB.js";import"../../chunk-G7V4ZZZ3.js";import"../../chunk-W23MESHM.js";import"../../chunk-LB24UKHZ.js";import"../../chunk-PWTTCSQA.js";import"../../chunk-WTMJSL7R.js";import"../../chunk-GN3ZHQ46.js";import"../../chunk-U2NT5OSQ.js";import"../../chunk-KGURGIZ2.js";import"../../chunk-UPFH72PF.js";import"../../chunk-BJSVATVJ.js";import"../../chunk-CDY7TQFZ.js";import"../../chunk-RIVEBBZC.js";import"../../chunk-QBNLZJIR.js";import"../../chunk-N7ODX6PO.js";import"../../chunk-PJ3WHQ67.js";import"../../chunk-VBXL7XO7.js";import"../../chunk-TZA4HAVF.js";import{a as f}from"../../chunk-DSJNZWCZ.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-OOFGV7EX.js";import"../../chunk-VYZKKSX4.js";import"../../chunk-YSLKV4XC.js";import"../../chunk-3AV3GTMP.js";import{e as d,f as p,h}from"../../chunk-UGACB66X.js";import"../../chunk-WMIUFMDI.js";import"../../chunk-PZNWH4VQ.js";import{a}from"../../chunk-ZLLER3HP.js";import{Args as P,Flags as y}from"@oclif/core";var c=a(s=>s==null?"n/a":`${Math.round(s*100)}%`,"pct"),g=class s extends f{static{a(this,"EvalRefineCases")}static description="Retire non-discriminating eval cases and regenerate discriminating replacements (\xA76e)";static examples=["<%= config.bin %> evals refine-cases <target-id> # preview","<%= config.bin %> evals refine-cases <target-id> --yes # apply: retire + regenerate","<%= config.bin %> evals refine-cases <target-id> --yes --no-generate"];static args={targetId:P.string({description:"Eval target ID",required:!0})};static flags={yes:y.boolean({char:"y",description:"Apply (retire + regenerate). Without this, only previews."}),"no-generate":y.boolean({description:"Retire dead cases but do not regenerate replacements."})};async run(){let{args:b,flags:l}=await this.parse(s);this.requireAuth();let n=b.targetId,o=await d(`/api/eval-targets/${n}`),m=await d(`/api/eval-targets/${n}/judge-calibration`),i=m.caseDiscrimination,t=w(i);if(this.log(`Target "${o.name}" v${o.version} \u2014 judge ${m.judge.currentModel??"(unstamped)"}`),t.refused==="no-discrimination-data"){this.log("No case-discrimination data yet \u2014 run some evals with AND without the target first (`evals run` / the web Run Evals button), then refine.");return}if(this.log(`${i.total} diagnosable case(s): ${i.discriminating} discriminate, ${i.nonDiscriminating} flat/wrong-sign, ${i.unpaired} unpaired.`),t.refused==="all-discriminating"){this.log("Every case discriminates \u2014 nothing to retire. \u{1F389}");return}let C=i.cases.filter(e=>!e.discriminating),u=new Set(t.retire.map(e=>e.evalId));this.log(`
|
|
2
2
|
Would retire ${t.retire.length} non-discriminating case(s):`);for(let e of C)u.has(e.evalId)&&this.log(` \u2717 ${e.name} \u2014 ${c(e.withPassRate)} with vs ${c(e.withoutPassRate)} without (\u0394${(e.separation*100).toFixed(0)}pp) \u2014 ${e.note}`);for(let e of i.unpairedCases)u.has(e.evalId)&&this.log(` \u2717 ${e.name} \u2014 ${c(e.withPassRate)} with vs ${c(e.withoutPassRate)} without \u2014 unpaired`);if(t.replacementsRequired&&this.log(`
|
|
3
3
|
${t.summary}. Replacements are generated and created BEFORE anything is retired \u2014 a target left under the floor drops out of the nightly evolution rotation with no error anywhere.`),!l.yes){this.log(`
|
|
4
4
|
Preview only. Re-run with --yes to retire ${t.retire.length} case(s)${l["no-generate"]?"":" and generate replacements"}.`);return}let r=await $(t,{generate:a(e=>l["no-generate"]?Promise.resolve([]):v({content:o.content,name:o.name,feedback:e}),"generate"),createCase:a(e=>p(`/api/eval-targets/${n}/evals`,{name:e.name,prompt:e.prompt,expectations:e.expectations}),"createCase"),retireCase:a(async(e,R)=>{await h(`/api/eval-targets/${n}/evals/${e}`,{retire:!0,retiredReason:R})},"retireCase"),log:a(e=>this.log(e),"log")});if(r.skipped==="no-llm-backend"){this.warn(r.summary+" Install the `claude` CLI (or set ANTHROPIC_API_KEY), then run `evals refine-cases` again.");return}if(r.skipped==="no-replacements-generated"){this.warn(r.summary);return}this.log(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as y,c as h}from"../../chunk-
|
|
1
|
+
import{b as y,c as h}from"../../chunk-NVABG3AO.js";import{e,i as p,k as m,m as f}from"../../chunk-QWCEZEDO.js";import"../../chunk-KKDHD4XA.js";import{b as d,d as u}from"../../chunk-SZ62CP55.js";import{B as l,E as g}from"../../chunk-OZQNSELV.js";import"../../chunk-HFGO5762.js";import"../../chunk-VS5ROGDP.js";import{a as c}from"../../chunk-DSJNZWCZ.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-OOFGV7EX.js";import"../../chunk-VYZKKSX4.js";import"../../chunk-YSLKV4XC.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-UGACB66X.js";import"../../chunk-WMIUFMDI.js";import"../../chunk-PZNWH4VQ.js";import{a}from"../../chunk-ZLLER3HP.js";import{spawn as S}from"node:child_process";import{existsSync as v,readFileSync as R,statSync as C,writeFileSync as M}from"node:fs";import{homedir as T}from"node:os";import{join as o}from"node:path";var s=o(T(),".config","rulemetric"),x=o(s,"proxy-addon.version"),_=o(s,"proxy.pid"),w=o(s,"proxy-drift-restart.at"),E=10*6e4,n=class P extends c{static{a(this,"GatewayEnsure")}static description="Ensure the gateway proxy is running (called by hooks, not for direct use)";static hidden=!0;async run(){await this.parse(P),this.maybeRestartStaleProxy();let t=await p(e);if(t.status==="ours-live"){let r=h(i=>{i==="vscode"?l(e):g(e)});r.length>0&&console.error(`[RuleMetric] Gateway healthy again \u2014 restored ${r.join(", ")} proxy settings.`);return}if(t.status==="foreign"){if(m())return;let r=y(e);console.error(`[RuleMetric] A non-RuleMetric process holds :${e} \u2014 cannot start gateway. `+(r.length>0?`Unpinned ${r.join(", ")} proxy settings so editors are not routed through it. `:"")+"Run `rulemetric diagnostics` if Claude Code HTTPS requests fail.");return}try{f(this.config.version)}catch(r){console.error(`[RuleMetric] Could not start gateway: ${r.message}`)}}maybeRestartStaleProxy(){try{if(!v(x))return;let t=R(x,"utf-8").trim();if(!t||t===this.config.version)return;let r=R(_,"utf-8").trim(),i=Number(r);if(!Number.isFinite(i)||!u(i,d))return;try{if(Date.now()-C(w).mtimeMs<E)return}catch{}M(w,new Date().toISOString()),S(process.execPath,[process.argv[1],"proxy","restart"],{detached:!0,stdio:"ignore"}).unref(),console.error(`[RuleMetric] Capture proxy is running CLI ${t} but ${this.config.version} is installed \u2014 restarting it in the background.`)}catch{}}};export{n as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as mt}from"../../chunk-5INUF4A4.js";import{a as yt}from"../../chunk-6XEC6474.js";import{e as s,i as F,j as V,k as q,m as A,n as W}from"../../chunk-QWCEZEDO.js";import{e as D}from"../../chunk-KKDHD4XA.js";import"../../chunk-SZ62CP55.js";import{B as ht,E as gt,H as pt,I as ft,e as Z,f as tt,g as et,i as st,j as ot,k as it,n as rt,p as at,q as nt,r as lt,u as ct,v as ut,y as dt}from"../../chunk-3QXRLIGC.js";import{a as J,b as z,c as m,d as Q,g as R}from"../../chunk-HFGO5762.js";import"../../chunk-N7ODX6PO.js";import{a as f}from"../../chunk-PJ3WHQ67.js";import{a as X}from"../../chunk-G3HODHFN.js";import{a as B}from"../../chunk-DSJNZWCZ.js";import"../../chunk-IZTIYR5Q.js";import{c as Y}from"../../chunk-OOFGV7EX.js";import"../../chunk-VYZKKSX4.js";import{b as M}from"../../chunk-YSLKV4XC.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-UGACB66X.js";import"../../chunk-WMIUFMDI.js";import{a as L}from"../../chunk-PZNWH4VQ.js";import{a as w}from"../../chunk-ZLLER3HP.js";import{Flags as y}from"@oclif/core";import{execFileSync as Ct,spawnSync as l}from"node:child_process";import{existsSync as u}from"node:fs";import{homedir as kt}from"node:os";import{join as _,dirname as wt}from"node:path";function xt(){try{let h=Ct("/bin/sh",["-c","command -v rulemetric"],{encoding:"utf-8"}).trim();if(h&&u(h))return wt(h)}catch{}}w(xt,"resolveHookBinDir");function Pt(){try{return Ct("launchctl",["list","com.rulemetric.gateway"],{stdio:["ignore","pipe","pipe"]}),!0}catch{return!1}}w(Pt,"isGatewayLaunchdManaged");var o=_(kt(),".mitmproxy","mitmproxy-ca-cert.pem"),K=class h extends B{static{w(this,"HooksInstall")}static description="Install session tracking hooks and context capture proxy for Claude Code";static examples=["<%= config.bin %> hooks install","<%= config.bin %> hooks install --global","<%= config.bin %> hooks install --no-proxy"];static flags={"no-proxy":y.boolean({default:!1,description:"Skip proxy/gateway configuration (hooks only)"}),"project-dir":y.string({description:"Project directory to install hooks in (defaults to cwd)"}),"user-hooks":y.boolean({description:"Write user-level Cursor/Antigravity hooks (~/.cursor, ~/.gemini). Required for Cursor capture \u2014 its traffic bypasses the proxy.",default:!0,allowNo:!0}),global:y.boolean({char:"g",default:!1,description:"Install hooks globally (~/.claude/settings.json) so all projects are tracked"}),"statusline-usage":y.boolean({default:!1,description:"Install the statusline shim so Claude Code pushes live rate_limits on every refresh (makes /usage rings update in real time without needing the proxy)"})};async run(){let{flags:i}=await this.parse(h),r=i.global,a=r?kt():i["project-dir"]??process.cwd(),x=_(a,".claude"),C=it(x,r),$=r?"settings.json":"settings.local.json",P=i["no-proxy"],b=!1,g=P?"no_proxy_flag":void 0,p=!1,S=[];r&&this.log(`Installing hooks globally \u2192 ${C}`);let{settings:n,recoveredBackup:I}=Z(C);if(I&&this.log(`[!!] ${C} was not valid JSON \u2014 backed it up to ${I} and continued with a fresh file.`),!r){let e=rt(_(x,"settings.json"),s);e.migrated&&(this.log("[OK] Moved RuleMetric machine-local state out of the shared .claude/settings.json (it now lives in .claude/settings.local.json)"),e.backupPath&&this.log(` Previous shared settings backed up \u2192 ${e.backupPath}`),e.removedStatusline&&u(J)&&!R(n)&&(n.statusLine=m))}let E=L();(E.accessToken||process.env.RULEMETRIC_ACCESS_TOKEN)&&!E.apiKey&&!process.env.RULEMETRIC_API_KEY&&await X(this.log.bind(this),this.warn.bind(this),this.config.version);let vt=st(n),k=xt();if(et(n,k),this.log(vt?`[OK] Refreshed RuleMetric Claude Code session hooks \u2192 .claude/${$}`:`[OK] Installed RuleMetric Claude Code session hooks \u2192 .claude/${$}`),!P){let e=!!f("mitmdump");if(e||(this.log(""),this.log("[!!] mitmproxy not found \u2014 installing..."),S=["brew","pipx","uv"].filter(t=>!!f(t)),e=this.installMitmproxy(),e||(this.log("[!!] Could not install mitmproxy. Skipping proxy config."),this.log(" Install manually: pipx install mitmproxy"),this.log(" Then re-run: rulemetric hooks install"))),u(o))this.log("[OK] CA certificate found");else{this.log("[..] Generating CA certificate...");let t=f("mitmdump");t&&(l(t,["--set","listen_port=0","-q"],{timeout:5e3,stdio:"ignore"}),u(o)?this.log(`[OK] CA certificate generated at ${o}`):this.log("[!!] Could not generate CA cert"))}let c=u(o);c&&!this.isCACertTrusted()?(this.log("[..] Installing CA certificate into system trust store (requires admin)..."),p=this.trustCACert(),p?this.log("[OK] CA certificate trusted by system"):(this.log("[!!] Could not install CA cert automatically."),process.platform==="darwin"?this.log(` Run manually: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${o}`):process.platform==="linux"&&this.log(` Run manually: sudo cp ${o} /usr/local/share/ca-certificates/mitmproxy-ca.crt && sudo update-ca-certificates`))):c&&(this.log("[OK] CA certificate already trusted"),p=!0);let d=Pt(),O=await F(s);if(d)this.log("[OK] Gateway managed by launchd (com.rulemetric.gateway)");else if(O.status==="ours-live")this.log("[OK] Gateway already running");else if(O.status==="foreign"&&q()){this.log("[..] Restarting gateway (running build predates the identity handshake)..."),W(),await new Promise(t=>setTimeout(t,500));try{let t=A(this.config.version);this.log(`[OK] Gateway restarted (PID ${t})`)}catch(t){this.log(`[!!] Could not restart gateway: ${t.message}`)}}else if(O.status!=="foreign")try{let t=A(this.config.version);this.log(`[OK] Gateway started (PID ${t})`)}catch(t){this.log(`[!!] Could not start gateway: ${t.message}`)}let G=await V(s,{timeoutMs:4e3});if(!c)g=e?"ca_not_generated":S.length===0?"no_package_manager":"mitmproxy_install_failed",this.log("[!!] No CA certificate \u2014 NOT setting HTTPS_PROXY (capture stays hooks-only)."),this.log(" Install mitmproxy, then re-run: rulemetric hooks install");else if(G.status==="foreign"&&!d){g="gateway_port_foreign";let t=D(s);this.log(`[!!] Port :${s} is held by a process that is NOT the RuleMetric gateway \u2014 NOT setting HTTPS_PROXY.`),this.log(t?` Holding the port: ${t}`:` Could not identify the holder (try: lsof -nP -iTCP:${s} -sTCP:LISTEN)`),this.log(" Capture still works via hooks. Free the port, then re-run: rulemetric hooks install")}else if(G.status==="dead")g="gateway_not_live",this.log(`[!!] Gateway is not answering on :${s} \u2014 NOT setting HTTPS_PROXY.`),this.log(" Capture still works via hooks. To enable deep (proxy) capture later:"),this.log(" rulemetric proxy start && rulemetric hooks install");else{let t=n.env??{};t.HTTPS_PROXY=`http://localhost:${s}`,t.NO_PROXY=ot,u(o)&&(t.NODE_EXTRA_CA_CERTS=o),n.env=t,b=!0,this.log(`[OK] HTTPS_PROXY set to gateway on :${s} (verified live)`),ct(a,s,o)&&this.log("[OK] Cursor proxy configured \u2192 .cursor/settings.json"),ut(a,s,o)&&this.log("[OK] VS Code workspace proxy configured \u2192 .vscode/settings.json"),ht(s)&&this.log("[OK] VS Code user proxy configured \u2192 ~/Library/Application Support/Code/User/settings.json"),gt(s)&&this.log("[OK] Cursor user proxy configured \u2192 ~/Library/Application Support/Cursor/User/settings.json"),p?dt(s,o)&&this.log("[OK] HTTPS_PROXY set for GUI apps (launchctl + LaunchAgent)"):(g="ca_untrusted",this.log("[!!] CA not trusted \u2014 skipping machine-wide GUI proxy (would break native-app TLS)."),this.log(" Claude Code capture is unaffected. Trust the CA + re-run to enable cross-app capture."))}}let v=[];if(!r){let e=at(a,k);e&&(this.log(`[OK] Cursor hooks configured \u2192 ${e}`),v.push(e));let c=lt(a,k);c&&(this.log(`[OK] Copilot Agent hooks configured \u2192 ${c}`),v.push(c));let d=pt(a);d&&(this.log(`[OK] Antigravity workspace hooks configured \u2192 ${d}`),v.push(d))}let H=i["user-hooks"]?ft():null;H&&this.log(`[OK] Antigravity user hooks configured \u2192 ${H}`);let U=i["user-hooks"]?nt(k):null;if(U&&this.log(`[OK] Cursor user hooks configured \u2192 ${U}`),i["user-hooks"]||(this.log("[--] Skipped user-level Cursor/Antigravity hooks (--no-user-hooks)."),this.log(" Cursor capture will not work: its chat traffic bypasses the proxy,"),this.log(" so hooks are the only path. Claude Code capture is unaffected.")),i["statusline-usage"])if(R(n))this.log("[OK] Statusline shim already installed");else{let e=Q(n);z(e),n.statusLine=m,e?this.log(`[OK] Statusline shim installed \u2192 ${m.command} (chains to: ${e})`):this.log(`[OK] Statusline shim installed \u2192 ${m.command}`),this.log(" Rate-limit rings will now update on Claude Code's statusline refresh cadence")}let{backupPath:N}=tt(C,n);N&&this.log(`[OK] Backed up previous settings \u2192 ${N}`),this.log(""),this.log("Setup complete! Next steps:"),r?(this.log(" 1. Install always-on API: rulemetric service install"),this.log(" 2. Start Claude Code in any project \u2014 all sessions tracked automatically"),this.log(""),this.log("The API service starts on login and restarts on crash.")):P?(this.log(" 1. Start Claude Code \u2014 sessions are captured by the hooks just installed"),this.log(""),this.log("No proxy means no mitmproxy / CA cert needed. The hooks capture full"),this.log("sessions on their own; re-run without --no-proxy to also capture system"),this.log("prompts for instruction-effectiveness linking.")):(this.log(" 1. Start Claude Code \u2014 sessions are captured by hooks immediately"),b?this.log(" 2. Full-depth capture is ON \u2014 the proxy is live on :"+s+"."):this.log(" 2. Enable full depth (proxy not yet live): rulemetric proxy start"),this.log(""),this.log("Hooks capture every session (lifecycle + transcript). The proxy adds the"),this.log("rendered system prompt (instruction-effectiveness linking) + cross-tool capture."),this.log(""),this.log("To capture traffic from other clients (Python, curl, etc.):"),this.log(' eval "$(rulemetric proxy env --all)"'));let j=mt(a,v);j&&this.log(j),await M(),Y("hooks_installed",{proxy:b,caTrusted:p,reason:g,installers:S,global:r},this.config.version);let T=await yt();this.log(""),T.available?this.log(`[OK] tmux found${T.version?` (v${T.version})`:""} \u2014 live send enabled`):this.log("[!!] tmux not found \u2014 live send will fall back to opening Terminal. Install with: brew install tmux")}installMitmproxy(){for(let[i,r]of[["pipx",["install","mitmproxy"]],["uv",["tool","install","mitmproxy"]],["brew",["install","mitmproxy"]]]){let a=f(i);if(a&&(this.log(` Installing via ${i}...`),l(a,[...r],{stdio:"inherit"}).status===0))return!0}return!1}isCACertTrusted(){return process.platform==="darwin"?l("security",["verify-cert","-c",o],{stdio:"pipe"}).status===0:process.platform==="linux"?u("/usr/local/share/ca-certificates/mitmproxy-ca.crt"):process.platform==="win32"?l("certutil",["-verify",o],{stdio:"pipe"}).status===0:!1}trustCACert(){return process.platform==="darwin"?l("sudo",["security","add-trusted-cert","-d","-r","trustRoot","-k","/Library/Keychains/System.keychain",o],{stdio:"inherit"}).status===0:process.platform==="linux"?l("sudo",["cp",o,"/usr/local/share/ca-certificates/mitmproxy-ca.crt"],{stdio:"inherit"}).status!==0?!1:l("sudo",["update-ca-certificates"],{stdio:"inherit"}).status===0:process.platform==="win32"?l("certutil",["-addstore","-f","Root",o],{stdio:"inherit"}).status===0:!1}};export{K as default};
|
|
1
|
+
import{b as mt}from"../../chunk-5INUF4A4.js";import{a as yt}from"../../chunk-6XEC6474.js";import{e as s,i as F,j as V,k as q,m as A,n as W}from"../../chunk-QWCEZEDO.js";import{e as D}from"../../chunk-KKDHD4XA.js";import"../../chunk-SZ62CP55.js";import{B as ht,E as gt,H as pt,I as ft,e as Z,f as tt,g as et,i as st,j as ot,k as it,n as rt,p as at,q as nt,r as lt,u as ct,v as ut,y as dt}from"../../chunk-OZQNSELV.js";import{a as J,b as z,c as m,d as Q,g as R}from"../../chunk-HFGO5762.js";import"../../chunk-VS5ROGDP.js";import"../../chunk-N7ODX6PO.js";import{a as f}from"../../chunk-PJ3WHQ67.js";import{a as X}from"../../chunk-G3HODHFN.js";import{a as B}from"../../chunk-DSJNZWCZ.js";import"../../chunk-IZTIYR5Q.js";import{c as Y}from"../../chunk-OOFGV7EX.js";import"../../chunk-VYZKKSX4.js";import{b as M}from"../../chunk-YSLKV4XC.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-UGACB66X.js";import"../../chunk-WMIUFMDI.js";import{a as L}from"../../chunk-PZNWH4VQ.js";import{a as w}from"../../chunk-ZLLER3HP.js";import{Flags as y}from"@oclif/core";import{execFileSync as Ct,spawnSync as l}from"node:child_process";import{existsSync as u}from"node:fs";import{homedir as kt}from"node:os";import{join as _,dirname as wt}from"node:path";function xt(){try{let h=Ct("/bin/sh",["-c","command -v rulemetric"],{encoding:"utf-8"}).trim();if(h&&u(h))return wt(h)}catch{}}w(xt,"resolveHookBinDir");function Pt(){try{return Ct("launchctl",["list","com.rulemetric.gateway"],{stdio:["ignore","pipe","pipe"]}),!0}catch{return!1}}w(Pt,"isGatewayLaunchdManaged");var o=_(kt(),".mitmproxy","mitmproxy-ca-cert.pem"),K=class h extends B{static{w(this,"HooksInstall")}static description="Install session tracking hooks and context capture proxy for Claude Code";static examples=["<%= config.bin %> hooks install","<%= config.bin %> hooks install --global","<%= config.bin %> hooks install --no-proxy"];static flags={"no-proxy":y.boolean({default:!1,description:"Skip proxy/gateway configuration (hooks only)"}),"project-dir":y.string({description:"Project directory to install hooks in (defaults to cwd)"}),"user-hooks":y.boolean({description:"Write user-level Cursor/Antigravity hooks (~/.cursor, ~/.gemini). Required for Cursor capture \u2014 its traffic bypasses the proxy.",default:!0,allowNo:!0}),global:y.boolean({char:"g",default:!1,description:"Install hooks globally (~/.claude/settings.json) so all projects are tracked"}),"statusline-usage":y.boolean({default:!1,description:"Install the statusline shim so Claude Code pushes live rate_limits on every refresh (makes /usage rings update in real time without needing the proxy)"})};async run(){let{flags:i}=await this.parse(h),r=i.global,a=r?kt():i["project-dir"]??process.cwd(),x=_(a,".claude"),C=it(x,r),$=r?"settings.json":"settings.local.json",P=i["no-proxy"],b=!1,g=P?"no_proxy_flag":void 0,p=!1,S=[];r&&this.log(`Installing hooks globally \u2192 ${C}`);let{settings:n,recoveredBackup:I}=Z(C);if(I&&this.log(`[!!] ${C} was not valid JSON \u2014 backed it up to ${I} and continued with a fresh file.`),!r){let e=rt(_(x,"settings.json"),s);e.migrated&&(this.log("[OK] Moved RuleMetric machine-local state out of the shared .claude/settings.json (it now lives in .claude/settings.local.json)"),e.backupPath&&this.log(` Previous shared settings backed up \u2192 ${e.backupPath}`),e.removedStatusline&&u(J)&&!R(n)&&(n.statusLine=m))}let E=L();(E.accessToken||process.env.RULEMETRIC_ACCESS_TOKEN)&&!E.apiKey&&!process.env.RULEMETRIC_API_KEY&&await X(this.log.bind(this),this.warn.bind(this),this.config.version);let vt=st(n),k=xt();if(et(n,k),this.log(vt?`[OK] Refreshed RuleMetric Claude Code session hooks \u2192 .claude/${$}`:`[OK] Installed RuleMetric Claude Code session hooks \u2192 .claude/${$}`),!P){let e=!!f("mitmdump");if(e||(this.log(""),this.log("[!!] mitmproxy not found \u2014 installing..."),S=["brew","pipx","uv"].filter(t=>!!f(t)),e=this.installMitmproxy(),e||(this.log("[!!] Could not install mitmproxy. Skipping proxy config."),this.log(" Install manually: pipx install mitmproxy"),this.log(" Then re-run: rulemetric hooks install"))),u(o))this.log("[OK] CA certificate found");else{this.log("[..] Generating CA certificate...");let t=f("mitmdump");t&&(l(t,["--set","listen_port=0","-q"],{timeout:5e3,stdio:"ignore"}),u(o)?this.log(`[OK] CA certificate generated at ${o}`):this.log("[!!] Could not generate CA cert"))}let c=u(o);c&&!this.isCACertTrusted()?(this.log("[..] Installing CA certificate into system trust store (requires admin)..."),p=this.trustCACert(),p?this.log("[OK] CA certificate trusted by system"):(this.log("[!!] Could not install CA cert automatically."),process.platform==="darwin"?this.log(` Run manually: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${o}`):process.platform==="linux"&&this.log(` Run manually: sudo cp ${o} /usr/local/share/ca-certificates/mitmproxy-ca.crt && sudo update-ca-certificates`))):c&&(this.log("[OK] CA certificate already trusted"),p=!0);let d=Pt(),O=await F(s);if(d)this.log("[OK] Gateway managed by launchd (com.rulemetric.gateway)");else if(O.status==="ours-live")this.log("[OK] Gateway already running");else if(O.status==="foreign"&&q()){this.log("[..] Restarting gateway (running build predates the identity handshake)..."),W(),await new Promise(t=>setTimeout(t,500));try{let t=A(this.config.version);this.log(`[OK] Gateway restarted (PID ${t})`)}catch(t){this.log(`[!!] Could not restart gateway: ${t.message}`)}}else if(O.status!=="foreign")try{let t=A(this.config.version);this.log(`[OK] Gateway started (PID ${t})`)}catch(t){this.log(`[!!] Could not start gateway: ${t.message}`)}let G=await V(s,{timeoutMs:4e3});if(!c)g=e?"ca_not_generated":S.length===0?"no_package_manager":"mitmproxy_install_failed",this.log("[!!] No CA certificate \u2014 NOT setting HTTPS_PROXY (capture stays hooks-only)."),this.log(" Install mitmproxy, then re-run: rulemetric hooks install");else if(G.status==="foreign"&&!d){g="gateway_port_foreign";let t=D(s);this.log(`[!!] Port :${s} is held by a process that is NOT the RuleMetric gateway \u2014 NOT setting HTTPS_PROXY.`),this.log(t?` Holding the port: ${t}`:` Could not identify the holder (try: lsof -nP -iTCP:${s} -sTCP:LISTEN)`),this.log(" Capture still works via hooks. Free the port, then re-run: rulemetric hooks install")}else if(G.status==="dead")g="gateway_not_live",this.log(`[!!] Gateway is not answering on :${s} \u2014 NOT setting HTTPS_PROXY.`),this.log(" Capture still works via hooks. To enable deep (proxy) capture later:"),this.log(" rulemetric proxy start && rulemetric hooks install");else{let t=n.env??{};t.HTTPS_PROXY=`http://localhost:${s}`,t.NO_PROXY=ot,u(o)&&(t.NODE_EXTRA_CA_CERTS=o),n.env=t,b=!0,this.log(`[OK] HTTPS_PROXY set to gateway on :${s} (verified live)`),ct(a,s,o)&&this.log("[OK] Cursor proxy configured \u2192 .cursor/settings.json"),ut(a,s,o)&&this.log("[OK] VS Code workspace proxy configured \u2192 .vscode/settings.json"),ht(s)&&this.log("[OK] VS Code user proxy configured \u2192 ~/Library/Application Support/Code/User/settings.json"),gt(s)&&this.log("[OK] Cursor user proxy configured \u2192 ~/Library/Application Support/Cursor/User/settings.json"),p?dt(s,o)&&this.log("[OK] HTTPS_PROXY set for GUI apps (launchctl + LaunchAgent)"):(g="ca_untrusted",this.log("[!!] CA not trusted \u2014 skipping machine-wide GUI proxy (would break native-app TLS)."),this.log(" Claude Code capture is unaffected. Trust the CA + re-run to enable cross-app capture."))}}let v=[];if(!r){let e=at(a,k);e&&(this.log(`[OK] Cursor hooks configured \u2192 ${e}`),v.push(e));let c=lt(a,k);c&&(this.log(`[OK] Copilot Agent hooks configured \u2192 ${c}`),v.push(c));let d=pt(a);d&&(this.log(`[OK] Antigravity workspace hooks configured \u2192 ${d}`),v.push(d))}let H=i["user-hooks"]?ft():null;H&&this.log(`[OK] Antigravity user hooks configured \u2192 ${H}`);let U=i["user-hooks"]?nt(k):null;if(U&&this.log(`[OK] Cursor user hooks configured \u2192 ${U}`),i["user-hooks"]||(this.log("[--] Skipped user-level Cursor/Antigravity hooks (--no-user-hooks)."),this.log(" Cursor capture will not work: its chat traffic bypasses the proxy,"),this.log(" so hooks are the only path. Claude Code capture is unaffected.")),i["statusline-usage"])if(R(n))this.log("[OK] Statusline shim already installed");else{let e=Q(n);z(e),n.statusLine=m,e?this.log(`[OK] Statusline shim installed \u2192 ${m.command} (chains to: ${e})`):this.log(`[OK] Statusline shim installed \u2192 ${m.command}`),this.log(" Rate-limit rings will now update on Claude Code's statusline refresh cadence")}let{backupPath:N}=tt(C,n);N&&this.log(`[OK] Backed up previous settings \u2192 ${N}`),this.log(""),this.log("Setup complete! Next steps:"),r?(this.log(" 1. Install always-on API: rulemetric service install"),this.log(" 2. Start Claude Code in any project \u2014 all sessions tracked automatically"),this.log(""),this.log("The API service starts on login and restarts on crash.")):P?(this.log(" 1. Start Claude Code \u2014 sessions are captured by the hooks just installed"),this.log(""),this.log("No proxy means no mitmproxy / CA cert needed. The hooks capture full"),this.log("sessions on their own; re-run without --no-proxy to also capture system"),this.log("prompts for instruction-effectiveness linking.")):(this.log(" 1. Start Claude Code \u2014 sessions are captured by hooks immediately"),b?this.log(" 2. Full-depth capture is ON \u2014 the proxy is live on :"+s+"."):this.log(" 2. Enable full depth (proxy not yet live): rulemetric proxy start"),this.log(""),this.log("Hooks capture every session (lifecycle + transcript). The proxy adds the"),this.log("rendered system prompt (instruction-effectiveness linking) + cross-tool capture."),this.log(""),this.log("To capture traffic from other clients (Python, curl, etc.):"),this.log(' eval "$(rulemetric proxy env --all)"'));let j=mt(a,v);j&&this.log(j),await M(),Y("hooks_installed",{proxy:b,caTrusted:p,reason:g,installers:S,global:r},this.config.version);let T=await yt();this.log(""),T.available?this.log(`[OK] tmux found${T.version?` (v${T.version})`:""} \u2014 live send enabled`):this.log("[!!] tmux not found \u2014 live send will fall back to opening Terminal. Install with: brew install tmux")}installMitmproxy(){for(let[i,r]of[["pipx",["install","mitmproxy"]],["uv",["tool","install","mitmproxy"]],["brew",["install","mitmproxy"]]]){let a=f(i);if(a&&(this.log(` Installing via ${i}...`),l(a,[...r],{stdio:"inherit"}).status===0))return!0}return!1}isCACertTrusted(){return process.platform==="darwin"?l("security",["verify-cert","-c",o],{stdio:"pipe"}).status===0:process.platform==="linux"?u("/usr/local/share/ca-certificates/mitmproxy-ca.crt"):process.platform==="win32"?l("certutil",["-verify",o],{stdio:"pipe"}).status===0:!1}trustCACert(){return process.platform==="darwin"?l("sudo",["security","add-trusted-cert","-d","-r","trustRoot","-k","/Library/Keychains/System.keychain",o],{stdio:"inherit"}).status===0:process.platform==="linux"?l("sudo",["cp",o,"/usr/local/share/ca-certificates/mitmproxy-ca.crt"],{stdio:"inherit"}).status!==0?!1:l("sudo",["update-ca-certificates"],{stdio:"inherit"}).status===0:process.platform==="win32"?l("certutil",["-addstore","-f","Root",o],{stdio:"inherit"}).status===0:!1}};export{K as default};
|