loki-mode 7.104.0 → 7.104.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  // @bun
2
- var z8=Object.defineProperty;var X8=($)=>$;function K8($,Q){this[$]=X8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)z8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:K8.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var y1={};b(y1,{lokiDir:()=>P,homeLokiDir:()=>T$,findRepoRootForVersion:()=>e$,REPO_ROOT:()=>h});import{resolve as t,dirname as i$}from"path";import{fileURLToPath as q8}from"url";import{existsSync as E$}from"fs";import{homedir as J8}from"os";function V8(){let $=h1;for(let Q=0;Q<6;Q++){if(E$(t($,"VERSION"))&&E$(t($,"autonomy/run.sh")))return $;let Z=i$($);if(Z===$)break;$=Z}return t(h1,"..","..","..")}function e$($){let Q=$;for(let Z=0;Z<6;Z++){if(E$(t(Q,"VERSION"))&&E$(t(Q,"autonomy/run.sh")))return Q;let z=i$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function P(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(J8(),".loki")}var h1,h;var C=L(()=>{h1=i$(q8(import.meta.url));h=V8()});import{readFileSync as W8}from"fs";import{resolve as U8,dirname as H8}from"path";import{fileURLToPath as G8}from"url";function N$(){if(Q$!==null)return Q$;let $="7.104.0";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=H8(G8(import.meta.url)),Z=e$(Q);Q$=W8(U8(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var $1=L(()=>{C()});var u1={};b(u1,{runOrThrow:()=>x8,run:()=>F,readStreamCapped:()=>f1,commandVersion:()=>N8,commandExists:()=>f,ShellError:()=>Q1,MAX_STDOUT_BYTES:()=>m1});async function f1($,Q=m1){let Z=$.getReader(),z=new TextDecoder,X="",q=0;try{while(q<Q){let{done:K,value:W}=await Z.read();if(K)break;if(!W)continue;if(q+=W.byteLength,q>Q){let V=W.byteLength-(q-Q);X+=z.decode(W.subarray(0,V),{stream:!0});break}X+=z.decode(W,{stream:!0})}X+=z.decode()}finally{try{await Z.cancel()}catch{}Z.releaseLock()}return X}async function F($,Q={}){let Z=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Q.env?{...process.env,...Q.env}:process.env,cwd:Q.cwd}),z,X;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[q,K,W]=await Promise.all([f1(Z.stdout),new Response(Z.stderr).text(),Z.exited]);return{stdout:q,stderr:K,exitCode:W}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function x8($,Q={}){let Z=await F($,Q);if(Z.exitCode!==0)throw new Q1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function f($){let Q=E8($),Z=await F(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function E8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function N8($,Q="--version"){if(!await f($))return null;let z=await F([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var m1=16777216,Q1;var d=L(()=>{Q1=class Q1 extends Error{message;exitCode;stdout;stderr;constructor($,Q,Z,z){super($);this.message=$;this.exitCode=Q;this.stdout=Z;this.stderr=z;this.name="ShellError"}}});function r($){return S8?"":$}var S8,T,S,_,lZ,I,k,y,J;var c=L(()=>{S8=(process.env.NO_COLOR??"").length>0;T=r("\x1B[0;31m"),S=r("\x1B[0;32m"),_=r("\x1B[1;33m"),lZ=r("\x1B[0;34m"),I=r("\x1B[0;36m"),k=r("\x1B[1m"),y=r("\x1B[2m"),J=r("\x1B[0m")});import{existsSync as u8}from"fs";async function Z$(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(u8($))return A$=$,$;let Q=await f("python3.12");if(Q)return A$=Q,Q;let Z=await f("python3");return A$=Z,Z}async function z$($,Q={}){let Z=await Z$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return F([Z,"-c",$],Q)}var A$;var V$=L(()=>{d()});var q0={};b(q0,{runStatus:()=>W3});import{existsSync as v,readFileSync as U$,readdirSync as i1,statSync as e1}from"fs";import{resolve as D,basename as $3}from"path";import{homedir as Q3}from"os";function $0($){let Q=Math.trunc($);if(Q>=1e6)return`${(Math.trunc(Q/1e6*10)/10).toFixed(1)}M`;if(Q>=1000)return`${(Math.trunc(Q/1000*10)/10).toFixed(1)}K`;return String(Q)}function Q0($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*D$/Q);if(X>D$)X=D$;let q=D$-X,K=S;if(z>=80)K=T;else if(z>=50)K=_;let W="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),V=$0($),U=$0(Q);return` ${k}${Z}${J} ${K}[${W}]${J} ${z}% (${V} / ${U})`}async function z3(){if(await f("jq"))return!0;return process.stdout.write(`${T}Error: jq is required but not installed.${J}
2
+ var X8=Object.defineProperty;var K8=($)=>$;function q8($,Q){this[$]=K8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)X8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:q8.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var v1={};b(v1,{lokiDir:()=>P,homeLokiDir:()=>T$,findRepoRootForVersion:()=>e$,REPO_ROOT:()=>h});import{resolve as r,dirname as i$}from"path";import{fileURLToPath as J8}from"url";import{existsSync as x$}from"fs";import{homedir as V8}from"os";function W8(){let $=y1;for(let Q=0;Q<6;Q++){if(x$(r($,"VERSION"))&&x$(r($,"autonomy/run.sh")))return $;let Z=i$($);if(Z===$)break;$=Z}return r(y1,"..","..","..")}function e$($){let Q=$;for(let Z=0;Z<6;Z++){if(x$(r(Q,"VERSION"))&&x$(r(Q,"autonomy/run.sh")))return Q;let z=i$(Q);if(z===Q)break;Q=z}return r($,"..","..","..")}function P(){return process.env.LOKI_DIR??r(process.cwd(),".loki")}function T$(){return r(V8(),".loki")}var y1,h;var C=L(()=>{y1=i$(J8(import.meta.url));h=W8()});import{readFileSync as U8}from"fs";import{resolve as H8,dirname as G8}from"path";import{fileURLToPath as B8}from"url";function N$(){if(Q$!==null)return Q$;let $="7.104.2";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=G8(B8(import.meta.url)),Z=e$(Q);Q$=U8(H8(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var $1=L(()=>{C()});var c1={};b(c1,{runOrThrow:()=>x8,run:()=>F,readStreamCapped:()=>u1,commandVersion:()=>S8,commandExists:()=>f,ShellError:()=>Q1,MAX_STDOUT_BYTES:()=>f1});async function u1($,Q=f1){let Z=$.getReader(),z=new TextDecoder,X="",q=0;try{while(q<Q){let{done:K,value:W}=await Z.read();if(K)break;if(!W)continue;if(q+=W.byteLength,q>Q){let V=W.byteLength-(q-Q);X+=z.decode(W.subarray(0,V),{stream:!0});break}X+=z.decode(W,{stream:!0})}X+=z.decode()}finally{try{await Z.cancel()}catch{}Z.releaseLock()}return X}async function F($,Q={}){let Z=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Q.env?{...process.env,...Q.env}:process.env,cwd:Q.cwd}),z,X;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[q,K,W]=await Promise.all([u1(Z.stdout),new Response(Z.stderr).text(),Z.exited]);return{stdout:q,stderr:K,exitCode:W}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function x8($,Q={}){let Z=await F($,Q);if(Z.exitCode!==0)throw new Q1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function f($){let Q=N8($),Z=await F(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function N8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function S8($,Q="--version"){if(!await f($))return null;let z=await F([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var f1=16777216,Q1;var d=L(()=>{Q1=class Q1 extends Error{message;exitCode;stdout;stderr;constructor($,Q,Z,z){super($);this.message=$;this.exitCode=Q;this.stdout=Z;this.stderr=z;this.name="ShellError"}}});function t($){return D8?"":$}var D8,T,S,_,nZ,I,k,y,J;var c=L(()=>{D8=(process.env.NO_COLOR??"").length>0;T=t("\x1B[0;31m"),S=t("\x1B[0;32m"),_=t("\x1B[1;33m"),nZ=t("\x1B[0;34m"),I=t("\x1B[0;36m"),k=t("\x1B[1m"),y=t("\x1B[2m"),J=t("\x1B[0m")});import{existsSync as c8}from"fs";async function Z$(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(c8($))return A$=$,$;let Q=await f("python3.12");if(Q)return A$=Q,Q;let Z=await f("python3");return A$=Z,Z}async function z$($,Q={}){let Z=await Z$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return F([Z,"-c",$],Q)}var A$;var V$=L(()=>{d()});var J0={};b(J0,{runStatus:()=>U3});import{existsSync as v,readFileSync as U$,readdirSync as e1,statSync as $0}from"fs";import{resolve as D,basename as Q3}from"path";import{homedir as Z3}from"os";function Q0($){let Q=Math.trunc($);if(Q>=1e6)return`${(Math.trunc(Q/1e6*10)/10).toFixed(1)}M`;if(Q>=1000)return`${(Math.trunc(Q/1000*10)/10).toFixed(1)}K`;return String(Q)}function Z0($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*D$/Q);if(X>D$)X=D$;let q=D$-X,K=S;if(z>=80)K=T;else if(z>=50)K=_;let W="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),V=Q0($),U=Q0(Q);return` ${k}${Z}${J} ${K}[${W}]${J} ${z}% (${V} / ${U})`}async function X3(){if(await f("jq"))return!0;return process.stdout.write(`${T}Error: jq is required but not installed.${J}
3
3
  `),process.stdout.write(`Install with:
4
4
  `),process.stdout.write(` brew install jq (macOS)
5
5
  `),process.stdout.write(` apt install jq (Debian/Ubuntu)
6
6
  `),process.stdout.write(` yum install jq (RHEL/CentOS)
7
- `),!1}function C$($){if(!Number.isFinite($)||$<=0)return!1;try{return process.kill($,0),!0}catch{return!1}}function b$($){if(!v($))return null;try{let Q=U$($,"utf-8").trim();if(!Q)return null;let Z=Number.parseInt(Q,10);return Number.isFinite(Z)?Z:null}catch{return null}}function X3($){let Q=[],Z=b$(D($,"loki.pid"));if(Z!==null&&C$(Z))Q.push(`global:${Z}`);let z=D($,"sessions");if(v(z)){let X=[];try{X=i1(z)}catch{X=[]}for(let q of X){let K=D(z,q);try{if(!e1(K).isDirectory())continue}catch{continue}let W=D(K,"loki.pid"),V=b$(W);if(V!==null&&C$(V))Q.push(`${q}:${V}`)}}if(v($)){let X=[];try{X=i1($)}catch{X=[]}for(let q of X){if(!q.startsWith("run-")||!q.endsWith(".pid"))continue;let K=D($,q);try{if(!e1(K).isFile())continue}catch{continue}let W=$3(q,".pid").slice(4),V=b$(K);if(V!==null&&C$(V)){if(!Q.some((H)=>H.startsWith(`${W}:`)))Q.push(`${W}:${V}`)}}}return Q}async function Z0($,Q){let Z=await F(["jq","-r",$,Q]);if(Z.exitCode!==0)return null;return Z.stdout.trim()}function z0($,Q){try{let Z=U$($,"utf-8"),X=JSON.parse(Z)[Q];if(typeof X==="number"){if(Q==="budget_used"){let q=Math.round(X*100)/100;if(Number.isInteger(q))return String(q);return String(q)}return String(X)}if(X===void 0||X===null)return"0";return String(X)}catch{return"0"}}function X0($,Q,Z){try{let z=U$($,"utf-8"),q=JSON.parse(z)[Q];if(typeof q==="number"&&Number.isFinite(q))return q;return Z}catch{return Z}}async function K3(){let $=P();if(!await z3())return 1;if(!v($))return process.stdout.write(`${k}Loki Mode Status${J}
7
+ `),!1}function C$($){if(!Number.isFinite($)||$<=0)return!1;try{return process.kill($,0),!0}catch{return!1}}function b$($){if(!v($))return null;try{let Q=U$($,"utf-8").trim();if(!Q)return null;let Z=Number.parseInt(Q,10);return Number.isFinite(Z)?Z:null}catch{return null}}function K3($){let Q=[],Z=b$(D($,"loki.pid"));if(Z!==null&&C$(Z))Q.push(`global:${Z}`);let z=D($,"sessions");if(v(z)){let X=[];try{X=e1(z)}catch{X=[]}for(let q of X){let K=D(z,q);try{if(!$0(K).isDirectory())continue}catch{continue}let W=D(K,"loki.pid"),V=b$(W);if(V!==null&&C$(V))Q.push(`${q}:${V}`)}}if(v($)){let X=[];try{X=e1($)}catch{X=[]}for(let q of X){if(!q.startsWith("run-")||!q.endsWith(".pid"))continue;let K=D($,q);try{if(!$0(K).isFile())continue}catch{continue}let W=Q3(q,".pid").slice(4),V=b$(K);if(V!==null&&C$(V)){if(!Q.some((H)=>H.startsWith(`${W}:`)))Q.push(`${W}:${V}`)}}}return Q}async function z0($,Q){let Z=await F(["jq","-r",$,Q]);if(Z.exitCode!==0)return null;return Z.stdout.trim()}function X0($,Q){try{let Z=U$($,"utf-8"),X=JSON.parse(Z)[Q];if(typeof X==="number"){if(Q==="budget_used"){let q=Math.round(X*100)/100;if(Number.isInteger(q))return String(q);return String(q)}return String(X)}if(X===void 0||X===null)return"0";return String(X)}catch{return"0"}}function K0($,Q,Z){try{let z=U$($,"utf-8"),q=JSON.parse(z)[Q];if(typeof q==="number"&&Number.isFinite(q))return q;return Z}catch{return Z}}async function q3(){let $=P();if(!await X3())return 1;if(!v($))return process.stdout.write(`${k}Loki Mode Status${J}
8
8
  `),process.stdout.write(`
9
9
  `),process.stdout.write(`${_}No active session found.${J}
10
10
  `),process.stdout.write(`Loki Mode has not been initialized in this directory.
@@ -19,7 +19,7 @@ var z8=Object.defineProperty;var X8=($)=>$;function K8($,Q){this[$]=X8.bind(null
19
19
  `);let Q="",Z=D($,"state","provider");if(v(Z))try{Q=U$(Z,"utf-8").trim()}catch{Q=""}let z=Q||process.env.LOKI_PROVIDER||"claude",X="full features";switch(z){case"codex":case"aider":X="degraded mode";break;case"cline":X="near-full mode";break;default:X="full features";break}process.stdout.write(`${I}Provider:${J} ${z} (${X})
20
20
  `),process.stdout.write(`${y} Switch with: loki provider set <claude|codex|cline|aider>${J}
21
21
  `),process.stdout.write(`
22
- `);let q=X3($);if(q.length>0){process.stdout.write(`${S}Active Sessions: ${q.length}${J}
22
+ `);let q=K3($);if(q.length>0){process.stdout.write(`${S}Active Sessions: ${q.length}${J}
23
23
  `);for(let Y of q){let O=Y.indexOf(":"),M=O>=0?Y.slice(0,O):Y,R=O>=0?Y.slice(O+1):"";if(M==="global")process.stdout.write(` ${I}[global]${J} PID ${R}
24
24
  `);else process.stdout.write(` ${I}[#${M}]${J} PID ${R}
25
25
  `)}process.stdout.write(`
@@ -35,27 +35,27 @@ var z8=Object.defineProperty;var X8=($)=>$;function K8($,Q){this[$]=X8.bind(null
35
35
  `);let K=D($,"STATUS.txt");if(v(K)){process.stdout.write(`${I}Session Info:${J}
36
36
  `);try{process.stdout.write(U$(K,"utf-8"))}catch{}process.stdout.write(`
37
37
  `)}let W=D($,"state","orchestrator.json");if(v(W)){process.stdout.write(`${I}Orchestrator State:${J}
38
- `);let Y=await Z0('.currentPhase // "unknown"',W);process.stdout.write(`${Y??"unknown"}
39
- `)}let V=D($,"queue","pending.json");if(v(V)){let Y=await Z0('if type == "array" then length elif .tasks then .tasks | length else 0 end',V);process.stdout.write(`${I}Pending Tasks:${J} ${Y??"0"}
40
- `)}let U=D($,"metrics","budget.json");if(v(U)){let Y=z0(U,"budget_limit"),O=z0(U,"budget_used");if(Y!=="0"){process.stdout.write(`${I}Budget:${J} $${O} / $${Y}
41
- `);let M=Math.trunc((Number.parseFloat(O)||0)*100),R=Number.parseFloat(Y),N=Number.isFinite(R)&&R!==0?Math.trunc(R*100):100,g=Q0(M,N,"Budget");if(g!==null)process.stdout.write(`${g}
38
+ `);let Y=await z0('.currentPhase // "unknown"',W);process.stdout.write(`${Y??"unknown"}
39
+ `)}let V=D($,"queue","pending.json");if(v(V)){let Y=await z0('if type == "array" then length elif .tasks then .tasks | length else 0 end',V);process.stdout.write(`${I}Pending Tasks:${J} ${Y??"0"}
40
+ `)}let U=D($,"metrics","budget.json");if(v(U)){let Y=X0(U,"budget_limit"),O=X0(U,"budget_used");if(Y!=="0"){process.stdout.write(`${I}Budget:${J} $${O} / $${Y}
41
+ `);let M=Math.trunc((Number.parseFloat(O)||0)*100),R=Number.parseFloat(Y),N=Number.isFinite(R)&&R!==0?Math.trunc(R*100):100,g=Z0(M,N,"Budget");if(g!==null)process.stdout.write(`${g}
42
42
  `)}else process.stdout.write(`${I}Cost:${J} $${O} (no limit)
43
- `)}let H=D($,"state","context-usage.json");if(v(H)){let Y=X0(H,"window_size",200000),O=X0(H,"used_tokens",0),M=Q0(O,Y,"Context");if(M!==null)process.stdout.write(`${M}
44
- `)}let G=[D($,"dashboard","dashboard.pid"),D(Q3(),".loki","dashboard","dashboard.pid")].find((Y)=>v(Y))??"";if(G&&v(G)){let Y=b$(G);if(Y!==null&&C$(Y)){let O=D(G,".."),M=(u,w)=>{let x=D(O,u);try{return v(x)?U$(x,"utf-8").trim()||w:w}catch{return w}},R=M("scheme","http"),N=M("host","127.0.0.1"),g=M("port",process.env.LOKI_DASHBOARD_PORT||"57374");if(N==="0.0.0.0")N="127.0.0.1";process.stdout.write(`${I}Dashboard:${J} ${R}://${N}:${g}/
45
- `)}}return await q3($),process.stdout.write(`
43
+ `)}let H=D($,"state","context-usage.json");if(v(H)){let Y=K0(H,"window_size",200000),O=K0(H,"used_tokens",0),M=Z0(O,Y,"Context");if(M!==null)process.stdout.write(`${M}
44
+ `)}let G=[D($,"dashboard","dashboard.pid"),D(Z3(),".loki","dashboard","dashboard.pid")].find((Y)=>v(Y))??"";if(G&&v(G)){let Y=b$(G);if(Y!==null&&C$(Y)){let O=D(G,".."),M=(u,w)=>{let E=D(O,u);try{return v(E)?U$(E,"utf-8").trim()||w:w}catch{return w}},R=M("scheme","http"),N=M("host","127.0.0.1"),g=M("port",process.env.LOKI_DASHBOARD_PORT||"57374");if(N==="0.0.0.0")N="127.0.0.1";process.stdout.write(`${I}Dashboard:${J} ${R}://${N}:${g}/
45
+ `)}}return await J3($),process.stdout.write(`
46
46
  `),process.stdout.write(`${y} Tip: loki analyze context show - detailed token breakdown${J}
47
47
  `),process.stdout.write(`${y} Tip: loki analyze code overview - codebase intelligence${J}
48
- `),0}async function q3($){let Q=D($,"state"),Z=J3(Q),z=D(Q,"relevant-learnings.json"),X=D($,"escalations"),q=Z.length>0,K=v(z),W=v(X);if(!q&&!K&&!W)return;if(process.stdout.write(`
48
+ `),0}async function J3($){let Q=D($,"state"),Z=V3(Q),z=D(Q,"relevant-learnings.json"),X=D($,"escalations"),q=Z.length>0,K=v(z),W=v(X);if(!q&&!K&&!W)return;if(process.stdout.write(`
49
49
  ${I}Phase 1 artifacts:${J}
50
- `),q){let V=Z[Z.length-1],U=K0(V);if(U&&Array.isArray(U.findings)){let H={Critical:0,High:0,Medium:0,Low:0};for(let G of U.findings){let Y=String(G.severity??"");if(Y in H)H[Y]=(H[Y]??0)+1}let B=Object.entries(H).filter(([,G])=>G>0).map(([G,Y])=>`${Y} ${G.toLowerCase()}`).join(", ");process.stdout.write(` Findings (iter ${U.iteration??"?"}): ${B||"none"} -- ${U.findings.length} total
51
- `)}}if(K){let V=K0(z);if(V&&Array.isArray(V.learnings)&&V.learnings.length>0){let U=new Map;for(let B of V.learnings){let G=String(B.trigger??"unknown");U.set(G,(U.get(G)??0)+1)}let H=[...U.entries()].sort((B,G)=>G[1]-B[1]).slice(0,3).map(([B,G])=>`${G} ${B}`).join(", ");process.stdout.write(` Learnings: ${V.learnings.length} total (${H})
50
+ `),q){let V=Z[Z.length-1],U=q0(V);if(U&&Array.isArray(U.findings)){let H={Critical:0,High:0,Medium:0,Low:0};for(let G of U.findings){let Y=String(G.severity??"");if(Y in H)H[Y]=(H[Y]??0)+1}let B=Object.entries(H).filter(([,G])=>G>0).map(([G,Y])=>`${Y} ${G.toLowerCase()}`).join(", ");process.stdout.write(` Findings (iter ${U.iteration??"?"}): ${B||"none"} -- ${U.findings.length} total
51
+ `)}}if(K){let V=q0(z);if(V&&Array.isArray(V.learnings)&&V.learnings.length>0){let U=new Map;for(let B of V.learnings){let G=String(B.trigger??"unknown");U.set(G,(U.get(G)??0)+1)}let H=[...U.entries()].sort((B,G)=>G[1]-B[1]).slice(0,3).map(([B,G])=>`${G} ${B}`).join(", ");process.stdout.write(` Learnings: ${V.learnings.length} total (${H})
52
52
  `)}}if(W){let V=0,U="";try{let B=(await import("fs")).readdirSync(X).filter((G)=>G.endsWith(".md"));if(V=B.length,B.length>0)B.sort(),U=B[B.length-1]??""}catch{}if(V>0)process.stdout.write(` Escalations: ${V} handoff doc${V===1?"":"s"} (latest: ${U})
53
- `)}}function J3($){if(!v($))return[];try{return J$("fs").readdirSync($).filter((z)=>/^findings-\d+\.json$/.test(z)).sort((z,X)=>{let q=Number.parseInt(z.replace(/[^0-9]/g,""),10)||0,K=Number.parseInt(X.replace(/[^0-9]/g,""),10)||0;return q-K}).map((z)=>D($,z))}catch{return[]}}function K0($){try{let Q=J$("fs");return JSON.parse(Q.readFileSync($,"utf-8"))}catch{return null}}async function V3(){let $=await Z$();if(!$)return process.stderr.write(`{"error": "Failed to generate JSON status. Ensure python3 is available."}
54
- `),1;let Q=h,Z=P(),z=process.env.LOKI_DASHBOARD_PORT||"57374",X=process.env.LOKI_PROVIDER||"claude",q=await F([$,"-c",Z3,Q,Z,z,X],{timeoutMs:30000});if(q.exitCode!==0)return process.stderr.write(`{"error": "Failed to generate JSON status. Ensure python3 is available."}
55
- `),1;return process.stdout.write(q.stdout),0}async function W3($){let Q=[...$];while(Q.length>0){let Z=Q[0];if(Z==="--json")return V3();if(Z==="--help"||Z==="-h")return process.stdout.write(`Usage: loki status [--json]
53
+ `)}}function V3($){if(!v($))return[];try{return J$("fs").readdirSync($).filter((z)=>/^findings-\d+\.json$/.test(z)).sort((z,X)=>{let q=Number.parseInt(z.replace(/[^0-9]/g,""),10)||0,K=Number.parseInt(X.replace(/[^0-9]/g,""),10)||0;return q-K}).map((z)=>D($,z))}catch{return[]}}function q0($){try{let Q=J$("fs");return JSON.parse(Q.readFileSync($,"utf-8"))}catch{return null}}async function W3(){let $=await Z$();if(!$)return process.stderr.write(`{"error": "Failed to generate JSON status. Ensure python3 is available."}
54
+ `),1;let Q=h,Z=P(),z=process.env.LOKI_DASHBOARD_PORT||"57374",X=process.env.LOKI_PROVIDER||"claude",q=await F([$,"-c",z3,Q,Z,z,X],{timeoutMs:30000});if(q.exitCode!==0)return process.stderr.write(`{"error": "Failed to generate JSON status. Ensure python3 is available."}
55
+ `),1;return process.stdout.write(q.stdout),0}async function U3($){let Q=[...$];while(Q.length>0){let Z=Q[0];if(Z==="--json")return W3();if(Z==="--help"||Z==="-h")return process.stdout.write(`Usage: loki status [--json]
56
56
  `),0;return process.stdout.write(`${T}Unknown flag: ${Z}${J}
57
57
  `),process.stdout.write(`Usage: loki status [--json]
58
- `),1}return K3()}var D$=30,Z3=`
58
+ `),1}return q3()}var D$=30,z3=`
59
59
  import json, os, sys, time
60
60
 
61
61
  skill_dir = sys.argv[1]
@@ -329,11 +329,11 @@ if os.path.isfile(gate_count_file):
329
329
  result['phase1'] = phase1
330
330
 
331
331
  print(json.dumps(result, indent=2))
332
- `;var J0=L(()=>{d();V$();c();C()});var W0={};b(W0,{emitDeprecatedAlias:()=>X1,deprecatedAliasShouldSuppress:()=>V0});function V0($){let Q=$[0];if(Q!==void 0&&H3.has(Q))return!0;for(let Z of $)if(U3.has(Z))return!0;return!1}function X1($,Q,Z){if(V0(Z))return;process.stderr.write(`note: 'loki ${$}' is now 'loki ${Q}'. The old form still works.
333
- `)}var U3,H3;var K1=L(()=>{U3=new Set(["--json","-q","--quiet"]),H3=new Set(["json","csv","timeline"])});var B0={};b(B0,{runStats:()=>O3,computeStats:()=>G0});import{readdirSync as U0,readFileSync as G3,statSync as H0}from"fs";import{join as i}from"path";function H$($){try{if(!H0($).isFile())return null;return JSON.parse(G3($,"utf-8"))}catch{return null}}function V1($){try{return H0($).isDirectory()}catch{return!1}}function B3($){if(!V1($))return[];try{let Q=U0($).filter((Z)=>Z.startsWith("iteration-")&&Z.endsWith(".json"));return Q.sort(),Q.map((Z)=>i($,Z))}catch{return[]}}function G$($){return Math.trunc($).toLocaleString("en-US")}function q1($){let Q=Math.trunc($);if(Q<60)return`${Q}s`;let Z=Math.trunc(Q/3600),z=Math.trunc(Q%3600/60),X=Q%60;if(Z>0)return`${Z}h ${String(z).padStart(2,"0")}m`;return`${z}m ${String(X).padStart(2,"0")}s`}function e($,Q=0){let Z=Math.pow(10,Q);return Math.round($*Z)/Z}function B$($,Q){return $.toFixed(Q)}function J1($,Q){return $.length>=Q?$:$+" ".repeat(Q-$.length)}function Y3($){let Q="N/A",Z=0,z=H$(i($,"state","orchestrator.json"));if(z&&typeof z==="object"){if(typeof z.currentPhase==="string")Q=z.currentPhase;if(typeof z.currentIteration==="number")Z=z.currentIteration}let X=i($,"metrics","efficiency"),q=B3(X),K=[];for(let j of q){let E=H$(j);if(E&&typeof E==="object")K.push(E)}if(K.length>0)Z=Math.max(Z,K.length);let W=K.reduce((j,E)=>j+(E.input_tokens??0),0),V=K.reduce((j,E)=>j+(E.output_tokens??0),0),U=W+V,H=K.reduce((j,E)=>j+(E.cost_usd??0),0),B=K.reduce((j,E)=>j+(E.duration_seconds??0),0),G=0,Y=0,O=H$(i($,"metrics","budget.json"));if(O&&typeof O==="object"){if(typeof O.budget_limit==="number")G=O.budget_limit;if(typeof O.budget_used==="number")Y=O.budget_used}let M=0,R=0,N=H$(i($,"state","quality-gates.json"));if(N&&typeof N==="object"){if(Array.isArray(N)){for(let j of N)if(R+=1,j===!0)M+=1;else if(j&&typeof j==="object"){let E=j;if(E.passed===!0||E.status==="passed")M+=1}}else for(let j of Object.values(N))if(typeof j==="boolean"){if(R+=1,j)M+=1}else if(j&&typeof j==="object"){R+=1;let E=j;if(E.passed===!0||E.status==="passed")M+=1}}let g={},u=H$(i($,"quality","gate-failure-count.json"));if(u&&typeof u==="object"&&!Array.isArray(u)){let j={};for(let[E,l]of Object.entries(u))if(typeof l==="number")j[E]=l;g=j}let w=0,x=0,s=0,r$=i($,"quality");if(V1(r$)){let j=[];try{j=U0(r$)}catch{j=[]}for(let E of j){if(!E.endsWith(".json")||E==="gate-failure-count.json")continue;let l=H$(i(r$,E));if(!l||typeof l!=="object")continue;if(!(("verdict"in l)||("approved"in l)||("reviewers"in l)))continue;w+=1;let b1=(l.verdict??"").toString().toLowerCase();if(l.approved===!0||["approved","approve","pass"].includes(b1))x+=1;else if(["revision","revise","changes_requested","reject"].includes(b1))s+=1}}return{phase:Q,iterationCount:Z,iterations:K,totalInput:W,totalOutput:V,totalTokens:U,totalCost:H,totalDuration:B,budgetLimit:G,budgetUsed:Y,gatesPassed:M,gatesTotal:R,gateFailures:g,reviewsTotal:w,reviewsApproved:x,reviewsRevision:s}}function M3($,Q){let Z=$.iterationCount,z={session:{iterations:Z,duration_seconds:$.totalDuration,phase:$.phase},tokens:{input:$.totalInput,output:$.totalOutput,total:$.totalTokens,cost_usd:e($.totalCost,2)},quality:{gates_passed:$.gatesPassed,gates_total:$.gatesTotal,reviews_total:$.reviewsTotal,reviews_approved:$.reviewsApproved,reviews_revision:$.reviewsRevision,gate_failures:$.gateFailures},efficiency:{avg_tokens_per_iteration:Z>0?e($.totalTokens/Z,0):0,avg_cost_per_iteration:Z>0?e($.totalCost/Z,2):0,avg_duration_per_iteration:Z>0?e($.totalDuration/Z,1):0},budget:{used:e($.budgetUsed,2),limit:$.budgetLimit,percent:$.budgetLimit>0?e($.budgetUsed/$.budgetLimit*100,1):0}};if(Q)z.iterations=$.iterations.map((K,W)=>({number:W+1,input_tokens:K.input_tokens??0,output_tokens:K.output_tokens??0,cost_usd:e(K.cost_usd??0,2),duration_seconds:K.duration_seconds??0}));let X=JSON.stringify(z,null,2);function q(K,W){if(!W)return;let V=new RegExp(`("${K}": )(-?\\d+)(,?)$`,"m");X=X.replace(V,(U,H,B,G)=>`${H}${B}.0${G}`)}if(q("avg_duration_per_iteration",Z>0&&Number.isInteger(z.efficiency.avg_duration_per_iteration)),q("percent",$.budgetLimit>0&&Number.isInteger(z.budget.percent)),q("cost_usd",Z>0&&Number.isInteger(z.tokens.cost_usd)),Q)X=X.replace(/("cost_usd": )(-?\d+)(,?)$/gm,(K,W,V,U)=>`${W}${V}.0${U}`);return X}function T3($,Q){let Z=[];if(Z.push("Loki Mode Session Statistics"),Z.push("============================"),Z.push(""),Z.push("Session"),Z.push(` Iterations completed: ${$.iterationCount}`),Z.push(` Duration: ${q1($.totalDuration)}`),Z.push(` Current phase: ${$.phase}`),Z.push(""),Z.push("Token Usage"),$.iterations.length>0)Z.push(` Input tokens: ${G$($.totalInput)}`),Z.push(` Output tokens: ${G$($.totalOutput)}`),Z.push(` Total tokens: ${G$($.totalTokens)}`),Z.push(` Estimated cost: $${B$($.totalCost,2)}`);else Z.push(" N/A (no iteration metrics found)");if(Z.push(""),Z.push("Quality Gates"),$.gatesTotal>0){let z=Math.round($.gatesPassed/$.gatesTotal*100);Z.push(` Gates passed: ${$.gatesPassed}/${$.gatesTotal} (${z}%)`)}else Z.push(" Gates passed: N/A");if($.reviewsTotal>0){let z=[];if($.reviewsApproved>0)z.push(`${$.reviewsApproved} approved`);if($.reviewsRevision>0)z.push(`${$.reviewsRevision} revision requested`);let X=z.length>0?z.join(", "):"N/A";Z.push(` Code reviews: ${$.reviewsTotal} (${X})`)}if(Object.keys($.gateFailures).length>0){let z=Object.entries($.gateFailures).filter(([,X])=>X>0).map(([X,q])=>`${X} (${q})`);if(z.length>0)Z.push(` Gate failures: ${z.join(", ")}`)}if(Z.push(""),Z.push("Efficiency"),$.iterationCount>0&&$.iterations.length>0){let z=Math.round($.totalTokens/$.iterationCount),X=$.totalCost/$.iterationCount,q=$.totalDuration/$.iterationCount;Z.push(` Avg tokens/iteration: ${G$(z)}`),Z.push(` Avg cost/iteration: $${B$(X,2)}`),Z.push(` Avg duration/iteration: ${q1(q)}`)}else Z.push(" N/A (no iteration metrics found)");if(Z.push(""),Z.push("Budget"),$.budgetLimit>0){let z=e($.budgetUsed/$.budgetLimit*100,1),X=Number.isInteger(z)?`${z}.0`:`${z}`;Z.push(` Used: $${B$($.budgetUsed,2)} / $${B$($.budgetLimit,2)} (${X}%)`)}else if($.budgetUsed>0)Z.push(` Used: $${B$($.budgetUsed,2)} (no limit set)`);else Z.push(" N/A");if(Q&&$.iterations.length>0)Z.push(""),Z.push("Per-Iteration Breakdown"),$.iterations.forEach((z,X)=>{let q=X+1,K=J1(G$(z.input_tokens??0),10),W=J1(G$(z.output_tokens??0),10),V=z.cost_usd??0,U=q1(z.duration_seconds??0),H=J1(`${q}`,3);Z.push(` #${H} input: ${K} output: ${W} cost: $${B$(V,2)} time: ${U}`)});return Z.join(`
334
- `)}function G0($){let Q=!1,Z=!1;for(let K of $)if(K==="--json")Q=!0;else if(K==="--efficiency")Z=!0;let z=P();if(!V1(z)){if(Q)return{exitCode:0,stdout:'{"error": "No active session"}'};return{exitCode:0,stdout:`${_}No active session found.${J}
335
- Start a session with: loki start <prd>`}}let X=Y3(z);return{exitCode:0,stdout:Q?M3(X,Z):T3(X,Z)}}async function O3($){let{emitDeprecatedAlias:Q}=await Promise.resolve().then(() => (K1(),W0));Q("stats","report session",$);let Z=G0($);return console.log(Z.stdout),Z.exitCode}var Y0=L(()=>{C();c()});var P0={};b(P0,{runDoctor:()=>S3,pythonImportOk:()=>G1,httpReachable:()=>U1,checkTool:()=>w0,checkSkills:()=>_0,checkDisk:()=>H1,buildDoctorJson:()=>L0,_setPythonImportOkForTest:()=>j3});import{existsSync as M0,lstatSync as A3,readlinkSync as w3,statfsSync as _3}from"fs";import{spawnSync as I3}from"child_process";import{homedir as T0}from"os";import{resolve as W1}from"path";function P3($){let Q=$.match(L3);return Q?Q[1]:null}async function O0($){try{let Q=await F([$,"--version"],{timeoutMs:5000}),Z=(Q.stdout||Q.stderr||"").trim();return P3(Z)}catch{return null}}function A0($,Q){let Z=$.split(".").map((X)=>parseInt(X,10)),z=Q.split(".").map((X)=>parseInt(X,10));while(Z.length<2)Z.push(0);while(z.length<2)z.push(0);for(let X=0;X<2;X++){let q=Z[X]??0,K=z[X]??0;if(Number.isNaN(q)||Number.isNaN(K))return 0;if(q!==K)return q-K}return 0}async function w0($,Q,Z,z=null){let X=await f(Q),q=X!==null,K=q?await O0(Q):null,W="pass";if(!q)W=Z==="required"?"fail":"warn";else if(z&&K){if(A0(K,z)<0)W=Z==="required"?"fail":"warn"}return{name:$,command:Q,found:q,version:K,required:Z,min_version:z,status:W,path:X}}function H1(){let $=null;try{let Z=_3(T0()),z=Number(Z.bavail)*Number(Z.bsize);$=Math.round(z/1073741824*10)/10}catch{$=null}let Q="pass";if($!==null){if($<1)Q="fail";else if($<5)Q="warn"}return{available_gb:$,status:Q}}async function U1($,Q=2000){try{return(await fetch($,{signal:AbortSignal.timeout(Q)})).ok}catch{return!1}}async function G1($,Q=!1){let Z=`import ${$}`,z=Q?30000:5000;if(!Q)return(await z$(Z,{timeoutMs:z})).exitCode===0;let X=await Z$();if(!X)return!1;return(await F([X,"-c",Z],{timeoutMs:z})).exitCode===0}function j3($){v$.fn=$??G1}function _0(){let $=T0();return F3.map(({name:Q,dir:Z})=>{let z=W1($,Z),X=z,q=W1(z,"SKILL.md");if(M0(q))return{name:Q,path:X,status:"pass",detail:""};try{if(A3(z).isSymbolicLink()){let W="unknown";try{W=w3(z)}catch{}return{name:Q,path:X,status:"fail",detail:`(broken symlink -> ${W})`}}}catch{}return{name:Q,path:X,status:"warn",detail:"(not found - run 'loki setup-skill')"}})}async function I0(){return Promise.all(k3.map(async($)=>{return{...await w0($.jsonName,$.cmd,$.required,$.min??null),displayName:$.displayName}}))}async function R3(){let Q=await f("sentrux")!==null,Z=Q?await O0("sentrux"):null;return{found:Q,version:Z,status:Q?"pass":"warn",required:"optional"}}async function x3(){let{openSync:$,statSync:Q,readSync:Z,closeSync:z,existsSync:X}=await import("fs"),{join:q}=await import("path"),K=65536,W=process.env.LOKI_DIR??".loki",V=q(W,"memory",".errors.log"),U=[],H=!1;try{if(X(V)){H=!0;let B=Q(V).size,G=Math.max(0,B-65536),Y=B-G,O=Buffer.alloc(Y),M=$(V,"r");try{Z(M,O,0,Y,G)}finally{z(M)}let N=O.toString("utf-8").split(`
336
- `);if(G>0&&N.length>0)N=N.slice(1);N=N.map((g)=>g.trim()).filter((g)=>g.length>0),U=N.slice(-5)}}catch{U=[]}return{errors_log_path:H?V:null,recent_errors:U,recent_error_count:U.length,status:U.length===0?"pass":"warn"}}async function L0(){let Q=(await I0()).map(({displayName:V,...U})=>U),Z=H1(),z=await R3(),X=await x3(),q=0,K=0,W=0;for(let V of Q)if(V.status==="pass")q++;else if(V.status==="fail")K++;else W++;if(Z.status==="pass")q++;else if(Z.status==="fail")K++;else W++;return{loki_mode_version:N$(),checks:Q,disk:Z,sentrux:z,memory:X,summary:{passed:q,failed:K,warnings:W,ok:K===0}}}function A($){switch($){case"pass":return`${S}PASS${J}`;case"fail":return`${T}FAIL${J}`;case"warn":return`${_}WARN${J}`}}function h$($){let Q=$.version?` (v${$.version})`:"",Z=$.displayName;if(!$.found){let z=$.required==="required"?"not found":$.required==="recommended"?"not found (recommended)":"not found (optional)";return` ${A($.status)} ${Z} - ${z}`}if($.min_version&&$.version&&A0($.version,$.min_version)<0){let z=$.required==="required"?"requires":"recommended";return` ${A($.status)} ${Z}${Q} - ${z} >= ${$.min_version}`}return` ${A($.status)} ${Z}${Q}`}function y$($,Q){if(Q==="pass")$.pass++;else if(Q==="fail")$.fail++;else $.warn++}function E3(){process.stdout.write(`${k}loki doctor${J} - Check system prerequisites
332
+ `;var V0=L(()=>{d();V$();c();C()});var U0={};b(U0,{emitDeprecatedAlias:()=>X1,deprecatedAliasShouldSuppress:()=>W0});function W0($){let Q=$[0];if(Q!==void 0&&G3.has(Q))return!0;for(let Z of $)if(H3.has(Z))return!0;return!1}function X1($,Q,Z){if(W0(Z))return;process.stderr.write(`note: 'loki ${$}' is now 'loki ${Q}'. The old form still works.
333
+ `)}var H3,G3;var K1=L(()=>{H3=new Set(["--json","-q","--quiet"]),G3=new Set(["json","csv","timeline"])});var Y0={};b(Y0,{runStats:()=>A3,computeStats:()=>B0});import{readdirSync as H0,readFileSync as B3,statSync as G0}from"fs";import{join as i}from"path";function H$($){try{if(!G0($).isFile())return null;return JSON.parse(B3($,"utf-8"))}catch{return null}}function V1($){try{return G0($).isDirectory()}catch{return!1}}function Y3($){if(!V1($))return[];try{let Q=H0($).filter((Z)=>Z.startsWith("iteration-")&&Z.endsWith(".json"));return Q.sort(),Q.map((Z)=>i($,Z))}catch{return[]}}function G$($){return Math.trunc($).toLocaleString("en-US")}function q1($){let Q=Math.trunc($);if(Q<60)return`${Q}s`;let Z=Math.trunc(Q/3600),z=Math.trunc(Q%3600/60),X=Q%60;if(Z>0)return`${Z}h ${String(z).padStart(2,"0")}m`;return`${z}m ${String(X).padStart(2,"0")}s`}function e($,Q=0){let Z=Math.pow(10,Q);return Math.round($*Z)/Z}function B$($,Q){return $.toFixed(Q)}function J1($,Q){return $.length>=Q?$:$+" ".repeat(Q-$.length)}function M3($){let Q="N/A",Z=0,z=H$(i($,"state","orchestrator.json"));if(z&&typeof z==="object"){if(typeof z.currentPhase==="string")Q=z.currentPhase;if(typeof z.currentIteration==="number")Z=z.currentIteration}let X=i($,"metrics","efficiency"),q=Y3(X),K=[];for(let j of q){let x=H$(j);if(x&&typeof x==="object")K.push(x)}if(K.length>0)Z=Math.max(Z,K.length);let W=K.reduce((j,x)=>j+(x.input_tokens??0),0),V=K.reduce((j,x)=>j+(x.output_tokens??0),0),U=W+V,H=K.reduce((j,x)=>j+(x.cost_usd??0),0),B=K.reduce((j,x)=>j+(x.duration_seconds??0),0),G=0,Y=0,O=H$(i($,"metrics","budget.json"));if(O&&typeof O==="object"){if(typeof O.budget_limit==="number")G=O.budget_limit;if(typeof O.budget_used==="number")Y=O.budget_used}let M=0,R=0,N=H$(i($,"state","quality-gates.json"));if(N&&typeof N==="object"){if(Array.isArray(N)){for(let j of N)if(R+=1,j===!0)M+=1;else if(j&&typeof j==="object"){let x=j;if(x.passed===!0||x.status==="passed")M+=1}}else for(let j of Object.values(N))if(typeof j==="boolean"){if(R+=1,j)M+=1}else if(j&&typeof j==="object"){R+=1;let x=j;if(x.passed===!0||x.status==="passed")M+=1}}let g={},u=H$(i($,"quality","gate-failure-count.json"));if(u&&typeof u==="object"&&!Array.isArray(u)){let j={};for(let[x,l]of Object.entries(u))if(typeof l==="number")j[x]=l;g=j}let w=0,E=0,s=0,t$=i($,"quality");if(V1(t$)){let j=[];try{j=H0(t$)}catch{j=[]}for(let x of j){if(!x.endsWith(".json")||x==="gate-failure-count.json")continue;let l=H$(i(t$,x));if(!l||typeof l!=="object")continue;if(!(("verdict"in l)||("approved"in l)||("reviewers"in l)))continue;w+=1;let h1=(l.verdict??"").toString().toLowerCase();if(l.approved===!0||["approved","approve","pass"].includes(h1))E+=1;else if(["revision","revise","changes_requested","reject"].includes(h1))s+=1}}return{phase:Q,iterationCount:Z,iterations:K,totalInput:W,totalOutput:V,totalTokens:U,totalCost:H,totalDuration:B,budgetLimit:G,budgetUsed:Y,gatesPassed:M,gatesTotal:R,gateFailures:g,reviewsTotal:w,reviewsApproved:E,reviewsRevision:s}}function T3($,Q){let Z=$.iterationCount,z={session:{iterations:Z,duration_seconds:$.totalDuration,phase:$.phase},tokens:{input:$.totalInput,output:$.totalOutput,total:$.totalTokens,cost_usd:e($.totalCost,2)},quality:{gates_passed:$.gatesPassed,gates_total:$.gatesTotal,reviews_total:$.reviewsTotal,reviews_approved:$.reviewsApproved,reviews_revision:$.reviewsRevision,gate_failures:$.gateFailures},efficiency:{avg_tokens_per_iteration:Z>0?e($.totalTokens/Z,0):0,avg_cost_per_iteration:Z>0?e($.totalCost/Z,2):0,avg_duration_per_iteration:Z>0?e($.totalDuration/Z,1):0},budget:{used:e($.budgetUsed,2),limit:$.budgetLimit,percent:$.budgetLimit>0?e($.budgetUsed/$.budgetLimit*100,1):0}};if(Q)z.iterations=$.iterations.map((K,W)=>({number:W+1,input_tokens:K.input_tokens??0,output_tokens:K.output_tokens??0,cost_usd:e(K.cost_usd??0,2),duration_seconds:K.duration_seconds??0}));let X=JSON.stringify(z,null,2);function q(K,W){if(!W)return;let V=new RegExp(`("${K}": )(-?\\d+)(,?)$`,"m");X=X.replace(V,(U,H,B,G)=>`${H}${B}.0${G}`)}if(q("avg_duration_per_iteration",Z>0&&Number.isInteger(z.efficiency.avg_duration_per_iteration)),q("percent",$.budgetLimit>0&&Number.isInteger(z.budget.percent)),q("cost_usd",Z>0&&Number.isInteger(z.tokens.cost_usd)),Q)X=X.replace(/("cost_usd": )(-?\d+)(,?)$/gm,(K,W,V,U)=>`${W}${V}.0${U}`);return X}function O3($,Q){let Z=[];if(Z.push("Loki Mode Session Statistics"),Z.push("============================"),Z.push(""),Z.push("Session"),Z.push(` Iterations completed: ${$.iterationCount}`),Z.push(` Duration: ${q1($.totalDuration)}`),Z.push(` Current phase: ${$.phase}`),Z.push(""),Z.push("Token Usage"),$.iterations.length>0)Z.push(` Input tokens: ${G$($.totalInput)}`),Z.push(` Output tokens: ${G$($.totalOutput)}`),Z.push(` Total tokens: ${G$($.totalTokens)}`),Z.push(` Estimated cost: $${B$($.totalCost,2)}`);else Z.push(" N/A (no iteration metrics found)");if(Z.push(""),Z.push("Quality Gates"),$.gatesTotal>0){let z=Math.round($.gatesPassed/$.gatesTotal*100);Z.push(` Gates passed: ${$.gatesPassed}/${$.gatesTotal} (${z}%)`)}else Z.push(" Gates passed: N/A");if($.reviewsTotal>0){let z=[];if($.reviewsApproved>0)z.push(`${$.reviewsApproved} approved`);if($.reviewsRevision>0)z.push(`${$.reviewsRevision} revision requested`);let X=z.length>0?z.join(", "):"N/A";Z.push(` Code reviews: ${$.reviewsTotal} (${X})`)}if(Object.keys($.gateFailures).length>0){let z=Object.entries($.gateFailures).filter(([,X])=>X>0).map(([X,q])=>`${X} (${q})`);if(z.length>0)Z.push(` Gate failures: ${z.join(", ")}`)}if(Z.push(""),Z.push("Efficiency"),$.iterationCount>0&&$.iterations.length>0){let z=Math.round($.totalTokens/$.iterationCount),X=$.totalCost/$.iterationCount,q=$.totalDuration/$.iterationCount;Z.push(` Avg tokens/iteration: ${G$(z)}`),Z.push(` Avg cost/iteration: $${B$(X,2)}`),Z.push(` Avg duration/iteration: ${q1(q)}`)}else Z.push(" N/A (no iteration metrics found)");if(Z.push(""),Z.push("Budget"),$.budgetLimit>0){let z=e($.budgetUsed/$.budgetLimit*100,1),X=Number.isInteger(z)?`${z}.0`:`${z}`;Z.push(` Used: $${B$($.budgetUsed,2)} / $${B$($.budgetLimit,2)} (${X}%)`)}else if($.budgetUsed>0)Z.push(` Used: $${B$($.budgetUsed,2)} (no limit set)`);else Z.push(" N/A");if(Q&&$.iterations.length>0)Z.push(""),Z.push("Per-Iteration Breakdown"),$.iterations.forEach((z,X)=>{let q=X+1,K=J1(G$(z.input_tokens??0),10),W=J1(G$(z.output_tokens??0),10),V=z.cost_usd??0,U=q1(z.duration_seconds??0),H=J1(`${q}`,3);Z.push(` #${H} input: ${K} output: ${W} cost: $${B$(V,2)} time: ${U}`)});return Z.join(`
334
+ `)}function B0($){let Q=!1,Z=!1;for(let K of $)if(K==="--json")Q=!0;else if(K==="--efficiency")Z=!0;let z=P();if(!V1(z)){if(Q)return{exitCode:0,stdout:'{"error": "No active session"}'};return{exitCode:0,stdout:`${_}No active session found.${J}
335
+ Start a session with: loki start <prd>`}}let X=M3(z);return{exitCode:0,stdout:Q?T3(X,Z):O3(X,Z)}}async function A3($){let{emitDeprecatedAlias:Q}=await Promise.resolve().then(() => (K1(),U0));Q("stats","report session",$);let Z=B0($);return console.log(Z.stdout),Z.exitCode}var M0=L(()=>{C();c()});var j0={};b(j0,{runDoctor:()=>b3,pythonImportOk:()=>B1,httpReachable:()=>U1,checkTool:()=>_0,checkSkills:()=>I0,checkDisk:()=>G1,buildDoctorJson:()=>P0,_setPythonImportOkForTest:()=>F3});import{existsSync as T0,lstatSync as w3,readFileSync as _3,readlinkSync as I3,statfsSync as L3}from"fs";import{spawnSync as O0}from"child_process";import{homedir as H1}from"os";import{resolve as W1}from"path";function j3($){let Q=$.match(P3);return Q?Q[1]:null}async function A0($){try{let Q=await F([$,"--version"],{timeoutMs:5000}),Z=(Q.stdout||Q.stderr||"").trim();return j3(Z)}catch{return null}}function w0($,Q){let Z=$.split(".").map((X)=>parseInt(X,10)),z=Q.split(".").map((X)=>parseInt(X,10));while(Z.length<2)Z.push(0);while(z.length<2)z.push(0);for(let X=0;X<2;X++){let q=Z[X]??0,K=z[X]??0;if(Number.isNaN(q)||Number.isNaN(K))return 0;if(q!==K)return q-K}return 0}async function _0($,Q,Z,z=null){let X=await f(Q),q=X!==null,K=q?await A0(Q):null,W="pass";if(!q)W=Z==="required"?"fail":"warn";else if(z&&K){if(w0(K,z)<0)W=Z==="required"?"fail":"warn"}return{name:$,command:Q,found:q,version:K,required:Z,min_version:z,status:W,path:X}}function G1(){let $=null;try{let Z=L3(H1()),z=Number(Z.bavail)*Number(Z.bsize);$=Math.round(z/1073741824*10)/10}catch{$=null}let Q="pass";if($!==null){if($<1)Q="fail";else if($<5)Q="warn"}return{available_gb:$,status:Q}}async function U1($,Q=2000){try{return(await fetch($,{signal:AbortSignal.timeout(Q)})).ok}catch{return!1}}async function B1($,Q=!1){let Z=`import ${$}`,z=Q?30000:5000;if(!Q)return(await z$(Z,{timeoutMs:z})).exitCode===0;let X=await Z$();if(!X)return!1;return(await F([X,"-c",Z],{timeoutMs:z})).exitCode===0}function F3($){v$.fn=$??B1}function I0(){let $=H1();return k3.map(({name:Q,dir:Z})=>{let z=W1($,Z),X=z,q=W1(z,"SKILL.md");if(T0(q))return{name:Q,path:X,status:"pass",detail:""};try{if(w3(z).isSymbolicLink()){let W="unknown";try{W=I3(z)}catch{}return{name:Q,path:X,status:"fail",detail:`(broken symlink -> ${W})`}}}catch{}return{name:Q,path:X,status:"warn",detail:"(not found - run 'loki setup-skill')"}})}async function L0(){return Promise.all(R3.map(async($)=>{return{...await _0($.jsonName,$.cmd,$.required,$.min??null),displayName:$.displayName}}))}async function E3(){let Q=await f("sentrux")!==null,Z=Q?await A0("sentrux"):null;return{found:Q,version:Z,status:Q?"pass":"warn",required:"optional"}}async function x3(){let{openSync:$,statSync:Q,readSync:Z,closeSync:z,existsSync:X}=await import("fs"),{join:q}=await import("path"),K=65536,W=process.env.LOKI_DIR??".loki",V=q(W,"memory",".errors.log"),U=[],H=!1;try{if(X(V)){H=!0;let B=Q(V).size,G=Math.max(0,B-65536),Y=B-G,O=Buffer.alloc(Y),M=$(V,"r");try{Z(M,O,0,Y,G)}finally{z(M)}let N=O.toString("utf-8").split(`
336
+ `);if(G>0&&N.length>0)N=N.slice(1);N=N.map((g)=>g.trim()).filter((g)=>g.length>0),U=N.slice(-5)}}catch{U=[]}return{errors_log_path:H?V:null,recent_errors:U,recent_error_count:U.length,status:U.length===0?"pass":"warn"}}async function P0(){let Q=(await L0()).map(({displayName:V,...U})=>U),Z=G1(),z=await E3(),X=await x3(),q=0,K=0,W=0;for(let V of Q)if(V.status==="pass")q++;else if(V.status==="fail")K++;else W++;if(Z.status==="pass")q++;else if(Z.status==="fail")K++;else W++;return{loki_mode_version:N$(),checks:Q,disk:Z,sentrux:z,memory:X,summary:{passed:q,failed:K,warnings:W,ok:K===0}}}function N3(){try{let $=process.env.CLAUDE_CONFIG_DIR||`${H1()}/.claude`,Q=_3(`${$}/.credentials.json`,"utf8");if(!Q)return!1;let Z=JSON.parse(Q)?.claudeAiOauth?.expiresAt;return typeof Z==="number"&&Z>0&&Z/1000<=Date.now()/1000+60}catch{return!1}}function S3(){try{let Q=(O0("claude",["auth","status"],{encoding:"utf8",timeout:5000}).stdout||"").trim();if(!Q)return"";let Z=JSON.parse(Q);if(Z?.loggedIn===!0)return"yes";if(Z?.loggedIn===!1)return"no";return""}catch{return""}}function A($){switch($){case"pass":return`${S}PASS${J}`;case"fail":return`${T}FAIL${J}`;case"warn":return`${_}WARN${J}`}}function h$($){let Q=$.version?` (v${$.version})`:"",Z=$.displayName;if(!$.found){let z=$.required==="required"?"not found":$.required==="recommended"?"not found (recommended)":"not found (optional)";return` ${A($.status)} ${Z} - ${z}`}if($.min_version&&$.version&&w0($.version,$.min_version)<0){let z=$.required==="required"?"requires":"recommended";return` ${A($.status)} ${Z}${Q} - ${z} >= ${$.min_version}`}return` ${A($.status)} ${Z}${Q}`}function y$($,Q){if(Q==="pass")$.pass++;else if(Q==="fail")$.fail++;else $.warn++}function D3(){process.stdout.write(`${k}loki doctor${J} - Check system prerequisites
337
337
 
338
338
  `),process.stdout.write(`Usage: loki doctor [--json]
339
339
 
@@ -342,30 +342,33 @@ Start a session with: loki start <prd>`}}let X=Y3(z);return{exitCode:0,stdout:Q?
342
342
 
343
343
  `),process.stdout.write(`Checks: node, python3, jq, git, curl, bash version,
344
344
  `),process.stdout.write(` claude/codex CLIs, and disk space.
345
- `)}async function N3(){process.stdout.write(`${k}Loki Mode Doctor${J}
345
+ `)}async function C3(){process.stdout.write(`${k}Loki Mode Doctor${J}
346
346
 
347
347
  `),process.stdout.write(`Checking system prerequisites...
348
348
 
349
- `);let $={pass:0,fail:0,warn:0},Q=await I0(),Z=new Map(Q.map((w)=>[w.command,w]));process.stdout.write(`${I}Required:${J}
350
- `);for(let w of["node","python3","jq","git","curl"]){let x=Z.get(w);process.stdout.write(h$(x)+`
351
- `),y$($,x.status)}process.stdout.write(`
349
+ `);let $={pass:0,fail:0,warn:0},Q=await L0(),Z=new Map(Q.map((w)=>[w.command,w]));process.stdout.write(`${I}Required:${J}
350
+ `);for(let w of["node","python3","jq","git","curl"]){let E=Z.get(w);process.stdout.write(h$(E)+`
351
+ `),y$($,E.status)}process.stdout.write(`
352
352
  `),process.stdout.write(`${I}AI Providers:${J}
353
- `);let z=["claude","codex","cline","aider"],X={claude:"npm install -g @anthropic-ai/claude-code",codex:"npm install -g @openai/codex",cline:"npm install -g cline",aider:"pip install aider-chat"},q=!1;for(let w of z){let x=Z.get(w);if(process.stdout.write(h$(x)+`
354
- `),!x.found&&X[w])process.stderr.write(` ${_}Install: ${X[w]}${J}
355
- `);if(y$($,x.status),x.found)q=!0}if(!q){if(process.stdout.write(` ${A("fail")} No AI provider CLI installed -- at least one is required
353
+ `);let z=["claude","codex","cline","aider"],X={claude:"npm install -g @anthropic-ai/claude-code",codex:"npm install -g @openai/codex",cline:"npm install -g cline",aider:"pip install aider-chat"},q=!1;for(let w of z){let E=Z.get(w);if(process.stdout.write(h$(E)+`
354
+ `),!E.found&&X[w])process.stderr.write(` ${_}Install: ${X[w]}${J}
355
+ `);if(y$($,E.status),E.found)q=!0}if(!q){if(process.stdout.write(` ${A("fail")} No AI provider CLI installed -- at least one is required
356
356
  `),process.stdout.write(` ${_}Install: npm install -g @anthropic-ai/claude-code${J}
357
- `),$.fail++,process.stdout.isTTY){let w=W1(h,"autonomy/provider-offer.sh");if(M0(w))I3("bash",[w,"report"],{stdio:"inherit"})}}process.stdout.write(`
357
+ `),$.fail++,process.stdout.isTTY){let w=W1(h,"autonomy/provider-offer.sh");if(T0(w))O0("bash",[w,"report"],{stdio:"inherit"})}}process.stdout.write(`
358
358
  `),process.stdout.write(`${I}API Keys:${J}
359
359
  `);let K=Z.get("claude")?.found??!1,W=Z.get("codex")?.found??!1,V=process.env;if(V.ANTHROPIC_API_KEY)process.stdout.write(` ${A("pass")} ANTHROPIC_API_KEY is set
360
- `),$.pass++;else if(K)process.stdout.write(` ${y} -- ${J} ANTHROPIC_API_KEY not set (Claude CLI uses its own login)
361
- `);if(V.OPENAI_API_KEY)process.stdout.write(` ${A("pass")} OPENAI_API_KEY is set
360
+ `),$.pass++;else if(K){let w=S3();if(w==="yes")process.stdout.write(` ${A("pass")} Claude CLI is logged in (subscription/OAuth login)
361
+ `),$.pass++;else if(w==="no")process.stdout.write(` ${A("warn")} Claude CLI is NOT logged in -- run 'claude login' before a build (it would otherwise stall)
362
+ `),$.warn++;else if(N3())process.stdout.write(` ${A("warn")} Claude login has EXPIRED -- run 'claude login' before a build (it would otherwise stall)
363
+ `),$.warn++;else process.stdout.write(` ${y} -- ${J} ANTHROPIC_API_KEY not set (Claude CLI uses its own login)
364
+ `)}if(V.OPENAI_API_KEY)process.stdout.write(` ${A("pass")} OPENAI_API_KEY is set
362
365
  `),$.pass++;else if(W)process.stdout.write(` ${y} -- ${J} OPENAI_API_KEY not set (Codex CLI uses its own login)
363
366
  `);if(V.ANTHROPIC_BASE_URL){let w=V.ANTHROPIC_BASE_URL;if(process.stdout.write(` ${A("pass")} ANTHROPIC_BASE_URL: ${w}
364
367
  `),$.pass++,!V.LOKI_MODEL_OVERRIDE)process.stdout.write(` ${A("warn")} LOKI_MODEL_OVERRIDE not set -- opus/sonnet/haiku aliases may not resolve on alt-provider
365
368
  `),$.warn++;else process.stdout.write(` ${A("pass")} LOKI_MODEL_OVERRIDE: ${V.LOKI_MODEL_OVERRIDE}
366
369
  `),$.pass++}process.stdout.write(`
367
370
  `),process.stdout.write(`${I}Skills:${J}
368
- `);for(let w of _0())if(w.status==="pass")process.stdout.write(` ${A("pass")} ${w.name} ${y}${w.path}${J}
371
+ `);for(let w of I0())if(w.status==="pass")process.stdout.write(` ${A("pass")} ${w.name} ${y}${w.path}${J}
369
372
  `),$.pass++;else if(w.status==="fail")process.stdout.write(` ${A("fail")} ${w.name} ${y}${w.detail}${J}
370
373
  `),process.stdout.write(` ${_}Fix: loki setup-skill${J}
371
374
  `),$.fail++;else process.stdout.write(` ${A("warn")} ${w.name} ${y}${w.detail}${J}
@@ -379,7 +382,7 @@ Start a session with: loki start <prd>`}}let X=Y3(z);return{exitCode:0,stdout:Q?
379
382
  `),$.pass++;else process.stdout.write(` ${A("warn")} sentence-transformers - not installed (loki memory vectors setup)
380
383
  `),$.warn++;if(await U1("http://localhost:8100/api/v2/heartbeat"))process.stdout.write(` ${A("pass")} ChromaDB server (port 8100)
381
384
  `),$.pass++;else process.stdout.write(` ${A("warn")} ChromaDB - not running (docker start loki-chroma)
382
- `),$.warn++;{let w=["pyright-langserver","pylsp","typescript-language-server","gopls","rust-analyzer","jdtls"],x=[];for(let s of w)if(await f(s))x.push(s);if(x.length>0)process.stdout.write(` ${A("pass")} LSP servers detected (${x.length}): ${x.join(", ")}
385
+ `),$.warn++;{let w=["pyright-langserver","pylsp","typescript-language-server","gopls","rust-analyzer","jdtls"],E=[];for(let s of w)if(await f(s))E.push(s);if(E.length>0)process.stdout.write(` ${A("pass")} LSP servers detected (${E.length}): ${E.join(", ")}
383
386
  `),$.pass++;else process.stdout.write(` ${A("warn")} LSP servers - none on PATH (install for symbol grounding: npm i -g pyright typescript-language-server; brew install gopls)
384
387
  `),$.warn++}let G=process.env.LOKI_MIROFISH_URL;if(G)if(await U1(`${G}/health`))process.stdout.write(` ${A("pass")} MiroFish server (${G})
385
388
  `),$.pass++;else process.stdout.write(` ${A("warn")} MiroFish - not running (loki start --mirofish-docker <image>)
@@ -391,7 +394,7 @@ Start a session with: loki start <prd>`}}let X=Y3(z);return{exitCode:0,stdout:Q?
391
394
  `),process.stdout.write(`${I}System:${J}
392
395
  `);let Y=Z.get("bash");process.stdout.write(h$(Y)+`
393
396
  `),y$($,Y.status);let O=Z.get("bun");if(O)process.stdout.write(h$(O)+`
394
- `),y$($,O.status);let M=H1(),R=M.available_gb===null?null:Math.floor(M.available_gb);if(R===null)process.stdout.write(` ${A("warn")} Disk space: unable to determine
397
+ `),y$($,O.status);let M=G1(),R=M.available_gb===null?null:Math.floor(M.available_gb);if(R===null)process.stdout.write(` ${A("warn")} Disk space: unable to determine
395
398
  `),$.warn++;else if(M.status==="fail")process.stdout.write(` ${A("fail")} Disk space: ${R}GB available (need >= 1GB)
396
399
  `),$.fail++;else if(M.status==="warn")process.stdout.write(` ${A("warn")} Disk space: ${R}GB available (low)
397
400
  `),$.warn++;else process.stdout.write(` ${A("pass")} Disk space: ${R}GB available
@@ -401,8 +404,8 @@ Start a session with: loki start <prd>`}}let X=Y3(z);return{exitCode:0,stdout:Q?
401
404
  `),process.env.LOKI_LEGACY_BASH==="1"||process.env.LOKI_LEGACY_BASH==="true")process.stdout.write(` ${A("warn")} LOKI_LEGACY_BASH set: shim routes every command to autonomy/loki (bash)
402
405
  `);if(process.env.LOKI_TS_ENTRY)process.stdout.write(` ${A("pass")} LOKI_TS_ENTRY override: ${process.env.LOKI_TS_ENTRY}
403
406
  `);if(process.env.BUN_FROM_SOURCE==="1"||process.env.BUN_FROM_SOURCE==="true")process.stdout.write(` ${A("pass")} BUN_FROM_SOURCE set: shim prefers loki-ts/src/ over dist/
404
- `);let u=await Z$();if(u!==null){let x=(await F([u,"-c","import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')"],{timeoutMs:5000})).stdout.trim();if(x.startsWith("3.12"))process.stdout.write(` ${A("pass")} Python 3.12 (chromadb / sentence-transformers): ${x} at ${u}
405
- `);else if(x)process.stdout.write(` ${A("warn")} Python 3.12 recommended for memory vector search (chromadb / sentence-transformers); found ${x} at ${u}. Core memory and the rest of Loki work without it. Install: brew install python@3.12 (macOS) or apt install python3.12 (Debian/Ubuntu).
407
+ `);let u=await Z$();if(u!==null){let E=(await F([u,"-c","import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')"],{timeoutMs:5000})).stdout.trim();if(E.startsWith("3.12"))process.stdout.write(` ${A("pass")} Python 3.12 (chromadb / sentence-transformers): ${E} at ${u}
408
+ `);else if(E)process.stdout.write(` ${A("warn")} Python 3.12 recommended for memory vector search (chromadb / sentence-transformers); found ${E} at ${u}. Core memory and the rest of Loki work without it. Install: brew install python@3.12 (macOS) or apt install python3.12 (Debian/Ubuntu).
406
409
  `);else process.stdout.write(` ${A("warn")} Python 3 found at ${u} but version probe failed; memory vector search (chromadb / sentence-transformers) may not work. The rest of Loki is unaffected.
407
410
  `)}else process.stdout.write(` ${A("warn")} Python 3 not on PATH -- memory + MCP integrations disabled. The rest of Loki works without them.
408
411
  `);if(process.stdout.write(`
@@ -415,15 +418,15 @@ Start a session with: loki start <prd>`}}let X=Y3(z);return{exitCode:0,stdout:Q?
415
418
  `);return process.stdout.write(`
416
419
  `),process.stdout.write(`Next: loki quickstart (guided first build from your idea, no PRD needed)
417
420
  `),process.stdout.write(` or loki demo (builds a sample todo app end to end) or loki start ./prd.md
418
- `),0}async function S3($){let Q=!1;for(let Z of $)if(Z==="--json")Q=!0;else if(Z==="--help"||Z==="-h")return E3(),0;else return process.stderr.write(`${T}Unknown option: ${Z}${J}
421
+ `),0}async function b3($){let Q=!1;for(let Z of $)if(Z==="--json")Q=!0;else if(Z==="--help"||Z==="-h")return D3(),0;else return process.stderr.write(`${T}Unknown option: ${Z}${J}
419
422
  `),process.stderr.write(`Usage: loki doctor [--json]
420
- `),1;if(Q){let Z=await L0();return process.stdout.write(JSON.stringify(Z,null,2)+`
421
- `),0}return N3()}var L3,v$,F3,k3;var j0=L(()=>{C();d();V$();c();$1();L3=/(\d+\.\d+(?:\.\d+)*)/;v$={fn:G1};F3=[{name:"Claude Code",dir:".claude/skills/loki-mode"},{name:"Codex CLI",dir:".codex/skills/loki-mode"},{name:"Cline CLI",dir:".cline/skills/loki-mode"},{name:"Aider CLI",dir:".aider/skills/loki-mode"}];k3=[{displayName:"Node.js (>= 18)",jsonName:"Node.js",cmd:"node",required:"required",min:"18.0"},{displayName:"Python 3 (>= 3.8)",jsonName:"Python 3",cmd:"python3",required:"required",min:"3.8"},{displayName:"jq",jsonName:"jq",cmd:"jq",required:"required"},{displayName:"git",jsonName:"git",cmd:"git",required:"required"},{displayName:"curl",jsonName:"curl",cmd:"curl",required:"required"},{displayName:"bash (>= 4.0)",jsonName:"bash",cmd:"bash",required:"recommended",min:"4.0"},{displayName:"Bun (>= 1.3)",jsonName:"Bun",cmd:"bun",required:"recommended",min:"1.3"},{displayName:"Claude CLI",jsonName:"Claude CLI",cmd:"claude",required:"optional"},{displayName:"Codex CLI",jsonName:"Codex CLI",cmd:"codex",required:"optional"},{displayName:"Cline CLI",jsonName:"Cline CLI",cmd:"cline",required:"optional"},{displayName:"Aider CLI",jsonName:"Aider CLI",cmd:"aider",required:"optional"}]});import{existsSync as R0,mkdirSync as v9,readdirSync as D3,readFileSync as x0,renameSync as g9,writeFileSync as m9}from"fs";import{dirname as C3,join as b3,resolve as h3}from"path";import{fileURLToPath as y3}from"url";function v3(){try{let $=C3(y3(import.meta.url)),Q=h3($,"..","..","data","model-pricing.json");if(!R0(Q))return _$;let z=JSON.parse(x0(Q,"utf8")).pricing;if(!z||typeof z!=="object")return _$;let X={};for(let[q,K]of Object.entries(z))if(K!==null&&typeof K==="object"&&typeof K.input==="number"&&typeof K.output==="number")X[q]={input:K.input,output:K.output};for(let q of Object.keys(_$))if(!(q in X))return _$;return X}catch{return _$}}function g3($){return Math.round(($+Number.EPSILON)*1e4)/1e4}function m3($){let Q=($??k0).toLowerCase();return F0[Q]??F0[k0]}function E0($){let Q=0;for(let Z of $){if(typeof Z.cost_usd==="number"&&Number.isFinite(Z.cost_usd)){Q+=Z.cost_usd;continue}let z=m3(Z.model),X=typeof Z.input_tokens==="number"?Z.input_tokens:0,q=typeof Z.output_tokens==="number"?Z.output_tokens:0;Q+=X/1e6*z.input+q/1e6*z.output}return g3(Q)}function N0($){if(!R0($))return[];let Q=[],Z;try{Z=D3($)}catch{return[]}for(let z of Z){if(!z.endsWith(".json"))continue;let X=b3($,z);try{let q=x0(X,"utf8"),K=JSON.parse(q);if(K&&typeof K==="object")Q.push(K)}catch{}}return Q}var _$,F0,k0="sonnet";var S0=L(()=>{C();_$={fable:{input:10,output:50},opus:{input:5,output:25},sonnet:{input:3,output:15},haiku:{input:1,output:5},"gpt-5.3-codex":{input:1.5,output:12}};F0=Object.freeze(v3())});import{existsSync as g$,readdirSync as f3,readFileSync as u3,statSync as c3}from"fs";import{join as m$}from"path";function p3($){let Q=[],Z=m$($,"votes");if(!g$(Z))return Q;let z;try{z=f3(Z)}catch{return Q}for(let X of z){if(!X.startsWith("round-")||!X.endsWith(".json"))continue;try{let q=m$(Z,X);if(!c3(q).isFile())continue;let K=JSON.parse(u3(q,"utf8"));Q.push({iteration:typeof K.iteration==="number"?K.iteration:void 0,verdict:typeof K.verdict==="string"?K.verdict:void 0,complete_votes:typeof K.complete_votes==="number"?K.complete_votes:void 0,total_members:typeof K.total_members==="number"?K.total_members:void 0,threshold:typeof K.threshold==="number"?K.threshold:void 0})}catch{}}return Q}function l3(){return{iteration_count:0,total_cost_usd:0,avg_cost_per_iteration:null,total_input_tokens:0,total_output_tokens:0,total_duration_ms:0,avg_duration_ms_per_iteration:null,model_breakdown:{},phase_breakdown:{},status_breakdown:{}}}function d3(){return{council_rounds:0,unanimous_rate:null,approval_rate:null,iteration_success_rate:null}}function o3($){let Q=l3();if($.length===0)return Q;Q.iteration_count=$.length,Q.total_cost_usd=Math.round(E0($)*1e4)/1e4;for(let Z of $){if(typeof Z.input_tokens==="number")Q.total_input_tokens+=Z.input_tokens;if(typeof Z.output_tokens==="number")Q.total_output_tokens+=Z.output_tokens;let z=Z;if(typeof z.duration_ms==="number")Q.total_duration_ms+=z.duration_ms;if(typeof Z.model==="string")Q.model_breakdown[Z.model]=(Q.model_breakdown[Z.model]??0)+1;if(typeof z.phase==="string")Q.phase_breakdown[z.phase]=(Q.phase_breakdown[z.phase]??0)+1;if(typeof z.status==="string")Q.status_breakdown[z.status]=(Q.status_breakdown[z.status]??0)+1}return Q.avg_cost_per_iteration=Math.round(Q.total_cost_usd/Q.iteration_count*1e4)/1e4,Q.avg_duration_ms_per_iteration=Math.round(Q.total_duration_ms/Q.iteration_count),Q}function n3($,Q,Z){let z=d3();if(z.council_rounds=$.length,$.length>0){let X=0,q=0;for(let K of $){if(typeof K.complete_votes==="number"&&typeof K.total_members==="number"&&K.total_members>0&&K.complete_votes===K.total_members)X+=1;if(K.verdict==="COMPLETE")q+=1}z.unanimous_rate=Math.round(X/$.length*1e4)/1e4,z.approval_rate=Math.round(q/$.length*1e4)/1e4}if(Z>0)z.iteration_success_rate=Math.round(Q/Z*1e4)/1e4;return z}function D0($){let Q=[],Z=m$($,"metrics","efficiency"),z=m$($,"council"),X=g$(Z)?N0(Z):[];if(!g$(Z))Q.push("no .loki/metrics/efficiency/ dir (efficiency KPIs zeroed)");else if(X.length===0)Q.push(".loki/metrics/efficiency/ exists but no iteration files found");let q=p3(z);if(!g$(z))Q.push("no .loki/council/ dir (accuracy KPIs zeroed)");else if(q.length===0)Q.push(".loki/council/ exists but no round-N.json files found");let K=o3(X),W=K.status_breakdown.success??0,V=n3(q,W,K.iteration_count);return{schema_version:1,generated_at:new Date().toISOString(),loki_dir:$,efficiency:K,accuracy:V,notes:Q}}function C0($){return JSON.stringify($,null,2)}function b0($){let Q=[];Q.push(`Loki Mode KPIs (snapshot at ${$.generated_at})`),Q.push(`Source: ${$.loki_dir}`),Q.push(""),Q.push("Efficiency"),Q.push(` Iterations: ${$.efficiency.iteration_count}`),Q.push(` Total cost USD: ${$.efficiency.total_cost_usd}`),Q.push(` Avg cost per iter: ${$.efficiency.avg_cost_per_iteration??"n/a"}`),Q.push(` Total input tokens: ${$.efficiency.total_input_tokens}`),Q.push(` Total output tokens: ${$.efficiency.total_output_tokens}`),Q.push(` Total duration (ms): ${$.efficiency.total_duration_ms}`),Q.push(` Avg duration / iter: ${$.efficiency.avg_duration_ms_per_iteration??"n/a"}`);let Z=Object.entries($.efficiency.model_breakdown).sort((q,K)=>q[0].localeCompare(K[0]));if(Z.length>0)Q.push(` Model breakdown: ${Z.map(([q,K])=>`${q}=${K}`).join(", ")}`);let z=Object.entries($.efficiency.phase_breakdown).sort((q,K)=>q[0].localeCompare(K[0]));if(z.length>0)Q.push(` Phase breakdown: ${z.map(([q,K])=>`${q}=${K}`).join(", ")}`);let X=Object.entries($.efficiency.status_breakdown).sort((q,K)=>q[0].localeCompare(K[0]));if(X.length>0)Q.push(` Status breakdown: ${X.map(([q,K])=>`${q}=${K}`).join(", ")}`);if(Q.push(""),Q.push("Accuracy"),Q.push(` Council rounds: ${$.accuracy.council_rounds}`),Q.push(` Unanimous rate: ${$.accuracy.unanimous_rate??"n/a"}`),Q.push(` Approval rate: ${$.accuracy.approval_rate??"n/a"}`),Q.push(` Iter success rate: ${$.accuracy.iteration_success_rate??"n/a"}`),$.notes.length>0){Q.push(""),Q.push("Notes");for(let q of $.notes)Q.push(` - ${q}`)}return Q.push(""),Q.push("See also: loki trust (trust trajectory across runs)"),Q.join(`
422
- `)}var h0=L(()=>{S0()});var B1={};b(B1,{runKpis:()=>s3});function s3($,Q={}){if(Q.aliasOf)X1(Q.aliasOf,"report kpis",$);let Z=!1;for(let X of $){if(X==="--help"||X==="-h"||X==="help")return process.stdout.write(a3),0;if(X==="--json"){Z=!0;continue}if(X==="-q"||X==="--quiet")continue;return process.stderr.write(`loki kpis: unknown arg: ${X}
423
+ `),1;if(Q){let Z=await P0();return process.stdout.write(JSON.stringify(Z,null,2)+`
424
+ `),0}return C3()}var P3,v$,k3,R3;var F0=L(()=>{C();d();V$();c();$1();P3=/(\d+\.\d+(?:\.\d+)*)/;v$={fn:B1};k3=[{name:"Claude Code",dir:".claude/skills/loki-mode"},{name:"Codex CLI",dir:".codex/skills/loki-mode"},{name:"Cline CLI",dir:".cline/skills/loki-mode"},{name:"Aider CLI",dir:".aider/skills/loki-mode"}];R3=[{displayName:"Node.js (>= 18)",jsonName:"Node.js",cmd:"node",required:"required",min:"18.0"},{displayName:"Python 3 (>= 3.8)",jsonName:"Python 3",cmd:"python3",required:"required",min:"3.8"},{displayName:"jq",jsonName:"jq",cmd:"jq",required:"required"},{displayName:"git",jsonName:"git",cmd:"git",required:"required"},{displayName:"curl",jsonName:"curl",cmd:"curl",required:"required"},{displayName:"bash (>= 4.0)",jsonName:"bash",cmd:"bash",required:"recommended",min:"4.0"},{displayName:"Bun (>= 1.3)",jsonName:"Bun",cmd:"bun",required:"recommended",min:"1.3"},{displayName:"Claude CLI",jsonName:"Claude CLI",cmd:"claude",required:"optional"},{displayName:"Codex CLI",jsonName:"Codex CLI",cmd:"codex",required:"optional"},{displayName:"Cline CLI",jsonName:"Cline CLI",cmd:"cline",required:"optional"},{displayName:"Aider CLI",jsonName:"Aider CLI",cmd:"aider",required:"optional"}]});import{existsSync as E0,mkdirSync as f9,readdirSync as h3,readFileSync as x0,renameSync as u9,writeFileSync as c9}from"fs";import{dirname as y3,join as v3,resolve as g3}from"path";import{fileURLToPath as m3}from"url";function f3(){try{let $=y3(m3(import.meta.url)),Q=g3($,"..","..","data","model-pricing.json");if(!E0(Q))return _$;let z=JSON.parse(x0(Q,"utf8")).pricing;if(!z||typeof z!=="object")return _$;let X={};for(let[q,K]of Object.entries(z))if(K!==null&&typeof K==="object"&&typeof K.input==="number"&&typeof K.output==="number")X[q]={input:K.input,output:K.output};for(let q of Object.keys(_$))if(!(q in X))return _$;return X}catch{return _$}}function u3($){return Math.round(($+Number.EPSILON)*1e4)/1e4}function c3($){let Q=($??R0).toLowerCase();return k0[Q]??k0[R0]}function N0($){let Q=0;for(let Z of $){if(typeof Z.cost_usd==="number"&&Number.isFinite(Z.cost_usd)){Q+=Z.cost_usd;continue}let z=c3(Z.model),X=typeof Z.input_tokens==="number"?Z.input_tokens:0,q=typeof Z.output_tokens==="number"?Z.output_tokens:0;Q+=X/1e6*z.input+q/1e6*z.output}return u3(Q)}function S0($){if(!E0($))return[];let Q=[],Z;try{Z=h3($)}catch{return[]}for(let z of Z){if(!z.endsWith(".json"))continue;let X=v3($,z);try{let q=x0(X,"utf8"),K=JSON.parse(q);if(K&&typeof K==="object")Q.push(K)}catch{}}return Q}var _$,k0,R0="sonnet";var D0=L(()=>{C();_$={fable:{input:10,output:50},opus:{input:5,output:25},sonnet:{input:3,output:15},haiku:{input:1,output:5},"gpt-5.3-codex":{input:1.5,output:12}};k0=Object.freeze(f3())});import{existsSync as g$,readdirSync as p3,readFileSync as l3,statSync as d3}from"fs";import{join as m$}from"path";function o3($){let Q=[],Z=m$($,"votes");if(!g$(Z))return Q;let z;try{z=p3(Z)}catch{return Q}for(let X of z){if(!X.startsWith("round-")||!X.endsWith(".json"))continue;try{let q=m$(Z,X);if(!d3(q).isFile())continue;let K=JSON.parse(l3(q,"utf8"));Q.push({iteration:typeof K.iteration==="number"?K.iteration:void 0,verdict:typeof K.verdict==="string"?K.verdict:void 0,complete_votes:typeof K.complete_votes==="number"?K.complete_votes:void 0,total_members:typeof K.total_members==="number"?K.total_members:void 0,threshold:typeof K.threshold==="number"?K.threshold:void 0})}catch{}}return Q}function n3(){return{iteration_count:0,total_cost_usd:0,avg_cost_per_iteration:null,total_input_tokens:0,total_output_tokens:0,total_duration_ms:0,avg_duration_ms_per_iteration:null,model_breakdown:{},phase_breakdown:{},status_breakdown:{}}}function a3(){return{council_rounds:0,unanimous_rate:null,approval_rate:null,iteration_success_rate:null}}function s3($){let Q=n3();if($.length===0)return Q;Q.iteration_count=$.length,Q.total_cost_usd=Math.round(N0($)*1e4)/1e4;for(let Z of $){if(typeof Z.input_tokens==="number")Q.total_input_tokens+=Z.input_tokens;if(typeof Z.output_tokens==="number")Q.total_output_tokens+=Z.output_tokens;let z=Z;if(typeof z.duration_ms==="number")Q.total_duration_ms+=z.duration_ms;if(typeof Z.model==="string")Q.model_breakdown[Z.model]=(Q.model_breakdown[Z.model]??0)+1;if(typeof z.phase==="string")Q.phase_breakdown[z.phase]=(Q.phase_breakdown[z.phase]??0)+1;if(typeof z.status==="string")Q.status_breakdown[z.status]=(Q.status_breakdown[z.status]??0)+1}return Q.avg_cost_per_iteration=Math.round(Q.total_cost_usd/Q.iteration_count*1e4)/1e4,Q.avg_duration_ms_per_iteration=Math.round(Q.total_duration_ms/Q.iteration_count),Q}function r3($,Q,Z){let z=a3();if(z.council_rounds=$.length,$.length>0){let X=0,q=0;for(let K of $){if(typeof K.complete_votes==="number"&&typeof K.total_members==="number"&&K.total_members>0&&K.complete_votes===K.total_members)X+=1;if(K.verdict==="COMPLETE")q+=1}z.unanimous_rate=Math.round(X/$.length*1e4)/1e4,z.approval_rate=Math.round(q/$.length*1e4)/1e4}if(Z>0)z.iteration_success_rate=Math.round(Q/Z*1e4)/1e4;return z}function C0($){let Q=[],Z=m$($,"metrics","efficiency"),z=m$($,"council"),X=g$(Z)?S0(Z):[];if(!g$(Z))Q.push("no .loki/metrics/efficiency/ dir (efficiency KPIs zeroed)");else if(X.length===0)Q.push(".loki/metrics/efficiency/ exists but no iteration files found");let q=o3(z);if(!g$(z))Q.push("no .loki/council/ dir (accuracy KPIs zeroed)");else if(q.length===0)Q.push(".loki/council/ exists but no round-N.json files found");let K=s3(X),W=K.status_breakdown.success??0,V=r3(q,W,K.iteration_count);return{schema_version:1,generated_at:new Date().toISOString(),loki_dir:$,efficiency:K,accuracy:V,notes:Q}}function b0($){return JSON.stringify($,null,2)}function h0($){let Q=[];Q.push(`Loki Mode KPIs (snapshot at ${$.generated_at})`),Q.push(`Source: ${$.loki_dir}`),Q.push(""),Q.push("Efficiency"),Q.push(` Iterations: ${$.efficiency.iteration_count}`),Q.push(` Total cost USD: ${$.efficiency.total_cost_usd}`),Q.push(` Avg cost per iter: ${$.efficiency.avg_cost_per_iteration??"n/a"}`),Q.push(` Total input tokens: ${$.efficiency.total_input_tokens}`),Q.push(` Total output tokens: ${$.efficiency.total_output_tokens}`),Q.push(` Total duration (ms): ${$.efficiency.total_duration_ms}`),Q.push(` Avg duration / iter: ${$.efficiency.avg_duration_ms_per_iteration??"n/a"}`);let Z=Object.entries($.efficiency.model_breakdown).sort((q,K)=>q[0].localeCompare(K[0]));if(Z.length>0)Q.push(` Model breakdown: ${Z.map(([q,K])=>`${q}=${K}`).join(", ")}`);let z=Object.entries($.efficiency.phase_breakdown).sort((q,K)=>q[0].localeCompare(K[0]));if(z.length>0)Q.push(` Phase breakdown: ${z.map(([q,K])=>`${q}=${K}`).join(", ")}`);let X=Object.entries($.efficiency.status_breakdown).sort((q,K)=>q[0].localeCompare(K[0]));if(X.length>0)Q.push(` Status breakdown: ${X.map(([q,K])=>`${q}=${K}`).join(", ")}`);if(Q.push(""),Q.push("Accuracy"),Q.push(` Council rounds: ${$.accuracy.council_rounds}`),Q.push(` Unanimous rate: ${$.accuracy.unanimous_rate??"n/a"}`),Q.push(` Approval rate: ${$.accuracy.approval_rate??"n/a"}`),Q.push(` Iter success rate: ${$.accuracy.iteration_success_rate??"n/a"}`),$.notes.length>0){Q.push(""),Q.push("Notes");for(let q of $.notes)Q.push(` - ${q}`)}return Q.push(""),Q.push("See also: loki trust (trust trajectory across runs)"),Q.join(`
425
+ `)}var y0=L(()=>{D0()});var Y1={};b(Y1,{runKpis:()=>i3});function i3($,Q={}){if(Q.aliasOf)X1(Q.aliasOf,"report kpis",$);let Z=!1;for(let X of $){if(X==="--help"||X==="-h"||X==="help")return process.stdout.write(t3),0;if(X==="--json"){Z=!0;continue}if(X==="-q"||X==="--quiet")continue;return process.stderr.write(`loki kpis: unknown arg: ${X}
423
426
  Run 'loki kpis --help' for usage.
424
- `),1}let z=D0(P());return process.stdout.write(Z?C0(z)+`
425
- `:b0(z)+`
426
- `),0}var a3=`loki report kpis -- accuracy + efficiency KPI snapshot (v7.5.28 MVP)
427
+ `),1}let z=C0(P());return process.stdout.write(Z?b0(z)+`
428
+ `:h0(z)+`
429
+ `),0}var t3=`loki report kpis -- accuracy + efficiency KPI snapshot (v7.5.28 MVP)
427
430
 
428
431
  Usage:
429
432
  loki report kpis Pretty-print KPI snapshot
@@ -444,13 +447,13 @@ iteration success rate.
444
447
  This is the Phase K MVP -- read-only derivation. Per-iteration
445
448
  emission, dashboard panel, and the loki-bench harness are deferred
446
449
  follow-ups (see project_v7_5_18_arc_status.md).
447
- `;var Y1=L(()=>{h0();C();K1()});var y0={};b(y0,{delegateToBash:()=>i3});import{resolve as t3}from"path";async function i3($){let Q=t3(h,"autonomy","loki"),Z=Bun.spawn({cmd:[Q,...$],stdin:"inherit",stdout:"inherit",stderr:"inherit",env:{...process.env,LOKI_LEGACY_BASH:"1"}}),z=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},r3);try{return await Z.exited}finally{clearTimeout(z)}}var r3=3600000;var v0=L(()=>{C()});import{existsSync as e3,mkdirSync as $6,readdirSync as Q6,readFileSync as Z6,statSync as z6,writeFileSync as X6}from"fs";import{join as I$}from"path";function M1($){return $&&typeof $==="object"?$:{}}function X$($){return Math.round($*1e4)/1e4}function W6($){let Q=String($??"").trim().toUpperCase();if(!Q)return null;for(let Z of m0)if(Q.startsWith(Z))return!0;return!1}function U6($){let Q=W6($.final_verdict);if(Q!==null)return Q?1:0;let Z=$.reviewers;if(Array.isArray(Z)&&Z.length>0){let z=0,X=0;for(let q of Z){if(!q||typeof q!=="object")continue;X+=1;let K=String(q.vote??"").trim().toUpperCase();if(m0.some((W)=>K.startsWith(W)))z+=1}if(X>0)return z===X?1:0}return null}function H6($){let Q=Number($.total),Z=Number($.passed);if(!Number.isFinite(Q)||!Number.isFinite(Z))return null;if(Q<=0)return null;return Math.max(0,Math.min(1,Z/Q))}function G6($){let Q;if($&&typeof $==="object")Q=$.count;else Q=$;let Z=Number(Q);if(!Number.isFinite(Z)||Z<0)return null;return Z}function B6($){let Q=M1($.council);for(let Z of[Q.interventions,$.interventions]){let z=Number(Z);if(Number.isFinite(z)&&z>=0)return z}return null}function Y6($){let Q=I$($,"proofs"),Z=[];if(!e3(Q))return Z;let z;try{z=Q6(Q).sort()}catch{return Z}for(let X of z){let q=I$(Q,X);try{if(!z6(q).isDirectory())continue}catch{continue}let K=null;try{K=JSON.parse(Z6(I$(q,"proof.json"),"utf8"))}catch{continue}if(!K||typeof K!=="object")continue;Z.push({run_id:String(K.run_id??X),generated_at:typeof K.generated_at==="string"?K.generated_at:null,council_pass_rate:U6(M1(K.council)),gate_pass_rate:H6(M1(K.quality_gates)),iterations:G6(K.iterations),interventions:B6(K)})}return Z.sort((X,q)=>{let K=X.generated_at===null?1:0,W=q.generated_at===null?1:0;if(K!==W)return K-W;return(X.generated_at??"").localeCompare(q.generated_at??"")}),Z}function g0($){return $.reduce((Q,Z)=>Q+Z,0)/$.length}function M6($,Q){let Z=q6[$],z=J6[$],X=V6[$],q=Q.filter((M)=>M!==null),K=q.length;if(K===0)return{axis:$,label:X,available:!1,higher_is_better:Z,note:"no runs recorded this metric"};if(K<2)return{axis:$,label:X,available:!0,higher_is_better:Z,data_points:K,latest:X$(q[K-1]),direction:"flat",improving:null,delta:0,earlier_mean:X$(q[0]),later_mean:X$(q[K-1]),insufficient:!0,note:"not enough history yet (need 2+ runs with this metric)"};let W=Math.floor(K/2),V=q.slice(0,W),U=q.slice(K-W),H=g0(V),B=g0(U),G=B-H,Y;if(Math.abs(G)<=z)Y="flat";else if(G>0)Y="up";else Y="down";let O;if(Y==="flat")O=null;else O=Y==="up"===Z;return{axis:$,label:X,available:!0,higher_is_better:Z,data_points:K,latest:X$(q[K-1]),direction:Y,improving:O,delta:X$(G),earlier_mean:X$(H),later_mean:X$(B),insufficient:!1}}function f0($){let Q=Y6($),Z=Q.map((V)=>({run_id:V.run_id,generated_at:V.generated_at,council_pass_rate:V.council_pass_rate,gate_pass_rate:V.gate_pass_rate,iterations:V.iterations,interventions:V.interventions})),z={};for(let V of f$)z[V]=M6(V,Q.map((U)=>U[V]));let X=Q.length<2,q=f$.filter((V)=>z[V].available&&z[V].improving===!0),K=f$.filter((V)=>z[V].available&&z[V].improving===!1),W=[];if(X)W.push(`not enough history yet: ${Q.length} run(s) recorded, need 2+ to show a trend`);if(!z.interventions.available)W.push("intervention trend unavailable: no per-run intervention count in proof.json yet (axis lights up automatically once recorded)");return{schema_version:K6,generated_at:new Date().toISOString(),loki_dir:$,runs_count:Q.length,insufficient:X,axes:z,improving_count:q.length,regressing_count:K.length,improving_axes:q,regressing_axes:K,series:Z,notes:W}}function u0($){return JSON.stringify($,null,2)}function c0($,Q){let Z=I$($,"metrics"),z=I$(Z,"trust-trajectory.json");try{return $6(Z,{recursive:!0}),X6(z,JSON.stringify(Q,null,2)),z}catch{return null}}function T6($){if($==="up")return"up";if($==="down")return"down";return"flat"}function O6($){let Q=$.label??$.axis;if(!$.available)return` ${(Q+":").padEnd(26)} no data`;let Z;if($.insufficient)Z="(need 2+ runs)";else if($.improving===!0)Z="improving";else if($.improving===!1)Z="regressing";else Z="stable";let z=$.higher_is_better?"higher better":"lower better",X=$.latest??"n/a";return` ${(Q+":").padEnd(26)} ${T6($.direction).padEnd(5)} latest=${String(X).padEnd(7)} ${Z.padEnd(11)} [${z}]`}function p0($){let Q=[];if(Q.push(`Loki Mode Trust Trajectory (snapshot at ${$.generated_at})`),Q.push(`Source: ${$.loki_dir}`),Q.push(`Runs analyzed: ${$.runs_count}`),Q.push(""),$.insufficient){if(Q.push("Not enough history yet."),Q.push("Trust trajectory needs 2+ recorded runs to show a direction."),Q.push("Each `loki start` run writes a proof-of-run; come back after the next run."),$.notes.length>0){Q.push(""),Q.push("Notes");for(let X of $.notes)Q.push(` - ${X}`)}return Q.join(`
448
- `)}Q.push("Is the agent earning autonomy on this repo?");for(let X of f$)if($.axes[X])Q.push(O6($.axes[X]));Q.push("");let{improving_count:Z,regressing_count:z}=$;if(Z&&!z)Q.push(`Overall: trending more trustworthy (${Z} axis improving).`);else if(z&&!Z)Q.push(`Overall: trust regressing (${z} axis regressing). Review recent runs.`);else if(Z||z)Q.push(`Overall: mixed (${Z} improving / ${z} regressing).`);else Q.push("Overall: stable.");if($.notes.length>0){Q.push(""),Q.push("Notes");for(let X of $.notes)Q.push(` - ${X}`)}return Q.join(`
449
- `)}var K6=1,f$,q6,J6,V6,m0;var l0=L(()=>{f$=["council_pass_rate","gate_pass_rate","iterations","interventions"],q6={council_pass_rate:!0,gate_pass_rate:!0,iterations:!1,interventions:!1},J6={council_pass_rate:0.01,gate_pass_rate:0.01,iterations:0.25,interventions:0.25},V6={council_pass_rate:"Council pass rate",gate_pass_rate:"Gate pass rate",iterations:"Iterations to completion",interventions:"Human interventions"},m0=["APPROVE","APPROVED","COMPLETE","PASS","PASSED"]});var d0={};b(d0,{runTrust:()=>w6});function w6($){let Q=!1;for(let X of $){if(X==="--help"||X==="-h"||X==="help")return process.stdout.write(A6),0;if(X==="--json"){Q=!0;continue}return process.stderr.write(`loki trust: unknown arg: ${X}
450
+ `;var M1=L(()=>{y0();C();K1()});var v0={};b(v0,{delegateToBash:()=>Q6});import{resolve as e3}from"path";async function Q6($){let Q=e3(h,"autonomy","loki"),Z=Bun.spawn({cmd:[Q,...$],stdin:"inherit",stdout:"inherit",stderr:"inherit",env:{...process.env,LOKI_LEGACY_BASH:"1"}}),z=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},$6);try{return await Z.exited}finally{clearTimeout(z)}}var $6=3600000;var g0=L(()=>{C()});import{existsSync as Z6,mkdirSync as z6,readdirSync as X6,readFileSync as K6,statSync as q6,writeFileSync as J6}from"fs";import{join as I$}from"path";function T1($){return $&&typeof $==="object"?$:{}}function X$($){return Math.round($*1e4)/1e4}function G6($){let Q=String($??"").trim().toUpperCase();if(!Q)return null;for(let Z of f0)if(Q.startsWith(Z))return!0;return!1}function B6($){let Q=G6($.final_verdict);if(Q!==null)return Q?1:0;let Z=$.reviewers;if(Array.isArray(Z)&&Z.length>0){let z=0,X=0;for(let q of Z){if(!q||typeof q!=="object")continue;X+=1;let K=String(q.vote??"").trim().toUpperCase();if(f0.some((W)=>K.startsWith(W)))z+=1}if(X>0)return z===X?1:0}return null}function Y6($){let Q=Number($.total),Z=Number($.passed);if(!Number.isFinite(Q)||!Number.isFinite(Z))return null;if(Q<=0)return null;return Math.max(0,Math.min(1,Z/Q))}function M6($){let Q;if($&&typeof $==="object")Q=$.count;else Q=$;let Z=Number(Q);if(!Number.isFinite(Z)||Z<0)return null;return Z}function T6($){let Q=T1($.council);for(let Z of[Q.interventions,$.interventions]){let z=Number(Z);if(Number.isFinite(z)&&z>=0)return z}return null}function O6($){let Q=I$($,"proofs"),Z=[];if(!Z6(Q))return Z;let z;try{z=X6(Q).sort()}catch{return Z}for(let X of z){let q=I$(Q,X);try{if(!q6(q).isDirectory())continue}catch{continue}let K=null;try{K=JSON.parse(K6(I$(q,"proof.json"),"utf8"))}catch{continue}if(!K||typeof K!=="object")continue;Z.push({run_id:String(K.run_id??X),generated_at:typeof K.generated_at==="string"?K.generated_at:null,council_pass_rate:B6(T1(K.council)),gate_pass_rate:Y6(T1(K.quality_gates)),iterations:M6(K.iterations),interventions:T6(K)})}return Z.sort((X,q)=>{let K=X.generated_at===null?1:0,W=q.generated_at===null?1:0;if(K!==W)return K-W;return(X.generated_at??"").localeCompare(q.generated_at??"")}),Z}function m0($){return $.reduce((Q,Z)=>Q+Z,0)/$.length}function A6($,Q){let Z=W6[$],z=U6[$],X=H6[$],q=Q.filter((M)=>M!==null),K=q.length;if(K===0)return{axis:$,label:X,available:!1,higher_is_better:Z,note:"no runs recorded this metric"};if(K<2)return{axis:$,label:X,available:!0,higher_is_better:Z,data_points:K,latest:X$(q[K-1]),direction:"flat",improving:null,delta:0,earlier_mean:X$(q[0]),later_mean:X$(q[K-1]),insufficient:!0,note:"not enough history yet (need 2+ runs with this metric)"};let W=Math.floor(K/2),V=q.slice(0,W),U=q.slice(K-W),H=m0(V),B=m0(U),G=B-H,Y;if(Math.abs(G)<=z)Y="flat";else if(G>0)Y="up";else Y="down";let O;if(Y==="flat")O=null;else O=Y==="up"===Z;return{axis:$,label:X,available:!0,higher_is_better:Z,data_points:K,latest:X$(q[K-1]),direction:Y,improving:O,delta:X$(G),earlier_mean:X$(H),later_mean:X$(B),insufficient:!1}}function u0($){let Q=O6($),Z=Q.map((V)=>({run_id:V.run_id,generated_at:V.generated_at,council_pass_rate:V.council_pass_rate,gate_pass_rate:V.gate_pass_rate,iterations:V.iterations,interventions:V.interventions})),z={};for(let V of f$)z[V]=A6(V,Q.map((U)=>U[V]));let X=Q.length<2,q=f$.filter((V)=>z[V].available&&z[V].improving===!0),K=f$.filter((V)=>z[V].available&&z[V].improving===!1),W=[];if(X)W.push(`not enough history yet: ${Q.length} run(s) recorded, need 2+ to show a trend`);if(!z.interventions.available)W.push("intervention trend unavailable: no per-run intervention count in proof.json yet (axis lights up automatically once recorded)");return{schema_version:V6,generated_at:new Date().toISOString(),loki_dir:$,runs_count:Q.length,insufficient:X,axes:z,improving_count:q.length,regressing_count:K.length,improving_axes:q,regressing_axes:K,series:Z,notes:W}}function c0($){return JSON.stringify($,null,2)}function p0($,Q){let Z=I$($,"metrics"),z=I$(Z,"trust-trajectory.json");try{return z6(Z,{recursive:!0}),J6(z,JSON.stringify(Q,null,2)),z}catch{return null}}function w6($){if($==="up")return"up";if($==="down")return"down";return"flat"}function _6($){let Q=$.label??$.axis;if(!$.available)return` ${(Q+":").padEnd(26)} no data`;let Z;if($.insufficient)Z="(need 2+ runs)";else if($.improving===!0)Z="improving";else if($.improving===!1)Z="regressing";else Z="stable";let z=$.higher_is_better?"higher better":"lower better",X=$.latest??"n/a";return` ${(Q+":").padEnd(26)} ${w6($.direction).padEnd(5)} latest=${String(X).padEnd(7)} ${Z.padEnd(11)} [${z}]`}function l0($){let Q=[];if(Q.push(`Loki Mode Trust Trajectory (snapshot at ${$.generated_at})`),Q.push(`Source: ${$.loki_dir}`),Q.push(`Runs analyzed: ${$.runs_count}`),Q.push(""),$.insufficient){if(Q.push("Not enough history yet."),Q.push("Trust trajectory needs 2+ recorded runs to show a direction."),Q.push("Each `loki start` run writes a proof-of-run; come back after the next run."),$.notes.length>0){Q.push(""),Q.push("Notes");for(let X of $.notes)Q.push(` - ${X}`)}return Q.join(`
451
+ `)}Q.push("Is the agent earning autonomy on this repo?");for(let X of f$)if($.axes[X])Q.push(_6($.axes[X]));Q.push("");let{improving_count:Z,regressing_count:z}=$;if(Z&&!z)Q.push(`Overall: trending more trustworthy (${Z} axis improving).`);else if(z&&!Z)Q.push(`Overall: trust regressing (${z} axis regressing). Review recent runs.`);else if(Z||z)Q.push(`Overall: mixed (${Z} improving / ${z} regressing).`);else Q.push("Overall: stable.");if($.notes.length>0){Q.push(""),Q.push("Notes");for(let X of $.notes)Q.push(` - ${X}`)}return Q.join(`
452
+ `)}var V6=1,f$,W6,U6,H6,f0;var d0=L(()=>{f$=["council_pass_rate","gate_pass_rate","iterations","interventions"],W6={council_pass_rate:!0,gate_pass_rate:!0,iterations:!1,interventions:!1},U6={council_pass_rate:0.01,gate_pass_rate:0.01,iterations:0.25,interventions:0.25},H6={council_pass_rate:"Council pass rate",gate_pass_rate:"Gate pass rate",iterations:"Iterations to completion",interventions:"Human interventions"},f0=["APPROVE","APPROVED","COMPLETE","PASS","PASSED"]});var o0={};b(o0,{runTrust:()=>L6});function L6($){let Q=!1;for(let X of $){if(X==="--help"||X==="-h"||X==="help")return process.stdout.write(I6),0;if(X==="--json"){Q=!0;continue}return process.stderr.write(`loki trust: unknown arg: ${X}
450
453
  Run 'loki trust --help' for usage.
451
- `),1}let Z=P(),z=f0(Z);return c0(Z,z),process.stdout.write(Q?u0(z)+`
452
- `:p0(z)+`
453
- `),0}var A6=`loki trust -- visible trust trajectory (R4)
454
+ `),1}let Z=P(),z=u0(Z);return p0(Z,z),process.stdout.write(Q?c0(z)+`
455
+ `:l0(z)+`
456
+ `),0}var I6=`loki trust -- visible trust trajectory (R4)
454
457
 
455
458
  Usage:
456
459
  loki trust Pretty-print the per-project trust trajectory
@@ -466,30 +469,30 @@ Shows whether the agent is earning autonomy on THIS repo over time:
466
469
  Derived read-only from proof-of-run history in .loki/proofs/. With fewer
467
470
  than 2 recorded runs it reports "not enough history yet" rather than a
468
471
  fabricated trend. Complements 'loki kpis' (single-run snapshot).
469
- `;var o0=L(()=>{l0();C()});import{closeSync as L$,fstatSync as _6,fsyncSync as n0,lstatSync as I6,mkdirSync as a0,openSync as c$,readSync as L6,renameSync as P6,rmSync as s0,statSync as j6,unlinkSync as t0,writeSync as r0}from"fs";import{dirname as T1}from"path";function O1($,Q){a0(T1($),{recursive:!0});let Z=`${$}.tmp.${process.pid}.${++F6}`,z=c$(Z,"w");try{r0(z,Q),n0(z)}finally{L$(z)}P6(Z,$),k6($)}function k6($){let Q=null;try{Q=c$(T1($),"r"),n0(Q)}catch{}finally{if(Q!==null)try{L$(Q)}catch{}}}function P$($,Q){O1($,`${JSON.stringify(Q,null,2)}
470
- `)}async function i0($,Q){let Z=u$.get($)??Promise.resolve(),z=()=>{},X=new Promise((K)=>{z=K}),q=Z.catch(()=>{}).then(()=>X);u$.set($,q);try{return await Z.catch(()=>{}),await Q()}finally{if(z(),u$.get($)===q)u$.delete($)}}function x6($){return`${$}.lock`}function E6($){if(!Number.isFinite($)||$<=0)return!1;try{return process.kill($,0),!0}catch(Q){return Q?.code==="EPERM"}}function N6($){let Q=null;try{return a0(T1($),{recursive:!0}),Q=c$($,"wx"),r0(Q,`${process.pid}
471
- `),Q}catch(Z){if(Q!==null){try{L$(Q)}catch{}try{t0($)}catch{}}if(Z?.code==="EEXIST")return null;throw Z}}function S6($,Q){let Z;try{Z=I6($)}catch{return!0}if(Z.isSymbolicLink())try{return t0($),!0}catch{return!1}let z;try{z=c$($,"r")}catch{return!0}try{let X=_6(z);if(Date.now()-X.mtimeMs<Q)return!1;let K=NaN;try{let W=Buffer.alloc(64),V=L6(z,W,0,64,0);K=Number.parseInt(W.subarray(0,V).toString("utf-8").trim(),10)}catch{}if(Number.isFinite(K)&&E6(K))return!1;try{if(j6($).mtimeMs>X.mtimeMs)return!1}catch{return!0}try{s0($,{force:!0})}catch{}return!0}finally{try{L$(z)}catch{}}}function j$($,Q,Z={}){let z=Z.timeoutMs??1e4,X=Z.pollMs??25,q=Z.staleMs??30000,K=x6($),W=Date.now()+z,V=null,U=0,H=new Int32Array(new SharedArrayBuffer(4));while(V===null){if(V=N6(K),V!==null)break;if(Date.now()>W)throw Error(`withFileLockSync: timed out after ${z}ms acquiring ${K}`);if(S6(K,q))continue;let B=Math.min(X*2**Math.min(U,4),R6);U+=1,Atomics.wait(H,0,0,B)}try{return Q()}finally{try{L$(V)}catch{}try{s0(K,{force:!0})}catch{}}}var F6=0,u$,R6=50;var F$=L(()=>{u$=new Map});import{existsSync as K$,mkdirSync as Y$,copyFileSync as ZQ,readFileSync as _1,readdirSync as D6,statSync as C6,writeFileSync as b6,renameSync as zQ,appendFileSync as XQ,rmSync as h6}from"fs";import{join as m,dirname as p$}from"path";function v6($){let Q=$Q.then($,$);return $Q=Q.catch((Z)=>{console.warn("[checkpoint] serialized op rejected:",Z);return}),Q}function o($){return m($,"state","checkpoints")}function KQ($){return m(o($),"index.jsonl")}async function g6($){let Q=await F(["git","rev-parse","HEAD"],{cwd:$,timeoutMs:5000});if(Q.exitCode!==0)return"no-git";return Q.stdout.trim()||"no-git"}async function m6($){let Q=await F(["git","branch","--show-current"],{cwd:$,timeoutMs:5000});if(Q.exitCode!==0)return"unknown";return Q.stdout.trim()||"unknown"}async function f6($){let Q=await F(["git","diff","--quiet"],{cwd:$,timeoutMs:5000}),Z=await F(["git","diff","--cached","--quiet"],{cwd:$,timeoutMs:5000}),z=Q.exitCode===1,X=Z.exitCode===1;return z||X}function u6($){let Q=m($,"state","orchestrator.json");if(!K$(Q))return"unknown";try{let z=JSON.parse(_1(Q,"utf-8")).currentPhase;return typeof z==="string"&&z.length>0?z:"unknown"}catch{return"unknown"}}function p6($,Q){for(let Z of c6){let z=m($,Z);if(!K$(z))continue;let X=m(Q,Z);Y$(p$(X),{recursive:!0});try{ZQ(z,X)}catch{}}}function JQ($,Q){Y$(p$($),{recursive:!0});let Z=`${$}.tmp.${process.pid}.${++qQ}`;b6(Z,Q),zQ(Z,$)}function l6($){return JSON.stringify($,null,2)}function VQ($){return`{${[`"id": ${JSON.stringify($.id)}`,`"ts": ${JSON.stringify($.ts)}`,`"iter": ${JSON.stringify($.iter)}`,`"task": ${JSON.stringify($.task)}`,`"sha": ${JSON.stringify($.sha)}`].join(", ")}}`}async function d6($){return v6(()=>o6($))}async function o6($){let Q=$.lokiDirOverride??P(),Z=process.cwd(),z=o(Q);if(Y$(z,{recursive:!0}),!$.forceCreate){if(!await f6(Z))return{created:!1,reason:"no uncommitted changes"}}let X=await g6(Z),q=await m6(Z),K=$.iteration??Number.parseInt(process.env.ITERATION_COUNT??"0",10),W=$.epochOverride??Math.floor(Date.now()/1000),V=`cp-${K}-${W}`,U=m(z,V);Y$(U,{recursive:!0}),p6(Q,U);let H=new Date().toISOString().replace(/\.\d{3}Z$/,"Z"),B=($.taskDescription??"task completed").slice(0,y6),G=$.provider??process.env.PROVIDER_NAME??"claude",Y={id:V,timestamp:H,iteration:K,task_id:$.taskId??"unknown",task_description:B,git_sha:X,git_branch:q,provider:G,phase:u6(Q)};JQ(m(U,"metadata.json"),l6(Y));let O={id:Y.id,ts:Y.timestamp,iter:Y.iteration,task:Y.task_description,sha:Y.git_sha},M=KQ(Q);return j$(M,()=>{XQ(M,`${VQ(O)}
472
- `)}),n6(Q),{created:!0,id:V,metadata:Y,dir:U}}function I1($){let Q=o($);if(!K$(Q))return[];return D6(Q).filter((Z)=>Z.startsWith("cp-")).filter((Z)=>{try{return C6(m(Q,Z)).isDirectory()}catch{return!1}})}function L1($){return[...$].sort((Q,Z)=>{let z=QQ(Q),X=QQ(Z);return z-X})}function QQ($){let Q=$.split("-");if(Q.length<3)return 0;let Z=Q[Q.length-1],z=Number.parseInt(Z??"0",10);return Number.isFinite(z)?z:0}function n6($){let Q=I1($);if(Q.length<=e0)return;let Z=L1(Q),z=Z.slice(0,Z.length-e0);for(let X of z)try{h6(m(o($),X),{recursive:!0,force:!0})}catch{}a6($)}function a6($){let Q=L1(I1($)),Z=[];for(let q of Q){let K=m(o($),q,"metadata.json"),W=m(o($),q);if(!K$(K)){A1($,W,"missing_field","metadata.json");continue}try{let V=JSON.parse(_1(K,"utf-8")),U=UQ(V,K);if(!U.ok){A1($,W,U.reason,U.field);continue}let H=U.value;Z.push(VQ({id:H.id,ts:H.timestamp,iter:H.iteration,task:H.task_description??"",sha:H.git_sha}))}catch{A1($,W,"invalid_type","metadata.json")}}let z=KQ($),X=Z.length>0?`${Z.join(`
472
+ `;var n0=L(()=>{d0();C()});import{closeSync as L$,fstatSync as P6,fsyncSync as a0,lstatSync as j6,mkdirSync as s0,openSync as c$,readSync as F6,renameSync as k6,rmSync as r0,statSync as R6,unlinkSync as t0,writeSync as i0}from"fs";import{dirname as O1}from"path";function A1($,Q){s0(O1($),{recursive:!0});let Z=`${$}.tmp.${process.pid}.${++E6}`,z=c$(Z,"w");try{i0(z,Q),a0(z)}finally{L$(z)}k6(Z,$),x6($)}function x6($){let Q=null;try{Q=c$(O1($),"r"),a0(Q)}catch{}finally{if(Q!==null)try{L$(Q)}catch{}}}function P$($,Q){A1($,`${JSON.stringify(Q,null,2)}
473
+ `)}async function e0($,Q){let Z=u$.get($)??Promise.resolve(),z=()=>{},X=new Promise((K)=>{z=K}),q=Z.catch(()=>{}).then(()=>X);u$.set($,q);try{return await Z.catch(()=>{}),await Q()}finally{if(z(),u$.get($)===q)u$.delete($)}}function S6($){return`${$}.lock`}function D6($){if(!Number.isFinite($)||$<=0)return!1;try{return process.kill($,0),!0}catch(Q){return Q?.code==="EPERM"}}function C6($){let Q=null;try{return s0(O1($),{recursive:!0}),Q=c$($,"wx"),i0(Q,`${process.pid}
474
+ `),Q}catch(Z){if(Q!==null){try{L$(Q)}catch{}try{t0($)}catch{}}if(Z?.code==="EEXIST")return null;throw Z}}function b6($,Q){let Z;try{Z=j6($)}catch{return!0}if(Z.isSymbolicLink())try{return t0($),!0}catch{return!1}let z;try{z=c$($,"r")}catch{return!0}try{let X=P6(z);if(Date.now()-X.mtimeMs<Q)return!1;let K=NaN;try{let W=Buffer.alloc(64),V=F6(z,W,0,64,0);K=Number.parseInt(W.subarray(0,V).toString("utf-8").trim(),10)}catch{}if(Number.isFinite(K)&&D6(K))return!1;try{if(R6($).mtimeMs>X.mtimeMs)return!1}catch{return!0}try{r0($,{force:!0})}catch{}return!0}finally{try{L$(z)}catch{}}}function j$($,Q,Z={}){let z=Z.timeoutMs??1e4,X=Z.pollMs??25,q=Z.staleMs??30000,K=S6($),W=Date.now()+z,V=null,U=0,H=new Int32Array(new SharedArrayBuffer(4));while(V===null){if(V=C6(K),V!==null)break;if(Date.now()>W)throw Error(`withFileLockSync: timed out after ${z}ms acquiring ${K}`);if(b6(K,q))continue;let B=Math.min(X*2**Math.min(U,4),N6);U+=1,Atomics.wait(H,0,0,B)}try{return Q()}finally{try{L$(V)}catch{}try{r0(K,{force:!0})}catch{}}}var E6=0,u$,N6=50;var F$=L(()=>{u$=new Map});import{existsSync as K$,mkdirSync as Y$,copyFileSync as zQ,readFileSync as I1,readdirSync as h6,statSync as y6,writeFileSync as v6,renameSync as XQ,appendFileSync as KQ,rmSync as g6}from"fs";import{join as m,dirname as p$}from"path";function f6($){let Q=QQ.then($,$);return QQ=Q.catch((Z)=>{console.warn("[checkpoint] serialized op rejected:",Z);return}),Q}function o($){return m($,"state","checkpoints")}function qQ($){return m(o($),"index.jsonl")}async function u6($){let Q=await F(["git","rev-parse","HEAD"],{cwd:$,timeoutMs:5000});if(Q.exitCode!==0)return"no-git";return Q.stdout.trim()||"no-git"}async function c6($){let Q=await F(["git","branch","--show-current"],{cwd:$,timeoutMs:5000});if(Q.exitCode!==0)return"unknown";return Q.stdout.trim()||"unknown"}async function p6($){let Q=await F(["git","diff","--quiet"],{cwd:$,timeoutMs:5000}),Z=await F(["git","diff","--cached","--quiet"],{cwd:$,timeoutMs:5000}),z=Q.exitCode===1,X=Z.exitCode===1;return z||X}function l6($){let Q=m($,"state","orchestrator.json");if(!K$(Q))return"unknown";try{let z=JSON.parse(I1(Q,"utf-8")).currentPhase;return typeof z==="string"&&z.length>0?z:"unknown"}catch{return"unknown"}}function o6($,Q){for(let Z of d6){let z=m($,Z);if(!K$(z))continue;let X=m(Q,Z);Y$(p$(X),{recursive:!0});try{zQ(z,X)}catch{}}}function VQ($,Q){Y$(p$($),{recursive:!0});let Z=`${$}.tmp.${process.pid}.${++JQ}`;v6(Z,Q),XQ(Z,$)}function n6($){return JSON.stringify($,null,2)}function WQ($){return`{${[`"id": ${JSON.stringify($.id)}`,`"ts": ${JSON.stringify($.ts)}`,`"iter": ${JSON.stringify($.iter)}`,`"task": ${JSON.stringify($.task)}`,`"sha": ${JSON.stringify($.sha)}`].join(", ")}}`}async function a6($){return f6(()=>s6($))}async function s6($){let Q=$.lokiDirOverride??P(),Z=process.cwd(),z=o(Q);if(Y$(z,{recursive:!0}),!$.forceCreate){if(!await p6(Z))return{created:!1,reason:"no uncommitted changes"}}let X=await u6(Z),q=await c6(Z),K=$.iteration??Number.parseInt(process.env.ITERATION_COUNT??"0",10),W=$.epochOverride??Math.floor(Date.now()/1000),V=`cp-${K}-${W}`,U=m(z,V);Y$(U,{recursive:!0}),o6(Q,U);let H=new Date().toISOString().replace(/\.\d{3}Z$/,"Z"),B=($.taskDescription??"task completed").slice(0,m6),G=$.provider??process.env.PROVIDER_NAME??"claude",Y={id:V,timestamp:H,iteration:K,task_id:$.taskId??"unknown",task_description:B,git_sha:X,git_branch:q,provider:G,phase:l6(Q)};VQ(m(U,"metadata.json"),n6(Y));let O={id:Y.id,ts:Y.timestamp,iter:Y.iteration,task:Y.task_description,sha:Y.git_sha},M=qQ(Q);return j$(M,()=>{KQ(M,`${WQ(O)}
475
+ `)}),r6(Q),{created:!0,id:V,metadata:Y,dir:U}}function L1($){let Q=o($);if(!K$(Q))return[];return h6(Q).filter((Z)=>Z.startsWith("cp-")).filter((Z)=>{try{return y6(m(Q,Z)).isDirectory()}catch{return!1}})}function P1($){return[...$].sort((Q,Z)=>{let z=ZQ(Q),X=ZQ(Z);return z-X})}function ZQ($){let Q=$.split("-");if(Q.length<3)return 0;let Z=Q[Q.length-1],z=Number.parseInt(Z??"0",10);return Number.isFinite(z)?z:0}function r6($){let Q=L1($);if(Q.length<=$Q)return;let Z=P1(Q),z=Z.slice(0,Z.length-$Q);for(let X of z)try{g6(m(o($),X),{recursive:!0,force:!0})}catch{}t6($)}function t6($){let Q=P1(L1($)),Z=[];for(let q of Q){let K=m(o($),q,"metadata.json"),W=m(o($),q);if(!K$(K)){w1($,W,"missing_field","metadata.json");continue}try{let V=JSON.parse(I1(K,"utf-8")),U=HQ(V,K);if(!U.ok){w1($,W,U.reason,U.field);continue}let H=U.value;Z.push(WQ({id:H.id,ts:H.timestamp,iter:H.iteration,task:H.task_description??"",sha:H.git_sha}))}catch{w1($,W,"invalid_type","metadata.json")}}let z=qQ($),X=Z.length>0?`${Z.join(`
473
476
  `)}
474
- `:"";JQ(z,X)}function A1($,Q,Z,z){let X=m($,"events.jsonl"),q={timestamp:new Date().toISOString(),type:"checkpoint.metadata.dropped",checkpoint_dir:Q,reason:Z,field:z};try{Y$(p$(X),{recursive:!0}),j$(X,()=>{XQ(X,`${JSON.stringify(q)}
475
- `)})}catch{}}function P1($){let Q=$??P(),Z=L1(I1(Q)),z=[];for(let X of Z){let q=WQ(Q,X);if(q)z.push(q)}return z}function WQ($,Q){let Z=m(o($),Q,"metadata.json");if(!K$(Z))return null;try{let z=JSON.parse(_1(Z,"utf-8"));return s6(z,Z)}catch{return null}}function s6($,Q){let Z=UQ($,Q);return Z.ok?Z.value:null}function UQ($,Q){if($===null||typeof $!=="object")return console.warn(`[checkpoint] invalid metadata at ${Q}: not an object`),{ok:!1,reason:"invalid_type",field:"<root>"};let Z=$,z=["id","timestamp","task_id","task_description","git_sha","git_branch","provider","phase"];for(let X of z){if(!(X in Z))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${X}" missing`),{ok:!1,reason:"missing_field",field:X};if(typeof Z[X]!=="string")return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${X}" not a string`),{ok:!1,reason:"invalid_type",field:X}}if(!Object.prototype.hasOwnProperty.call(Z,"iteration"))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "iteration" missing`),{ok:!1,reason:"missing_field",field:"iteration"};if(typeof Z.iteration!=="number"||!Number.isFinite(Z.iteration))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "iteration" not a finite number`),{ok:!1,reason:"invalid_type",field:"iteration"};for(let X of r6){let q=Z[X];if(t6.test(q))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${X}" contains control characters`),{ok:!1,reason:"control_chars",field:X}}return{ok:!0,value:{id:Z.id,timestamp:Z.timestamp,iteration:Z.iteration,task_id:Z.task_id,task_description:Z.task_description,git_sha:Z.git_sha,git_branch:Z.git_branch,provider:Z.provider,phase:Z.phase}}}function j1($,Q){if(!i6.test($))throw new HQ($);let Z=Q??P(),z=m(o(Z),$);if(!K$(z))throw new w1($);let X=WQ(Z,$);if(!X)throw new w1($);return X}function GQ($,Q){let Z=j1($,Q),z=Q??P(),X=m(o(z),$),q=[];for(let K of e6){let W=m(X,K);if(!K$(W))continue;q.push({from:W,to:m(z,K)})}return{id:$,metadata:Z,restore:q}}function $7($){let Q=[],Z=0;for(let z of $.restore)try{Y$(p$(z.to),{recursive:!0});let X=`${z.to}.tmp.${process.pid}.${++qQ}`;ZQ(z.from,X),zQ(X,z.to),Z+=1}catch(X){Q.push(`${z.from} -> ${z.to}: ${X.message}`)}return{restored:Z,errors:Q}}async function BQ($,Q,Z=!1){let z=null;try{let q=await d6({taskDescription:`pre-rollback snapshot (before restoring ${$.id})`,taskId:"rollback",forceCreate:!0,lokiDirOverride:Q});if(q.created)z=q.id}catch(q){let K=q instanceof Error?q.message:String(q);if(!Z)throw Error("pre-rollback snapshot failed ("+K+"); aborting rollback to preserve current state. Re-run with force to roll back anyway without a safety snapshot.");console.warn("[checkpoint] pre-rollback snapshot failed; proceeding due to force:",K)}let X=$7($);return{preRollbackSnapshotId:z,restored:X.restored,errors:X.errors}}var e0=50,y6=200,$Q,c6,qQ=0,t6,r6,i6,w1,HQ,e6;var YQ=L(()=>{C();d();F$();$Q=Promise.resolve();c6=["state/orchestrator.json","autonomy-state.json","queue/pending.json","queue/completed.json","queue/in-progress.json","queue/current-task.json","CONTINUITY.md"];t6=/[\x00-\x08\x0a-\x1f\x7f-\x9f]/,r6=["id","task_id","git_sha","git_branch","provider","phase"];i6=/^[a-zA-Z0-9_-]+$/;w1=class w1 extends Error{id;constructor($){super(`Checkpoint not found: ${$}`);this.id=$;this.name="CheckpointNotFoundError"}};HQ=class HQ extends Error{id;constructor($){super(`Invalid checkpoint ID: must be alphanumeric, hyphens, underscores only (got: ${$})`);this.id=$;this.name="InvalidCheckpointIdError"}};e6=["state/orchestrator.json","queue/pending.json","queue/completed.json","queue/in-progress.json","queue/current-task.json","CONTINUITY.md"]});var OQ={};b(OQ,{runRollback:()=>Q7});async function Q7($){let Q=$[0],Z=$.slice(1);if(Q===void 0||Q==="help"||Q==="--help"||Q==="-h")return process.stdout.write(MQ),Q===void 0?1:0;switch(Q){case"list":{let z=[...P1()].reverse();if(z.length===0)return process.stdout.write(`${_}No checkpoints found.${J}
477
+ `:"";VQ(z,X)}function w1($,Q,Z,z){let X=m($,"events.jsonl"),q={timestamp:new Date().toISOString(),type:"checkpoint.metadata.dropped",checkpoint_dir:Q,reason:Z,field:z};try{Y$(p$(X),{recursive:!0}),j$(X,()=>{KQ(X,`${JSON.stringify(q)}
478
+ `)})}catch{}}function j1($){let Q=$??P(),Z=P1(L1(Q)),z=[];for(let X of Z){let q=UQ(Q,X);if(q)z.push(q)}return z}function UQ($,Q){let Z=m(o($),Q,"metadata.json");if(!K$(Z))return null;try{let z=JSON.parse(I1(Z,"utf-8"));return i6(z,Z)}catch{return null}}function i6($,Q){let Z=HQ($,Q);return Z.ok?Z.value:null}function HQ($,Q){if($===null||typeof $!=="object")return console.warn(`[checkpoint] invalid metadata at ${Q}: not an object`),{ok:!1,reason:"invalid_type",field:"<root>"};let Z=$,z=["id","timestamp","task_id","task_description","git_sha","git_branch","provider","phase"];for(let X of z){if(!(X in Z))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${X}" missing`),{ok:!1,reason:"missing_field",field:X};if(typeof Z[X]!=="string")return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${X}" not a string`),{ok:!1,reason:"invalid_type",field:X}}if(!Object.prototype.hasOwnProperty.call(Z,"iteration"))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "iteration" missing`),{ok:!1,reason:"missing_field",field:"iteration"};if(typeof Z.iteration!=="number"||!Number.isFinite(Z.iteration))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "iteration" not a finite number`),{ok:!1,reason:"invalid_type",field:"iteration"};for(let X of $7){let q=Z[X];if(e6.test(q))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${X}" contains control characters`),{ok:!1,reason:"control_chars",field:X}}return{ok:!0,value:{id:Z.id,timestamp:Z.timestamp,iteration:Z.iteration,task_id:Z.task_id,task_description:Z.task_description,git_sha:Z.git_sha,git_branch:Z.git_branch,provider:Z.provider,phase:Z.phase}}}function F1($,Q){if(!Q7.test($))throw new GQ($);let Z=Q??P(),z=m(o(Z),$);if(!K$(z))throw new _1($);let X=UQ(Z,$);if(!X)throw new _1($);return X}function BQ($,Q){let Z=F1($,Q),z=Q??P(),X=m(o(z),$),q=[];for(let K of Z7){let W=m(X,K);if(!K$(W))continue;q.push({from:W,to:m(z,K)})}return{id:$,metadata:Z,restore:q}}function z7($){let Q=[],Z=0;for(let z of $.restore)try{Y$(p$(z.to),{recursive:!0});let X=`${z.to}.tmp.${process.pid}.${++JQ}`;zQ(z.from,X),XQ(X,z.to),Z+=1}catch(X){Q.push(`${z.from} -> ${z.to}: ${X.message}`)}return{restored:Z,errors:Q}}async function YQ($,Q,Z=!1){let z=null;try{let q=await a6({taskDescription:`pre-rollback snapshot (before restoring ${$.id})`,taskId:"rollback",forceCreate:!0,lokiDirOverride:Q});if(q.created)z=q.id}catch(q){let K=q instanceof Error?q.message:String(q);if(!Z)throw Error("pre-rollback snapshot failed ("+K+"); aborting rollback to preserve current state. Re-run with force to roll back anyway without a safety snapshot.");console.warn("[checkpoint] pre-rollback snapshot failed; proceeding due to force:",K)}let X=z7($);return{preRollbackSnapshotId:z,restored:X.restored,errors:X.errors}}var $Q=50,m6=200,QQ,d6,JQ=0,e6,$7,Q7,_1,GQ,Z7;var MQ=L(()=>{C();d();F$();QQ=Promise.resolve();d6=["state/orchestrator.json","autonomy-state.json","queue/pending.json","queue/completed.json","queue/in-progress.json","queue/current-task.json","CONTINUITY.md"];e6=/[\x00-\x08\x0a-\x1f\x7f-\x9f]/,$7=["id","task_id","git_sha","git_branch","provider","phase"];Q7=/^[a-zA-Z0-9_-]+$/;_1=class _1 extends Error{id;constructor($){super(`Checkpoint not found: ${$}`);this.id=$;this.name="CheckpointNotFoundError"}};GQ=class GQ extends Error{id;constructor($){super(`Invalid checkpoint ID: must be alphanumeric, hyphens, underscores only (got: ${$})`);this.id=$;this.name="InvalidCheckpointIdError"}};Z7=["state/orchestrator.json","queue/pending.json","queue/completed.json","queue/in-progress.json","queue/current-task.json","CONTINUITY.md"]});var AQ={};b(AQ,{runRollback:()=>X7});async function X7($){let Q=$[0],Z=$.slice(1);if(Q===void 0||Q==="help"||Q==="--help"||Q==="-h")return process.stdout.write(TQ),Q===void 0?1:0;switch(Q){case"list":{let z=[...j1()].reverse();if(z.length===0)return process.stdout.write(`${_}No checkpoints found.${J}
476
479
  `),0;process.stdout.write(`${k}Checkpoints${J} (${z.length}, newest first):
477
480
  `);for(let X of z)process.stdout.write(` ${I}${X.id}${J} iter=${X.iteration} ${X.git_branch||"(no branch)"}@${(X.git_sha||"").slice(0,7)} ${X.timestamp}
478
481
  `);return 0}case"show":{let z=Z[0];if(!z)return process.stderr.write(`${T}Missing checkpoint id.${J} Use \`loki rollback list\`.
479
- `),2;try{let X=j1(z);return process.stdout.write(`${JSON.stringify(X,null,2)}
482
+ `),2;try{let X=F1(z);return process.stdout.write(`${JSON.stringify(X,null,2)}
480
483
  `),0}catch(X){return process.stderr.write(`${T}Failed to read checkpoint:${J} ${X.message}
481
484
  `),1}}case"to":{let z=Z[0];if(!z)return process.stderr.write(`${T}Missing checkpoint id.${J} Use \`loki rollback list\`.
482
- `),2;return await TQ(z,Z.includes("--force"))}case"latest":{let z=P1(),X=z[z.length-1];if(!X)return process.stderr.write(`${T}No checkpoints found to roll back to.${J}
485
+ `),2;return await OQ(z,Z.includes("--force"))}case"latest":{let z=j1(),X=z[z.length-1];if(!X)return process.stderr.write(`${T}No checkpoints found to roll back to.${J}
483
486
  `),1;return process.stdout.write(`Rolling back to latest checkpoint: ${I}${X.id}${J}
484
- `),await TQ(X.id,Z.includes("--force"))}default:return process.stderr.write(`Unknown subcommand: ${Q}
485
- `),process.stderr.write(MQ),2}}async function TQ($,Q=!1){let Z;try{Z=GQ($)}catch(X){return process.stderr.write(`${T}Cannot plan rollback:${J} ${X.message}
487
+ `),await OQ(X.id,Z.includes("--force"))}default:return process.stderr.write(`Unknown subcommand: ${Q}
488
+ `),process.stderr.write(TQ),2}}async function OQ($,Q=!1){let Z;try{Z=BQ($)}catch(X){return process.stderr.write(`${T}Cannot plan rollback:${J} ${X.message}
486
489
  `),1}if(Z.restore.length===0)return process.stdout.write(`${_}Checkpoint ${$} has no restorable state files; nothing to do.${J}
487
- `),0;let z;try{z=await BQ(Z,void 0,Q)}catch(X){return process.stderr.write(`${T}Rollback aborted:${J} ${X.message}
490
+ `),0;let z;try{z=await YQ(Z,void 0,Q)}catch(X){return process.stderr.write(`${T}Rollback aborted:${J} ${X.message}
488
491
  `),1}if(z.errors.length>0){for(let X of z.errors)process.stderr.write(`${T}restore error:${J} ${X}
489
492
  `);return process.stderr.write(`${T}Partial rollback: ${z.restored}/${Z.restore.length} files restored.${J}
490
493
  `),1}if(process.stdout.write(`${S}Rolled back ${z.restored}/${Z.restore.length} state files from ${$}.${J}
491
494
  `),z.preRollbackSnapshotId)process.stdout.write(`Saved your prior state as ${I}${z.preRollbackSnapshotId}${J}; undo this rollback with \`loki rollback to ${z.preRollbackSnapshotId}\`.
492
- `);return process.stdout.write("Run `loki start` to resume from the restored state.\n"),0}var MQ=`Usage: loki rollback <subcommand>
495
+ `);return process.stdout.write("Run `loki start` to resume from the restored state.\n"),0}var TQ=`Usage: loki rollback <subcommand>
493
496
 
494
497
  Subcommands:
495
498
  list List checkpoints (newest first)
@@ -510,33 +513,33 @@ to the checkpoint's snapshot (if one was anchored at checkpoint time):
510
513
  git stash apply refs/loki/cp/<id>
511
514
 
512
515
  Re-run \`loki start\` to resume from the restored state.
513
- `;var AQ=L(()=>{YQ();c()});function Z7(){return process.env.LOKI_TIER||"oss"}function wQ($){let Q=Z7();if(Q==="oss")return{allowed:!0,notes:[]};if(!process.env.LOKI_LICENSE_KEY)return{allowed:!1,notes:[`${_}LOKI_TIER='${Q}' requested but no LOKI_LICENSE_KEY set.${J}`,`Hosted/enterprise license verification is not available yet (capability: ${$}).`,"OSS users: leave LOKI_TIER unset (or 'oss') -- everything stays free."]};return{allowed:!0,notes:[`${_}LOKI_LICENSE_KEY set but the verification backend is not available yet (R9 seam).${J}`]}}var _Q=L(()=>{c()});var LQ={};b(LQ,{runProof:()=>w7});import{existsSync as q$,readdirSync as z7,readFileSync as IQ,mkdtempSync as X7,copyFileSync as K7,rmSync as q7}from"fs";import{join as n,resolve as J7}from"path";import{tmpdir as V7}from"os";import{createInterface as W7}from"readline";import{readFile as U7}from"fs/promises";function a($){return $&&typeof $==="object"?$:{}}function p($){return $===void 0||$===null?"-":String($)}function M$(){return n(P(),"proofs")}function F1($){let Q=n(M$(),$,"proof.json");if(!q$(Q))return null;try{return JSON.parse(IQ(Q,"utf8"))}catch{return{}}}function $$($,Q){return $.length>=Q?$:$+" ".repeat(Q-$.length)}function G7(){let $=M$();if(!q$($))return process.stdout.write(`${_}No proofs found.${J} Run 'loki start' to generate one.
514
- `),0;let Q=[];try{Q=z7($,{withFileTypes:!0}).filter((z)=>z.isDirectory()).map((z)=>z.name).sort()}catch{Q=[]}let Z=[];for(let z of Q){let X=n($,z,"proof.json");if(!q$(X))continue;let q={};try{q=JSON.parse(IQ(X,"utf8"))}catch{q={}}let K=p(q.run_id),W=p(q.generated_at),V=a(q.honesty).headline,U=p(V??a(q.council).final_verdict),H=p(a(q.cost).usd),B=p(a(q.files_changed).count);Z.push(`${$$(K,26)} ${$$(W,20)} ${$$(U,18)} ${$$(H,9)} ${B}`)}if(Z.length===0)return process.stdout.write(`${_}No proofs found.${J} Run 'loki start' to generate one.
516
+ `;var wQ=L(()=>{MQ();c()});function K7(){return process.env.LOKI_TIER||"oss"}function _Q($){let Q=K7();if(Q==="oss")return{allowed:!0,notes:[]};if(!process.env.LOKI_LICENSE_KEY)return{allowed:!1,notes:[`${_}LOKI_TIER='${Q}' requested but no LOKI_LICENSE_KEY set.${J}`,`Hosted/enterprise license verification is not available yet (capability: ${$}).`,"OSS users: leave LOKI_TIER unset (or 'oss') -- everything stays free."]};return{allowed:!0,notes:[`${_}LOKI_LICENSE_KEY set but the verification backend is not available yet (R9 seam).${J}`]}}var IQ=L(()=>{c()});var PQ={};b(PQ,{runProof:()=>L7});import{existsSync as q$,readdirSync as q7,readFileSync as LQ,mkdtempSync as J7,copyFileSync as V7,rmSync as W7}from"fs";import{join as n,resolve as U7}from"path";import{tmpdir as H7}from"os";import{createInterface as G7}from"readline";import{readFile as B7}from"fs/promises";function a($){return $&&typeof $==="object"?$:{}}function p($){return $===void 0||$===null?"-":String($)}function M$(){return n(P(),"proofs")}function k1($){let Q=n(M$(),$,"proof.json");if(!q$(Q))return null;try{return JSON.parse(LQ(Q,"utf8"))}catch{return{}}}function $$($,Q){return $.length>=Q?$:$+" ".repeat(Q-$.length)}function M7(){let $=M$();if(!q$($))return process.stdout.write(`${_}No proofs found.${J} Run 'loki start' to generate one.
517
+ `),0;let Q=[];try{Q=q7($,{withFileTypes:!0}).filter((z)=>z.isDirectory()).map((z)=>z.name).sort()}catch{Q=[]}let Z=[];for(let z of Q){let X=n($,z,"proof.json");if(!q$(X))continue;let q={};try{q=JSON.parse(LQ(X,"utf8"))}catch{q={}}let K=p(q.run_id),W=p(q.generated_at),V=a(q.honesty).headline,U=p(V??a(q.council).final_verdict),H=p(a(q.cost).usd),B=p(a(q.files_changed).count);Z.push(`${$$(K,26)} ${$$(W,20)} ${$$(U,18)} ${$$(H,9)} ${B}`)}if(Z.length===0)return process.stdout.write(`${_}No proofs found.${J} Run 'loki start' to generate one.
515
518
  `),0;process.stdout.write(`${$$("RUN_ID",26)} ${$$("GENERATED_AT",20)} ${$$("VERDICT",18)} ${$$("COST_USD",9)} FILES
516
519
  `);for(let z of Z)process.stdout.write(`${z}
517
- `);return 0}function B7($){if(!$)return process.stderr.write(`${T}Missing proof id.${J} Use 'loki proof list'.
518
- `),2;let Q=F1($);if(Q===null)return process.stderr.write(`${T}Proof not found: ${$}${J}
520
+ `);return 0}function T7($){if(!$)return process.stderr.write(`${T}Missing proof id.${J} Use 'loki proof list'.
521
+ `),2;let Q=k1($);if(Q===null)return process.stderr.write(`${T}Proof not found: ${$}${J}
519
522
  `),process.stderr.write(`Use 'loki proof list' to see available proofs.
520
523
  `),1;return process.stdout.write(`${JSON.stringify(Q,null,2)}
521
- `),0}async function Y7($){if(!$)return process.stderr.write(`${T}Missing proof id.${J} Use 'loki proof list'.
524
+ `),0}async function O7($){if(!$)return process.stderr.write(`${T}Missing proof id.${J} Use 'loki proof list'.
522
525
  `),2;let Q=n(M$(),$,"index.html");if(!q$(Q))return process.stderr.write(`${T}Proof page not found: ${$}/index.html${J}
523
526
  `),process.stderr.write(`Use 'loki proof list' to see available proofs.
524
527
  `),1;process.stdout.write(`${S}Opening proof: ${Q}${J}
525
528
  `);for(let Z of["open","xdg-open","start"])try{if((await F([Z,Q],{timeoutMs:5000})).exitCode===0)return 0}catch{}return process.stdout.write(`
526
529
  Could not detect browser opener.
527
530
  `),process.stdout.write(`Please open in browser: ${Q}
528
- `),0}function M7($){return new Promise((Q)=>{let Z=W7({input:process.stdin,output:process.stdout});Z.question($,(z)=>{Z.close();let X=z.trim().toLowerCase();Q(X==="y"||X==="yes")})})}async function T7($,Q,Z){let z=wQ("hosted_publish");for(let G of z.notes)process.stderr.write(`${G}
531
+ `),0}function A7($){return new Promise((Q)=>{let Z=G7({input:process.stdin,output:process.stdout});Z.question($,(z)=>{Z.close();let X=z.trim().toLowerCase();Q(X==="y"||X==="yes")})})}async function w7($,Q,Z){let z=_Q("hosted_publish");for(let G of z.notes)process.stderr.write(`${G}
529
532
  `);let X=process.env.LOKI_HOSTED_ENDPOINT||"";if(!X)return process.stderr.write(`${_}Hosted publishing backend not available.${J}
530
533
  `),process.stderr.write(`There is no official Loki hosted service yet (R9 ships the seam, not a live backend).
531
534
  `),process.stderr.write(`To publish to your own hosted endpoint, set LOKI_HOSTED_ENDPOINT to its URL.
532
535
  `),process.stderr.write(`Or publish to a GitHub Gist instead: loki proof share ${$}
533
- `),1;let q=F1($);if(q){if(a(q.redaction).applied!==!0)return process.stderr.write(`${T}Refusing to publish: proof redaction was not confirmed applied.${J}
536
+ `),1;let q=k1($);if(q){if(a(q.redaction).applied!==!0)return process.stderr.write(`${T}Refusing to publish: proof redaction was not confirmed applied.${J}
534
537
  `),process.stderr.write(`Regenerate the proof (LOKI_PROOF=1) so the redactor runs, then retry.
535
538
  `),1}process.stdout.write(`${k}Publishing proof '${$}' to hosted endpoint${J}
536
539
  `),process.stdout.write(` endpoint: ${X}
537
540
  `),process.stdout.write(` payload: ${Q} (already redacted by the generator)
538
541
 
539
- `);let K;try{K=await U7(Q)}catch{return process.stderr.write(`${T}Could not read proof page: ${Q}${J}
542
+ `);let K;try{K=await B7(Q)}catch{return process.stderr.write(`${T}Could not read proof page: ${Q}${J}
540
543
  `),1}let W={"Content-Type":"text/html","X-Loki-Proof-Id":$},V=process.env.LOKI_LICENSE_KEY||"";if(V)W.Authorization=`Bearer ${V}`;let U;try{U=await fetch(X,{method:"POST",headers:W,body:new Uint8Array(K)})}catch(G){return process.stderr.write(`${T}Failed to reach hosted endpoint: ${String(G.message||G)}${J}
541
544
  `),process.stderr.write(`Check LOKI_HOSTED_ENDPOINT or publish to a gist: loki proof share ${$}
542
545
  `),1}let H=await U.text();if(!U.ok){if(process.stderr.write(`${T}Hosted endpoint returned HTTP ${U.status}.${J}
@@ -546,11 +549,11 @@ Could not detect browser opener.
546
549
  `),1}let B="";try{let G=JSON.parse(H);if(G&&typeof G==="object"){let Y=G.url??G.public_url;if(typeof Y==="string")B=Y}}catch{}if(B)process.stdout.write(`${S}Published: ${B}${J}
547
550
  `);else process.stdout.write(`${S}Published to ${X} (HTTP ${U.status}).${J}
548
551
  `),process.stdout.write(`The endpoint did not return a 'url' field; check your endpoint's response.
549
- `);return 0}async function O7($){let Q="",Z=!1,z="--public",X=!1;for(let M of $)if(M==="--yes"||M==="-y")Z=!0;else if(M==="--private")z="";else if(M==="--public")z="--public";else if(M==="--hosted")X=!0;else if(M.startsWith("-"))return process.stderr.write(`${T}Unknown option: ${M}${J}
552
+ `);return 0}async function _7($){let Q="",Z=!1,z="--public",X=!1;for(let M of $)if(M==="--yes"||M==="-y")Z=!0;else if(M==="--private")z="";else if(M==="--public")z="--public";else if(M==="--hosted")X=!0;else if(M.startsWith("-"))return process.stderr.write(`${T}Unknown option: ${M}${J}
550
553
  `),1;else Q=M;if(!Q)return process.stderr.write(`${T}Missing proof id.${J} Use 'loki proof list'.
551
554
  `),2;let q=n(M$(),Q,"index.html");if(!q$(q))return process.stderr.write(`${T}Proof page not found: ${Q}/index.html${J}
552
555
  `),process.stderr.write(`Use 'loki proof list' to see available proofs.
553
- `),1;if(X)return T7(Q,q,n(M$(),Q,"proof.json"));if((await F(["gh","--version"],{timeoutMs:5000})).exitCode!==0)return process.stderr.write(`${T}gh CLI not found${J}
556
+ `),1;if(X)return w7(Q,q,n(M$(),Q,"proof.json"));if((await F(["gh","--version"],{timeoutMs:5000})).exitCode!==0)return process.stderr.write(`${T}gh CLI not found${J}
554
557
  `),process.stderr.write(`Install the GitHub CLI to publish a proof:
555
558
  `),process.stderr.write(` brew install gh # macOS
556
559
  `),process.stderr.write(` sudo apt install gh # Ubuntu/Debian
@@ -561,25 +564,25 @@ Could not detect browser opener.
561
564
 
562
565
  `),process.stdout.write(`What will be shared:
563
566
  `),process.stdout.write(` - ${q}
564
- `);let U=F1(Q);if(U){let M=p(a(U.cost).usd),R=p(a(U.files_changed).count),N=p(a(U.council).final_verdict),g=a(U.redaction);process.stdout.write(` - cost.usd: ${M}
567
+ `);let U=k1(Q);if(U){let M=p(a(U.cost).usd),R=p(a(U.files_changed).count),N=p(a(U.council).final_verdict),g=a(U.redaction);process.stdout.write(` - cost.usd: ${M}
565
568
  `),process.stdout.write(` - files_changed: ${R}
566
569
  `),process.stdout.write(` - council verdict: ${N}
567
570
  `),process.stdout.write(` - redaction: applied=${p(g.applied)} rules_version=${p(g.rules_version)} redactions_count=${p(g.redactions_count)}
568
571
  `)}if(process.stdout.write(`
569
572
  ${_}Secrets, API keys, tokens, env values, and absolute paths have already been stripped by the generator.${J}
570
573
 
571
- `),!Z){if(!await M7(`Publish this proof to a ${V} gist? [y/N] `))return process.stdout.write(`Aborted. Nothing was published.
572
- `),0}let H=X7(n(V7(),"loki-proof-")),B=n(H,"index.html");K7(q,B),process.stdout.write(`Uploading proof page...
573
- `);let G=`Loki Mode proof-of-run ${Q}`,Y=["gh","gist","create",B,"--desc",G];if(z!=="")Y.push(z);let O=await F(Y,{timeoutMs:60000});try{q7(H,{recursive:!0,force:!0})}catch{}if(O.exitCode!==0)return process.stderr.write(`${T}Failed to create gist${J}
574
+ `),!Z){if(!await A7(`Publish this proof to a ${V} gist? [y/N] `))return process.stdout.write(`Aborted. Nothing was published.
575
+ `),0}let H=J7(n(H7(),"loki-proof-")),B=n(H,"index.html");V7(q,B),process.stdout.write(`Uploading proof page...
576
+ `);let G=`Loki Mode proof-of-run ${Q}`,Y=["gh","gist","create",B,"--desc",G];if(z!=="")Y.push(z);let O=await F(Y,{timeoutMs:60000});try{W7(H,{recursive:!0,force:!0})}catch{}if(O.exitCode!==0)return process.stderr.write(`${T}Failed to create gist${J}
574
577
  `),process.stderr.write(`${O.stdout}${O.stderr}
575
578
  `),1;return process.stdout.write(`${S}Shared: ${O.stdout.trim()}${J}
576
- `),0}async function A7($){if(!$)return process.stderr.write(`${T}Missing proof id.${J} Use 'loki proof list'.
579
+ `),0}async function I7($){if(!$)return process.stderr.write(`${T}Missing proof id.${J} Use 'loki proof list'.
577
580
  `),2;let Q=n(M$(),$,"proof.json");if(!q$(Q))return process.stderr.write(`${T}Proof not found: ${$}${J}
578
581
  `),process.stderr.write(`Use 'loki proof list' to see available proofs.
579
- `),1;let Z=J7(h,"autonomy","lib","proof-verify.py");if(!q$(Z))return process.stderr.write(`${T}Verifier not found (autonomy/lib/proof-verify.py).${J}
580
- `),2;let z=process.env.TARGET_DIR||".",X=await F(["python3",Z,Q,z],{timeoutMs:30000});if(X.stdout)process.stdout.write(X.stdout);if(X.stderr)process.stderr.write(X.stderr);return X.exitCode}async function w7($){let Q=$[0],Z=$.slice(1);if(Q===void 0||Q==="help"||Q==="--help"||Q==="-h")return process.stdout.write(H7),Q===void 0?1:0;switch(Q){case"list":return G7();case"show":return B7(Z[0]);case"verify":return A7(Z[0]);case"open":return Y7(Z[0]);case"share":return O7(Z);default:return process.stderr.write(`${T}Unknown subcommand: ${Q}${J}
582
+ `),1;let Z=U7(h,"autonomy","lib","proof-verify.py");if(!q$(Z))return process.stderr.write(`${T}Verifier not found (autonomy/lib/proof-verify.py).${J}
583
+ `),2;let z=process.env.TARGET_DIR||".",X=await F(["python3",Z,Q,z],{timeoutMs:30000});if(X.stdout)process.stdout.write(X.stdout);if(X.stderr)process.stderr.write(X.stderr);return X.exitCode}async function L7($){let Q=$[0],Z=$.slice(1);if(Q===void 0||Q==="help"||Q==="--help"||Q==="-h")return process.stdout.write(Y7),Q===void 0?1:0;switch(Q){case"list":return M7();case"show":return T7(Z[0]);case"verify":return I7(Z[0]);case"open":return O7(Z[0]);case"share":return _7(Z);default:return process.stderr.write(`${T}Unknown subcommand: ${Q}${J}
581
584
  `),process.stderr.write(`Run 'loki proof --help' for usage.
582
- `),1}}var H7;var PQ=L(()=>{C();d();c();_Q();H7=`${k}loki proof${J} - inspect and share proof-of-run artifacts
585
+ `),1}}var Y7;var jQ=L(()=>{C();d();c();IQ();Y7=`${k}loki proof${J} - inspect and share proof-of-run artifacts
583
586
 
584
587
  Usage: loki proof <subcommand> [args]
585
588
 
@@ -596,31 +599,31 @@ Options for 'share':
596
599
  --hosted Publish to LOKI_HOSTED_ENDPOINT (open-core seam; no official backend yet)
597
600
 
598
601
  Proofs are generated automatically at run completion (LOKI_PROOF=0 to opt out).
599
- `});var EQ={};b(EQ,{runCrash:()=>x7});import{existsSync as FQ,readdirSync as _7,readFileSync as I7}from"fs";import{join as kQ}from"path";function k$($){return $===void 0||$===null?"-":String($)}function l$($,Q){return $.length>=Q?$:$+" ".repeat(Q-$.length)}function RQ(){return kQ(P(),"crash")}function k1(){let $=RQ();if(!FQ($))return[];try{return _7($,{withFileTypes:!0}).filter((Q)=>Q.isFile()&&Q.name.endsWith(".json")).map((Q)=>Q.name.slice(0,-5)).sort()}catch{return[]}}function P7($){if($.length===0)return!1;if($.includes("/")||$.includes("\\"))return!1;if($.includes(".."))return!1;return!0}function d$($){if(!P7($))return null;let Q=kQ(RQ(),`${$}.json`);if(!FQ(Q))return null;try{return JSON.parse(I7(Q,"utf8"))}catch{return{}}}function j7(){let $=k1();if($.length===0)return process.stdout.write(`${_}No crash reports found.${J} Nothing has been captured in .loki/crash/.
602
+ `});var NQ={};b(NQ,{runCrash:()=>S7});import{existsSync as kQ,readdirSync as P7,readFileSync as j7}from"fs";import{join as RQ}from"path";function k$($){return $===void 0||$===null?"-":String($)}function l$($,Q){return $.length>=Q?$:$+" ".repeat(Q-$.length)}function EQ(){return RQ(P(),"crash")}function R1(){let $=EQ();if(!kQ($))return[];try{return P7($,{withFileTypes:!0}).filter((Q)=>Q.isFile()&&Q.name.endsWith(".json")).map((Q)=>Q.name.slice(0,-5)).sort()}catch{return[]}}function k7($){if($.length===0)return!1;if($.includes("/")||$.includes("\\"))return!1;if($.includes(".."))return!1;return!0}function d$($){if(!k7($))return null;let Q=RQ(EQ(),`${$}.json`);if(!kQ(Q))return null;try{return JSON.parse(j7(Q,"utf8"))}catch{return{}}}function R7(){let $=R1();if($.length===0)return process.stdout.write(`${_}No crash reports found.${J} Nothing has been captured in .loki/crash/.
600
603
  `),0;process.stdout.write(`${l$("ID",40)} ${l$("CAPTURED_AT",22)} ERROR_CLASS
601
604
  `);for(let Q of $){let Z=d$(Q)??{},z=k$(Z.fingerprint),X=k$(Z.captured_at),q=k$(Z.error_class),K=z!=="-"?z:Q;process.stdout.write(`${l$(K,40)} ${l$(X,22)} ${q}
602
605
  `)}return process.stdout.write(`
603
606
  ${$.length} report(s). Run 'loki crash show <id>' to inspect, 'loki crash submit' to get a prefilled GitHub issue URL.
604
- `),0}function xQ($){let Q=d$($);if(Q!==null)return{id:$,report:Q};for(let Z of k1()){let z=d$(Z);if(z&&String(z.fingerprint??"")===$)return{id:Z,report:z}}return null}function F7($){if(!$)return process.stderr.write(`${T}Missing crash id.${J} Use 'loki crash' to list reports.
607
+ `),0}function xQ($){let Q=d$($);if(Q!==null)return{id:$,report:Q};for(let Z of R1()){let z=d$(Z);if(z&&String(z.fingerprint??"")===$)return{id:Z,report:z}}return null}function E7($){if(!$)return process.stderr.write(`${T}Missing crash id.${J} Use 'loki crash' to list reports.
605
608
  `),2;let Q=xQ($);if(Q===null)return process.stderr.write(`${T}Crash report not found: ${$}${J}
606
609
  `),process.stderr.write(`Use 'loki crash' to see available reports.
607
610
  `),1;return process.stdout.write(`${JSON.stringify(Q.report,null,2)}
608
- `),0}function k7($){let Q=k$($.error_class),Z=k$($.fingerprint),z=Z!=="-"?Z.slice(0,12):"unknown",X=`crash: ${Q} (${z})`,K=["Anonymous crash report captured by Loki Mode (scrubbed, whitelist-only).","","Scrubbed payload:","```json",JSON.stringify($,null,2),"```","","Nothing was sent automatically. This issue is submitted manually by me."].join(`
609
- `),W=new URLSearchParams({title:X,body:K});return`${L7}?${W.toString()}`}function R7($){let Q;if($){if(Q=xQ($),Q===null)return process.stderr.write(`${T}Crash report not found: ${$}${J}
611
+ `),0}function x7($){let Q=k$($.error_class),Z=k$($.fingerprint),z=Z!=="-"?Z.slice(0,12):"unknown",X=`crash: ${Q} (${z})`,K=["Anonymous crash report captured by Loki Mode (scrubbed, whitelist-only).","","Scrubbed payload:","```json",JSON.stringify($,null,2),"```","","Nothing was sent automatically. This issue is submitted manually by me."].join(`
612
+ `),W=new URLSearchParams({title:X,body:K});return`${F7}?${W.toString()}`}function N7($){let Q;if($){if(Q=xQ($),Q===null)return process.stderr.write(`${T}Crash report not found: ${$}${J}
610
613
  `),process.stderr.write(`Use 'loki crash' to see available reports.
611
- `),1}else{let Z=k1();if(Z.length===0)return process.stdout.write(`${_}No crash reports found.${J} Nothing to submit.
614
+ `),1}else{let Z=R1();if(Z.length===0)return process.stdout.write(`${_}No crash reports found.${J} Nothing to submit.
612
615
  `),0;let z=Z[Z.length-1],X=d$(z)??{};Q={id:z,report:X}}return process.stdout.write(`${k}Scrubbed payload (this is the ENTIRE report):${J}
613
616
  `),process.stdout.write(`${JSON.stringify(Q.report,null,2)}
614
617
 
615
618
  `),process.stdout.write(`${_}Nothing is sent automatically in this version.${J} Loki Mode never transmits crash data on its own.
616
619
  `),process.stdout.write(`To submit manually, open this prefilled GitHub issue and review it first:
617
620
 
618
- `),process.stdout.write(` ${I}${k7(Q.report)}${J}
621
+ `),process.stdout.write(` ${I}${x7(Q.report)}${J}
619
622
 
620
623
  `),process.stdout.write(`${S}The payload above is exactly what the URL contains.${J}
621
624
  `),process.stdout.write(`See docs/PRIVACY.md for what is and is not collected.
622
- `),0}async function x7($){let Q=$[0];switch(Q){case void 0:case"list":return j7();case"--help":case"-h":case"help":return process.stdout.write(jQ),0;case"show":return F7($[1]);case"submit":return R7($[1]);default:return process.stderr.write(`${T}Unknown crash subcommand: ${Q}${J}
623
- `),process.stdout.write(jQ),2}}var L7="https://github.com/asklokesh/loki-mode/issues/new",jQ;var NQ=L(()=>{C();c();jQ=`${k}loki crash${J} - inspect and manually submit local crash reports
625
+ `),0}async function S7($){let Q=$[0];switch(Q){case void 0:case"list":return R7();case"--help":case"-h":case"help":return process.stdout.write(FQ),0;case"show":return E7($[1]);case"submit":return N7($[1]);default:return process.stderr.write(`${T}Unknown crash subcommand: ${Q}${J}
626
+ `),process.stdout.write(FQ),2}}var F7="https://github.com/asklokesh/loki-mode/issues/new",FQ;var SQ=L(()=>{C();c();FQ=`${k}loki crash${J} - inspect and manually submit local crash reports
624
627
 
625
628
  Usage: loki crash [subcommand] [args]
626
629
 
@@ -632,15 +635,15 @@ Subcommands:
632
635
 
633
636
  Crash reports are anonymous, scrubbed, and stored locally only. Nothing is
634
637
  sent automatically in this version. See docs/PRIVACY.md.
635
- `});var bQ={};b(bQ,{runWiki:()=>C7});import{existsSync as R1,readFileSync as SQ}from"fs";import{join as x1,resolve as E7}from"path";function S7(){return x1(process.cwd(),".loki","wiki")}function D7($){let Q="";for(let X of $){if(X==="--help"||X==="-h")return process.stdout.write(`Usage: loki wiki show [section]
638
+ `});var hQ={};b(hQ,{runWiki:()=>y7});import{existsSync as E1,readFileSync as DQ}from"fs";import{join as x1,resolve as D7}from"path";function b7(){return x1(process.cwd(),".loki","wiki")}function h7($){let Q="";for(let X of $){if(X==="--help"||X==="-h")return process.stdout.write(`Usage: loki wiki show [section]
636
639
  Sections: architecture, modules, data-flow
637
640
  `),0;if(X.startsWith("-"))return process.stderr.write(`${T}Unknown option: ${X}${J}
638
- `),1;Q=X}let Z=S7();if(!R1(Z))return process.stderr.write(`${_}No wiki found. Run 'loki wiki generate' first.${J}
639
- `),1;if(Q){if(!N7.has(Q))return process.stderr.write(`${T}No such section: ${Q} (try: architecture, modules, data-flow)${J}
640
- `),1;let X=x1(Z,`${Q}.md`);if(!R1(X))return process.stderr.write(`${T}Section not generated: ${Q}${J}
641
- `),1;return process.stdout.write(SQ(X,"utf8")),0}let z=x1(Z,"index.md");if(!R1(z))return process.stderr.write(`${T}Wiki index not found. Run 'loki wiki generate'.${J}
642
- `),1;return process.stdout.write(SQ(z,"utf8")),0}async function CQ($,Q){let Z=E7(h,"autonomy","loki"),z=3600000,X=Bun.spawn({cmd:[Z,"wiki",$,...Q],stdin:"inherit",stdout:"inherit",stderr:"inherit",env:{...process.env,LOKI_LEGACY_BASH:"1"}}),q=setTimeout(()=>{try{X.kill("SIGKILL")}catch{}},3600000);try{return await X.exited}finally{clearTimeout(q)}}async function C7($){let Q=$[0],Z=$.slice(1);switch(Q){case void 0:case"help":case"--help":case"-h":return process.stdout.write(DQ),0;case"show":return D7(Z);case"generate":return CQ("generate",Z);case"ask":return CQ("ask",Z);default:return process.stderr.write(`${T}Unknown wiki command: ${Q}${J}
643
- `),process.stdout.write(DQ),1}}var DQ,N7;var hQ=L(()=>{C();c();DQ=`${k}loki wiki${J} - Auto-generated, cited codebase wiki + Q&A
641
+ `),1;Q=X}let Z=b7();if(!E1(Z))return process.stderr.write(`${_}No wiki found. Run 'loki wiki generate' first.${J}
642
+ `),1;if(Q){if(!C7.has(Q))return process.stderr.write(`${T}No such section: ${Q} (try: architecture, modules, data-flow)${J}
643
+ `),1;let X=x1(Z,`${Q}.md`);if(!E1(X))return process.stderr.write(`${T}Section not generated: ${Q}${J}
644
+ `),1;return process.stdout.write(DQ(X,"utf8")),0}let z=x1(Z,"index.md");if(!E1(z))return process.stderr.write(`${T}Wiki index not found. Run 'loki wiki generate'.${J}
645
+ `),1;return process.stdout.write(DQ(z,"utf8")),0}async function bQ($,Q){let Z=D7(h,"autonomy","loki"),z=3600000,X=Bun.spawn({cmd:[Z,"wiki",$,...Q],stdin:"inherit",stdout:"inherit",stderr:"inherit",env:{...process.env,LOKI_LEGACY_BASH:"1"}}),q=setTimeout(()=>{try{X.kill("SIGKILL")}catch{}},3600000);try{return await X.exited}finally{clearTimeout(q)}}async function y7($){let Q=$[0],Z=$.slice(1);switch(Q){case void 0:case"help":case"--help":case"-h":return process.stdout.write(CQ),0;case"show":return h7(Z);case"generate":return bQ("generate",Z);case"ask":return bQ("ask",Z);default:return process.stderr.write(`${T}Unknown wiki command: ${Q}${J}
646
+ `),process.stdout.write(CQ),1}}var CQ,C7;var yQ=L(()=>{C();c();CQ=`${k}loki wiki${J} - Auto-generated, cited codebase wiki + Q&A
644
647
 
645
648
  Usage: loki wiki <command> [options]
646
649
 
@@ -656,8 +659,8 @@ Examples:
656
659
  loki wiki generate
657
660
  loki wiki show architecture
658
661
  loki wiki ask "how does the cli dispatch commands"
659
- `,N7=new Set(["architecture","modules","data-flow"])});var N1={};b(N1,{renderFindingsForPrompt:()=>g7,loadPreviousFindings:()=>E1,findLatestReviewDir:()=>fQ,_parseReviewerOutputForTests:()=>m7});import{existsSync as vQ,readFileSync as yQ,readdirSync as gQ,statSync as b7}from"fs";import{join as o$}from"path";function v7($){let Q=$.toLowerCase();if(Q==="critical")return"Critical";if(Q==="high")return"High";if(Q==="medium")return"Medium";return"Low"}function mQ($,Q,Z,z){let X=[],q=$.split(/\r?\n/);for(let K of q){let W=K.trim();if(W.length===0)continue;let V=W.replace(/^[-*]\s*/,""),U=h7.exec(V);if(!U||!U[1]||!U[2])continue;let H=v7(U[1]),B=U[2].trim(),G=y7.exec(B),Y=G&&G[1]?G[1]:null,O=G&&G[2]?Number.parseInt(G[2],10):null;X.push({reviewId:Z,iteration:z,reviewer:Q,severity:H,description:B,file:Y,line:Number.isFinite(O)?O:null,raw:W})}return X}function fQ($,Q){let Z=o$($,"quality","reviews");if(!vQ(Z))return null;let z;try{z=gQ(Z)}catch{return null}let X=Q===void 0?z.filter((W)=>W.startsWith("review-")):z.filter((W)=>W.endsWith(`-${Q}`)&&W.startsWith("review-"));if(X.length===0)return null;X.sort();let q=X[X.length-1];if(!q)return null;let K=o$(Z,q);try{if(!b7(K).isDirectory())return null}catch{return null}return K}function E1($,Q){let Z=fQ($,Q);if(Z===null)return{reviewDir:null,reviewId:null,iteration:null,findings:[]};let z=null,X=null,q=o$(Z,"aggregate.json");if(vQ(q))try{let U=yQ(q,"utf-8"),H=JSON.parse(U);if(typeof H.review_id==="string")z=H.review_id;if(typeof H.iteration==="number")X=H.iteration}catch{}let K;try{K=gQ(Z)}catch{return{reviewDir:Z,reviewId:z,iteration:X,findings:[]}}let W=new Set(["diff.txt","files.txt","anti-sycophancy.txt"]),V=[];for(let U of K){if(!U.endsWith(".txt"))continue;if(W.has(U))continue;if(U.endsWith("-prompt.txt"))continue;let H=U.replace(/\.txt$/,""),B;try{B=yQ(o$(Z,U),"utf-8")}catch{continue}V.push(...mQ(B,H,z??"",X??-1))}return{reviewDir:Z,reviewId:z,iteration:X,findings:V}}function g7($){if($.length===0)return"";let Q=["Critical","High","Medium","Low"],Z=new Map;for(let X of Q)Z.set(X,[]);for(let X of $){let q=Z.get(X.severity);if(q)q.push(X)}let z=[];z.push("PREVIOUS REVIEWER FINDINGS (must address each, or supply counter-evidence in .loki/state/counter-evidence-<iter>.json):");for(let X of Q){let q=Z.get(X)??[];if(q.length===0)continue;z.push(` [${X}] (${q.length}):`);for(let K of q){let W=K.file?` (${K.file}${K.line!==null?":"+K.line:""})`:"";z.push(` - ${K.description}${W} -- via ${K.reviewer}`)}}return z.join(`
660
- `)}function m7($,Q,Z="review-test",z=0){return mQ($,Q,Z,z)}var h7,y7;var n$=L(()=>{h7=/\[(Critical|High|Medium|Low)\]\s*(.+)/i,y7=/([\w.\-/]+\.[a-zA-Z]+):(\d+)/});import{existsSync as f7}from"fs";import{join as u7}from"path";async function uQ($,Q){let Z=u7($,"memory");if(!f7(Z))return{stored:!1,reason:"memory dir not initialized"};let z=Math.max(0,Math.floor(Q.durationSeconds??0)),X={_LOKI_PROJECT_DIR:h,_LOKI_TARGET_DIR:process.cwd(),_LOKI_TASK_ID:Q.taskId,_LOKI_OUTCOME:Q.outcome,_LOKI_PHASE:Q.phase,_LOKI_GOAL:Q.goal,_LOKI_DURATION:String(z),_LOKI_LOKI_DIR:$},K=await z$(`
662
+ `,C7=new Set(["architecture","modules","data-flow"])});var S1={};b(S1,{renderFindingsForPrompt:()=>u7,loadPreviousFindings:()=>N1,findLatestReviewDir:()=>uQ,_parseReviewerOutputForTests:()=>c7});import{existsSync as gQ,readFileSync as vQ,readdirSync as mQ,statSync as v7}from"fs";import{join as o$}from"path";function f7($){let Q=$.toLowerCase();if(Q==="critical")return"Critical";if(Q==="high")return"High";if(Q==="medium")return"Medium";return"Low"}function fQ($,Q,Z,z){let X=[],q=$.split(/\r?\n/);for(let K of q){let W=K.trim();if(W.length===0)continue;let V=W.replace(/^[-*]\s*/,""),U=g7.exec(V);if(!U||!U[1]||!U[2])continue;let H=f7(U[1]),B=U[2].trim(),G=m7.exec(B),Y=G&&G[1]?G[1]:null,O=G&&G[2]?Number.parseInt(G[2],10):null;X.push({reviewId:Z,iteration:z,reviewer:Q,severity:H,description:B,file:Y,line:Number.isFinite(O)?O:null,raw:W})}return X}function uQ($,Q){let Z=o$($,"quality","reviews");if(!gQ(Z))return null;let z;try{z=mQ(Z)}catch{return null}let X=Q===void 0?z.filter((W)=>W.startsWith("review-")):z.filter((W)=>W.endsWith(`-${Q}`)&&W.startsWith("review-"));if(X.length===0)return null;X.sort();let q=X[X.length-1];if(!q)return null;let K=o$(Z,q);try{if(!v7(K).isDirectory())return null}catch{return null}return K}function N1($,Q){let Z=uQ($,Q);if(Z===null)return{reviewDir:null,reviewId:null,iteration:null,findings:[]};let z=null,X=null,q=o$(Z,"aggregate.json");if(gQ(q))try{let U=vQ(q,"utf-8"),H=JSON.parse(U);if(typeof H.review_id==="string")z=H.review_id;if(typeof H.iteration==="number")X=H.iteration}catch{}let K;try{K=mQ(Z)}catch{return{reviewDir:Z,reviewId:z,iteration:X,findings:[]}}let W=new Set(["diff.txt","files.txt","anti-sycophancy.txt"]),V=[];for(let U of K){if(!U.endsWith(".txt"))continue;if(W.has(U))continue;if(U.endsWith("-prompt.txt"))continue;let H=U.replace(/\.txt$/,""),B;try{B=vQ(o$(Z,U),"utf-8")}catch{continue}V.push(...fQ(B,H,z??"",X??-1))}return{reviewDir:Z,reviewId:z,iteration:X,findings:V}}function u7($){if($.length===0)return"";let Q=["Critical","High","Medium","Low"],Z=new Map;for(let X of Q)Z.set(X,[]);for(let X of $){let q=Z.get(X.severity);if(q)q.push(X)}let z=[];z.push("PREVIOUS REVIEWER FINDINGS (must address each, or supply counter-evidence in .loki/state/counter-evidence-<iter>.json):");for(let X of Q){let q=Z.get(X)??[];if(q.length===0)continue;z.push(` [${X}] (${q.length}):`);for(let K of q){let W=K.file?` (${K.file}${K.line!==null?":"+K.line:""})`:"";z.push(` - ${K.description}${W} -- via ${K.reviewer}`)}}return z.join(`
663
+ `)}function c7($,Q,Z="review-test",z=0){return fQ($,Q,Z,z)}var g7,m7;var n$=L(()=>{g7=/\[(Critical|High|Medium|Low)\]\s*(.+)/i,m7=/([\w.\-/]+\.[a-zA-Z]+):(\d+)/});import{existsSync as p7}from"fs";import{join as l7}from"path";async function cQ($,Q){let Z=l7($,"memory");if(!p7(Z))return{stored:!1,reason:"memory dir not initialized"};let z=Math.max(0,Math.floor(Q.durationSeconds??0)),X={_LOKI_PROJECT_DIR:h,_LOKI_TARGET_DIR:process.cwd(),_LOKI_TASK_ID:Q.taskId,_LOKI_OUTCOME:Q.outcome,_LOKI_PHASE:Q.phase,_LOKI_GOAL:Q.goal,_LOKI_DURATION:String(z),_LOKI_LOKI_DIR:$},K=await z$(`
661
664
  import os, sys
662
665
  project = os.environ.get('_LOKI_PROJECT_DIR', '')
663
666
  loki = os.environ.get('_LOKI_LOKI_DIR', '.loki')
@@ -684,25 +687,25 @@ try:
684
687
  print('OK')
685
688
  except Exception as e:
686
689
  print('ERR:' + str(e))
687
- `,{env:X,timeoutMs:15000});if(K.exitCode===127)return{stored:!1,reason:"python3 not found"};let W=K.stdout.trim();if(W==="OK")return{stored:!0,reason:"stored"};if(W.startsWith("ERR:"))return{stored:!1,reason:W.replace(/^ERR:/,"")};return{stored:!1,reason:K.stderr.trim()||"unknown"}}var cQ=L(()=>{V$();C()});var oQ={};b(oQ,{loadLearnings:()=>S1,appendLearning:()=>R$,appendFromGateFailure:()=>s7});import{existsSync as c7,readFileSync as p7}from"fs";import{join as pQ}from"path";import{createHash as l7}from"crypto";function lQ($){return pQ($,d7)}function o7($){if($===null||typeof $!=="object")return!1;let Q=$;return typeof Q.id==="string"&&typeof Q.timestamp==="string"&&typeof Q.iteration==="number"&&typeof Q.trigger==="string"&&typeof Q.rootCause==="string"&&typeof Q.fix==="string"&&typeof Q.preventInFuture==="string"&&typeof Q.evidence==="object"&&Q.evidence!==null}function dQ($){if(!c7($))return{version:1,learnings:[]};try{let Q=p7($,"utf-8"),Z=JSON.parse(Q);if(Z.version===1&&Array.isArray(Z.learnings))return{version:1,learnings:Z.learnings.filter(o7)}}catch{}return{version:1,learnings:[]}}function n7($,Q,Z){return l7("sha256").update(`${$} ${Q} ${Z??""}`).digest("hex").slice(0,16)}async function R$($,Q,Z={}){let z=n7(Q.trigger,Q.rootCause,Q.evidence.file),X=new Date().toISOString(),q={id:z,timestamp:X,...Q},K=lQ($);if(await i0(K,()=>{j$(K,()=>{let V=dQ(K),U=V.learnings.findIndex((H)=>H.id===z);if(U>=0){let H=V.learnings[U];V.learnings[U]={...H,timestamp:X,iteration:q.iteration}}else V.learnings.push(q);P$(K,V)})}),Z.episodeBridge!==null&&(Z.episodeBridge!==void 0||process.env.LOKI_AUTO_LEARNINGS_EPISODE==="1")){let V=Z.episodeBridge??uQ,U=Z.bridgeFailureLog??a7;try{let H=await V($,{taskId:`learning-${z}`,outcome:"failure",phase:"VERIFY",goal:`${Q.trigger}: ${Q.rootCause}`});if(H&&!H.stored){if(!new Set(["memory dir not initialized","stub"]).has(H.reason))U(`episode_bridge skipped: ${H.reason}`)}}catch(H){U(`episode_bridge threw: ${H.message}`)}}return q}function a7($){process.stderr.write(`[learnings_writer] ${$}
688
- `)}async function s7($,Q,Z,z={}){let X=`[${Z.severity}] ${Z.description}`;return R$($,{iteration:Q,trigger:"gate_failure",rootCause:X,fix:"pending: dev agent must address in next iteration or supply counter-evidence",preventInFuture:"if this finding recurs, lower its severity threshold or add a regression test",evidence:{reviewId:Z.reviewId,file:Z.file??void 0,line:Z.line??void 0,severity:Z.severity,reviewer:Z.reviewer}},z)}function S1($){return dQ(lQ($))}var d7;var a$=L(()=>{F$();cQ();d7=pQ("state","relevant-learnings.json")});var aQ={};b(aQ,{runOverrideCouncil:()=>QZ,recordOverrideOutcome:()=>ZZ,loadCounterEvidence:()=>$Z,canonicalFindingId:()=>s$,DEFAULT_OVERRIDE_JUDGES:()=>nQ});import{existsSync as t7,readFileSync as r7}from"fs";import{join as i7}from"path";function $Z($,Q){let Z=i7($,"state",`counter-evidence-${Q}.json`);if(!t7(Z))return null;try{let z=r7(Z,"utf-8"),X=JSON.parse(z);if(typeof X.iteration!=="number")return null;let q=Array.isArray(X.evidence)?X.evidence:[],K=[];for(let W of q){if(typeof W!=="object"||W===null)continue;let V=W;if(typeof V.findingId!=="string")continue;if(typeof V.claim!=="string")continue;let U=V.proofType;if(typeof U!=="string"||!e7.has(U))continue;let H=U,B=Array.isArray(V.artifacts)?V.artifacts:[];K.push({findingId:V.findingId,claim:V.claim,proofType:H,artifacts:B.filter((G)=>typeof G==="string")})}return{iteration:X.iteration,evidence:K}}catch{return null}}async function QZ($,Q,Z,z={}){let X=z.judges??nQ,q=new Set,K=new Set,W={},V=new Map;for(let H of Q.evidence)V.set(H.findingId,H);let U=new Map;for(let H of $){let B=s$(H);U.set(B,(U.get(B)??0)+1)}for(let H of $){let B=s$(H);if((U.get(B)??0)>1){K.add(B);continue}let G=V.get(B);if(!G){K.add(B);continue}let Y=await Promise.all(X.map((M)=>Z({finding:H,evidence:G,judge:M})));if(W[B]=Y,Y.filter((M)=>M.verdict==="APPROVE_OVERRIDE").length>=2)q.add(B);else K.add(B)}return{approvedFindingIds:q,rejectedFindingIds:K,votes:W}}function s$($){let Q=$.raw.slice(0,80).replace(/\s+/g," ").trim();return`${$.reviewer}::${Q}`}async function ZZ($,Q,Z,z,X={}){let q={episodeBridge:X.episodeBridge===void 0?null:X.episodeBridge};for(let K of z){let W=s$(K);if(Z.approvedFindingIds.has(W))await R$($,{iteration:Q,trigger:"override_approved",rootCause:`[${K.severity}] ${K.description}`,fix:"override council approved counter-evidence; finding lifted",preventInFuture:"if this reviewer/file pair recurs, narrow the reviewer's selector OR add a baseline doc",evidence:{findingId:W,reviewId:K.reviewId,file:K.file??void 0,line:K.line??void 0,severity:K.severity,reviewer:K.reviewer}},q);else if(Z.rejectedFindingIds.has(W))await R$($,{iteration:Q,trigger:"override_rejected",rootCause:`[${K.severity}] ${K.description}`,fix:"override council rejected -- dev agent must fix the finding",preventInFuture:"address this finding in the next iteration",evidence:{findingId:W,reviewId:K.reviewId,file:K.file??void 0,line:K.line??void 0,severity:K.severity,reviewer:K.reviewer}},q)}}var e7,nQ;var sQ=L(()=>{a$();e7=new Set(["file-exists","test-passes","grep-miss","reviewer-misread","duplicate-code-path","out-of-scope"]);nQ=["judge-primary","judge-secondary","judge-tertiary"]});var rQ={};b(rQ,{writeEscalationHandoff:()=>HZ,renderHandoff:()=>tQ,readLatestHandoff:()=>GZ});import{existsSync as zZ,readdirSync as XZ,readFileSync as KZ}from"fs";import{join as t$}from"path";function qZ(){return new Date().toISOString()}function JZ($){let Q=$.file?` (${$.file}${$.line!==null?":"+$.line:""})`:"";return` - [${$.severity}] ${$.description}${Q} -- ${$.reviewer}`}function VZ($){let Q=$.evidence,Z=Q.file?` ${Q.file}${Q.line!==void 0?":"+Q.line:""}`:"";return` - **${$.trigger}** (iter ${$.iteration})${Z}: ${$.rootCause}`}function tQ($,Q,Z){let z=[];if(z.push(`# Loki escalation handoff -- ${qZ()}`),z.push(""),z.push(`Gate **${$.gateName}** has failed ${$.consecutiveFailures} consecutive times at iteration ${$.iteration}.`),z.push(""),z.push(`Reason: ${$.detail}`),z.push(""),Q.length>0){z.push(`## Outstanding findings (${Q.length})`),z.push("");for(let X of Q)z.push(JZ(X));z.push("")}else z.push("## Outstanding findings"),z.push(""),z.push("(no per-finding records captured -- gate failed without populating reviewer outputs)"),z.push("");if(Z.length>0){z.push(`## Recent learnings (${Math.min(Z.length,10)})`),z.push("");for(let X of Z.slice(-10))z.push(VZ(X));z.push("")}return z.push("## What the human must decide"),z.push(""),z.push("- Fix the finding? Address it in the code, then `rm .loki/PAUSE` to resume. A code_review BLOCK is NOT lifted by self-supplied counter-evidence -- the gated agent authors that file, so it cannot self-certify a trust-gate finding away."),z.push('- Override after your own review? You (the operator) are the escape path: review the finding and, if you accept it, `rm .loki/PAUSE` to resume. To direct the agent on resume, `echo "instructions" > .loki/HUMAN_INPUT.md` first.'),z.push("- Disable a gate? Set `LOKI_GATE_<NAME>=false` in env (see skills/quality-gates.md)."),z.push("- Tweak escalation? Set `LOKI_GATE_PAUSE_LIMIT` or `LOKI_GATE_ESCALATE_LIMIT`."),z.push("- Roll back? Switch to `LOKI_LEGACY_BASH=1` and re-run; the bash route does not consult this handoff doc."),z.push(""),z.push("To resume: fix the findings (or, after your own review, accept them), then `rm .loki/PAUSE`."),z.join(`
689
- `)}function UZ($,Q){O1($,Q)}function HZ($,Q,Z={}){let z=Z.findings??E1($,Q.iteration).findings,X=Z.learnings??S1($).learnings,q=tQ(Q,z,X),K=(Z.now?.()??new Date).toISOString().replace(/[-:.]/g,""),W=t$($,"escalations"),V=++WZ,U=t$(W,`handoff-${K}-${process.pid}-${V}-${Q.gateName}.md`);return UZ(U,q),{path:U,bytes:q.length}}function GZ($){let Q=t$($,"escalations");if(!zZ(Q))return null;let Z;try{Z=XZ(Q).filter((q)=>q.endsWith(".md"))}catch{return null}if(Z.length===0)return null;Z.sort();let z=Z[Z.length-1];if(!z)return null;let X=t$(Q,z);try{return{path:X,body:KZ(X,"utf-8")}}catch{return null}}var WZ=0;var iQ=L(()=>{F$();n$();a$()});var $8={};b($8,{runInternalPhase1Hooks:()=>AZ,_resolveForTests:()=>OZ,_internalPhase1HooksHelp:()=>LZ,__testAppendHook:()=>eQ});import{existsSync as BZ,mkdirSync as YZ,readdirSync as MZ,statSync as TZ}from"fs";import{join as x$,resolve as OZ}from"path";async function AZ($){let[Q,...Z]=$;switch(Q){case void 0:case"help":case"--help":case"-h":return process.stdout.write(D1),Q===void 0?1:0;case"reflect":return wZ(Z);case"override":return _Z(Z);case"handoff":return IZ(Z);default:return process.stderr.write(`Unknown subcommand: ${Q}
690
- `),process.stderr.write(D1),2}}async function wZ($){let Q=C1($[0]);if(Q===null)return process.stderr.write(`reflect: missing or invalid <iter>
691
- `),2;let Z=P();try{let X=(await Promise.resolve().then(() => (n$(),N1))).loadPreviousFindings(Z,Q);if(X.findings.length===0)return process.stdout.write(`reflect: no findings for iter ${Q} (nothing to do)
692
- `),0;let q=x$(Z,"state");YZ(q,{recursive:!0}),P$(x$(q,`findings-${Q}.json`),{review_id:X.reviewId,iteration:Q,findings:X.findings});let K=await Promise.resolve().then(() => (a$(),oQ)),W=0,V=0;if(process.env.LOKI_AUTO_LEARNINGS!=="0"){let H=X.findings.filter((G)=>G.severity==="Critical"||G.severity==="High"),B=eQ.fn??K.appendFromGateFailure;for(let G of H)try{await B(Z,Q,G,{episodeBridge:null}),W+=1}catch(Y){V+=1,process.stderr.write(`reflect: learning append failed for finding ${G.reviewer}/${G.severity}: ${Y.message}
690
+ `,{env:X,timeoutMs:15000});if(K.exitCode===127)return{stored:!1,reason:"python3 not found"};let W=K.stdout.trim();if(W==="OK")return{stored:!0,reason:"stored"};if(W.startsWith("ERR:"))return{stored:!1,reason:W.replace(/^ERR:/,"")};return{stored:!1,reason:K.stderr.trim()||"unknown"}}var pQ=L(()=>{V$();C()});var nQ={};b(nQ,{loadLearnings:()=>D1,appendLearning:()=>R$,appendFromGateFailure:()=>i7});import{existsSync as d7,readFileSync as o7}from"fs";import{join as lQ}from"path";import{createHash as n7}from"crypto";function dQ($){return lQ($,a7)}function s7($){if($===null||typeof $!=="object")return!1;let Q=$;return typeof Q.id==="string"&&typeof Q.timestamp==="string"&&typeof Q.iteration==="number"&&typeof Q.trigger==="string"&&typeof Q.rootCause==="string"&&typeof Q.fix==="string"&&typeof Q.preventInFuture==="string"&&typeof Q.evidence==="object"&&Q.evidence!==null}function oQ($){if(!d7($))return{version:1,learnings:[]};try{let Q=o7($,"utf-8"),Z=JSON.parse(Q);if(Z.version===1&&Array.isArray(Z.learnings))return{version:1,learnings:Z.learnings.filter(s7)}}catch{}return{version:1,learnings:[]}}function r7($,Q,Z){return n7("sha256").update(`${$} ${Q} ${Z??""}`).digest("hex").slice(0,16)}async function R$($,Q,Z={}){let z=r7(Q.trigger,Q.rootCause,Q.evidence.file),X=new Date().toISOString(),q={id:z,timestamp:X,...Q},K=dQ($);if(await e0(K,()=>{j$(K,()=>{let V=oQ(K),U=V.learnings.findIndex((H)=>H.id===z);if(U>=0){let H=V.learnings[U];V.learnings[U]={...H,timestamp:X,iteration:q.iteration}}else V.learnings.push(q);P$(K,V)})}),Z.episodeBridge!==null&&(Z.episodeBridge!==void 0||process.env.LOKI_AUTO_LEARNINGS_EPISODE==="1")){let V=Z.episodeBridge??cQ,U=Z.bridgeFailureLog??t7;try{let H=await V($,{taskId:`learning-${z}`,outcome:"failure",phase:"VERIFY",goal:`${Q.trigger}: ${Q.rootCause}`});if(H&&!H.stored){if(!new Set(["memory dir not initialized","stub"]).has(H.reason))U(`episode_bridge skipped: ${H.reason}`)}}catch(H){U(`episode_bridge threw: ${H.message}`)}}return q}function t7($){process.stderr.write(`[learnings_writer] ${$}
691
+ `)}async function i7($,Q,Z,z={}){let X=`[${Z.severity}] ${Z.description}`;return R$($,{iteration:Q,trigger:"gate_failure",rootCause:X,fix:"pending: dev agent must address in next iteration or supply counter-evidence",preventInFuture:"if this finding recurs, lower its severity threshold or add a regression test",evidence:{reviewId:Z.reviewId,file:Z.file??void 0,line:Z.line??void 0,severity:Z.severity,reviewer:Z.reviewer}},z)}function D1($){return oQ(dQ($))}var a7;var a$=L(()=>{F$();pQ();a7=lQ("state","relevant-learnings.json")});var sQ={};b(sQ,{runOverrideCouncil:()=>XZ,recordOverrideOutcome:()=>KZ,loadCounterEvidence:()=>zZ,canonicalFindingId:()=>s$,DEFAULT_OVERRIDE_JUDGES:()=>aQ});import{existsSync as e7,readFileSync as $Z}from"fs";import{join as QZ}from"path";function zZ($,Q){let Z=QZ($,"state",`counter-evidence-${Q}.json`);if(!e7(Z))return null;try{let z=$Z(Z,"utf-8"),X=JSON.parse(z);if(typeof X.iteration!=="number")return null;let q=Array.isArray(X.evidence)?X.evidence:[],K=[];for(let W of q){if(typeof W!=="object"||W===null)continue;let V=W;if(typeof V.findingId!=="string")continue;if(typeof V.claim!=="string")continue;let U=V.proofType;if(typeof U!=="string"||!ZZ.has(U))continue;let H=U,B=Array.isArray(V.artifacts)?V.artifacts:[];K.push({findingId:V.findingId,claim:V.claim,proofType:H,artifacts:B.filter((G)=>typeof G==="string")})}return{iteration:X.iteration,evidence:K}}catch{return null}}async function XZ($,Q,Z,z={}){let X=z.judges??aQ,q=new Set,K=new Set,W={},V=new Map;for(let H of Q.evidence)V.set(H.findingId,H);let U=new Map;for(let H of $){let B=s$(H);U.set(B,(U.get(B)??0)+1)}for(let H of $){let B=s$(H);if((U.get(B)??0)>1){K.add(B);continue}let G=V.get(B);if(!G){K.add(B);continue}let Y=await Promise.all(X.map((M)=>Z({finding:H,evidence:G,judge:M})));if(W[B]=Y,Y.filter((M)=>M.verdict==="APPROVE_OVERRIDE").length>=2)q.add(B);else K.add(B)}return{approvedFindingIds:q,rejectedFindingIds:K,votes:W}}function s$($){let Q=$.raw.slice(0,80).replace(/\s+/g," ").trim();return`${$.reviewer}::${Q}`}async function KZ($,Q,Z,z,X={}){let q={episodeBridge:X.episodeBridge===void 0?null:X.episodeBridge};for(let K of z){let W=s$(K);if(Z.approvedFindingIds.has(W))await R$($,{iteration:Q,trigger:"override_approved",rootCause:`[${K.severity}] ${K.description}`,fix:"override council approved counter-evidence; finding lifted",preventInFuture:"if this reviewer/file pair recurs, narrow the reviewer's selector OR add a baseline doc",evidence:{findingId:W,reviewId:K.reviewId,file:K.file??void 0,line:K.line??void 0,severity:K.severity,reviewer:K.reviewer}},q);else if(Z.rejectedFindingIds.has(W))await R$($,{iteration:Q,trigger:"override_rejected",rootCause:`[${K.severity}] ${K.description}`,fix:"override council rejected -- dev agent must fix the finding",preventInFuture:"address this finding in the next iteration",evidence:{findingId:W,reviewId:K.reviewId,file:K.file??void 0,line:K.line??void 0,severity:K.severity,reviewer:K.reviewer}},q)}}var ZZ,aQ;var rQ=L(()=>{a$();ZZ=new Set(["file-exists","test-passes","grep-miss","reviewer-misread","duplicate-code-path","out-of-scope"]);aQ=["judge-primary","judge-secondary","judge-tertiary"]});var iQ={};b(iQ,{writeEscalationHandoff:()=>YZ,renderHandoff:()=>tQ,readLatestHandoff:()=>MZ});import{existsSync as qZ,readdirSync as JZ,readFileSync as VZ}from"fs";import{join as r$}from"path";function WZ(){return new Date().toISOString()}function UZ($){let Q=$.file?` (${$.file}${$.line!==null?":"+$.line:""})`:"";return` - [${$.severity}] ${$.description}${Q} -- ${$.reviewer}`}function HZ($){let Q=$.evidence,Z=Q.file?` ${Q.file}${Q.line!==void 0?":"+Q.line:""}`:"";return` - **${$.trigger}** (iter ${$.iteration})${Z}: ${$.rootCause}`}function tQ($,Q,Z){let z=[];if(z.push(`# Loki escalation handoff -- ${WZ()}`),z.push(""),z.push(`Gate **${$.gateName}** has failed ${$.consecutiveFailures} consecutive times at iteration ${$.iteration}.`),z.push(""),z.push(`Reason: ${$.detail}`),z.push(""),Q.length>0){z.push(`## Outstanding findings (${Q.length})`),z.push("");for(let X of Q)z.push(UZ(X));z.push("")}else z.push("## Outstanding findings"),z.push(""),z.push("(no per-finding records captured -- gate failed without populating reviewer outputs)"),z.push("");if(Z.length>0){z.push(`## Recent learnings (${Math.min(Z.length,10)})`),z.push("");for(let X of Z.slice(-10))z.push(HZ(X));z.push("")}return z.push("## What the human must decide"),z.push(""),z.push("- Fix the finding? Address it in the code, then `rm .loki/PAUSE` to resume. A code_review BLOCK is NOT lifted by self-supplied counter-evidence -- the gated agent authors that file, so it cannot self-certify a trust-gate finding away."),z.push('- Override after your own review? You (the operator) are the escape path: review the finding and, if you accept it, `rm .loki/PAUSE` to resume. To direct the agent on resume, `echo "instructions" > .loki/HUMAN_INPUT.md` first.'),z.push("- Disable a gate? Set `LOKI_GATE_<NAME>=false` in env (see skills/quality-gates.md)."),z.push("- Tweak escalation? Set `LOKI_GATE_PAUSE_LIMIT` or `LOKI_GATE_ESCALATE_LIMIT`."),z.push("- Roll back? Switch to `LOKI_LEGACY_BASH=1` and re-run; the bash route does not consult this handoff doc."),z.push(""),z.push("To resume: fix the findings (or, after your own review, accept them), then `rm .loki/PAUSE`."),z.join(`
692
+ `)}function BZ($,Q){A1($,Q)}function YZ($,Q,Z={}){let z=Z.findings??N1($,Q.iteration).findings,X=Z.learnings??D1($).learnings,q=tQ(Q,z,X),K=(Z.now?.()??new Date).toISOString().replace(/[-:.]/g,""),W=r$($,"escalations"),V=++GZ,U=r$(W,`handoff-${K}-${process.pid}-${V}-${Q.gateName}.md`);return BZ(U,q),{path:U,bytes:q.length}}function MZ($){let Q=r$($,"escalations");if(!qZ(Q))return null;let Z;try{Z=JZ(Q).filter((q)=>q.endsWith(".md"))}catch{return null}if(Z.length===0)return null;Z.sort();let z=Z[Z.length-1];if(!z)return null;let X=r$(Q,z);try{return{path:X,body:VZ(X,"utf-8")}}catch{return null}}var GZ=0;var eQ=L(()=>{F$();n$();a$()});var Q8={};b(Q8,{runInternalPhase1Hooks:()=>IZ,_resolveForTests:()=>_Z,_internalPhase1HooksHelp:()=>FZ,__testAppendHook:()=>$8});import{existsSync as TZ,mkdirSync as OZ,readdirSync as AZ,statSync as wZ}from"fs";import{join as E$,resolve as _Z}from"path";async function IZ($){let[Q,...Z]=$;switch(Q){case void 0:case"help":case"--help":case"-h":return process.stdout.write(C1),Q===void 0?1:0;case"reflect":return LZ(Z);case"override":return PZ(Z);case"handoff":return jZ(Z);default:return process.stderr.write(`Unknown subcommand: ${Q}
693
+ `),process.stderr.write(C1),2}}async function LZ($){let Q=b1($[0]);if(Q===null)return process.stderr.write(`reflect: missing or invalid <iter>
694
+ `),2;let Z=P();try{let X=(await Promise.resolve().then(() => (n$(),S1))).loadPreviousFindings(Z,Q);if(X.findings.length===0)return process.stdout.write(`reflect: no findings for iter ${Q} (nothing to do)
695
+ `),0;let q=E$(Z,"state");OZ(q,{recursive:!0}),P$(E$(q,`findings-${Q}.json`),{review_id:X.reviewId,iteration:Q,findings:X.findings});let K=await Promise.resolve().then(() => (a$(),nQ)),W=0,V=0;if(process.env.LOKI_AUTO_LEARNINGS!=="0"){let H=X.findings.filter((G)=>G.severity==="Critical"||G.severity==="High"),B=$8.fn??K.appendFromGateFailure;for(let G of H)try{await B(Z,Q,G,{episodeBridge:null}),W+=1}catch(Y){V+=1,process.stderr.write(`reflect: learning append failed for finding ${G.reviewer}/${G.severity}: ${Y.message}
693
696
  `)}if(V>0&&W===0)return process.stderr.write(`reflect: all ${V} learning appends failed (iter ${Q})
694
697
  `),1}let U=V>0?` (${V} failed)`:"";return process.stdout.write(`reflect: persisted ${X.findings.length} findings + ${W} learnings${U} (iter ${Q})
695
698
  `),0}catch(z){return process.stderr.write(`reflect: ${z.message}
696
- `),1}}async function _Z($){let Q=C1($[0]);if(Q===null)return process.stderr.write(`override: missing or invalid <iter>
697
- `),2;let Z=P();try{let z=await Promise.resolve().then(() => (sQ(),aQ)),X=z.loadCounterEvidence(Z,Q);if(X===null||X.evidence.length===0)return process.stdout.write(`override: no counter-evidence for iter ${Q} (skip)
698
- `),0;let K=(await Promise.resolve().then(() => (n$(),N1))).loadPreviousFindings(Z,Q),W=K.findings.filter((O)=>O.severity==="Critical"||O.severity==="High");if(W.length===0)return process.stdout.write(`override: no blocking findings for iter ${Q} (skip)
699
- `),0;let V=async(O)=>{return{judge:O.judge,verdict:"REJECT_OVERRIDE",reasoning:`[stub] proofType=${O.evidence.proofType}: self-supplied counter-evidence cannot lift a trust-gate BLOCK on the agent-authored route. Fix the finding, or use the human-escape path (rm .loki/PAUSE; optionally .loki/HUMAN_INPUT.md). The only adjudicated override is the Bun-route real-LLM judge.`}},U=await z.runOverrideCouncil(W,X,V);await z.recordOverrideOutcome(Z,Q,U,W);let H=x$(Z,"quality","reviews");if(BZ(H))try{let O=MZ(H).filter((R)=>R.startsWith("review-")).sort(),M=O[O.length-1];if(M&&TZ(x$(H,M)).isDirectory())P$(x$(H,M,`override-${Q}.json`),{review_id:K.reviewId,iteration:Q,approved_finding_ids:Array.from(U.approvedFindingIds),rejected_finding_ids:Array.from(U.rejectedFindingIds),votes:U.votes})}catch{}let B=U.approvedFindingIds.size,G=U.rejectedFindingIds.size;if(G===0&&B>0)process.stdout.write(`override: LIFTED -- ${B} approved, ${G} rejected
699
+ `),1}}async function PZ($){let Q=b1($[0]);if(Q===null)return process.stderr.write(`override: missing or invalid <iter>
700
+ `),2;let Z=P();try{let z=await Promise.resolve().then(() => (rQ(),sQ)),X=z.loadCounterEvidence(Z,Q);if(X===null||X.evidence.length===0)return process.stdout.write(`override: no counter-evidence for iter ${Q} (skip)
701
+ `),0;let K=(await Promise.resolve().then(() => (n$(),S1))).loadPreviousFindings(Z,Q),W=K.findings.filter((O)=>O.severity==="Critical"||O.severity==="High");if(W.length===0)return process.stdout.write(`override: no blocking findings for iter ${Q} (skip)
702
+ `),0;let V=async(O)=>{return{judge:O.judge,verdict:"REJECT_OVERRIDE",reasoning:`[stub] proofType=${O.evidence.proofType}: self-supplied counter-evidence cannot lift a trust-gate BLOCK on the agent-authored route. Fix the finding, or use the human-escape path (rm .loki/PAUSE; optionally .loki/HUMAN_INPUT.md). The only adjudicated override is the Bun-route real-LLM judge.`}},U=await z.runOverrideCouncil(W,X,V);await z.recordOverrideOutcome(Z,Q,U,W);let H=E$(Z,"quality","reviews");if(TZ(H))try{let O=AZ(H).filter((R)=>R.startsWith("review-")).sort(),M=O[O.length-1];if(M&&wZ(E$(H,M)).isDirectory())P$(E$(H,M,`override-${Q}.json`),{review_id:K.reviewId,iteration:Q,approved_finding_ids:Array.from(U.approvedFindingIds),rejected_finding_ids:Array.from(U.rejectedFindingIds),votes:U.votes})}catch{}let B=U.approvedFindingIds.size,G=U.rejectedFindingIds.size;if(G===0&&B>0)process.stdout.write(`override: LIFTED -- ${B} approved, ${G} rejected
700
703
  `);else process.stdout.write(`override: BLOCKED -- ${B} approved, ${G} rejected
701
704
  `);return 0}catch(z){return process.stderr.write(`override: ${z.message}
702
- `),1}}async function IZ($){let Q=$[0],Z=Number.parseInt($[1]??"0",10),z=C1($[2]);if(!Q||!Number.isFinite(Z)||z===null)return process.stderr.write(`handoff: usage: handoff <gate> <consecutive-failures> <iter>
703
- `),2;let X=P();try{let K=(await Promise.resolve().then(() => (iQ(),rQ))).writeEscalationHandoff(X,{gateName:Q,iteration:z,consecutiveFailures:Z,detail:`${Q} hit PAUSE_LIMIT (${Z} consecutive failures)`});return process.stdout.write(`handoff: wrote ${K.path} (${K.bytes}B)
705
+ `),1}}async function jZ($){let Q=$[0],Z=Number.parseInt($[1]??"0",10),z=b1($[2]);if(!Q||!Number.isFinite(Z)||z===null)return process.stderr.write(`handoff: usage: handoff <gate> <consecutive-failures> <iter>
706
+ `),2;let X=P();try{let K=(await Promise.resolve().then(() => (eQ(),iQ))).writeEscalationHandoff(X,{gateName:Q,iteration:z,consecutiveFailures:Z,detail:`${Q} hit PAUSE_LIMIT (${Z} consecutive failures)`});return process.stdout.write(`handoff: wrote ${K.path} (${K.bytes}B)
704
707
  `),0}catch(q){return process.stderr.write(`handoff: ${q.message}
705
- `),1}}function C1($){if($===void 0)return null;let Q=Number.parseInt($,10);return Number.isFinite(Q)&&Q>=0?Q:null}var eQ,D1=`loki internal phase1-hooks <subcommand>
708
+ `),1}}function b1($){if($===void 0)return null;let Q=Number.parseInt($,10);return Number.isFinite(Q)&&Q>=0?Q:null}var $8,C1=`loki internal phase1-hooks <subcommand>
706
709
 
707
710
  Subcommands:
708
711
  reflect <iter> Persist structured findings + auto-learnings.
@@ -711,9 +714,9 @@ Subcommands:
711
714
 
712
715
  This command is invoked by autonomy/run.sh between iterations. Users
713
716
  should not run it directly -- run \`loki start\` instead.
714
- `,LZ;var Q8=L(()=>{C();F$();eQ={fn:null};LZ=D1});$1();C();import{mkdirSync as B8,readFileSync as Y8,writeFileSync as M8}from"fs";import{dirname as T8,resolve as O8}from"path";var A8="https://registry.npmjs.org/loki-mode/latest",w8=86400000,_8=1500;function I8(){return O8(T$(),"cache","update-check.json")}function O$($){let Q=/^(\d+)\.(\d+)\.(\d+)$/.exec($.trim());if(!Q)return null;return[Number(Q[1]),Number(Q[2]),Number(Q[3])]}function L8($,Q){let Z=O$($),z=O$(Q);if(!Z||!z)return!1;let[X,q,K]=Z,[W,V,U]=z;if(X!==W)return X>W;if(q!==V)return q>V;return K>U}function P8(){if(process.env.LOKI_NO_UPDATE_CHECK==="1")return!0;if(process.env.CI)return!0;if(!process.stdout.isTTY)return!0;return!1}function j8($){try{let Q=Y8($,"utf-8"),Z=JSON.parse(Q);if(typeof Z.checkedAt==="number"&&typeof Z.latest==="string"&&O$(Z.latest)!==null)return{checkedAt:Z.checkedAt,latest:Z.latest}}catch{}return null}function F8($,Q){try{B8(T8($),{recursive:!0}),M8($,JSON.stringify(Q),"utf-8")}catch{}}async function k8(){try{let $=await fetch(A8,{signal:AbortSignal.timeout(_8),headers:{accept:"application/json"}});if(!$.ok)return null;let Q=await $.json();if(typeof Q.version==="string"&&O$(Q.version)!==null)return Q.version}catch{}return null}async function R8($=Date.now(),Q=k8,Z=I8()){let z=j8(Z);if(z&&$-z.checkedAt<w8)return z.latest;let X=await Q();if(X===null)return null;return F8(Z,{checkedAt:$,latest:X}),X}async function v1($,Q={}){try{if(P8())return;if(O$($)===null)return;let Z=await R8(Q.now,Q.fetcher,Q.cacheFile);if(Z===null)return;if(!L8(Z,$))return;(Q.write??((X)=>process.stderr.write(X)))(`A newer Loki Mode is available: ${Z} (you have ${$}). Update: bun install -g loki-mode (or npm i -g loki-mode)
715
- `)}catch{}}async function g1(){let $=N$();return process.stdout.write(`Loki Mode v${$}
716
- `),await v1($),0}d();c();C();import{readFileSync as D8,existsSync as C8}from"fs";import{resolve as b8}from"path";var h8=["claude","codex","cline","aider"];function c1(){let $=b8(P(),"state","provider");if(!C8($))return"";try{return D8($,"utf-8").trim()}catch{return""}}function y8($,Q){return $||Q||process.env.LOKI_PROVIDER||"claude"}function v8($){let Q=c1(),Z=y8($,Q);switch(process.stdout.write(`${k}Current Provider${J}
717
+ `,FZ;var Z8=L(()=>{C();F$();$8={fn:null};FZ=C1});$1();C();import{mkdirSync as Y8,readFileSync as M8,writeFileSync as T8}from"fs";import{dirname as O8,resolve as A8}from"path";var w8="https://registry.npmjs.org/loki-mode/latest",_8=86400000,I8=1500;function L8(){return A8(T$(),"cache","update-check.json")}function O$($){let Q=/^(\d+)\.(\d+)\.(\d+)$/.exec($.trim());if(!Q)return null;return[Number(Q[1]),Number(Q[2]),Number(Q[3])]}function P8($,Q){let Z=O$($),z=O$(Q);if(!Z||!z)return!1;let[X,q,K]=Z,[W,V,U]=z;if(X!==W)return X>W;if(q!==V)return q>V;return K>U}function j8(){if(process.env.LOKI_NO_UPDATE_CHECK==="1")return!0;if(process.env.CI)return!0;if(!process.stdout.isTTY)return!0;return!1}function F8($){try{let Q=M8($,"utf-8"),Z=JSON.parse(Q);if(typeof Z.checkedAt==="number"&&typeof Z.latest==="string"&&O$(Z.latest)!==null)return{checkedAt:Z.checkedAt,latest:Z.latest}}catch{}return null}function k8($,Q){try{Y8(O8($),{recursive:!0}),T8($,JSON.stringify(Q),"utf-8")}catch{}}async function R8(){try{let $=await fetch(w8,{signal:AbortSignal.timeout(I8),headers:{accept:"application/json"}});if(!$.ok)return null;let Q=await $.json();if(typeof Q.version==="string"&&O$(Q.version)!==null)return Q.version}catch{}return null}async function E8($=Date.now(),Q=R8,Z=L8()){let z=F8(Z);if(z&&$-z.checkedAt<_8)return z.latest;let X=await Q();if(X===null)return null;return k8(Z,{checkedAt:$,latest:X}),X}async function g1($,Q={}){try{if(j8())return;if(O$($)===null)return;let Z=await E8(Q.now,Q.fetcher,Q.cacheFile);if(Z===null)return;if(!P8(Z,$))return;(Q.write??((X)=>process.stderr.write(X)))(`A newer Loki Mode is available: ${Z} (you have ${$}). Update: bun install -g loki-mode (or npm i -g loki-mode)
718
+ `)}catch{}}async function m1(){let $=N$();return process.stdout.write(`Loki Mode v${$}
719
+ `),await g1($),0}d();c();C();import{readFileSync as C8,existsSync as b8}from"fs";import{resolve as h8}from"path";var y8=["claude","codex","cline","aider"];function p1(){let $=h8(P(),"state","provider");if(!b8($))return"";try{return C8($,"utf-8").trim()}catch{return""}}function v8($,Q){return $||Q||process.env.LOKI_PROVIDER||"claude"}function g8($){let Q=p1(),Z=v8($,Q);switch(process.stdout.write(`${k}Current Provider${J}
717
720
  `),process.stdout.write(`
718
721
  `),process.stdout.write(`${I}Provider:${J} ${Z}
719
722
  `),Z){case"claude":process.stdout.write(`${S}Status:${J} Full features (subagents, parallel, MCP)
@@ -724,12 +727,12 @@ should not run it directly -- run \`loki start\` instead.
724
727
  `);return process.stdout.write(`
725
728
  `),process.stdout.write(`Switch provider: ${I}loki provider set <name>${J}
726
729
  `),process.stdout.write(`Available: ${I}loki provider list${J}
727
- `),0}async function g8(){let Q=c1()||process.env.LOKI_PROVIDER||"claude";process.stdout.write(`${k}Available Providers${J}
730
+ `),0}async function m8(){let Q=p1()||process.env.LOKI_PROVIDER||"claude";process.stdout.write(`${k}Available Providers${J}
728
731
  `),process.stdout.write(`
729
- `);let Z=await Promise.all(h8.map(async(q)=>[q,await f(q)!==null])),z=new Map;for(let[q,K]of Z)z.set(q,K?`${S}installed${J}`:`${T}not installed${J}`);let X=[["claude","claude - Claude Code (Anthropic) "],["codex","codex - Codex CLI (OpenAI) "],["cline","cline - Cline (multi-provider) "],["aider","aider - Aider (terminal pair prog) "]];for(let[q,K]of X){let W=Q===q?` ${I}(current)${J}`:"";process.stdout.write(` ${K} ${z.get(q)}${W}
732
+ `);let Z=await Promise.all(y8.map(async(q)=>[q,await f(q)!==null])),z=new Map;for(let[q,K]of Z)z.set(q,K?`${S}installed${J}`:`${T}not installed${J}`);let X=[["claude","claude - Claude Code (Anthropic) "],["codex","codex - Codex CLI (OpenAI) "],["cline","cline - Cline (multi-provider) "],["aider","aider - Aider (terminal pair prog) "]];for(let[q,K]of X){let W=Q===q?` ${I}(current)${J}`:"";process.stdout.write(` ${K} ${z.get(q)}${W}
730
733
  `)}return process.stdout.write(`
731
734
  `),process.stdout.write(`Set provider: ${I}loki provider set <name>${J}
732
- `),0}function m8(){return process.stdout.write(`${k}Loki Mode Provider Management${J}
735
+ `),0}function f8(){return process.stdout.write(`${k}Loki Mode Provider Management${J}
733
736
  `),process.stdout.write(`
734
737
  `),process.stdout.write(`Usage: loki provider <command>
735
738
  `),process.stdout.write(`
@@ -747,8 +750,8 @@ should not run it directly -- run \`loki start\` instead.
747
750
  `),process.stdout.write(` loki provider list
748
751
  `),process.stdout.write(` loki provider info codex
749
752
  `),process.stdout.write(` loki provider models
750
- `),0}async function p1($){let Q=$[0]??"show",Z=$.slice(1);switch(Q){case"show":case"current":return v8(Z[0]);case"list":return g8();case"set":case"info":case"models":return f8(["provider",Q,...Z]);default:return m8()}}async function f8($){let{run:Q}=await Promise.resolve().then(() => (d(),u1)),{resolve:Z}=await import("path"),{REPO_ROOT:z}=await Promise.resolve().then(() => (C(),y1)),X=Z(z,"autonomy","loki"),q=await Q([X,...$],{env:{LOKI_LEGACY_BASH:"1"},timeoutMs:3600000});return process.stdout.write(q.stdout),process.stderr.write(q.stderr),q.exitCode}c();C();V$();import{existsSync as l1,readFileSync as c8}from"fs";import{resolve as W$}from"path";import{mkdir as p8}from"fs/promises";var w$=W$(T$(),"learnings");function Z1($){if(!l1($))return 0;try{let Q=c8($,"utf-8"),Z=0;for(let z of Q.split(`
751
- `))if(z.includes('"description"'))Z++;return Z}catch{return 0}}async function l8(){await p8(w$,{recursive:!0});let $=Z1(W$(w$,"patterns.jsonl")),Q=Z1(W$(w$,"mistakes.jsonl")),Z=Z1(W$(w$,"successes.jsonl"));return process.stdout.write(`${k}Cross-Project Learnings${J}
753
+ `),0}async function l1($){let Q=$[0]??"show",Z=$.slice(1);switch(Q){case"show":case"current":return g8(Z[0]);case"list":return m8();case"set":case"info":case"models":return u8(["provider",Q,...Z]);default:return f8()}}async function u8($){let{run:Q}=await Promise.resolve().then(() => (d(),c1)),{resolve:Z}=await import("path"),{REPO_ROOT:z}=await Promise.resolve().then(() => (C(),v1)),X=Z(z,"autonomy","loki"),q=await Q([X,...$],{env:{LOKI_LEGACY_BASH:"1"},timeoutMs:3600000});return process.stdout.write(q.stdout),process.stderr.write(q.stderr),q.exitCode}c();C();V$();import{existsSync as d1,readFileSync as p8}from"fs";import{resolve as W$}from"path";import{mkdir as l8}from"fs/promises";var w$=W$(T$(),"learnings");function Z1($){if(!d1($))return 0;try{let Q=p8($,"utf-8"),Z=0;for(let z of Q.split(`
754
+ `))if(z.includes('"description"'))Z++;return Z}catch{return 0}}async function d8(){await l8(w$,{recursive:!0});let $=Z1(W$(w$,"patterns.jsonl")),Q=Z1(W$(w$,"mistakes.jsonl")),Z=Z1(W$(w$,"successes.jsonl"));return process.stdout.write(`${k}Cross-Project Learnings${J}
752
755
  `),process.stdout.write(`
753
756
  `),process.stdout.write(` Patterns: ${S}${$}${J}
754
757
  `),process.stdout.write(` Mistakes: ${_}${Q}${J}
@@ -757,7 +760,7 @@ should not run it directly -- run \`loki start\` instead.
757
760
  `),process.stdout.write(`Location: ${w$}
758
761
  `),process.stdout.write(`
759
762
  `),process.stdout.write(`Use 'loki memory show <type>' to view entries
760
- `),0}async function d8($){if($){let z=`
763
+ `),0}async function o8($){if($){let z=`
761
764
  try:
762
765
  from memory.layers import IndexLayer
763
766
  layer = IndexLayer('.loki/memory')
@@ -767,12 +770,12 @@ except ImportError:
767
770
  print('Error: memory.layers module not found')
768
771
  except Exception as e:
769
772
  print(f'Error: {e}')
770
- `.trim(),X=await z$(z,{cwd:h});return process.stdout.write(X.stdout),0}let Q=W$(P(),"memory","index.json");if(!l1(Q))return process.stdout.write(`No index found
773
+ `.trim(),X=await z$(z,{cwd:h});return process.stdout.write(X.stdout),0}let Q=W$(P(),"memory","index.json");if(!d1(Q))return process.stdout.write(`No index found
771
774
  `),0;let Z=await z$(`import json, sys; sys.stdout.write(json.dumps(json.load(open(${JSON.stringify(Q)})), indent=4) + "\\n")`);if(Z.exitCode!==0)return process.stdout.write(`No index found
772
- `),0;return process.stdout.write(Z.stdout),0}async function d1($){switch($[0]??"list"){case"list":case"ls":return l8();case"index":return d8($[1]==="rebuild");default:{let Z=W$(h,"autonomy","loki"),z=3600000,X=Bun.spawn({cmd:[Z,"memory",...$],stdin:"inherit",stdout:"inherit",stderr:"inherit",env:{...process.env,LOKI_LEGACY_BASH:"1"}}),q=setTimeout(()=>{try{X.kill("SIGKILL")}catch{}},3600000);try{return await X.exited}finally{clearTimeout(q)}}}}C();V$();d();import{resolve as o8,join as n8}from"path";import{existsSync as z1,readFileSync as a8}from"fs";import{homedir as s8}from"os";import{spawnSync as s1}from"child_process";var t1=3000;function t8(){let $=(process.env.LOKI_TELEMETRY??"").toLowerCase();if($==="off")return!1;if(process.env.LOKI_TELEMETRY_DISABLED==="true")return!1;if(process.env.DO_NOT_TRACK==="1")return!1;let Q=!1,Z=!1;try{let z=n8(s8(),".loki","config");if(z1(z)){let X=a8(z,"utf8");for(let q of X.split(`
773
- `)){let K=q.replace(/\r$/,"");if(K==="TELEMETRY_DISABLED=true")Q=!0;if(K==="TELEMETRY_ENABLED=true")Z=!0}}}catch{}if(Q)return!1;if($==="on"||Z)return!0;return!1}var S$=!1;function r8(){return o8(h,"autonomy","lib","crash_capture.py")}function i8($,Q){let Z=[$,"--error-class",Q.errorClass,"--message",Q.message];if(Q.stack!==void 0)Z.push("--stack",Q.stack);if(Q.rarvPhase!==void 0)Z.push("--rarv-phase",Q.rarvPhase);if(Q.exitCode!==void 0)Z.push("--exit-code",String(Q.exitCode));if(Q.frictionKind!==void 0)Z.push("--friction-kind",Q.frictionKind);return Z.push("--target-dir",Q.targetDir??process.cwd()),Z}function e8(){if(z1("/opt/homebrew/bin/python3.12"))return"/opt/homebrew/bin/python3.12";for(let Q of["python3.12","python3"])try{let Z=s1("sh",["-c",`command -v ${Q}`],{timeout:t1,encoding:"utf8"});if(Z.status===0){let z=(Z.stdout||"").trim();if(z)return z}}catch{}return null}function o1($){try{if(!t8())return;let Q=r8();if(!z1(Q))return;let Z=e8();if(!Z)return;let z=i8(Q,$);s1(Z,z,{timeout:t1,stdio:"ignore"})}catch{}}function n1($,Q){if($ instanceof Error){let z={errorClass:$.name&&$.name.length>0?$.name:Q,message:$.message};if($.stack)z.stack=$.stack;return z}return{errorClass:Q,message:String($)}}var a1=!1;function r1(){if(a1)return;a1=!0,process.on("uncaughtException",($)=>{if(!S$){S$=!0;let Q=n1($,"UncaughtException");o1({errorClass:Q.errorClass,message:Q.message,...Q.stack!==void 0?{stack:Q.stack}:{},exitCode:1})}try{process.stderr.write(`${$&&$.stack||String($)}
774
- `)}catch{}process.exit(1)}),process.on("unhandledRejection",($)=>{if(!S$){S$=!0;let Q=n1($,"UnhandledRejection");o1({errorClass:Q.errorClass,message:Q.message,...Q.stack!==void 0?{stack:Q.stack}:{},exitCode:1})}try{let Q=$ instanceof Error?$.stack||$.message:String($);process.stderr.write(`Unhandled promise rejection: ${Q}
775
- `)}catch{}process.exit(1)})}var Z8=`Loki Mode (TypeScript port, Phase 2 of bash->Bun migration)
775
+ `),0;return process.stdout.write(Z.stdout),0}async function o1($){switch($[0]??"list"){case"list":case"ls":return d8();case"index":return o8($[1]==="rebuild");default:{let Z=W$(h,"autonomy","loki"),z=3600000,X=Bun.spawn({cmd:[Z,"memory",...$],stdin:"inherit",stdout:"inherit",stderr:"inherit",env:{...process.env,LOKI_LEGACY_BASH:"1"}}),q=setTimeout(()=>{try{X.kill("SIGKILL")}catch{}},3600000);try{return await X.exited}finally{clearTimeout(q)}}}}C();V$();d();import{resolve as n8,join as a8}from"path";import{existsSync as z1,readFileSync as s8}from"fs";import{homedir as r8}from"os";import{spawnSync as r1}from"child_process";var t1=3000;function t8(){let $=(process.env.LOKI_TELEMETRY??"").toLowerCase();if($==="off")return!1;if(process.env.LOKI_TELEMETRY_DISABLED==="true")return!1;if(process.env.DO_NOT_TRACK==="1")return!1;let Q=!1,Z=!1;try{let z=a8(r8(),".loki","config");if(z1(z)){let X=s8(z,"utf8");for(let q of X.split(`
776
+ `)){let K=q.replace(/\r$/,"");if(K==="TELEMETRY_DISABLED=true")Q=!0;if(K==="TELEMETRY_ENABLED=true")Z=!0}}}catch{}if(Q)return!1;if($==="on"||Z)return!0;return!1}var S$=!1;function i8(){return n8(h,"autonomy","lib","crash_capture.py")}function e8($,Q){let Z=[$,"--error-class",Q.errorClass,"--message",Q.message];if(Q.stack!==void 0)Z.push("--stack",Q.stack);if(Q.rarvPhase!==void 0)Z.push("--rarv-phase",Q.rarvPhase);if(Q.exitCode!==void 0)Z.push("--exit-code",String(Q.exitCode));if(Q.frictionKind!==void 0)Z.push("--friction-kind",Q.frictionKind);return Z.push("--target-dir",Q.targetDir??process.cwd()),Z}function $3(){if(z1("/opt/homebrew/bin/python3.12"))return"/opt/homebrew/bin/python3.12";for(let Q of["python3.12","python3"])try{let Z=r1("sh",["-c",`command -v ${Q}`],{timeout:t1,encoding:"utf8"});if(Z.status===0){let z=(Z.stdout||"").trim();if(z)return z}}catch{}return null}function n1($){try{if(!t8())return;let Q=i8();if(!z1(Q))return;let Z=$3();if(!Z)return;let z=e8(Q,$);r1(Z,z,{timeout:t1,stdio:"ignore"})}catch{}}function a1($,Q){if($ instanceof Error){let z={errorClass:$.name&&$.name.length>0?$.name:Q,message:$.message};if($.stack)z.stack=$.stack;return z}return{errorClass:Q,message:String($)}}var s1=!1;function i1(){if(s1)return;s1=!0,process.on("uncaughtException",($)=>{if(!S$){S$=!0;let Q=a1($,"UncaughtException");n1({errorClass:Q.errorClass,message:Q.message,...Q.stack!==void 0?{stack:Q.stack}:{},exitCode:1})}try{process.stderr.write(`${$&&$.stack||String($)}
777
+ `)}catch{}process.exit(1)}),process.on("unhandledRejection",($)=>{if(!S$){S$=!0;let Q=a1($,"UnhandledRejection");n1({errorClass:Q.errorClass,message:Q.message,...Q.stack!==void 0?{stack:Q.stack}:{},exitCode:1})}try{let Q=$ instanceof Error?$.stack||$.message:String($);process.stderr.write(`Unhandled promise rejection: ${Q}
778
+ `)}catch{}process.exit(1)})}var z8=`Loki Mode (TypeScript port, Phase 2 of bash->Bun migration)
776
779
 
777
780
  Usage: loki <command> [args...]
778
781
 
@@ -794,12 +797,12 @@ Phase 2 ported (Bun-native, fast):
794
797
 
795
798
  All other commands fall through to the bash CLI (autonomy/loki).
796
799
  Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
797
- `;function PZ(){let $=process.env.LOKI_LEGACY_BASH;if($===void 0)return;let Q=$.trim().toLowerCase();if(Q!=="1"&&Q!=="true"&&Q!=="yes"&&Q!=="on")return;if(process.env.LOKI_SUPPRESS_BUN_DIRECT_WARN==="1")return;process.stderr.write(`warning: LOKI_LEGACY_BASH is set, but you are running the Bun runtime directly (src/cli.ts). The env var only takes effect via the bin/loki shim, which dispatches between Bun and bash. Behavior is unchanged; this message is informational.
798
- `)}async function jZ($){PZ();let Q=$[0],Z=$.slice(1);switch(Q){case void 0:case"help":case"--help":case"-h":return process.stdout.write(Z8),0;case"version":case"--version":case"-v":return await g1();case"provider":return p1(Z);case"memory":return d1(Z);case"status":{let{runStatus:z}=await Promise.resolve().then(() => (J0(),q0));return z(Z)}case"stats":{let{runStats:z}=await Promise.resolve().then(() => (Y0(),B0));return z(Z)}case"doctor":{let{runDoctor:z}=await Promise.resolve().then(() => (j0(),P0));return z(Z)}case"kpis":{let{runKpis:z}=await Promise.resolve().then(() => (Y1(),B1));return z(Z,{aliasOf:"kpis"})}case"report":{if(Z.find((q)=>!q.startsWith("-"))==="kpis"){let{runKpis:q}=await Promise.resolve().then(() => (Y1(),B1)),K=!1,W=Z.filter((V)=>{if(!K&&V==="kpis")return K=!0,!1;return!0});return q(W)}let{delegateToBash:X}=await Promise.resolve().then(() => (v0(),y0));return X(["report",...Z])}case"trust":{let{runTrust:z}=await Promise.resolve().then(() => (o0(),d0));return z(Z)}case"rollback":{let{runRollback:z}=await Promise.resolve().then(() => (AQ(),OQ));return z(Z)}case"proof":case"receipt":{let{runProof:z}=await Promise.resolve().then(() => (PQ(),LQ));return z(Z)}case"crash":{let{runCrash:z}=await Promise.resolve().then(() => (NQ(),EQ));return z(Z)}case"wiki":{let{runWiki:z}=await Promise.resolve().then(() => (hQ(),bQ));return z(Z)}case"internal":{let z=Z[0];if(!z||z==="--help"||z==="-h"||z==="help"){let q=["loki internal -- runtime hooks driven by autonomy/run.sh","","Subcommands:"," phase1-hooks Persist structured findings, run override council,"," append learnings, and write the escalation handoff"," doc once per iteration. Driven by run.sh; not"," intended for direct invocation.","","Phase 1 (RARV-C closure) env vars:"," LOKI_INJECT_FINDINGS=1 Persist structured reviewer findings to"," .loki/state/findings-<iter>.json so the"," next iteration can address them."," LOKI_OVERRIDE_COUNCIL=1 Allow a 3-LLM override panel to lift a"," BLOCK when counter-evidence is presented."," See LOKI_OVERRIDE_JUDGES (csv),"," LOKI_OVERRIDE_PANEL_SIZE,"," LOKI_OVERRIDE_REAL_JUDGE."," LOKI_AUTO_LEARNINGS=1 Append failure rootcauses to"," .loki/state/relevant-learnings.json via"," the episodic memory bridge."," LOKI_HANDOFF_MD=1 Write a structured human handoff doc to"," .loki/escalations/<ts>.md before PAUSE.","","All four are default-on as of v7.5.3. Set to 0 to disable.","Reference: CHANGELOG.md (search 'Phase 1') and skills/healing.md.","","These commands are wired into the autonomous loop and may change","without notice. Do not script against them.",""].join(`
800
+ `;function kZ(){let $=process.env.LOKI_LEGACY_BASH;if($===void 0)return;let Q=$.trim().toLowerCase();if(Q!=="1"&&Q!=="true"&&Q!=="yes"&&Q!=="on")return;if(process.env.LOKI_SUPPRESS_BUN_DIRECT_WARN==="1")return;process.stderr.write(`warning: LOKI_LEGACY_BASH is set, but you are running the Bun runtime directly (src/cli.ts). The env var only takes effect via the bin/loki shim, which dispatches between Bun and bash. Behavior is unchanged; this message is informational.
801
+ `)}async function RZ($){kZ();let Q=$[0],Z=$.slice(1);switch(Q){case void 0:case"help":case"--help":case"-h":return process.stdout.write(z8),0;case"version":case"--version":case"-v":return await m1();case"provider":return l1(Z);case"memory":return o1(Z);case"status":{let{runStatus:z}=await Promise.resolve().then(() => (V0(),J0));return z(Z)}case"stats":{let{runStats:z}=await Promise.resolve().then(() => (M0(),Y0));return z(Z)}case"doctor":{let{runDoctor:z}=await Promise.resolve().then(() => (F0(),j0));return z(Z)}case"kpis":{let{runKpis:z}=await Promise.resolve().then(() => (M1(),Y1));return z(Z,{aliasOf:"kpis"})}case"report":{if(Z.find((q)=>!q.startsWith("-"))==="kpis"){let{runKpis:q}=await Promise.resolve().then(() => (M1(),Y1)),K=!1,W=Z.filter((V)=>{if(!K&&V==="kpis")return K=!0,!1;return!0});return q(W)}let{delegateToBash:X}=await Promise.resolve().then(() => (g0(),v0));return X(["report",...Z])}case"trust":{let{runTrust:z}=await Promise.resolve().then(() => (n0(),o0));return z(Z)}case"rollback":{let{runRollback:z}=await Promise.resolve().then(() => (wQ(),AQ));return z(Z)}case"proof":case"receipt":{let{runProof:z}=await Promise.resolve().then(() => (jQ(),PQ));return z(Z)}case"crash":{let{runCrash:z}=await Promise.resolve().then(() => (SQ(),NQ));return z(Z)}case"wiki":{let{runWiki:z}=await Promise.resolve().then(() => (yQ(),hQ));return z(Z)}case"internal":{let z=Z[0];if(!z||z==="--help"||z==="-h"||z==="help"){let q=["loki internal -- runtime hooks driven by autonomy/run.sh","","Subcommands:"," phase1-hooks Persist structured findings, run override council,"," append learnings, and write the escalation handoff"," doc once per iteration. Driven by run.sh; not"," intended for direct invocation.","","Phase 1 (RARV-C closure) env vars:"," LOKI_INJECT_FINDINGS=1 Persist structured reviewer findings to"," .loki/state/findings-<iter>.json so the"," next iteration can address them."," LOKI_OVERRIDE_COUNCIL=1 Allow a 3-LLM override panel to lift a"," BLOCK when counter-evidence is presented."," See LOKI_OVERRIDE_JUDGES (csv),"," LOKI_OVERRIDE_PANEL_SIZE,"," LOKI_OVERRIDE_REAL_JUDGE."," LOKI_AUTO_LEARNINGS=1 Append failure rootcauses to"," .loki/state/relevant-learnings.json via"," the episodic memory bridge."," LOKI_HANDOFF_MD=1 Write a structured human handoff doc to"," .loki/escalations/<ts>.md before PAUSE.","","All four are default-on as of v7.5.3. Set to 0 to disable.","Reference: CHANGELOG.md (search 'Phase 1') and skills/healing.md.","","These commands are wired into the autonomous loop and may change","without notice. Do not script against them.",""].join(`
799
802
  `);return process.stdout.write(`${q}
800
- `),0}if(z==="phase1-hooks"){let{runInternalPhase1Hooks:q}=await Promise.resolve().then(() => (Q8(),$8));return q(Z.slice(1))}return process.stderr.write(`Unknown internal subcommand: ${z}
803
+ `),0}if(z==="phase1-hooks"){let{runInternalPhase1Hooks:q}=await Promise.resolve().then(() => (Z8(),Q8));return q(Z.slice(1))}return process.stderr.write(`Unknown internal subcommand: ${z}
801
804
  `),process.stderr.write(`Run 'loki internal --help' for the supported list.
802
805
  `),2}default:return process.stderr.write(`Unknown command: ${Q}
803
- `),process.stderr.write(Z8),2}}r1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var FZ=await jZ(Bun.argv.slice(2));process.exit(FZ);
806
+ `),process.stderr.write(z8),2}}i1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var EZ=await RZ(Bun.argv.slice(2));process.exit(EZ);
804
807
 
805
- //# debugId=A8E5D35BB99B83EF64756E2164756E21
808
+ //# debugId=48A34AFD97DA2FEB64756E2164756E21