loki-mode 7.5.27 → 7.5.29

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.
Files changed (77) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/project-graph.sh +24 -14
  4. package/autonomy/loki +50 -18
  5. package/bin/loki +2 -1
  6. package/dashboard/__init__.py +1 -1
  7. package/docs/INSTALLATION.md +1 -1
  8. package/docs/MERGE-DEDUP-MAP.md +420 -0
  9. package/docs/MERGE-ROUTE-MAP.md +139 -0
  10. package/docs/MERGE3-PLAN.md +119 -0
  11. package/loki-ts/dist/loki.js +196 -171
  12. package/mcp/__init__.py +1 -1
  13. package/package.json +2 -2
  14. package/web-app/dist/assets/{AdminPage-DwVUK4v9.js → AdminPage-CKUOsWZW.js} +3 -3
  15. package/web-app/dist/assets/{Avatar-B7gqhcg3.js → Avatar-CL9Id9Hi.js} +1 -1
  16. package/web-app/dist/assets/{Badge-DA3xNJAS.js → Badge-B12zwlD7.js} +1 -1
  17. package/web-app/dist/assets/{Button-BPXURLaK.js → Button-CFLVoduT.js} +1 -1
  18. package/web-app/dist/assets/{ComparePage-B0JQMhKG.js → ComparePage-Dg0UdZAk.js} +1 -1
  19. package/web-app/dist/assets/{GitHubIssuesPanel-D38-fy29.js → GitHubIssuesPanel-CSitxtAX.js} +2 -2
  20. package/web-app/dist/assets/{GitHubPRsPanel-DLPcW3N0.js → GitHubPRsPanel-BIT06FRo.js} +1 -1
  21. package/web-app/dist/assets/HomePage-pU_0fGny.js +28 -0
  22. package/web-app/dist/assets/{LoginPage-DqCzxsfx.js → LoginPage-DTZtt2Yb.js} +1 -1
  23. package/web-app/dist/assets/MagicPage-10zfra8o.js +31 -0
  24. package/web-app/dist/assets/{MetricsPage-CPYQR0zr.js → MetricsPage-C-wiKUkv.js} +1 -1
  25. package/web-app/dist/assets/NotFoundPage-BDkcmhYe.js +1 -0
  26. package/web-app/dist/assets/{ProjectPage-DNujSl6j.js → ProjectPage-CiCavQ8n.js} +71 -71
  27. package/web-app/dist/assets/ProjectsPage-BLCXQwwC.js +6 -0
  28. package/web-app/dist/assets/{SettingsPage-BaQJbOgL.js → SettingsPage-PkxtaMyg.js} +3 -3
  29. package/web-app/dist/assets/{ShowcasePage-DQR_e-kg.js → ShowcasePage-iECp8Tha.js} +1 -1
  30. package/web-app/dist/assets/SystemSettingsPage-DS6Anno1.js +6 -0
  31. package/web-app/dist/assets/{TeamsPage-DOFErDqX.js → TeamsPage-ls6h6bNL.js} +1 -1
  32. package/web-app/dist/assets/{TemplatesPage-Ty72hILN.js → TemplatesPage-Bk0QzlPt.js} +3 -3
  33. package/web-app/dist/assets/{TerminalOutput-DqOVnR1p.js → TerminalOutput-4-1hWCtZ.js} +1 -1
  34. package/web-app/dist/assets/{activity-BgBZ4s4c.js → activity-DH3ih2nS.js} +1 -1
  35. package/web-app/dist/assets/{bell-C-UezVWi.js → bell-Gn17S6uv.js} +1 -1
  36. package/web-app/dist/assets/{bot-D70fEnm5.js → bot-Cbycc3VE.js} +1 -1
  37. package/web-app/dist/assets/{check-CBohulxQ.js → check-nIAqa-kf.js} +1 -1
  38. package/web-app/dist/assets/{chevron-left-C-emzUhB.js → chevron-left-D2jcWDll.js} +1 -1
  39. package/web-app/dist/assets/{circle-alert-8SRY0_GX.js → circle-alert-CpL4Bhvt.js} +1 -1
  40. package/web-app/dist/assets/{clock-mfq4XnPQ.js → clock-IW4Wq86N.js} +1 -1
  41. package/web-app/dist/assets/{cloud-DpRM7T8t.js → cloud-Cn8nNuH2.js} +1 -1
  42. package/web-app/dist/assets/{code-xml-1N2Ui-4c.js → code-xml-BiJBteXf.js} +1 -1
  43. package/web-app/dist/assets/{copy-LXquTgzI.js → copy-CnqkyNsi.js} +1 -1
  44. package/web-app/dist/assets/{database-S1dyXnuT.js → database-CKSReqa5.js} +1 -1
  45. package/web-app/dist/assets/{dollar-sign-CRqk0dW5.js → dollar-sign-CDzDY64R.js} +1 -1
  46. package/web-app/dist/assets/{file-code-corner-B99CwY_6.js → file-code-corner-Box4IwG1.js} +1 -1
  47. package/web-app/dist/assets/{file-plus-DZ5qnz5b.js → file-plus-DpGqlXF8.js} +1 -1
  48. package/web-app/dist/assets/{folder-open-DBCm7yuF.js → folder-open-B57dAoBv.js} +1 -1
  49. package/web-app/dist/assets/{git-commit-horizontal-DM1ERuNd.js → git-commit-horizontal-BVbucmO5.js} +1 -1
  50. package/web-app/dist/assets/{globe-B7xEJSL_.js → globe-BkOnKl4x.js} +1 -1
  51. package/web-app/dist/assets/{hammer-Cgi3LTuS.js → hammer-DRbIQ4QU.js} +1 -1
  52. package/web-app/dist/assets/{index-BN52-GQT.js → index-CM_b_EhP.js} +77 -77
  53. package/web-app/dist/assets/{layers-Bi8RPIBC.js → layers-B78BiFiU.js} +1 -1
  54. package/web-app/dist/assets/{lightbulb-Doc_n8JX.js → lightbulb-B-Itbm9g.js} +1 -1
  55. package/web-app/dist/assets/{loader-circle-BB932A7A.js → loader-circle-Oq6NQhW2.js} +1 -1
  56. package/web-app/dist/assets/{lock-Bt6gpMrs.js → lock-DbJ9zxbw.js} +1 -1
  57. package/web-app/dist/assets/{mail-BuzAu1IP.js → mail-CzMRod6m.js} +1 -1
  58. package/web-app/dist/assets/{package-BE5FHxQ8.js → package-WZ5osvej.js} +1 -1
  59. package/web-app/dist/assets/{plus-CNqABexN.js → plus-j08lFR-K.js} +1 -1
  60. package/web-app/dist/assets/{refresh-cw-34B13ztx.js → refresh-cw-CIr7E-g2.js} +1 -1
  61. package/web-app/dist/assets/{rotate-ccw-CrD2QB29.js → rotate-ccw-gwoXxDeE.js} +1 -1
  62. package/web-app/dist/assets/{save-DsJcqdnI.js → save-B8fV_ZpE.js} +1 -1
  63. package/web-app/dist/assets/{server-BcgRMArA.js → server-D5dO1paz.js} +1 -1
  64. package/web-app/dist/assets/{shield-alert-DLYLdVJ0.js → shield-alert-Du08zhdg.js} +1 -1
  65. package/web-app/dist/assets/{trash-2-Cc-VTvzt.js → trash-2-DEKSVae5.js} +1 -1
  66. package/web-app/dist/assets/{trending-down-CrDpO2a_.js → trending-down-DBiXUtxJ.js} +1 -1
  67. package/web-app/dist/assets/{trending-up-CNVsmM3G.js → trending-up-BgmK_tHq.js} +1 -1
  68. package/web-app/dist/assets/{upload-LuDuB7Wc.js → upload-IaViyeVD.js} +1 -1
  69. package/web-app/dist/assets/{usePolling-C8rvc-CG.js → usePolling-PiRLqNu6.js} +1 -1
  70. package/web-app/dist/assets/{user-BT79cI-o.js → user-BB5J8wAF.js} +1 -1
  71. package/web-app/dist/index.html +2 -3
  72. package/web-app/server.py +45 -7
  73. package/web-app/dist/assets/HomePage-CzeoS2V_.js +0 -28
  74. package/web-app/dist/assets/MagicPage-CBLqpa55.js +0 -31
  75. package/web-app/dist/assets/NotFoundPage-B62u4iCs.js +0 -1
  76. package/web-app/dist/assets/ProjectsPage-uHG7kxB-.js +0 -6
  77. package/web-app/dist/assets/SystemSettingsPage-C_Q_1WK4.js +0 -6
@@ -1,60 +1,60 @@
1
1
  // @bun
2
- var X6=Object.defineProperty;var Z6=($)=>$;function K6($,Q){this[$]=Z6.bind(null,Q)}var y=($,Q)=>{for(var z in Q)X6($,z,{get:Q[z],enumerable:!0,configurable:!0,set:K6.bind(Q,z)})};var w=($,Q)=>()=>($&&(Q=$($=0)),Q);var H1=import.meta.require;var a1={};y(a1,{lokiDir:()=>P,homeLokiDir:()=>E1,findRepoRootForVersion:()=>F1,REPO_ROOT:()=>u});import{resolve as f,dirname as R1}from"path";import{fileURLToPath as W6}from"url";import{existsSync as G1}from"fs";import{homedir as U6}from"os";function q6(){let $=n1;for(let Q=0;Q<6;Q++){if(G1(f($,"VERSION"))&&G1(f($,"autonomy/run.sh")))return $;let z=R1($);if(z===$)break;$=z}return f(n1,"..","..","..")}function F1($){let Q=$;for(let z=0;z<6;z++){if(G1(f(Q,"VERSION"))&&G1(f(Q,"autonomy/run.sh")))return Q;let X=R1(Q);if(X===Q)break;Q=X}return f($,"..","..","..")}function P(){return process.env.LOKI_DIR??f(process.cwd(),".loki")}function E1(){return f(U6(),".loki")}var n1,u;var v=w(()=>{n1=R1(W6(import.meta.url));u=q6()});var t1={};y(t1,{runOrThrow:()=>B6,run:()=>E,commandVersion:()=>M6,commandExists:()=>b,ShellError:()=>w1});async function E($,Q={}){let z=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Q.env?{...process.env,...Q.env}:process.env,cwd:Q.cwd}),X,Z;if(Q.timeoutMs&&Q.timeoutMs>0)X=setTimeout(()=>{try{z.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[K,W,q]=await Promise.all([new Response(z.stdout).text(),new Response(z.stderr).text(),z.exited]);return{stdout:K,stderr:W,exitCode:q}}finally{if(X)clearTimeout(X);if(Z)clearTimeout(Z)}}async function B6($,Q={}){let z=await E($,Q);if(z.exitCode!==0)throw new w1(`command failed (${z.exitCode}): ${$.join(" ")}`,z.exitCode,z.stdout,z.stderr);return z}async function b($){let Q=Y6($),z=await E(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(z.exitCode===0)return z.stdout.trim()||null;return null}function Y6($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function M6($,Q="--version"){if(!await b($))return null;let X=await E([$,Q],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var w1;var p=w(()=>{w1=class w1 extends Error{message;exitCode;stdout;stderr;constructor($,Q,z,X){super($);this.message=$;this.exitCode=Q;this.stdout=z;this.stderr=X;this.name="ShellError"}}});function c($){return A6?"":$}var A6,L,C,x,y5,A,D,R,U;var n=w(()=>{A6=(process.env.NO_COLOR??"").length>0;L=c("\x1B[0;31m"),C=c("\x1B[0;32m"),x=c("\x1B[1;33m"),y5=c("\x1B[0;34m"),A=c("\x1B[0;36m"),D=c("\x1B[1m"),R=c("\x1B[2m"),U=c("\x1B[0m")});import{existsSync as F6}from"fs";async function r(){if(Q1!==void 0)return Q1;let $="/opt/homebrew/bin/python3.12";if(F6($))return Q1=$,$;let Q=await b("python3.12");if(Q)return Q1=Q,Q;let z=await b("python3");return Q1=z,z}async function a($,Q={}){let z=await r();if(!z)return{stdout:"",stderr:"python3 not found",exitCode:127};return E([z,"-c",$],Q)}var Q1;var X1=w(()=>{p()});var q0={};y(q0,{runStatus:()=>g6});import{existsSync as S,readFileSync as K1,readdirSync as Q0,statSync as X0}from"fs";import{resolve as F,basename as D6}from"path";async function k6(){if(await b("jq"))return!0;return process.stdout.write(`${L}Error: jq is required but not installed.${U}
2
+ var j7=Object.defineProperty;var _7=(K)=>K;function I7(K,$){this[K]=_7.bind(null,$)}var b=(K,$)=>{for(var z in $)j7(K,z,{get:$[z],enumerable:!0,configurable:!0,set:I7.bind($,z)})};var L=(K,$)=>()=>(K&&($=K(K=0)),$);var U1=import.meta.require;var t1={};b(t1,{lokiDir:()=>P,homeLokiDir:()=>N1,findRepoRootForVersion:()=>S1,REPO_ROOT:()=>u});import{resolve as f,dirname as w1}from"path";import{fileURLToPath as P7}from"url";import{existsSync as J1}from"fs";import{homedir as L7}from"os";function R7(){let K=r1;for(let $=0;$<6;$++){if(J1(f(K,"VERSION"))&&J1(f(K,"autonomy/run.sh")))return K;let z=w1(K);if(z===K)break;K=z}return f(r1,"..","..","..")}function S1(K){let $=K;for(let z=0;z<6;z++){if(J1(f($,"VERSION"))&&J1(f($,"autonomy/run.sh")))return $;let Q=w1($);if(Q===$)break;$=Q}return f(K,"..","..","..")}function P(){return process.env.LOKI_DIR??f(process.cwd(),".loki")}function N1(){return f(L7(),".loki")}var r1,u;var y=L(()=>{r1=w1(P7(import.meta.url));u=R7()});var K0={};b(K0,{runOrThrow:()=>S7,run:()=>w,commandVersion:()=>k7,commandExists:()=>h,ShellError:()=>k1});async function w(K,$={}){let z=Bun.spawn({cmd:[...K],stdout:"pipe",stderr:"pipe",env:$.env?{...process.env,...$.env}:process.env,cwd:$.cwd}),Q,X;if($.timeoutMs&&$.timeoutMs>0)Q=setTimeout(()=>{try{z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{z.kill("SIGKILL")}catch{}},2000)},$.timeoutMs);try{let[H,Z,V]=await Promise.all([new Response(z.stdout).text(),new Response(z.stderr).text(),z.exited]);return{stdout:H,stderr:Z,exitCode:V}}finally{if(Q)clearTimeout(Q);if(X)clearTimeout(X)}}async function S7(K,$={}){let z=await w(K,$);if(z.exitCode!==0)throw new k1(`command failed (${z.exitCode}): ${K.join(" ")}`,z.exitCode,z.stdout,z.stderr);return z}async function h(K){let $=N7(K),z=await w(["sh","-c",`command -v ${$}`],{timeoutMs:5000});if(z.exitCode===0)return z.stdout.trim()||null;return null}function N7(K){if(!/^[A-Za-z0-9._/-]+$/.test(K))throw Error(`refused to shell-escape suspect token: ${K}`);return K}async function k7(K,$="--version"){if(!await h(K))return null;let Q=await w([K,$],{timeoutMs:5000});if(Q.exitCode!==0)return null;return((Q.stdout||Q.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var k1;var p=L(()=>{k1=class k1 extends Error{message;exitCode;stdout;stderr;constructor(K,$,z,Q){super(K);this.message=K;this.exitCode=$;this.stdout=z;this.stderr=Q;this.name="ShellError"}}});function c(K){return D7?"":K}var D7,R,D,E,Y6,O,k,x,W;var n=L(()=>{D7=(process.env.NO_COLOR??"").length>0;R=c("\x1B[0;31m"),D=c("\x1B[0;32m"),E=c("\x1B[1;33m"),Y6=c("\x1B[0;34m"),O=c("\x1B[0;36m"),k=c("\x1B[1m"),x=c("\x1B[2m"),W=c("\x1B[0m")});import{existsSync as p7}from"fs";async function r(){if(z1!==void 0)return z1;let K="/opt/homebrew/bin/python3.12";if(p7(K))return z1=K,K;let $=await h("python3.12");if($)return z1=$,$;let z=await h("python3");return z1=z,z}async function a(K,$={}){let z=await r();if(!z)return{stdout:"",stderr:"python3 not found",exitCode:127};return w([z,"-c",K],$)}var z1;var Q1=L(()=>{p()});var J0={};b(J0,{runStatus:()=>$5});import{existsSync as S,readFileSync as Z1,readdirSync as Z0,statSync as H0}from"fs";import{resolve as F,basename as n7}from"path";async function s7(){if(await h("jq"))return!0;return process.stdout.write(`${R}Error: jq is required but not installed.${W}
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 V1($){if(!Number.isFinite($)||$<=0)return!1;try{return process.kill($,0),!0}catch{return!1}}function J1($){if(!S($))return null;try{let Q=K1($,"utf-8").trim();if(!Q)return null;let z=Number.parseInt(Q,10);return Number.isFinite(z)?z:null}catch{return null}}function b6($){let Q=[],z=J1(F($,"loki.pid"));if(z!==null&&V1(z))Q.push(`global:${z}`);let X=F($,"sessions");if(S(X)){let Z=[];try{Z=Q0(X)}catch{Z=[]}for(let K of Z){let W=F(X,K);try{if(!X0(W).isDirectory())continue}catch{continue}let q=F(W,"loki.pid"),H=J1(q);if(H!==null&&V1(H))Q.push(`${K}:${H}`)}}if(S($)){let Z=[];try{Z=Q0($)}catch{Z=[]}for(let K of Z){if(!K.startsWith("run-")||!K.endsWith(".pid"))continue;let W=F($,K);try{if(!X0(W).isFile())continue}catch{continue}let q=D6(K,".pid").slice(4),H=J1(W);if(H!==null&&V1(H)){if(!Q.some((J)=>J.startsWith(`${q}:`)))Q.push(`${q}:${H}`)}}}return Q}async function Z0($,Q){let z=await E(["jq","-r",$,Q]);if(z.exitCode!==0)return null;return z.stdout.trim()}function K0($,Q){try{let z=K1($,"utf-8"),Z=JSON.parse(z)[Q];if(typeof Z==="number"){if(Q==="budget_used"){let K=Math.round(Z*100)/100;if(Number.isInteger(K))return String(K);return String(K)}return String(Z)}if(Z===void 0||Z===null)return"0";return String(Z)}catch{return"0"}}function W0($,Q,z){try{let X=K1($,"utf-8"),K=JSON.parse(X)[Q];if(typeof K==="number"&&Number.isFinite(K))return K;return z}catch{return z}}async function y6(){let $=P();if(!await k6())return 1;if(!S($))return process.stdout.write(`${D}Loki Mode Status${U}
7
+ `),!1}function G1(K){if(!Number.isFinite(K)||K<=0)return!1;try{return process.kill(K,0),!0}catch{return!1}}function B1(K){if(!S(K))return null;try{let $=Z1(K,"utf-8").trim();if(!$)return null;let z=Number.parseInt($,10);return Number.isFinite(z)?z:null}catch{return null}}function r7(K){let $=[],z=B1(F(K,"loki.pid"));if(z!==null&&G1(z))$.push(`global:${z}`);let Q=F(K,"sessions");if(S(Q)){let X=[];try{X=Z0(Q)}catch{X=[]}for(let H of X){let Z=F(Q,H);try{if(!H0(Z).isDirectory())continue}catch{continue}let V=F(Z,"loki.pid"),q=B1(V);if(q!==null&&G1(q))$.push(`${H}:${q}`)}}if(S(K)){let X=[];try{X=Z0(K)}catch{X=[]}for(let H of X){if(!H.startsWith("run-")||!H.endsWith(".pid"))continue;let Z=F(K,H);try{if(!H0(Z).isFile())continue}catch{continue}let V=n7(H,".pid").slice(4),q=B1(Z);if(q!==null&&G1(q)){if(!$.some((G)=>G.startsWith(`${V}:`)))$.push(`${V}:${q}`)}}}return $}async function W0(K,$){let z=await w(["jq","-r",K,$]);if(z.exitCode!==0)return null;return z.stdout.trim()}function V0(K,$){try{let z=Z1(K,"utf-8"),X=JSON.parse(z)[$];if(typeof X==="number"){if($==="budget_used"){let H=Math.round(X*100)/100;if(Number.isInteger(H))return String(H);return String(H)}return String(X)}if(X===void 0||X===null)return"0";return String(X)}catch{return"0"}}function q0(K,$,z){try{let Q=Z1(K,"utf-8"),H=JSON.parse(Q)[$];if(typeof H==="number"&&Number.isFinite(H))return H;return z}catch{return z}}async function t7(){let K=P();if(!await s7())return 1;if(!S(K))return process.stdout.write(`${k}Loki Mode Status${W}
8
8
  `),process.stdout.write(`
9
- `),process.stdout.write(`${x}No active session found.${U}
9
+ `),process.stdout.write(`${E}No active session found.${W}
10
10
  `),process.stdout.write(`Loki Mode has not been initialized in this directory.
11
11
  `),process.stdout.write(`
12
12
  `),process.stdout.write(`To start a session:
13
13
  `),process.stdout.write(` loki start <prd> - Start with a PRD file
14
14
  `),process.stdout.write(` loki start - Start without a PRD
15
15
  `),process.stdout.write(`
16
- `),process.stdout.write(`${R}Current directory: ${process.cwd()}${U}
17
- `),0;process.stdout.write(`${D}Loki Mode Status${U}
16
+ `),process.stdout.write(`${x}Current directory: ${process.cwd()}${W}
17
+ `),0;process.stdout.write(`${k}Loki Mode Status${W}
18
18
  `),process.stdout.write(`
19
- `);let Q="",z=F($,"state","provider");if(S(z))try{Q=K1(z,"utf-8").trim()}catch{Q=""}let X=Q||process.env.LOKI_PROVIDER||"claude",Z="full features";switch(X){case"codex":case"aider":Z="degraded mode";break;case"cline":Z="near-full mode";break;default:Z="full features";break}process.stdout.write(`${A}Provider:${U} ${X} (${Z})
20
- `),process.stdout.write(`${R} Switch with: loki provider set <claude|codex|cline|aider>${U}
19
+ `);let $="",z=F(K,"state","provider");if(S(z))try{$=Z1(z,"utf-8").trim()}catch{$=""}let Q=$||process.env.LOKI_PROVIDER||"claude",X="full features";switch(Q){case"codex":case"aider":X="degraded mode";break;case"cline":X="near-full mode";break;default:X="full features";break}process.stdout.write(`${O}Provider:${W} ${Q} (${X})
20
+ `),process.stdout.write(`${x} Switch with: loki provider set <claude|codex|cline|aider>${W}
21
21
  `),process.stdout.write(`
22
- `);let K=b6($);if(K.length>0){process.stdout.write(`${C}Active Sessions: ${K.length}${U}
23
- `);for(let V of K){let M=V.indexOf(":"),j=M>=0?V.slice(0,M):V,_=M>=0?V.slice(M+1):"";if(j==="global")process.stdout.write(` ${A}[global]${U} PID ${_}
24
- `);else process.stdout.write(` ${A}[#${j}]${U} PID ${_}
22
+ `);let H=r7(K);if(H.length>0){process.stdout.write(`${D}Active Sessions: ${H.length}${W}
23
+ `);for(let J of H){let Y=J.indexOf(":"),j=Y>=0?J.slice(0,Y):J,_=Y>=0?J.slice(Y+1):"";if(j==="global")process.stdout.write(` ${O}[global]${W} PID ${_}
24
+ `);else process.stdout.write(` ${O}[#${j}]${W} PID ${_}
25
25
  `)}process.stdout.write(`
26
- `),process.stdout.write(`${R} Stop specific: loki stop <session-id>${U}
27
- `),process.stdout.write(`${R} Stop all: loki stop${U}
26
+ `),process.stdout.write(`${x} Stop specific: loki stop <session-id>${W}
27
+ `),process.stdout.write(`${x} Stop all: loki stop${W}
28
28
  `),process.stdout.write(`
29
- `)}if(S(F($,"PAUSE")))process.stdout.write(`${x}Status: PAUSED${U}
30
- `),process.stdout.write(`${R} Resume with: loki resume${U}
29
+ `)}if(S(F(K,"PAUSE")))process.stdout.write(`${E}Status: PAUSED${W}
30
+ `),process.stdout.write(`${x} Resume with: loki resume${W}
31
31
  `),process.stdout.write(`
32
- `);else if(S(F($,"STOP")))process.stdout.write(`${L}Status: STOPPED${U}
33
- `),process.stdout.write(`${R} Clear with: loki resume${U}
32
+ `);else if(S(F(K,"STOP")))process.stdout.write(`${R}Status: STOPPED${W}
33
+ `),process.stdout.write(`${x} Clear with: loki resume${W}
34
34
  `),process.stdout.write(`
35
- `);let W=F($,"STATUS.txt");if(S(W)){process.stdout.write(`${A}Session Info:${U}
36
- `);try{process.stdout.write(K1(W,"utf-8"))}catch{}process.stdout.write(`
37
- `)}let q=F($,"state","orchestrator.json");if(S(q)){process.stdout.write(`${A}Orchestrator State:${U}
38
- `);let V=await Z0('.currentPhase // "unknown"',q);process.stdout.write(`${V??"unknown"}
39
- `)}let H=F($,"queue","pending.json");if(S(H)){let V=await Z0('if type == "array" then length elif .tasks then .tasks | length else 0 end',H);process.stdout.write(`${A}Pending Tasks:${U} ${V??"0"}
40
- `)}let G=F($,"metrics","budget.json");if(S(G)){let V=K0(G,"budget_limit"),M=K0(G,"budget_used");if(V!=="0")process.stdout.write(`${A}Budget:${U} $${M} / $${V}
41
- `);else process.stdout.write(`${A}Cost:${U} $${M} (no limit)
42
- `)}let J=F($,"state","context-usage.json");if(S(J)){let V=W0(J,"window_size",200000),M=W0(J,"used_tokens",0),j=0;if(V>0)j=Math.floor(M*100/V);process.stdout.write(`${A}Context:${U} ${j}% (${M} / ${V} tokens)
43
- `)}let B=F($,"dashboard","dashboard.pid");if(S(B)){let V=J1(B);if(V!==null&&V1(V)){let M=process.env.LOKI_DASHBOARD_PORT||"57374";process.stdout.write(`${A}Dashboard:${U} http://127.0.0.1:${M}/
44
- `)}}return await h6($),process.stdout.write(`
45
- `),process.stdout.write(`${R} Tip: loki context show - detailed token breakdown${U}
46
- `),process.stdout.write(`${R} Tip: loki code overview - codebase intelligence${U}
47
- `),0}async function h6($){let Q=F($,"state"),z=v6(Q),X=F(Q,"relevant-learnings.json"),Z=F($,"escalations"),K=z.length>0,W=S(X),q=S(Z);if(!K&&!W&&!q)return;if(process.stdout.write(`
48
- ${A}Phase 1 artifacts:${U}
49
- `),K){let H=z[z.length-1],G=U0(H);if(G&&Array.isArray(G.findings)){let J={Critical:0,High:0,Medium:0,Low:0};for(let V of G.findings){let M=String(V.severity??"");if(M in J)J[M]=(J[M]??0)+1}let B=Object.entries(J).filter(([,V])=>V>0).map(([V,M])=>`${M} ${V.toLowerCase()}`).join(", ");process.stdout.write(` Findings (iter ${G.iteration??"?"}): ${B||"none"} -- ${G.findings.length} total
50
- `)}}if(W){let H=U0(X);if(H&&Array.isArray(H.learnings)&&H.learnings.length>0){let G=new Map;for(let B of H.learnings){let V=String(B.trigger??"unknown");G.set(V,(G.get(V)??0)+1)}let J=[...G.entries()].sort((B,V)=>V[1]-B[1]).slice(0,3).map(([B,V])=>`${V} ${B}`).join(", ");process.stdout.write(` Learnings: ${H.learnings.length} total (${J})
51
- `)}}if(q){let H=0,G="";try{let B=(await import("fs")).readdirSync(Z).filter((V)=>V.endsWith(".md"));if(H=B.length,B.length>0)B.sort(),G=B[B.length-1]??""}catch{}if(H>0)process.stdout.write(` Escalations: ${H} handoff doc${H===1?"":"s"} (latest: ${G})
52
- `)}}function v6($){if(!S($))return[];try{return H1("fs").readdirSync($).filter((X)=>/^findings-\d+\.json$/.test(X)).sort((X,Z)=>{let K=Number.parseInt(X.replace(/[^0-9]/g,""),10)||0,W=Number.parseInt(Z.replace(/[^0-9]/g,""),10)||0;return K-W}).map((X)=>F($,X))}catch{return[]}}function U0($){try{let Q=H1("fs");return JSON.parse(Q.readFileSync($,"utf-8"))}catch{return null}}async function m6(){let $=await r();if(!$)return process.stderr.write(`{"error": "Failed to generate JSON status. Ensure python3 is available."}
53
- `),1;let Q=u,z=P(),X=process.env.LOKI_DASHBOARD_PORT||"57374",Z=process.env.LOKI_PROVIDER||"claude",K=await E([$,"-c",C6,Q,z,X,Z],{timeoutMs:30000});if(K.exitCode!==0)return process.stderr.write(`{"error": "Failed to generate JSON status. Ensure python3 is available."}
54
- `),1;return process.stdout.write(K.stdout),0}async function g6($){let Q=[...$];while(Q.length>0){let z=Q[0];if(z==="--json")return m6();if(z==="--help"||z==="-h")return process.stdout.write(`Usage: loki status [--json]
55
- `),0;return process.stdout.write(`${L}Unknown flag: ${z}${U}
35
+ `);let Z=F(K,"STATUS.txt");if(S(Z)){process.stdout.write(`${O}Session Info:${W}
36
+ `);try{process.stdout.write(Z1(Z,"utf-8"))}catch{}process.stdout.write(`
37
+ `)}let V=F(K,"state","orchestrator.json");if(S(V)){process.stdout.write(`${O}Orchestrator State:${W}
38
+ `);let J=await W0('.currentPhase // "unknown"',V);process.stdout.write(`${J??"unknown"}
39
+ `)}let q=F(K,"queue","pending.json");if(S(q)){let J=await W0('if type == "array" then length elif .tasks then .tasks | length else 0 end',q);process.stdout.write(`${O}Pending Tasks:${W} ${J??"0"}
40
+ `)}let U=F(K,"metrics","budget.json");if(S(U)){let J=V0(U,"budget_limit"),Y=V0(U,"budget_used");if(J!=="0")process.stdout.write(`${O}Budget:${W} $${Y} / $${J}
41
+ `);else process.stdout.write(`${O}Cost:${W} $${Y} (no limit)
42
+ `)}let G=F(K,"state","context-usage.json");if(S(G)){let J=q0(G,"window_size",200000),Y=q0(G,"used_tokens",0),j=0;if(J>0)j=Math.floor(Y*100/J);process.stdout.write(`${O}Context:${W} ${j}% (${Y} / ${J} tokens)
43
+ `)}let B=F(K,"dashboard","dashboard.pid");if(S(B)){let J=B1(B);if(J!==null&&G1(J)){let Y=process.env.LOKI_DASHBOARD_PORT||"57374";process.stdout.write(`${O}Dashboard:${W} http://127.0.0.1:${Y}/
44
+ `)}}return await i7(K),process.stdout.write(`
45
+ `),process.stdout.write(`${x} Tip: loki context show - detailed token breakdown${W}
46
+ `),process.stdout.write(`${x} Tip: loki code overview - codebase intelligence${W}
47
+ `),0}async function i7(K){let $=F(K,"state"),z=e7($),Q=F($,"relevant-learnings.json"),X=F(K,"escalations"),H=z.length>0,Z=S(Q),V=S(X);if(!H&&!Z&&!V)return;if(process.stdout.write(`
48
+ ${O}Phase 1 artifacts:${W}
49
+ `),H){let q=z[z.length-1],U=U0(q);if(U&&Array.isArray(U.findings)){let G={Critical:0,High:0,Medium:0,Low:0};for(let J of U.findings){let Y=String(J.severity??"");if(Y in G)G[Y]=(G[Y]??0)+1}let B=Object.entries(G).filter(([,J])=>J>0).map(([J,Y])=>`${Y} ${J.toLowerCase()}`).join(", ");process.stdout.write(` Findings (iter ${U.iteration??"?"}): ${B||"none"} -- ${U.findings.length} total
50
+ `)}}if(Z){let q=U0(Q);if(q&&Array.isArray(q.learnings)&&q.learnings.length>0){let U=new Map;for(let B of q.learnings){let J=String(B.trigger??"unknown");U.set(J,(U.get(J)??0)+1)}let G=[...U.entries()].sort((B,J)=>J[1]-B[1]).slice(0,3).map(([B,J])=>`${J} ${B}`).join(", ");process.stdout.write(` Learnings: ${q.learnings.length} total (${G})
51
+ `)}}if(V){let q=0,U="";try{let B=(await import("fs")).readdirSync(X).filter((J)=>J.endsWith(".md"));if(q=B.length,B.length>0)B.sort(),U=B[B.length-1]??""}catch{}if(q>0)process.stdout.write(` Escalations: ${q} handoff doc${q===1?"":"s"} (latest: ${U})
52
+ `)}}function e7(K){if(!S(K))return[];try{return U1("fs").readdirSync(K).filter((Q)=>/^findings-\d+\.json$/.test(Q)).sort((Q,X)=>{let H=Number.parseInt(Q.replace(/[^0-9]/g,""),10)||0,Z=Number.parseInt(X.replace(/[^0-9]/g,""),10)||0;return H-Z}).map((Q)=>F(K,Q))}catch{return[]}}function U0(K){try{let $=U1("fs");return JSON.parse($.readFileSync(K,"utf-8"))}catch{return null}}async function K5(){let K=await r();if(!K)return process.stderr.write(`{"error": "Failed to generate JSON status. Ensure python3 is available."}
53
+ `),1;let $=u,z=P(),Q=process.env.LOKI_DASHBOARD_PORT||"57374",X=process.env.LOKI_PROVIDER||"claude",H=await w([K,"-c",a7,$,z,Q,X],{timeoutMs:30000});if(H.exitCode!==0)return process.stderr.write(`{"error": "Failed to generate JSON status. Ensure python3 is available."}
54
+ `),1;return process.stdout.write(H.stdout),0}async function $5(K){let $=[...K];while($.length>0){let z=$[0];if(z==="--json")return K5();if(z==="--help"||z==="-h")return process.stdout.write(`Usage: loki status [--json]
55
+ `),0;return process.stdout.write(`${R}Unknown flag: ${z}${W}
56
56
  `),process.stdout.write(`Usage: loki status [--json]
57
- `),1}return y6()}var C6=`
57
+ `),1}return t7()}var a7=`
58
58
  import json, os, sys, time
59
59
 
60
60
  skill_dir = sys.argv[1]
@@ -261,9 +261,9 @@ if os.path.isfile(gate_count_file):
261
261
  result['phase1'] = phase1
262
262
 
263
263
  print(json.dumps(result, indent=2))
264
- `;var H0=w(()=>{p();X1();n();v()});var B0={};y(B0,{runStats:()=>d6,computeStats:()=>J0});import{readdirSync as G0,readFileSync as f6,statSync as V0}from"fs";import{join as l}from"path";function i($){try{if(!V0($).isFile())return null;return JSON.parse(f6($,"utf-8"))}catch{return null}}function C1($){try{return V0($).isDirectory()}catch{return!1}}function u6($){if(!C1($))return[];try{let Q=G0($).filter((z)=>z.startsWith("iteration-")&&z.endsWith(".json"));return Q.sort(),Q.map((z)=>l($,z))}catch{return[]}}function e($){return Math.trunc($).toLocaleString("en-US")}function N1($){let Q=Math.trunc($);if(Q<60)return`${Q}s`;let z=Math.trunc(Q/3600),X=Math.trunc(Q%3600/60),Z=Q%60;if(z>0)return`${z}h ${String(X).padStart(2,"0")}m`;return`${X}m ${String(Z).padStart(2,"0")}s`}function d($,Q=0){let z=Math.pow(10,Q);return Math.round($*z)/z}function $1($,Q){return $.toFixed(Q)}function D1($,Q){return $.length>=Q?$:$+" ".repeat(Q-$.length)}function p6($){let Q="N/A",z=0,X=i(l($,"state","orchestrator.json"));if(X&&typeof X==="object"){if(typeof X.currentPhase==="string")Q=X.currentPhase;if(typeof X.currentIteration==="number")z=X.currentIteration}let Z=l($,"metrics","efficiency"),K=u6(Z),W=[];for(let T of K){let I=i(T);if(I&&typeof I==="object")W.push(I)}if(W.length>0)z=Math.max(z,W.length);let q=W.reduce((T,I)=>T+(I.input_tokens??0),0),H=W.reduce((T,I)=>T+(I.output_tokens??0),0),G=q+H,J=W.reduce((T,I)=>T+(I.cost_usd??0),0),B=W.reduce((T,I)=>T+(I.duration_seconds??0),0),V=0,M=0,j=i(l($,"metrics","budget.json"));if(j&&typeof j==="object"){if(typeof j.budget_limit==="number")V=j.budget_limit;if(typeof j.budget_used==="number")M=j.budget_used}let _=0,k=0,m=i(l($,"state","quality-gates.json"));if(m&&typeof m==="object"){if(Array.isArray(m)){for(let T of m)if(k+=1,T===!0)_+=1;else if(T&&typeof T==="object"){let I=T;if(I.passed===!0||I.status==="passed")_+=1}}else for(let T of Object.values(m))if(typeof T==="boolean"){if(k+=1,T)_+=1}else if(T&&typeof T==="object"){k+=1;let I=T;if(I.passed===!0||I.status==="passed")_+=1}}let g={},O=i(l($,"quality","gate-failure-count.json"));if(O&&typeof O==="object"&&!Array.isArray(O)){let T={};for(let[I,h]of Object.entries(O))if(typeof h==="number")T[I]=h;g=T}let N=0,z1=0,d1=0,x1=l($,"quality");if(C1(x1)){let T=[];try{T=G0(x1)}catch{T=[]}for(let I of T){if(!I.endsWith(".json")||I==="gate-failure-count.json")continue;let h=i(l(x1,I));if(!h||typeof h!=="object")continue;if(!(("verdict"in h)||("approved"in h)||("reviewers"in h)))continue;N+=1;let o1=(h.verdict??"").toString().toLowerCase();if(h.approved===!0||["approved","approve","pass"].includes(o1))z1+=1;else if(["revision","revise","changes_requested","reject"].includes(o1))d1+=1}}return{phase:Q,iterationCount:z,iterations:W,totalInput:q,totalOutput:H,totalTokens:G,totalCost:J,totalDuration:B,budgetLimit:V,budgetUsed:M,gatesPassed:_,gatesTotal:k,gateFailures:g,reviewsTotal:N,reviewsApproved:z1,reviewsRevision:d1}}function c6($,Q){let z=$.iterationCount,X={session:{iterations:z,duration_seconds:$.totalDuration,phase:$.phase},tokens:{input:$.totalInput,output:$.totalOutput,total:$.totalTokens,cost_usd:d($.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?d($.totalTokens/z,0):0,avg_cost_per_iteration:z>0?d($.totalCost/z,2):0,avg_duration_per_iteration:z>0?d($.totalDuration/z,1):0},budget:{used:d($.budgetUsed,2),limit:$.budgetLimit,percent:$.budgetLimit>0?d($.budgetUsed/$.budgetLimit*100,1):0}};if(Q)X.iterations=$.iterations.map((W,q)=>({number:q+1,input_tokens:W.input_tokens??0,output_tokens:W.output_tokens??0,cost_usd:d(W.cost_usd??0,2),duration_seconds:W.duration_seconds??0}));let Z=JSON.stringify(X,null,2);function K(W,q){if(!q)return;let H=new RegExp(`("${W}": )(-?\\d+)(,?)$`,"m");Z=Z.replace(H,(G,J,B,V)=>`${J}${B}.0${V}`)}if(K("avg_duration_per_iteration",z>0&&Number.isInteger(X.efficiency.avg_duration_per_iteration)),K("percent",$.budgetLimit>0&&Number.isInteger(X.budget.percent)),K("cost_usd",z>0&&Number.isInteger(X.tokens.cost_usd)),Q)Z=Z.replace(/("cost_usd": )(-?\d+)(,?)$/gm,(W,q,H,G)=>`${q}${H}.0${G}`);return Z}function l6($,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: ${N1($.totalDuration)}`),z.push(` Current phase: ${$.phase}`),z.push(""),z.push("Token Usage"),$.iterations.length>0)z.push(` Input tokens: ${e($.totalInput)}`),z.push(` Output tokens: ${e($.totalOutput)}`),z.push(` Total tokens: ${e($.totalTokens)}`),z.push(` Estimated cost: $${$1($.totalCost,2)}`);else z.push(" N/A (no iteration metrics found)");if(z.push(""),z.push("Quality Gates"),$.gatesTotal>0){let X=Math.round($.gatesPassed/$.gatesTotal*100);z.push(` Gates passed: ${$.gatesPassed}/${$.gatesTotal} (${X}%)`)}else z.push(" Gates passed: N/A");if($.reviewsTotal>0){let X=[];if($.reviewsApproved>0)X.push(`${$.reviewsApproved} approved`);if($.reviewsRevision>0)X.push(`${$.reviewsRevision} revision requested`);let Z=X.length>0?X.join(", "):"N/A";z.push(` Code reviews: ${$.reviewsTotal} (${Z})`)}if(Object.keys($.gateFailures).length>0){let X=Object.entries($.gateFailures).filter(([,Z])=>Z>0).map(([Z,K])=>`${Z} (${K})`);if(X.length>0)z.push(` Gate failures: ${X.join(", ")}`)}if(z.push(""),z.push("Efficiency"),$.iterationCount>0&&$.iterations.length>0){let X=Math.round($.totalTokens/$.iterationCount),Z=$.totalCost/$.iterationCount,K=$.totalDuration/$.iterationCount;z.push(` Avg tokens/iteration: ${e(X)}`),z.push(` Avg cost/iteration: $${$1(Z,2)}`),z.push(` Avg duration/iteration: ${N1(K)}`)}else z.push(" N/A (no iteration metrics found)");if(z.push(""),z.push("Budget"),$.budgetLimit>0){let X=d($.budgetUsed/$.budgetLimit*100,1),Z=Number.isInteger(X)?`${X}.0`:`${X}`;z.push(` Used: $${$1($.budgetUsed,2)} / $${$1($.budgetLimit,2)} (${Z}%)`)}else if($.budgetUsed>0)z.push(` Used: $${$1($.budgetUsed,2)} (no limit set)`);else z.push(" N/A");if(Q&&$.iterations.length>0)z.push(""),z.push("Per-Iteration Breakdown"),$.iterations.forEach((X,Z)=>{let K=Z+1,W=D1(e(X.input_tokens??0),10),q=D1(e(X.output_tokens??0),10),H=X.cost_usd??0,G=N1(X.duration_seconds??0),J=D1(`${K}`,3);z.push(` #${J} input: ${W} output: ${q} cost: $${$1(H,2)} time: ${G}`)});return z.join(`
265
- `)}function J0($){let Q=!1,z=!1;for(let W of $)if(W==="--json")Q=!0;else if(W==="--efficiency")z=!0;let X=P();if(!C1(X)){if(Q)return{exitCode:0,stdout:'{"error": "No active session"}'};return{exitCode:0,stdout:`${x}No active session found.${U}
266
- Start a session with: loki start <prd>`}}let Z=p6(X);return{exitCode:0,stdout:Q?c6(Z,z):l6(Z,z)}}async function d6($){let Q=J0($);return console.log(Q.stdout),Q.exitCode}var Y0=w(()=>{v();n()});var P0={};y(P0,{runDoctor:()=>Z3,pythonImportOk:()=>y1,httpReachable:()=>k1,checkTool:()=>j0,checkSkills:()=>_0,checkDisk:()=>b1,buildDoctorJson:()=>L0,_setPythonImportOkForTest:()=>i6});import{existsSync as o6,lstatSync as n6,readlinkSync as a6,statfsSync as s6}from"fs";import{homedir as A0}from"os";import{resolve as M0}from"path";function t6($){let Q=$.match(r6);return Q?Q[1]:null}async function T0($){try{let Q=await E([$,"--version"],{timeoutMs:5000}),z=(Q.stdout||Q.stderr||"").trim();return t6(z)}catch{return null}}function O0($,Q){let z=$.split(".").map((Z)=>parseInt(Z,10)),X=Q.split(".").map((Z)=>parseInt(Z,10));while(z.length<2)z.push(0);while(X.length<2)X.push(0);for(let Z=0;Z<2;Z++){let K=z[Z]??0,W=X[Z]??0;if(Number.isNaN(K)||Number.isNaN(W))return 0;if(K!==W)return K-W}return 0}async function j0($,Q,z,X=null){let Z=await b(Q),K=Z!==null,W=K?await T0(Q):null,q="pass";if(!K)q=z==="required"?"fail":"warn";else if(X&&W){if(O0(W,X)<0)q=z==="required"?"fail":"warn"}return{name:$,command:Q,found:K,version:W,required:z,min_version:X,status:q,path:Z}}function b1(){let $=null;try{let z=s6(A0()),X=Number(z.bavail)*Number(z.bsize);$=Math.round(X/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 k1($,Q=2000){try{return(await fetch($,{signal:AbortSignal.timeout(Q)})).ok}catch{return!1}}async function y1($,Q=!1){let z=`import ${$}`,X=Q?30000:5000;if(!Q)return(await a(z,{timeoutMs:X})).exitCode===0;let Z=await r();if(!Z)return!1;return(await E([Z,"-c",z],{timeoutMs:X})).exitCode===0}function i6($){M1.fn=$??y1}function _0(){let $=A0();return e6.map(({name:Q,dir:z})=>{let X=M0($,z),Z=X,K=M0(X,"SKILL.md");if(o6(K))return{name:Q,path:Z,status:"pass",detail:""};try{if(n6(X).isSymbolicLink()){let q="unknown";try{q=a6(X)}catch{}return{name:Q,path:Z,status:"fail",detail:`(broken symlink -> ${q})`}}}catch{}return{name:Q,path:Z,status:"warn",detail:"(not found - run 'loki setup-skill')"}})}async function I0(){return Promise.all($3.map(async($)=>{return{...await j0($.jsonName,$.cmd,$.required,$.min??null),displayName:$.displayName}}))}async function z3(){let Q=await b("sentrux")!==null,z=Q?await T0("sentrux"):null;return{found:Q,version:z,status:Q?"pass":"warn",required:"optional"}}async function L0(){let Q=(await I0()).map(({displayName:q,...H})=>H),z=b1(),X=await z3(),Z=0,K=0,W=0;for(let q of Q)if(q.status==="pass")Z++;else if(q.status==="fail")K++;else W++;if(z.status==="pass")Z++;else if(z.status==="fail")K++;else W++;return{checks:Q,disk:z,sentrux:X,summary:{passed:Z,failed:K,warnings:W,ok:K===0}}}function Y($){switch($){case"pass":return`${C}PASS${U}`;case"fail":return`${L}FAIL${U}`;case"warn":return`${x}WARN${U}`}}function B1($){let Q=$.version?` (v${$.version})`:"",z=$.displayName;if(!$.found){let X=$.required==="required"?"not found":$.required==="recommended"?"not found (recommended)":"not found (optional)";return` ${Y($.status)} ${z} - ${X}`}if($.min_version&&$.version&&O0($.version,$.min_version)<0){let X=$.required==="required"?"requires":"recommended";return` ${Y($.status)} ${z}${Q} - ${X} >= ${$.min_version}`}return` ${Y($.status)} ${z}${Q}`}function Y1($,Q){if(Q==="pass")$.pass++;else if(Q==="fail")$.fail++;else $.warn++}function Q3(){process.stdout.write(`${D}loki doctor${U} - Check system prerequisites
264
+ `;var G0=L(()=>{p();Q1();n();y()});var O0={};b(O0,{runStats:()=>W5,computeStats:()=>Y0});import{readdirSync as B0,readFileSync as z5,statSync as M0}from"fs";import{join as l}from"path";function i(K){try{if(!M0(K).isFile())return null;return JSON.parse(z5(K,"utf-8"))}catch{return null}}function b1(K){try{return M0(K).isDirectory()}catch{return!1}}function Q5(K){if(!b1(K))return[];try{let $=B0(K).filter((z)=>z.startsWith("iteration-")&&z.endsWith(".json"));return $.sort(),$.map((z)=>l(K,z))}catch{return[]}}function e(K){return Math.trunc(K).toLocaleString("en-US")}function C1(K){let $=Math.trunc(K);if($<60)return`${$}s`;let z=Math.trunc($/3600),Q=Math.trunc($%3600/60),X=$%60;if(z>0)return`${z}h ${String(Q).padStart(2,"0")}m`;return`${Q}m ${String(X).padStart(2,"0")}s`}function d(K,$=0){let z=Math.pow(10,$);return Math.round(K*z)/z}function K1(K,$){return K.toFixed($)}function h1(K,$){return K.length>=$?K:K+" ".repeat($-K.length)}function X5(K){let $="N/A",z=0,Q=i(l(K,"state","orchestrator.json"));if(Q&&typeof Q==="object"){if(typeof Q.currentPhase==="string")$=Q.currentPhase;if(typeof Q.currentIteration==="number")z=Q.currentIteration}let X=l(K,"metrics","efficiency"),H=Q5(X),Z=[];for(let T of H){let I=i(T);if(I&&typeof I==="object")Z.push(I)}if(Z.length>0)z=Math.max(z,Z.length);let V=Z.reduce((T,I)=>T+(I.input_tokens??0),0),q=Z.reduce((T,I)=>T+(I.output_tokens??0),0),U=V+q,G=Z.reduce((T,I)=>T+(I.cost_usd??0),0),B=Z.reduce((T,I)=>T+(I.duration_seconds??0),0),J=0,Y=0,j=i(l(K,"metrics","budget.json"));if(j&&typeof j==="object"){if(typeof j.budget_limit==="number")J=j.budget_limit;if(typeof j.budget_used==="number")Y=j.budget_used}let _=0,C=0,g=i(l(K,"state","quality-gates.json"));if(g&&typeof g==="object"){if(Array.isArray(g)){for(let T of g)if(C+=1,T===!0)_+=1;else if(T&&typeof T==="object"){let I=T;if(I.passed===!0||I.status==="passed")_+=1}}else for(let T of Object.values(g))if(typeof T==="boolean"){if(C+=1,T)_+=1}else if(T&&typeof T==="object"){C+=1;let I=T;if(I.passed===!0||I.status==="passed")_+=1}}let m={},A=i(l(K,"quality","gate-failure-count.json"));if(A&&typeof A==="object"&&!Array.isArray(A)){let T={};for(let[I,v]of Object.entries(A))if(typeof v==="number")T[I]=v;m=T}let N=0,$1=0,a1=0,F1=l(K,"quality");if(b1(F1)){let T=[];try{T=B0(F1)}catch{T=[]}for(let I of T){if(!I.endsWith(".json")||I==="gate-failure-count.json")continue;let v=i(l(F1,I));if(!v||typeof v!=="object")continue;if(!(("verdict"in v)||("approved"in v)||("reviewers"in v)))continue;N+=1;let s1=(v.verdict??"").toString().toLowerCase();if(v.approved===!0||["approved","approve","pass"].includes(s1))$1+=1;else if(["revision","revise","changes_requested","reject"].includes(s1))a1+=1}}return{phase:$,iterationCount:z,iterations:Z,totalInput:V,totalOutput:q,totalTokens:U,totalCost:G,totalDuration:B,budgetLimit:J,budgetUsed:Y,gatesPassed:_,gatesTotal:C,gateFailures:m,reviewsTotal:N,reviewsApproved:$1,reviewsRevision:a1}}function Z5(K,$){let z=K.iterationCount,Q={session:{iterations:z,duration_seconds:K.totalDuration,phase:K.phase},tokens:{input:K.totalInput,output:K.totalOutput,total:K.totalTokens,cost_usd:d(K.totalCost,2)},quality:{gates_passed:K.gatesPassed,gates_total:K.gatesTotal,reviews_total:K.reviewsTotal,reviews_approved:K.reviewsApproved,reviews_revision:K.reviewsRevision,gate_failures:K.gateFailures},efficiency:{avg_tokens_per_iteration:z>0?d(K.totalTokens/z,0):0,avg_cost_per_iteration:z>0?d(K.totalCost/z,2):0,avg_duration_per_iteration:z>0?d(K.totalDuration/z,1):0},budget:{used:d(K.budgetUsed,2),limit:K.budgetLimit,percent:K.budgetLimit>0?d(K.budgetUsed/K.budgetLimit*100,1):0}};if($)Q.iterations=K.iterations.map((Z,V)=>({number:V+1,input_tokens:Z.input_tokens??0,output_tokens:Z.output_tokens??0,cost_usd:d(Z.cost_usd??0,2),duration_seconds:Z.duration_seconds??0}));let X=JSON.stringify(Q,null,2);function H(Z,V){if(!V)return;let q=new RegExp(`("${Z}": )(-?\\d+)(,?)$`,"m");X=X.replace(q,(U,G,B,J)=>`${G}${B}.0${J}`)}if(H("avg_duration_per_iteration",z>0&&Number.isInteger(Q.efficiency.avg_duration_per_iteration)),H("percent",K.budgetLimit>0&&Number.isInteger(Q.budget.percent)),H("cost_usd",z>0&&Number.isInteger(Q.tokens.cost_usd)),$)X=X.replace(/("cost_usd": )(-?\d+)(,?)$/gm,(Z,V,q,U)=>`${V}${q}.0${U}`);return X}function H5(K,$){let z=[];if(z.push("Loki Mode Session Statistics"),z.push("============================"),z.push(""),z.push("Session"),z.push(` Iterations completed: ${K.iterationCount}`),z.push(` Duration: ${C1(K.totalDuration)}`),z.push(` Current phase: ${K.phase}`),z.push(""),z.push("Token Usage"),K.iterations.length>0)z.push(` Input tokens: ${e(K.totalInput)}`),z.push(` Output tokens: ${e(K.totalOutput)}`),z.push(` Total tokens: ${e(K.totalTokens)}`),z.push(` Estimated cost: $${K1(K.totalCost,2)}`);else z.push(" N/A (no iteration metrics found)");if(z.push(""),z.push("Quality Gates"),K.gatesTotal>0){let Q=Math.round(K.gatesPassed/K.gatesTotal*100);z.push(` Gates passed: ${K.gatesPassed}/${K.gatesTotal} (${Q}%)`)}else z.push(" Gates passed: N/A");if(K.reviewsTotal>0){let Q=[];if(K.reviewsApproved>0)Q.push(`${K.reviewsApproved} approved`);if(K.reviewsRevision>0)Q.push(`${K.reviewsRevision} revision requested`);let X=Q.length>0?Q.join(", "):"N/A";z.push(` Code reviews: ${K.reviewsTotal} (${X})`)}if(Object.keys(K.gateFailures).length>0){let Q=Object.entries(K.gateFailures).filter(([,X])=>X>0).map(([X,H])=>`${X} (${H})`);if(Q.length>0)z.push(` Gate failures: ${Q.join(", ")}`)}if(z.push(""),z.push("Efficiency"),K.iterationCount>0&&K.iterations.length>0){let Q=Math.round(K.totalTokens/K.iterationCount),X=K.totalCost/K.iterationCount,H=K.totalDuration/K.iterationCount;z.push(` Avg tokens/iteration: ${e(Q)}`),z.push(` Avg cost/iteration: $${K1(X,2)}`),z.push(` Avg duration/iteration: ${C1(H)}`)}else z.push(" N/A (no iteration metrics found)");if(z.push(""),z.push("Budget"),K.budgetLimit>0){let Q=d(K.budgetUsed/K.budgetLimit*100,1),X=Number.isInteger(Q)?`${Q}.0`:`${Q}`;z.push(` Used: $${K1(K.budgetUsed,2)} / $${K1(K.budgetLimit,2)} (${X}%)`)}else if(K.budgetUsed>0)z.push(` Used: $${K1(K.budgetUsed,2)} (no limit set)`);else z.push(" N/A");if($&&K.iterations.length>0)z.push(""),z.push("Per-Iteration Breakdown"),K.iterations.forEach((Q,X)=>{let H=X+1,Z=h1(e(Q.input_tokens??0),10),V=h1(e(Q.output_tokens??0),10),q=Q.cost_usd??0,U=C1(Q.duration_seconds??0),G=h1(`${H}`,3);z.push(` #${G} input: ${Z} output: ${V} cost: $${K1(q,2)} time: ${U}`)});return z.join(`
265
+ `)}function Y0(K){let $=!1,z=!1;for(let Z of K)if(Z==="--json")$=!0;else if(Z==="--efficiency")z=!0;let Q=P();if(!b1(Q)){if($)return{exitCode:0,stdout:'{"error": "No active session"}'};return{exitCode:0,stdout:`${E}No active session found.${W}
266
+ Start a session with: loki start <prd>`}}let X=X5(Q);return{exitCode:0,stdout:$?Z5(X,z):H5(X,z)}}async function W5(K){let $=Y0(K);return console.log($.stdout),$.exitCode}var T0=L(()=>{y();n()});var x0={};b(x0,{runDoctor:()=>_5,pythonImportOk:()=>g1,httpReachable:()=>y1,checkTool:()=>P0,checkSkills:()=>L0,checkDisk:()=>v1,buildDoctorJson:()=>E0,_setPythonImportOkForTest:()=>M5});import{existsSync as V5,lstatSync as q5,readlinkSync as U5,statfsSync as J5}from"fs";import{homedir as j0}from"os";import{resolve as A0}from"path";function B5(K){let $=K.match(G5);return $?$[1]:null}async function _0(K){try{let $=await w([K,"--version"],{timeoutMs:5000}),z=($.stdout||$.stderr||"").trim();return B5(z)}catch{return null}}function I0(K,$){let z=K.split(".").map((X)=>parseInt(X,10)),Q=$.split(".").map((X)=>parseInt(X,10));while(z.length<2)z.push(0);while(Q.length<2)Q.push(0);for(let X=0;X<2;X++){let H=z[X]??0,Z=Q[X]??0;if(Number.isNaN(H)||Number.isNaN(Z))return 0;if(H!==Z)return H-Z}return 0}async function P0(K,$,z,Q=null){let X=await h($),H=X!==null,Z=H?await _0($):null,V="pass";if(!H)V=z==="required"?"fail":"warn";else if(Q&&Z){if(I0(Z,Q)<0)V=z==="required"?"fail":"warn"}return{name:K,command:$,found:H,version:Z,required:z,min_version:Q,status:V,path:X}}function v1(){let K=null;try{let z=J5(j0()),Q=Number(z.bavail)*Number(z.bsize);K=Math.round(Q/1073741824*10)/10}catch{K=null}let $="pass";if(K!==null){if(K<1)$="fail";else if(K<5)$="warn"}return{available_gb:K,status:$}}async function y1(K,$=2000){try{return(await fetch(K,{signal:AbortSignal.timeout($)})).ok}catch{return!1}}async function g1(K,$=!1){let z=`import ${K}`,Q=$?30000:5000;if(!$)return(await a(z,{timeoutMs:Q})).exitCode===0;let X=await r();if(!X)return!1;return(await w([X,"-c",z],{timeoutMs:Q})).exitCode===0}function M5(K){O1.fn=K??g1}function L0(){let K=j0();return Y5.map(({name:$,dir:z})=>{let Q=A0(K,z),X=Q,H=A0(Q,"SKILL.md");if(V5(H))return{name:$,path:X,status:"pass",detail:""};try{if(q5(Q).isSymbolicLink()){let V="unknown";try{V=U5(Q)}catch{}return{name:$,path:X,status:"fail",detail:`(broken symlink -> ${V})`}}}catch{}return{name:$,path:X,status:"warn",detail:"(not found - run 'loki setup-skill')"}})}async function R0(){return Promise.all(O5.map(async(K)=>{return{...await P0(K.jsonName,K.cmd,K.required,K.min??null),displayName:K.displayName}}))}async function T5(){let $=await h("sentrux")!==null,z=$?await _0("sentrux"):null;return{found:$,version:z,status:$?"pass":"warn",required:"optional"}}async function E0(){let $=(await R0()).map(({displayName:V,...q})=>q),z=v1(),Q=await T5(),X=0,H=0,Z=0;for(let V of $)if(V.status==="pass")X++;else if(V.status==="fail")H++;else Z++;if(z.status==="pass")X++;else if(z.status==="fail")H++;else Z++;return{checks:$,disk:z,sentrux:Q,summary:{passed:X,failed:H,warnings:Z,ok:H===0}}}function M(K){switch(K){case"pass":return`${D}PASS${W}`;case"fail":return`${R}FAIL${W}`;case"warn":return`${E}WARN${W}`}}function M1(K){let $=K.version?` (v${K.version})`:"",z=K.displayName;if(!K.found){let Q=K.required==="required"?"not found":K.required==="recommended"?"not found (recommended)":"not found (optional)";return` ${M(K.status)} ${z} - ${Q}`}if(K.min_version&&K.version&&I0(K.version,K.min_version)<0){let Q=K.required==="required"?"requires":"recommended";return` ${M(K.status)} ${z}${$} - ${Q} >= ${K.min_version}`}return` ${M(K.status)} ${z}${$}`}function Y1(K,$){if($==="pass")K.pass++;else if($==="fail")K.fail++;else K.warn++}function A5(){process.stdout.write(`${k}loki doctor${W} - Check system prerequisites
267
267
 
268
268
  `),process.stdout.write(`Usage: loki doctor [--json]
269
269
 
@@ -272,93 +272,118 @@ Start a session with: loki start <prd>`}}let Z=p6(X);return{exitCode:0,stdout:Q?
272
272
 
273
273
  `),process.stdout.write(`Checks: node, python3, jq, git, curl, bash version,
274
274
  `),process.stdout.write(` claude/codex CLIs, and disk space.
275
- `)}async function X3(){process.stdout.write(`${D}Loki Mode Doctor${U}
275
+ `)}async function j5(){process.stdout.write(`${k}Loki Mode Doctor${W}
276
276
 
277
277
  `),process.stdout.write(`Checking system prerequisites...
278
278
 
279
- `);let $={pass:0,fail:0,warn:0},Q=await I0(),z=new Map(Q.map((O)=>[O.command,O]));process.stdout.write(`${A}Required:${U}
280
- `);for(let O of["node","python3","jq","git","curl"]){let N=z.get(O);process.stdout.write(B1(N)+`
281
- `),Y1($,N.status)}process.stdout.write(`
282
- `),process.stdout.write(`${A}AI Providers:${U}
283
- `);let X=["claude","codex","cline","aider"],Z=!1;for(let O of X){let N=z.get(O);if(process.stdout.write(B1(N)+`
284
- `),Y1($,N.status),N.found)Z=!0}if(!Z)process.stdout.write(` ${Y("fail")} No AI provider CLI installed -- at least one is required
285
- `),process.stdout.write(` ${x}Install: npm install -g @anthropic-ai/claude-code${U}
286
- `),$.fail++;process.stdout.write(`
287
- `),process.stdout.write(`${A}API Keys:${U}
288
- `);let K=z.get("claude")?.found??!1,W=z.get("codex")?.found??!1,q=process.env;if(q.ANTHROPIC_API_KEY)process.stdout.write(` ${Y("pass")} ANTHROPIC_API_KEY is set
289
- `),$.pass++;else if(K)process.stdout.write(` ${R} -- ${U} ANTHROPIC_API_KEY not set (Claude CLI uses its own login)
290
- `);if(q.OPENAI_API_KEY)process.stdout.write(` ${Y("pass")} OPENAI_API_KEY is set
291
- `),$.pass++;else if(W)process.stdout.write(` ${R} -- ${U} OPENAI_API_KEY not set (Codex CLI uses its own login)
292
- `);if(q.ANTHROPIC_BASE_URL){let O=q.ANTHROPIC_BASE_URL;if(process.stdout.write(` ${Y("pass")} ANTHROPIC_BASE_URL: ${O}
293
- `),$.pass++,!q.LOKI_MODEL_OVERRIDE)process.stdout.write(` ${Y("warn")} LOKI_MODEL_OVERRIDE not set -- opus/sonnet/haiku aliases may not resolve on alt-provider
294
- `),$.warn++;else process.stdout.write(` ${Y("pass")} LOKI_MODEL_OVERRIDE: ${q.LOKI_MODEL_OVERRIDE}
295
- `),$.pass++}process.stdout.write(`
296
- `),process.stdout.write(`${A}Skills:${U}
297
- `);for(let O of _0())if(O.status==="pass")process.stdout.write(` ${Y("pass")} ${O.name} ${R}${O.path}${U}
298
- `),$.pass++;else if(O.status==="fail")process.stdout.write(` ${Y("fail")} ${O.name} ${R}${O.detail}${U}
299
- `),process.stdout.write(` ${x}Fix: loki setup-skill${U}
300
- `),$.fail++;else process.stdout.write(` ${Y("warn")} ${O.name} ${R}${O.detail}${U}
301
- `),$.warn++;process.stdout.write(`
302
- `),process.stdout.write(`${A}Integrations:${U}
303
- `);let[H,G,J]=await Promise.all([M1.fn("mcp"),M1.fn("numpy",!0),M1.fn("sentence_transformers",!0)]);if(H)process.stdout.write(` ${Y("pass")} MCP SDK (Python)
304
- `),$.pass++;else process.stdout.write(` ${Y("warn")} MCP SDK - not installed (pip3 install mcp)
305
- `),$.warn++;if(G)process.stdout.write(` ${Y("pass")} numpy (vector search)
306
- `),$.pass++;else process.stdout.write(` ${Y("warn")} numpy - not installed (pip3 install numpy)
307
- `),$.warn++;if(J)process.stdout.write(` ${Y("pass")} sentence-transformers (embeddings)
308
- `),$.pass++;else process.stdout.write(` ${Y("warn")} sentence-transformers - not installed (loki memory vectors setup)
309
- `),$.warn++;if(await k1("http://localhost:8100/api/v2/heartbeat"))process.stdout.write(` ${Y("pass")} ChromaDB server (port 8100)
310
- `),$.pass++;else process.stdout.write(` ${Y("warn")} ChromaDB - not running (docker start loki-chroma)
311
- `),$.warn++;let B=process.env.LOKI_MIROFISH_URL;if(B)if(await k1(`${B}/health`))process.stdout.write(` ${Y("pass")} MiroFish server (${B})
312
- `),$.pass++;else process.stdout.write(` ${Y("warn")} MiroFish - not running (loki start --mirofish-docker <image>)
313
- `),$.warn++;if(process.env.LOKI_OTEL_ENDPOINT)process.stdout.write(` ${Y("pass")} OTEL endpoint: ${process.env.LOKI_OTEL_ENDPOINT}
314
- `),$.pass++;else process.stdout.write(` ${Y("warn")} OTEL - not configured (set LOKI_OTEL_ENDPOINT)
315
- `),$.warn++;if(await b("sentrux")){let O="unknown";try{let z1=(await E(["sentrux","--version"],{timeoutMs:2000})).stdout.split(/\s+/).filter(Boolean).pop();if(z1)O=z1.replace(/^v/,"")}catch{}process.stdout.write(` ${Y("pass")} sentrux ${O} (architectural drift gate: loki sentrux help)
316
- `),$.pass++}else process.stdout.write(` ${Y("warn")} sentrux - not installed (optional, brew install sentrux/tap/sentrux)
317
- `),$.warn++;process.stdout.write(`
318
- `),process.stdout.write(`${A}System:${U}
319
- `);let V=z.get("bash");process.stdout.write(B1(V)+`
320
- `),Y1($,V.status);let M=z.get("bun");if(M)process.stdout.write(B1(M)+`
321
- `),Y1($,M.status);let j=b1(),_=j.available_gb===null?null:Math.floor(j.available_gb);if(_===null)process.stdout.write(` ${Y("warn")} Disk space: unable to determine
322
- `),$.warn++;else if(j.status==="fail")process.stdout.write(` ${Y("fail")} Disk space: ${_}GB available (need >= 1GB)
323
- `),$.fail++;else if(j.status==="warn")process.stdout.write(` ${Y("warn")} Disk space: ${_}GB available (low)
324
- `),$.warn++;else process.stdout.write(` ${Y("pass")} Disk space: ${_}GB available
325
- `),$.pass++;process.stdout.write(`
326
- `),process.stdout.write(`${A}Runtime route:${U}
327
- `);let k=process.versions.bun!==void 0,m=process.argv[0]??"(unknown)";if(process.stdout.write(` ${Y("pass")} Active runtime: ${k?"Bun":"Node"} (${m})
328
- `),process.env.LOKI_LEGACY_BASH==="1"||process.env.LOKI_LEGACY_BASH==="true")process.stdout.write(` ${Y("warn")} LOKI_LEGACY_BASH set: shim routes every command to autonomy/loki (bash)
329
- `);if(process.env.LOKI_TS_ENTRY)process.stdout.write(` ${Y("pass")} LOKI_TS_ENTRY override: ${process.env.LOKI_TS_ENTRY}
330
- `);if(process.env.BUN_FROM_SOURCE==="1"||process.env.BUN_FROM_SOURCE==="true")process.stdout.write(` ${Y("pass")} BUN_FROM_SOURCE set: shim prefers loki-ts/src/ over dist/
331
- `);let g=await r();if(g!==null){let N=(await E([g,"-c","import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')"],{timeoutMs:5000})).stdout.trim();if(N.startsWith("3.12"))process.stdout.write(` ${Y("pass")} Python 3.12 (chromadb / sentence-transformers): ${N} at ${g}
332
- `);else if(N)process.stdout.write(` ${Y("warn")} Python 3.12 NOT found -- using ${N} at ${g}; chromadb / sentence-transformers may fail. Install python3.12 (brew install python@3.12 / apt install python3.12).
333
- `);else process.stdout.write(` ${Y("warn")} Python 3 found at ${g} but version probe failed; chromadb may not work.
334
- `)}else process.stdout.write(` ${Y("warn")} Python 3 not on PATH -- memory + MCP integrations disabled.
279
+ `);let K={pass:0,fail:0,warn:0},$=await R0(),z=new Map($.map((A)=>[A.command,A]));process.stdout.write(`${O}Required:${W}
280
+ `);for(let A of["node","python3","jq","git","curl"]){let N=z.get(A);process.stdout.write(M1(N)+`
281
+ `),Y1(K,N.status)}process.stdout.write(`
282
+ `),process.stdout.write(`${O}AI Providers:${W}
283
+ `);let Q=["claude","codex","cline","aider"],X=!1;for(let A of Q){let N=z.get(A);if(process.stdout.write(M1(N)+`
284
+ `),Y1(K,N.status),N.found)X=!0}if(!X)process.stdout.write(` ${M("fail")} No AI provider CLI installed -- at least one is required
285
+ `),process.stdout.write(` ${E}Install: npm install -g @anthropic-ai/claude-code${W}
286
+ `),K.fail++;process.stdout.write(`
287
+ `),process.stdout.write(`${O}API Keys:${W}
288
+ `);let H=z.get("claude")?.found??!1,Z=z.get("codex")?.found??!1,V=process.env;if(V.ANTHROPIC_API_KEY)process.stdout.write(` ${M("pass")} ANTHROPIC_API_KEY is set
289
+ `),K.pass++;else if(H)process.stdout.write(` ${x} -- ${W} ANTHROPIC_API_KEY not set (Claude CLI uses its own login)
290
+ `);if(V.OPENAI_API_KEY)process.stdout.write(` ${M("pass")} OPENAI_API_KEY is set
291
+ `),K.pass++;else if(Z)process.stdout.write(` ${x} -- ${W} OPENAI_API_KEY not set (Codex CLI uses its own login)
292
+ `);if(V.ANTHROPIC_BASE_URL){let A=V.ANTHROPIC_BASE_URL;if(process.stdout.write(` ${M("pass")} ANTHROPIC_BASE_URL: ${A}
293
+ `),K.pass++,!V.LOKI_MODEL_OVERRIDE)process.stdout.write(` ${M("warn")} LOKI_MODEL_OVERRIDE not set -- opus/sonnet/haiku aliases may not resolve on alt-provider
294
+ `),K.warn++;else process.stdout.write(` ${M("pass")} LOKI_MODEL_OVERRIDE: ${V.LOKI_MODEL_OVERRIDE}
295
+ `),K.pass++}process.stdout.write(`
296
+ `),process.stdout.write(`${O}Skills:${W}
297
+ `);for(let A of L0())if(A.status==="pass")process.stdout.write(` ${M("pass")} ${A.name} ${x}${A.path}${W}
298
+ `),K.pass++;else if(A.status==="fail")process.stdout.write(` ${M("fail")} ${A.name} ${x}${A.detail}${W}
299
+ `),process.stdout.write(` ${E}Fix: loki setup-skill${W}
300
+ `),K.fail++;else process.stdout.write(` ${M("warn")} ${A.name} ${x}${A.detail}${W}
301
+ `),K.warn++;process.stdout.write(`
302
+ `),process.stdout.write(`${O}Integrations:${W}
303
+ `);let[q,U,G]=await Promise.all([O1.fn("mcp"),O1.fn("numpy",!0),O1.fn("sentence_transformers",!0)]);if(q)process.stdout.write(` ${M("pass")} MCP SDK (Python)
304
+ `),K.pass++;else process.stdout.write(` ${M("warn")} MCP SDK - not installed (pip3 install mcp)
305
+ `),K.warn++;if(U)process.stdout.write(` ${M("pass")} numpy (vector search)
306
+ `),K.pass++;else process.stdout.write(` ${M("warn")} numpy - not installed (pip3 install numpy)
307
+ `),K.warn++;if(G)process.stdout.write(` ${M("pass")} sentence-transformers (embeddings)
308
+ `),K.pass++;else process.stdout.write(` ${M("warn")} sentence-transformers - not installed (loki memory vectors setup)
309
+ `),K.warn++;if(await y1("http://localhost:8100/api/v2/heartbeat"))process.stdout.write(` ${M("pass")} ChromaDB server (port 8100)
310
+ `),K.pass++;else process.stdout.write(` ${M("warn")} ChromaDB - not running (docker start loki-chroma)
311
+ `),K.warn++;let B=process.env.LOKI_MIROFISH_URL;if(B)if(await y1(`${B}/health`))process.stdout.write(` ${M("pass")} MiroFish server (${B})
312
+ `),K.pass++;else process.stdout.write(` ${M("warn")} MiroFish - not running (loki start --mirofish-docker <image>)
313
+ `),K.warn++;if(process.env.LOKI_OTEL_ENDPOINT)process.stdout.write(` ${M("pass")} OTEL endpoint: ${process.env.LOKI_OTEL_ENDPOINT}
314
+ `),K.pass++;else process.stdout.write(` ${M("warn")} OTEL - not configured (set LOKI_OTEL_ENDPOINT)
315
+ `),K.warn++;if(await h("sentrux")){let A="unknown";try{let $1=(await w(["sentrux","--version"],{timeoutMs:2000})).stdout.split(/\s+/).filter(Boolean).pop();if($1)A=$1.replace(/^v/,"")}catch{}process.stdout.write(` ${M("pass")} sentrux ${A} (architectural drift gate: loki sentrux help)
316
+ `),K.pass++}else process.stdout.write(` ${M("warn")} sentrux - not installed (optional, brew install sentrux/tap/sentrux)
317
+ `),K.warn++;process.stdout.write(`
318
+ `),process.stdout.write(`${O}System:${W}
319
+ `);let J=z.get("bash");process.stdout.write(M1(J)+`
320
+ `),Y1(K,J.status);let Y=z.get("bun");if(Y)process.stdout.write(M1(Y)+`
321
+ `),Y1(K,Y.status);let j=v1(),_=j.available_gb===null?null:Math.floor(j.available_gb);if(_===null)process.stdout.write(` ${M("warn")} Disk space: unable to determine
322
+ `),K.warn++;else if(j.status==="fail")process.stdout.write(` ${M("fail")} Disk space: ${_}GB available (need >= 1GB)
323
+ `),K.fail++;else if(j.status==="warn")process.stdout.write(` ${M("warn")} Disk space: ${_}GB available (low)
324
+ `),K.warn++;else process.stdout.write(` ${M("pass")} Disk space: ${_}GB available
325
+ `),K.pass++;process.stdout.write(`
326
+ `),process.stdout.write(`${O}Runtime route:${W}
327
+ `);let C=process.versions.bun!==void 0,g=process.argv[0]??"(unknown)";if(process.stdout.write(` ${M("pass")} Active runtime: ${C?"Bun":"Node"} (${g})
328
+ `),process.env.LOKI_LEGACY_BASH==="1"||process.env.LOKI_LEGACY_BASH==="true")process.stdout.write(` ${M("warn")} LOKI_LEGACY_BASH set: shim routes every command to autonomy/loki (bash)
329
+ `);if(process.env.LOKI_TS_ENTRY)process.stdout.write(` ${M("pass")} LOKI_TS_ENTRY override: ${process.env.LOKI_TS_ENTRY}
330
+ `);if(process.env.BUN_FROM_SOURCE==="1"||process.env.BUN_FROM_SOURCE==="true")process.stdout.write(` ${M("pass")} BUN_FROM_SOURCE set: shim prefers loki-ts/src/ over dist/
331
+ `);let m=await r();if(m!==null){let N=(await w([m,"-c","import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')"],{timeoutMs:5000})).stdout.trim();if(N.startsWith("3.12"))process.stdout.write(` ${M("pass")} Python 3.12 (chromadb / sentence-transformers): ${N} at ${m}
332
+ `);else if(N)process.stdout.write(` ${M("warn")} Python 3.12 NOT found -- using ${N} at ${m}; chromadb / sentence-transformers may fail. Install python3.12 (brew install python@3.12 / apt install python3.12).
333
+ `);else process.stdout.write(` ${M("warn")} Python 3 found at ${m} but version probe failed; chromadb may not work.
334
+ `)}else process.stdout.write(` ${M("warn")} Python 3 not on PATH -- memory + MCP integrations disabled.
335
335
  `);if(process.stdout.write(`
336
- `),process.stdout.write(`${D}Summary:${U} ${C}${$.pass} passed${U}, ${L}${$.fail} failed${U}, ${x}${$.warn} warnings${U}
336
+ `),process.stdout.write(`${k}Summary:${W} ${D}${K.pass} passed${W}, ${R}${K.fail} failed${W}, ${E}${K.warn} warnings${W}
337
337
 
338
- `),$.fail>0)return process.stdout.write(`${L}Some required prerequisites are missing.${U}
338
+ `),K.fail>0)return process.stdout.write(`${R}Some required prerequisites are missing.${W}
339
339
  `),process.stdout.write(`Install missing dependencies and run 'loki doctor' again.
340
- `),1;if($.warn>0)return process.stdout.write(`${x}All required checks passed with some warnings.${U}
341
- `),0;return process.stdout.write(`${C}All checks passed. System is ready for Loki Mode.${U}
342
- `),0}async function Z3($){let Q=!1;for(let z of $)if(z==="--json")Q=!0;else if(z==="--help"||z==="-h")return Q3(),0;else return process.stderr.write(`${L}Unknown option: ${z}${U}
340
+ `),1;if(K.warn>0)return process.stdout.write(`${E}All required checks passed with some warnings.${W}
341
+ `),0;return process.stdout.write(`${D}All checks passed. System is ready for Loki Mode.${W}
342
+ `),0}async function _5(K){let $=!1;for(let z of K)if(z==="--json")$=!0;else if(z==="--help"||z==="-h")return A5(),0;else return process.stderr.write(`${R}Unknown option: ${z}${W}
343
343
  `),process.stderr.write(`Usage: loki doctor [--json]
344
- `),1;if(Q){let z=await L0();return process.stdout.write(JSON.stringify(z,null,2)+`
345
- `),0}return X3()}var r6,M1,e6,$3;var x0=w(()=>{p();X1();n();r6=/(\d+\.\d+(?:\.\d+)*)/;M1={fn:y1};e6=[{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"}];$3=[{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{closeSync as T7,fstatSync as O7,lstatSync as j7,mkdirSync as K3,openSync as _7,readSync as I7,renameSync as W3,rmSync as L7,statSync as P7,unlinkSync as x7,writeFileSync as U3,writeSync as R7}from"fs";import{dirname as q3}from"path";function W1($,Q){K3(q3($),{recursive:!0});let z=`${$}.tmp.${process.pid}.${++H3}`;U3(z,`${JSON.stringify(Q,null,2)}
346
- `),W3(z,$)}async function R0($,Q){let z=A1.get($)??Promise.resolve(),X=()=>{},Z=new Promise((W)=>{X=W}),K=z.catch(()=>{}).then(()=>Z);A1.set($,K);try{return await z.catch(()=>{}),await Q()}finally{if(X(),A1.get($)===K)A1.delete($)}}var H3=0,A1;var T1=w(()=>{A1=new Map});import{existsSync as O1,mkdirSync as G3,copyFileSync as V3,readFileSync as J3,readdirSync as B3,statSync as Y3,writeFileSync as N7,renameSync as M3,appendFileSync as D7,rmSync as C7}from"fs";import{join as s,dirname as A3}from"path";function j1($){return s($,"state","checkpoints")}function O3($){let Q=j1($);if(!O1(Q))return[];return B3(Q).filter((z)=>z.startsWith("cp-")).filter((z)=>{try{return Y3(s(Q,z)).isDirectory()}catch{return!1}})}function j3($){return[...$].sort((Q,z)=>{let X=F0(Q),Z=F0(z);return X-Z})}function F0($){let Q=$.split("-");if(Q.length<3)return 0;let z=Q[Q.length-1],X=Number.parseInt(z??"0",10);return Number.isFinite(X)?X:0}function v1($){let Q=$??P(),z=j3(O3(Q)),X=[];for(let Z of z){let K=E0(Q,Z);if(K)X.push(K)}return X}function E0($,Q){let z=s(j1($),Q,"metadata.json");if(!O1(z))return null;try{let X=JSON.parse(J3(z,"utf-8"));return _3(X,z)}catch{return null}}function _3($,Q){let z=P3($,Q);return z.ok?z.value:null}function P3($,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=$,X=["id","timestamp","task_id","task_description","git_sha","git_branch","provider","phase"];for(let Z of X){if(!(Z in z))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${Z}" missing`),{ok:!1,reason:"missing_field",field:Z};if(typeof z[Z]!=="string")return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${Z}" not a string`),{ok:!1,reason:"invalid_type",field:Z}}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 Z of L3){let K=z[Z];if(I3.test(K))return console.warn(`[checkpoint] invalid metadata at ${Q}: field "${Z}" contains control characters`),{ok:!1,reason:"control_chars",field:Z}}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 m1($,Q){if(!x3.test($))throw new w0($);let z=Q??P(),X=s(j1(z),$);if(!O1(X))throw new h1($);let Z=E0(z,$);if(!Z)throw new h1($);return Z}function S0($,Q){let z=m1($,Q),X=Q??P(),Z=s(j1(X),$),K=[];for(let W of R3){let q=s(Z,W);if(!O1(q))continue;K.push({from:q,to:s(X,W)})}return{id:$,metadata:z,restore:K}}function N0($){let Q=[],z=0;for(let X of $.restore)try{G3(A3(X.to),{recursive:!0});let Z=`${X.to}.tmp.${process.pid}.${++T3}`;V3(X.from,Z),M3(Z,X.to),z+=1}catch(Z){Q.push(`${X.from} -> ${X.to}: ${Z.message}`)}return{restored:z,errors:Q}}var v7,T3=0,I3,L3,x3,h1,w0,R3;var D0=w(()=>{v();p();T1();v7=Promise.resolve();I3=/[\x00-\x08\x0a-\x1f\x7f-\x9f]/,L3=["id","task_id","git_sha","git_branch","provider","phase"];x3=/^[a-zA-Z0-9_-]+$/;h1=class h1 extends Error{id;constructor($){super(`Checkpoint not found: ${$}`);this.id=$;this.name="CheckpointNotFoundError"}};w0=class w0 extends Error{id;constructor($){super(`Invalid checkpoint ID: must be alphanumeric, hyphens, underscores only (got: ${$})`);this.id=$;this.name="InvalidCheckpointIdError"}};R3=["state/orchestrator.json","queue/pending.json","queue/completed.json","queue/in-progress.json","queue/current-task.json"]});var b0={};y(b0,{runRollback:()=>F3});async function F3($){let Q=$[0],z=$.slice(1);if(Q===void 0||Q==="help"||Q==="--help"||Q==="-h")return process.stdout.write(C0),Q===void 0?1:0;switch(Q){case"list":{let X=[...v1()].reverse();if(X.length===0)return process.stdout.write(`${x}No checkpoints found.${U}
347
- `),0;process.stdout.write(`${D}Checkpoints${U} (${X.length}, newest first):
348
- `);for(let Z of X)process.stdout.write(` ${A}${Z.id}${U} iter=${Z.iteration} ${Z.git_branch||"(no branch)"}@${(Z.git_sha||"").slice(0,7)} ${Z.timestamp}
349
- `);return 0}case"show":{let X=z[0];if(!X)return process.stderr.write(`${L}Missing checkpoint id.${U} Use \`loki rollback list\`.
350
- `),2;try{let Z=m1(X);return process.stdout.write(`${JSON.stringify(Z,null,2)}
351
- `),0}catch(Z){return process.stderr.write(`${L}Failed to read checkpoint:${U} ${Z.message}
352
- `),1}}case"to":{let X=z[0];if(!X)return process.stderr.write(`${L}Missing checkpoint id.${U} Use \`loki rollback list\`.
353
- `),2;return k0(X)}case"latest":{let X=v1(),Z=X[X.length-1];if(!Z)return process.stderr.write(`${L}No checkpoints found to roll back to.${U}
354
- `),1;return process.stdout.write(`Rolling back to latest checkpoint: ${A}${Z.id}${U}
355
- `),k0(Z.id)}default:return process.stderr.write(`Unknown subcommand: ${Q}
356
- `),process.stderr.write(C0),2}}function k0($){let Q;try{Q=S0($)}catch(X){return process.stderr.write(`${L}Cannot plan rollback:${U} ${X.message}
357
- `),1}if(Q.restore.length===0)return process.stdout.write(`${x}Checkpoint ${$} has no restorable state files; nothing to do.${U}
358
- `),0;let z=N0(Q);if(z.errors.length>0){for(let X of z.errors)process.stderr.write(`${L}restore error:${U} ${X}
359
- `);return process.stderr.write(`${L}Partial rollback: ${z.restored}/${Q.restore.length} files restored.${U}
360
- `),1}return process.stdout.write(`${C}Rolled back ${z.restored}/${Q.restore.length} state files from ${$}.${U}
361
- `),process.stdout.write("Run `loki start` to resume from the restored state.\n"),0}var C0=`Usage: loki rollback <subcommand>
344
+ `),1;if($){let z=await E0();return process.stdout.write(JSON.stringify(z,null,2)+`
345
+ `),0}return j5()}var G5,O1,Y5,O5;var F0=L(()=>{p();Q1();n();G5=/(\d+\.\d+(?:\.\d+)*)/;O1={fn:g1};Y5=[{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"}];O5=[{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 N0,mkdirSync as t6,readdirSync as I5,readFileSync as k0,renameSync as i6,writeFileSync as e6}from"fs";import{dirname as P5,join as L5,resolve as R5}from"path";import{fileURLToPath as E5}from"url";function x5(){try{let K=P5(E5(import.meta.url)),$=R5(K,"..","..","data","model-pricing.json");if(!N0($))return H1;let Q=JSON.parse(k0($,"utf8")).pricing;if(!Q||typeof Q!=="object")return H1;let X={};for(let[H,Z]of Object.entries(Q))if(Z!==null&&typeof Z==="object"&&typeof Z.input==="number"&&typeof Z.output==="number")X[H]={input:Z.input,output:Z.output};for(let H of Object.keys(H1))if(!(H in X))return H1;return X}catch{return H1}}function F5(K){return Math.round((K+Number.EPSILON)*1e4)/1e4}function w5(K){let $=(K??S0).toLowerCase();return w0[$]??w0[S0]}function D0(K){let $=0;for(let z of K){if(typeof z.cost_usd==="number"&&Number.isFinite(z.cost_usd)){$+=z.cost_usd;continue}let Q=w5(z.model),X=typeof z.input_tokens==="number"?z.input_tokens:0,H=typeof z.output_tokens==="number"?z.output_tokens:0;$+=X/1e6*Q.input+H/1e6*Q.output}return F5($)}function C0(K){if(!N0(K))return[];let $=[],z;try{z=I5(K)}catch{return[]}for(let Q of z){if(!Q.endsWith(".json"))continue;let X=L5(K,Q);try{let H=k0(X,"utf8"),Z=JSON.parse(H);if(Z&&typeof Z==="object")$.push(Z)}catch{}}return $}var H1,w0,S0="sonnet";var h0=L(()=>{y();H1={opus:{input:5,output:25},sonnet:{input:3,output:15},haiku:{input:1,output:5},"gpt-5.3-codex":{input:1.5,output:12}};w0=Object.freeze(x5())});import{existsSync as T1,readdirSync as S5,readFileSync as N5,statSync as k5}from"fs";import{join as A1}from"path";function D5(K){let $=[],z=A1(K,"votes");if(!T1(z))return $;let Q;try{Q=S5(z)}catch{return $}for(let X of Q){if(!X.startsWith("round-")||!X.endsWith(".json"))continue;try{let H=A1(z,X);if(!k5(H).isFile())continue;let Z=JSON.parse(N5(H,"utf8"));$.push({iteration:typeof Z.iteration==="number"?Z.iteration:void 0,verdict:typeof Z.verdict==="string"?Z.verdict:void 0,complete_votes:typeof Z.complete_votes==="number"?Z.complete_votes:void 0,total_members:typeof Z.total_members==="number"?Z.total_members:void 0,threshold:typeof Z.threshold==="number"?Z.threshold:void 0})}catch{}}return $}function C5(){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 h5(){return{council_rounds:0,unanimous_rate:null,approval_rate:null,iteration_success_rate:null}}function b5(K){let $=C5();if(K.length===0)return $;$.iteration_count=K.length,$.total_cost_usd=Math.round(D0(K)*1e4)/1e4;for(let z of K){if(typeof z.input_tokens==="number")$.total_input_tokens+=z.input_tokens;if(typeof z.output_tokens==="number")$.total_output_tokens+=z.output_tokens;let Q=z;if(typeof Q.duration_ms==="number")$.total_duration_ms+=Q.duration_ms;if(typeof z.model==="string")$.model_breakdown[z.model]=($.model_breakdown[z.model]??0)+1;if(typeof Q.phase==="string")$.phase_breakdown[Q.phase]=($.phase_breakdown[Q.phase]??0)+1;if(typeof Q.status==="string")$.status_breakdown[Q.status]=($.status_breakdown[Q.status]??0)+1}return $.avg_cost_per_iteration=Math.round($.total_cost_usd/$.iteration_count*1e4)/1e4,$.avg_duration_ms_per_iteration=Math.round($.total_duration_ms/$.iteration_count),$}function y5(K,$,z){let Q=h5();if(Q.council_rounds=K.length,K.length>0){let X=0,H=0;for(let Z of K){if(typeof Z.complete_votes==="number"&&typeof Z.total_members==="number"&&Z.total_members>0&&Z.complete_votes===Z.total_members)X+=1;if(Z.verdict==="COMPLETE")H+=1}Q.unanimous_rate=Math.round(X/K.length*1e4)/1e4,Q.approval_rate=Math.round(H/K.length*1e4)/1e4}if(z>0)Q.iteration_success_rate=Math.round($/z*1e4)/1e4;return Q}function b0(K){let $=[],z=A1(K,"metrics","efficiency"),Q=A1(K,"council"),X=T1(z)?C0(z):[];if(!T1(z))$.push("no .loki/metrics/efficiency/ dir (efficiency KPIs zeroed)");else if(X.length===0)$.push(".loki/metrics/efficiency/ exists but no iteration files found");let H=D5(Q);if(!T1(Q))$.push("no .loki/council/ dir (accuracy KPIs zeroed)");else if(H.length===0)$.push(".loki/council/ exists but no round-N.json files found");let Z=b5(X),V=Z.status_breakdown.success??0,q=y5(H,V,Z.iteration_count);return{schema_version:1,generated_at:new Date().toISOString(),loki_dir:K,efficiency:Z,accuracy:q,notes:$}}function y0(K){return JSON.stringify(K,null,2)}function v0(K){let $=[];$.push(`Loki Mode KPIs (snapshot at ${K.generated_at})`),$.push(`Source: ${K.loki_dir}`),$.push(""),$.push("Efficiency"),$.push(` Iterations: ${K.efficiency.iteration_count}`),$.push(` Total cost USD: ${K.efficiency.total_cost_usd}`),$.push(` Avg cost per iter: ${K.efficiency.avg_cost_per_iteration??"n/a"}`),$.push(` Total input tokens: ${K.efficiency.total_input_tokens}`),$.push(` Total output tokens: ${K.efficiency.total_output_tokens}`),$.push(` Total duration (ms): ${K.efficiency.total_duration_ms}`),$.push(` Avg duration / iter: ${K.efficiency.avg_duration_ms_per_iteration??"n/a"}`);let z=Object.entries(K.efficiency.model_breakdown).sort((H,Z)=>H[0].localeCompare(Z[0]));if(z.length>0)$.push(` Model breakdown: ${z.map(([H,Z])=>`${H}=${Z}`).join(", ")}`);let Q=Object.entries(K.efficiency.phase_breakdown).sort((H,Z)=>H[0].localeCompare(Z[0]));if(Q.length>0)$.push(` Phase breakdown: ${Q.map(([H,Z])=>`${H}=${Z}`).join(", ")}`);let X=Object.entries(K.efficiency.status_breakdown).sort((H,Z)=>H[0].localeCompare(Z[0]));if(X.length>0)$.push(` Status breakdown: ${X.map(([H,Z])=>`${H}=${Z}`).join(", ")}`);if($.push(""),$.push("Accuracy"),$.push(` Council rounds: ${K.accuracy.council_rounds}`),$.push(` Unanimous rate: ${K.accuracy.unanimous_rate??"n/a"}`),$.push(` Approval rate: ${K.accuracy.approval_rate??"n/a"}`),$.push(` Iter success rate: ${K.accuracy.iteration_success_rate??"n/a"}`),K.notes.length>0){$.push(""),$.push("Notes");for(let H of K.notes)$.push(` - ${H}`)}return $.join(`
346
+ `)}var g0=L(()=>{h0()});var m0={};b(m0,{runKpis:()=>g5});function g5(K){let $=!1;for(let Q of K){if(Q==="--help"||Q==="-h"||Q==="help")return process.stdout.write(v5),0;if(Q==="--json"){$=!0;continue}return process.stderr.write(`loki kpis: unknown arg: ${Q}
347
+ Run 'loki kpis --help' for usage.
348
+ `),1}let z=b0(P());return process.stdout.write($?y0(z)+`
349
+ `:v0(z)+`
350
+ `),0}var v5=`loki kpis -- accuracy + efficiency KPI snapshot (v7.5.28 MVP)
351
+
352
+ Usage:
353
+ loki kpis Pretty-print KPI snapshot
354
+ loki kpis --json Emit KPIs as JSON
355
+ loki kpis --help Show this help
356
+
357
+ Reads from .loki/metrics/efficiency/iteration-*.json and
358
+ .loki/council/votes/round-*.json. Missing files yield zero/null KPIs
359
+ with explicit notes (not silent failure).
360
+
361
+ Efficiency KPIs: iteration count, total cost USD, avg cost per iter,
362
+ total input/output tokens, model/phase/status breakdowns, durations.
363
+
364
+ Accuracy KPIs: council rounds, unanimous rate, approval rate,
365
+ iteration success rate.
366
+
367
+ This is the Phase K MVP -- read-only derivation. Per-iteration
368
+ emission, dashboard panel, and the loki-bench harness are deferred
369
+ follow-ups (see project_v7_5_18_arc_status.md).
370
+ `;var f0=L(()=>{g0();y()});import{closeSync as J8,fstatSync as G8,lstatSync as B8,mkdirSync as m5,openSync as M8,readSync as Y8,renameSync as f5,rmSync as O8,statSync as T8,unlinkSync as A8,writeFileSync as u5,writeSync as j8}from"fs";import{dirname as p5}from"path";function W1(K,$){m5(p5(K),{recursive:!0});let z=`${K}.tmp.${process.pid}.${++c5}`;u5(z,`${JSON.stringify($,null,2)}
371
+ `),f5(z,K)}async function u0(K,$){let z=j1.get(K)??Promise.resolve(),Q=()=>{},X=new Promise((Z)=>{Q=Z}),H=z.catch(()=>{}).then(()=>X);j1.set(K,H);try{return await z.catch(()=>{}),await $()}finally{if(Q(),j1.get(K)===H)j1.delete(K)}}var c5=0,j1;var _1=L(()=>{j1=new Map});import{existsSync as I1,mkdirSync as l5,copyFileSync as d5,readFileSync as o5,readdirSync as n5,statSync as a5,writeFileSync as R8,renameSync as s5,appendFileSync as E8,rmSync as x8}from"fs";import{join as s,dirname as r5}from"path";function P1(K){return s(K,"state","checkpoints")}function i5(K){let $=P1(K);if(!I1($))return[];return n5($).filter((z)=>z.startsWith("cp-")).filter((z)=>{try{return a5(s($,z)).isDirectory()}catch{return!1}})}function e5(K){return[...K].sort(($,z)=>{let Q=p0($),X=p0(z);return Q-X})}function p0(K){let $=K.split("-");if($.length<3)return 0;let z=$[$.length-1],Q=Number.parseInt(z??"0",10);return Number.isFinite(Q)?Q:0}function f1(K){let $=K??P(),z=e5(i5($)),Q=[];for(let X of z){let H=c0($,X);if(H)Q.push(H)}return Q}function c0(K,$){let z=s(P1(K),$,"metadata.json");if(!I1(z))return null;try{let Q=JSON.parse(o5(z,"utf-8"));return KK(Q,z)}catch{return null}}function KK(K,$){let z=QK(K,$);return z.ok?z.value:null}function QK(K,$){if(K===null||typeof K!=="object")return console.warn(`[checkpoint] invalid metadata at ${$}: not an object`),{ok:!1,reason:"invalid_type",field:"<root>"};let z=K,Q=["id","timestamp","task_id","task_description","git_sha","git_branch","provider","phase"];for(let X of Q){if(!(X in z))return console.warn(`[checkpoint] invalid metadata at ${$}: field "${X}" missing`),{ok:!1,reason:"missing_field",field:X};if(typeof z[X]!=="string")return console.warn(`[checkpoint] invalid metadata at ${$}: 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 ${$}: 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 ${$}: field "iteration" not a finite number`),{ok:!1,reason:"invalid_type",field:"iteration"};for(let X of zK){let H=z[X];if($K.test(H))return console.warn(`[checkpoint] invalid metadata at ${$}: 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 u1(K,$){if(!XK.test(K))throw new l0(K);let z=$??P(),Q=s(P1(z),K);if(!I1(Q))throw new m1(K);let X=c0(z,K);if(!X)throw new m1(K);return X}function d0(K,$){let z=u1(K,$),Q=$??P(),X=s(P1(Q),K),H=[];for(let Z of ZK){let V=s(X,Z);if(!I1(V))continue;H.push({from:V,to:s(Q,Z)})}return{id:K,metadata:z,restore:H}}function o0(K){let $=[],z=0;for(let Q of K.restore)try{l5(r5(Q.to),{recursive:!0});let X=`${Q.to}.tmp.${process.pid}.${++t5}`;d5(Q.from,X),s5(X,Q.to),z+=1}catch(X){$.push(`${Q.from} -> ${Q.to}: ${X.message}`)}return{restored:z,errors:$}}var k8,t5=0,$K,zK,XK,m1,l0,ZK;var n0=L(()=>{y();p();_1();k8=Promise.resolve();$K=/[\x00-\x08\x0a-\x1f\x7f-\x9f]/,zK=["id","task_id","git_sha","git_branch","provider","phase"];XK=/^[a-zA-Z0-9_-]+$/;m1=class m1 extends Error{id;constructor(K){super(`Checkpoint not found: ${K}`);this.id=K;this.name="CheckpointNotFoundError"}};l0=class l0 extends Error{id;constructor(K){super(`Invalid checkpoint ID: must be alphanumeric, hyphens, underscores only (got: ${K})`);this.id=K;this.name="InvalidCheckpointIdError"}};ZK=["state/orchestrator.json","queue/pending.json","queue/completed.json","queue/in-progress.json","queue/current-task.json"]});var r0={};b(r0,{runRollback:()=>HK});async function HK(K){let $=K[0],z=K.slice(1);if($===void 0||$==="help"||$==="--help"||$==="-h")return process.stdout.write(a0),$===void 0?1:0;switch($){case"list":{let Q=[...f1()].reverse();if(Q.length===0)return process.stdout.write(`${E}No checkpoints found.${W}
372
+ `),0;process.stdout.write(`${k}Checkpoints${W} (${Q.length}, newest first):
373
+ `);for(let X of Q)process.stdout.write(` ${O}${X.id}${W} iter=${X.iteration} ${X.git_branch||"(no branch)"}@${(X.git_sha||"").slice(0,7)} ${X.timestamp}
374
+ `);return 0}case"show":{let Q=z[0];if(!Q)return process.stderr.write(`${R}Missing checkpoint id.${W} Use \`loki rollback list\`.
375
+ `),2;try{let X=u1(Q);return process.stdout.write(`${JSON.stringify(X,null,2)}
376
+ `),0}catch(X){return process.stderr.write(`${R}Failed to read checkpoint:${W} ${X.message}
377
+ `),1}}case"to":{let Q=z[0];if(!Q)return process.stderr.write(`${R}Missing checkpoint id.${W} Use \`loki rollback list\`.
378
+ `),2;return s0(Q)}case"latest":{let Q=f1(),X=Q[Q.length-1];if(!X)return process.stderr.write(`${R}No checkpoints found to roll back to.${W}
379
+ `),1;return process.stdout.write(`Rolling back to latest checkpoint: ${O}${X.id}${W}
380
+ `),s0(X.id)}default:return process.stderr.write(`Unknown subcommand: ${$}
381
+ `),process.stderr.write(a0),2}}function s0(K){let $;try{$=d0(K)}catch(Q){return process.stderr.write(`${R}Cannot plan rollback:${W} ${Q.message}
382
+ `),1}if($.restore.length===0)return process.stdout.write(`${E}Checkpoint ${K} has no restorable state files; nothing to do.${W}
383
+ `),0;let z=o0($);if(z.errors.length>0){for(let Q of z.errors)process.stderr.write(`${R}restore error:${W} ${Q}
384
+ `);return process.stderr.write(`${R}Partial rollback: ${z.restored}/${$.restore.length} files restored.${W}
385
+ `),1}return process.stdout.write(`${D}Rolled back ${z.restored}/${$.restore.length} state files from ${K}.${W}
386
+ `),process.stdout.write("Run `loki start` to resume from the restored state.\n"),0}var a0=`Usage: loki rollback <subcommand>
362
387
 
363
388
  Subcommands:
364
389
  list List checkpoints (newest first)
@@ -373,8 +398,8 @@ Restored files (matches autonomy/run.sh:7028 byte-for-byte):
373
398
  Note: only state files are restored. Source code, git history, and the
374
399
  session's autonomy-state.json are unchanged. Re-run \`loki start\` to
375
400
  resume from the restored state.
376
- `;var y0=w(()=>{D0();n()});var f1={};y(f1,{renderFindingsForPrompt:()=>D3,loadPreviousFindings:()=>g1,findLatestReviewDir:()=>f0,_parseReviewerOutputForTests:()=>C3});import{existsSync as v0,readFileSync as h0,readdirSync as m0,statSync as E3}from"fs";import{join as _1}from"path";function N3($){let Q=$.toLowerCase();if(Q==="critical")return"Critical";if(Q==="high")return"High";if(Q==="medium")return"Medium";return"Low"}function g0($,Q,z,X){let Z=[],K=$.split(/\r?\n/);for(let W of K){let q=W.trim();if(q.length===0)continue;let H=q.replace(/^[-*]\s*/,""),G=w3.exec(H);if(!G||!G[1]||!G[2])continue;let J=N3(G[1]),B=G[2].trim(),V=S3.exec(B),M=V&&V[1]?V[1]:null,j=V&&V[2]?Number.parseInt(V[2],10):null;Z.push({reviewId:z,iteration:X,reviewer:Q,severity:J,description:B,file:M,line:Number.isFinite(j)?j:null,raw:q})}return Z}function f0($,Q){let z=_1($,"quality","reviews");if(!v0(z))return null;let X;try{X=m0(z)}catch{return null}let Z=Q===void 0?X.filter((q)=>q.startsWith("review-")):X.filter((q)=>q.endsWith(`-${Q}`)&&q.startsWith("review-"));if(Z.length===0)return null;Z.sort();let K=Z[Z.length-1];if(!K)return null;let W=_1(z,K);try{if(!E3(W).isDirectory())return null}catch{return null}return W}function g1($,Q){let z=f0($,Q);if(z===null)return{reviewDir:null,reviewId:null,iteration:null,findings:[]};let X=null,Z=null,K=_1(z,"aggregate.json");if(v0(K))try{let G=h0(K,"utf-8"),J=JSON.parse(G);if(typeof J.review_id==="string")X=J.review_id;if(typeof J.iteration==="number")Z=J.iteration}catch{}let W;try{W=m0(z)}catch{return{reviewDir:z,reviewId:X,iteration:Z,findings:[]}}let q=new Set(["diff.txt","files.txt","anti-sycophancy.txt"]),H=[];for(let G of W){if(!G.endsWith(".txt"))continue;if(q.has(G))continue;if(G.endsWith("-prompt.txt"))continue;let J=G.replace(/\.txt$/,""),B;try{B=h0(_1(z,G),"utf-8")}catch{continue}H.push(...g0(B,J,X??"",Z??-1))}return{reviewDir:z,reviewId:X,iteration:Z,findings:H}}function D3($){if($.length===0)return"";let Q=["Critical","High","Medium","Low"],z=new Map;for(let Z of Q)z.set(Z,[]);for(let Z of $){let K=z.get(Z.severity);if(K)K.push(Z)}let X=[];X.push("PREVIOUS REVIEWER FINDINGS (must address each, or supply counter-evidence in .loki/state/counter-evidence-<iter>.json):");for(let Z of Q){let K=z.get(Z)??[];if(K.length===0)continue;X.push(` [${Z}] (${K.length}):`);for(let W of K){let q=W.file?` (${W.file}${W.line!==null?":"+W.line:""})`:"";X.push(` - ${W.description}${q} -- via ${W.reviewer}`)}}return X.join(`
377
- `)}function C3($,Q,z="review-test",X=0){return g0($,Q,z,X)}var w3,S3;var I1=w(()=>{w3=/\[(Critical|High|Medium|Low)\]\s*(.+)/i,S3=/([\w.\-/]+\.[a-zA-Z]+):(\d+)/});import{existsSync as k3}from"fs";import{join as b3}from"path";async function u0($,Q){let z=b3($,"memory");if(!k3(z))return{stored:!1,reason:"memory dir not initialized"};let X=Math.max(0,Math.floor(Q.durationSeconds??0)),Z={_LOKI_PROJECT_DIR:u,_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(X),_LOKI_LOKI_DIR:$},W=await a(`
401
+ `;var t0=L(()=>{n0();n()});var c1={};b(c1,{renderFindingsForPrompt:()=>JK,loadPreviousFindings:()=>p1,findLatestReviewDir:()=>z7,_parseReviewerOutputForTests:()=>GK});import{existsSync as e0,readFileSync as i0,readdirSync as K7,statSync as WK}from"fs";import{join as L1}from"path";function UK(K){let $=K.toLowerCase();if($==="critical")return"Critical";if($==="high")return"High";if($==="medium")return"Medium";return"Low"}function $7(K,$,z,Q){let X=[],H=K.split(/\r?\n/);for(let Z of H){let V=Z.trim();if(V.length===0)continue;let q=V.replace(/^[-*]\s*/,""),U=VK.exec(q);if(!U||!U[1]||!U[2])continue;let G=UK(U[1]),B=U[2].trim(),J=qK.exec(B),Y=J&&J[1]?J[1]:null,j=J&&J[2]?Number.parseInt(J[2],10):null;X.push({reviewId:z,iteration:Q,reviewer:$,severity:G,description:B,file:Y,line:Number.isFinite(j)?j:null,raw:V})}return X}function z7(K,$){let z=L1(K,"quality","reviews");if(!e0(z))return null;let Q;try{Q=K7(z)}catch{return null}let X=$===void 0?Q.filter((V)=>V.startsWith("review-")):Q.filter((V)=>V.endsWith(`-${$}`)&&V.startsWith("review-"));if(X.length===0)return null;X.sort();let H=X[X.length-1];if(!H)return null;let Z=L1(z,H);try{if(!WK(Z).isDirectory())return null}catch{return null}return Z}function p1(K,$){let z=z7(K,$);if(z===null)return{reviewDir:null,reviewId:null,iteration:null,findings:[]};let Q=null,X=null,H=L1(z,"aggregate.json");if(e0(H))try{let U=i0(H,"utf-8"),G=JSON.parse(U);if(typeof G.review_id==="string")Q=G.review_id;if(typeof G.iteration==="number")X=G.iteration}catch{}let Z;try{Z=K7(z)}catch{return{reviewDir:z,reviewId:Q,iteration:X,findings:[]}}let V=new Set(["diff.txt","files.txt","anti-sycophancy.txt"]),q=[];for(let U of Z){if(!U.endsWith(".txt"))continue;if(V.has(U))continue;if(U.endsWith("-prompt.txt"))continue;let G=U.replace(/\.txt$/,""),B;try{B=i0(L1(z,U),"utf-8")}catch{continue}q.push(...$7(B,G,Q??"",X??-1))}return{reviewDir:z,reviewId:Q,iteration:X,findings:q}}function JK(K){if(K.length===0)return"";let $=["Critical","High","Medium","Low"],z=new Map;for(let X of $)z.set(X,[]);for(let X of K){let H=z.get(X.severity);if(H)H.push(X)}let Q=[];Q.push("PREVIOUS REVIEWER FINDINGS (must address each, or supply counter-evidence in .loki/state/counter-evidence-<iter>.json):");for(let X of $){let H=z.get(X)??[];if(H.length===0)continue;Q.push(` [${X}] (${H.length}):`);for(let Z of H){let V=Z.file?` (${Z.file}${Z.line!==null?":"+Z.line:""})`:"";Q.push(` - ${Z.description}${V} -- via ${Z.reviewer}`)}}return Q.join(`
402
+ `)}function GK(K,$,z="review-test",Q=0){return $7(K,$,z,Q)}var VK,qK;var R1=L(()=>{VK=/\[(Critical|High|Medium|Low)\]\s*(.+)/i,qK=/([\w.\-/]+\.[a-zA-Z]+):(\d+)/});import{existsSync as BK}from"fs";import{join as MK}from"path";async function Q7(K,$){let z=MK(K,"memory");if(!BK(z))return{stored:!1,reason:"memory dir not initialized"};let Q=Math.max(0,Math.floor($.durationSeconds??0)),X={_LOKI_PROJECT_DIR:u,_LOKI_TARGET_DIR:process.cwd(),_LOKI_TASK_ID:$.taskId,_LOKI_OUTCOME:$.outcome,_LOKI_PHASE:$.phase,_LOKI_GOAL:$.goal,_LOKI_DURATION:String(Q),_LOKI_LOKI_DIR:K},Z=await a(`
378
403
  import os, sys
379
404
  project = os.environ.get('_LOKI_PROJECT_DIR', '')
380
405
  loki = os.environ.get('_LOKI_LOKI_DIR', '.loki')
@@ -401,23 +426,23 @@ try:
401
426
  print('OK')
402
427
  except Exception as e:
403
428
  print('ERR:' + str(e))
404
- `,{env:Z,timeoutMs:15000});if(W.exitCode===127)return{stored:!1,reason:"python3 not found"};let q=W.stdout.trim();if(q==="OK")return{stored:!0,reason:"stored"};if(q.startsWith("ERR:"))return{stored:!1,reason:q.replace(/^ERR:/,"")};return{stored:!1,reason:W.stderr.trim()||"unknown"}}var p0=w(()=>{X1();v()});var o0={};y(o0,{loadLearnings:()=>u1,appendLearning:()=>U1,appendFromGateFailure:()=>p3});import{existsSync as y3,readFileSync as h3}from"fs";import{join as c0}from"path";import{createHash as v3}from"crypto";function l0($){return c0($,m3)}function g3($){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 d0($){if(!y3($))return{version:1,learnings:[]};try{let Q=h3($,"utf-8"),z=JSON.parse(Q);if(z.version===1&&Array.isArray(z.learnings))return{version:1,learnings:z.learnings.filter(g3)}}catch{}return{version:1,learnings:[]}}function f3($,Q){return v3("sha256").update(`${$}\x00${Q}`).digest("hex").slice(0,16)}async function U1($,Q,z={}){let X=f3(Q.trigger,Q.rootCause),Z=new Date().toISOString(),K={id:X,timestamp:Z,...Q},W=l0($);if(await R0(W,()=>{let H=d0(W),G=H.learnings.findIndex((J)=>J.id===X);if(G>=0){let J=H.learnings[G];H.learnings[G]={...J,timestamp:Z,iteration:K.iteration}}else H.learnings.push(K);W1(W,H)}),z.episodeBridge!==null&&(z.episodeBridge!==void 0||process.env.LOKI_AUTO_LEARNINGS_EPISODE==="1")){let H=z.episodeBridge??u0,G=z.bridgeFailureLog??u3;try{let J=await H($,{taskId:`learning-${X}`,outcome:"failure",phase:"VERIFY",goal:`${Q.trigger}: ${Q.rootCause}`});if(J&&!J.stored){if(!new Set(["memory dir not initialized","stub"]).has(J.reason))G(`episode_bridge skipped: ${J.reason}`)}}catch(J){G(`episode_bridge threw: ${J.message}`)}}return K}function u3($){process.stderr.write(`[learnings_writer] ${$}
405
- `)}async function p3($,Q,z,X={}){let Z=`[${z.severity}] ${z.description}`;return U1($,{iteration:Q,trigger:"gate_failure",rootCause:Z,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}},X)}function u1($){return d0(l0($))}var m3;var L1=w(()=>{T1();p0();m3=c0("state","relevant-learnings.json")});var a0={};y(a0,{runOverrideCouncil:()=>a3,recordOverrideOutcome:()=>s3,loadCounterEvidence:()=>n3,canonicalFindingId:()=>p1,DEFAULT_OVERRIDE_JUDGES:()=>n0});import{existsSync as c3,readFileSync as l3}from"fs";import{join as d3}from"path";function n3($,Q){let z=d3($,"state",`counter-evidence-${Q}.json`);if(!c3(z))return null;try{let X=l3(z,"utf-8"),Z=JSON.parse(X);if(typeof Z.iteration!=="number")return null;let K=Array.isArray(Z.evidence)?Z.evidence:[],W=[];for(let q of K){if(typeof q!=="object"||q===null)continue;let H=q;if(typeof H.findingId!=="string")continue;if(typeof H.claim!=="string")continue;let G=H.proofType;if(typeof G!=="string"||!o3.has(G))continue;let J=G,B=Array.isArray(H.artifacts)?H.artifacts:[];W.push({findingId:H.findingId,claim:H.claim,proofType:J,artifacts:B.filter((V)=>typeof V==="string")})}return{iteration:Z.iteration,evidence:W}}catch{return null}}async function a3($,Q,z,X={}){let Z=X.judges??n0,K=new Set,W=new Set,q={},H=new Map;for(let G of Q.evidence)H.set(G.findingId,G);for(let G of $){let J=p1(G),B=H.get(J);if(!B){W.add(J);continue}let V=await Promise.all(Z.map((j)=>z({finding:G,evidence:B,judge:j})));if(q[J]=V,V.filter((j)=>j.verdict==="APPROVE_OVERRIDE").length>=2)K.add(J);else W.add(J)}return{approvedFindingIds:K,rejectedFindingIds:W,votes:q}}function p1($){let Q=$.raw.slice(0,80).replace(/\s+/g," ").trim();return`${$.reviewer}::${Q}`}async function s3($,Q,z,X,Z={}){let K={episodeBridge:Z.episodeBridge===void 0?null:Z.episodeBridge};for(let W of X){let q=p1(W);if(z.approvedFindingIds.has(q))await U1($,{iteration:Q,trigger:"override_approved",rootCause:`[${W.severity}] ${W.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:q,reviewId:W.reviewId,file:W.file??void 0,line:W.line??void 0,severity:W.severity,reviewer:W.reviewer}},K);else if(z.rejectedFindingIds.has(q))await U1($,{iteration:Q,trigger:"override_rejected",rootCause:`[${W.severity}] ${W.description}`,fix:"override council rejected -- dev agent must fix the finding",preventInFuture:"address this finding in the next iteration",evidence:{findingId:q,reviewId:W.reviewId,file:W.file??void 0,line:W.line??void 0,severity:W.severity,reviewer:W.reviewer}},K)}}var o3,n0;var s0=w(()=>{L1();o3=new Set(["file-exists","test-passes","grep-miss","reviewer-misread","duplicate-code-path","out-of-scope"]);n0=["judge-primary","judge-secondary","judge-tertiary"]});var i0={};y(i0,{writeEscalationHandoff:()=>U5,renderHandoff:()=>r0,readLatestHandoff:()=>q5});import{existsSync as r3,mkdirSync as t3,readdirSync as i3,readFileSync as e3,renameSync as $5,writeFileSync as z5}from"fs";import{dirname as Q5,join as P1}from"path";function X5(){return new Date().toISOString()}function Z5($){let Q=$.file?` (${$.file}${$.line!==null?":"+$.line:""})`:"";return` - [${$.severity}] ${$.description}${Q} -- ${$.reviewer}`}function K5($){let Q=$.evidence,z=Q.file?` ${Q.file}${Q.line!==void 0?":"+Q.line:""}`:"";return` - **${$.trigger}** (iter ${$.iteration})${z}: ${$.rootCause}`}function r0($,Q,z){let X=[];if(X.push(`# Loki escalation handoff -- ${X5()}`),X.push(""),X.push(`Gate **${$.gateName}** has failed ${$.consecutiveFailures} consecutive times at iteration ${$.iteration}.`),X.push(""),X.push(`Reason: ${$.detail}`),X.push(""),Q.length>0){X.push(`## Outstanding findings (${Q.length})`),X.push("");for(let Z of Q)X.push(Z5(Z));X.push("")}else X.push("## Outstanding findings"),X.push(""),X.push("(no per-finding records captured -- gate failed without populating reviewer outputs)"),X.push("");if(z.length>0){X.push(`## Recent learnings (${Math.min(z.length,10)})`),X.push("");for(let Z of z.slice(-10))X.push(K5(Z));X.push("")}return X.push("## What the human must decide"),X.push(""),X.push("- Approve override? Write `.loki/state/counter-evidence-<iter>.json` with one entry per finding to dispute, then `rm .loki/PAUSE` to resume."),X.push("- Disable a gate? Set `LOKI_GATE_<NAME>=false` in env (see skills/quality-gates.md)."),X.push("- Tweak escalation? Set `LOKI_GATE_PAUSE_LIMIT` or `LOKI_GATE_ESCALATE_LIMIT`."),X.push("- Roll back? Switch to `LOKI_LEGACY_BASH=1` and re-run; the bash route does not consult this handoff doc."),X.push(""),X.push("To resume: address the findings (or supply counter-evidence) and `rm .loki/PAUSE`."),X.join(`
406
- `)}function W5($,Q){t3(Q5($),{recursive:!0});let z=`${$}.tmp.${process.pid}.${++t0}`;z5(z,Q),$5(z,$)}function U5($,Q,z={}){let X=z.findings??g1($,Q.iteration).findings,Z=z.learnings??u1($).learnings,K=r0(Q,X,Z),W=(z.now?.()??new Date).toISOString().replace(/[-:.]/g,""),q=P1($,"escalations"),H=++t0,G=P1(q,`handoff-${W}-${process.pid}-${H}-${Q.gateName}.md`);return W5(G,K),{path:G,bytes:K.length}}function q5($){let Q=P1($,"escalations");if(!r3(Q))return null;let z;try{z=i3(Q).filter((K)=>K.endsWith(".md"))}catch{return null}if(z.length===0)return null;z.sort();let X=z[z.length-1];if(!X)return null;let Z=P1(Q,X);try{return{path:Z,body:e3(Z,"utf-8")}}catch{return null}}var t0=0;var e0=w(()=>{I1();L1()});var $6={};y($6,{runInternalPhase1Hooks:()=>Y5,_resolveForTests:()=>B5,_internalPhase1HooksHelp:()=>O5});import{existsSync as H5,mkdirSync as G5,readdirSync as V5,statSync as J5}from"fs";import{join as q1,resolve as B5}from"path";async function Y5($){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 M5(z);case"override":return A5(z);case"handoff":return T5(z);default:return process.stderr.write(`Unknown subcommand: ${Q}
407
- `),process.stderr.write(c1),2}}async function M5($){let Q=l1($[0]);if(Q===null)return process.stderr.write(`reflect: missing or invalid <iter>
408
- `),2;let z=P();try{let Z=(await Promise.resolve().then(() => (I1(),f1))).loadPreviousFindings(z,Q);if(Z.findings.length===0)return process.stdout.write(`reflect: no findings for iter ${Q} (nothing to do)
409
- `),0;let K=q1(z,"state");G5(K,{recursive:!0}),W1(q1(K,`findings-${Q}.json`),{review_id:Z.reviewId,iteration:Q,findings:Z.findings});let W=await Promise.resolve().then(() => (L1(),o0)),q=0;if(process.env.LOKI_AUTO_LEARNINGS!=="0"){for(let H of Z.findings)if(H.severity==="Critical"||H.severity==="High")await W.appendFromGateFailure(z,Q,H,{episodeBridge:null}),q+=1}return process.stdout.write(`reflect: persisted ${Z.findings.length} findings + ${q} learnings (iter ${Q})
410
- `),0}catch(X){return process.stderr.write(`reflect: ${X.message}
411
- `),1}}async function A5($){let Q=l1($[0]);if(Q===null)return process.stderr.write(`override: missing or invalid <iter>
412
- `),2;let z=P();try{let X=await Promise.resolve().then(() => (s0(),a0)),Z=X.loadCounterEvidence(z,Q);if(Z===null||Z.evidence.length===0)return process.stdout.write(`override: no counter-evidence for iter ${Q} (skip)
413
- `),0;let W=(await Promise.resolve().then(() => (I1(),f1))).loadPreviousFindings(z,Q),q=W.findings.filter((_)=>_.severity==="Critical"||_.severity==="High");if(q.length===0)return process.stdout.write(`override: no blocking findings for iter ${Q} (skip)
414
- `),0;let H=new Set(["duplicate-code-path","file-exists","test-passes","grep-miss","out-of-scope"]),G=async(_)=>{let k=H.has(_.evidence.proofType);return{judge:_.judge,verdict:k?"APPROVE_OVERRIDE":"REJECT_OVERRIDE",reasoning:k?`[stub] proofType=${_.evidence.proofType} trusted`:`[stub] proofType=${_.evidence.proofType} requires manual review`}},J=await X.runOverrideCouncil(q,Z,G);await X.recordOverrideOutcome(z,Q,J,q);let B=q1(z,"quality","reviews");if(H5(B))try{let _=V5(B).filter((m)=>m.startsWith("review-")).sort(),k=_[_.length-1];if(k&&J5(q1(B,k)).isDirectory())W1(q1(B,k,`override-${Q}.json`),{review_id:W.reviewId,iteration:Q,approved_finding_ids:Array.from(J.approvedFindingIds),rejected_finding_ids:Array.from(J.rejectedFindingIds),votes:J.votes})}catch{}let V=J.approvedFindingIds.size,M=J.rejectedFindingIds.size;if(M===0&&V>0)process.stdout.write(`override: LIFTED -- ${V} approved, ${M} rejected
415
- `);else process.stdout.write(`override: BLOCKED -- ${V} approved, ${M} rejected
416
- `);return 0}catch(X){return process.stderr.write(`override: ${X.message}
417
- `),1}}async function T5($){let Q=$[0],z=Number.parseInt($[1]??"0",10),X=l1($[2]);if(!Q||!Number.isFinite(z)||X===null)return process.stderr.write(`handoff: usage: handoff <gate> <consecutive-failures> <iter>
418
- `),2;let Z=P();try{let W=(await Promise.resolve().then(() => (e0(),i0))).writeEscalationHandoff(Z,{gateName:Q,iteration:X,consecutiveFailures:z,detail:`${Q} hit PAUSE_LIMIT (${z} consecutive failures)`});return process.stdout.write(`handoff: wrote ${W.path} (${W.bytes}B)
419
- `),0}catch(K){return process.stderr.write(`handoff: ${K.message}
420
- `),1}}function l1($){if($===void 0)return null;let Q=Number.parseInt($,10);return Number.isFinite(Q)&&Q>=0?Q:null}var c1=`loki internal phase1-hooks <subcommand>
429
+ `,{env:X,timeoutMs:15000});if(Z.exitCode===127)return{stored:!1,reason:"python3 not found"};let V=Z.stdout.trim();if(V==="OK")return{stored:!0,reason:"stored"};if(V.startsWith("ERR:"))return{stored:!1,reason:V.replace(/^ERR:/,"")};return{stored:!1,reason:Z.stderr.trim()||"unknown"}}var X7=L(()=>{Q1();y()});var V7={};b(V7,{loadLearnings:()=>l1,appendLearning:()=>V1,appendFromGateFailure:()=>PK});import{existsSync as YK,readFileSync as OK}from"fs";import{join as Z7}from"path";import{createHash as TK}from"crypto";function H7(K){return Z7(K,AK)}function jK(K){if(K===null||typeof K!=="object")return!1;let $=K;return typeof $.id==="string"&&typeof $.timestamp==="string"&&typeof $.iteration==="number"&&typeof $.trigger==="string"&&typeof $.rootCause==="string"&&typeof $.fix==="string"&&typeof $.preventInFuture==="string"&&typeof $.evidence==="object"&&$.evidence!==null}function W7(K){if(!YK(K))return{version:1,learnings:[]};try{let $=OK(K,"utf-8"),z=JSON.parse($);if(z.version===1&&Array.isArray(z.learnings))return{version:1,learnings:z.learnings.filter(jK)}}catch{}return{version:1,learnings:[]}}function _K(K,$){return TK("sha256").update(`${K}\x00${$}`).digest("hex").slice(0,16)}async function V1(K,$,z={}){let Q=_K($.trigger,$.rootCause),X=new Date().toISOString(),H={id:Q,timestamp:X,...$},Z=H7(K);if(await u0(Z,()=>{let q=W7(Z),U=q.learnings.findIndex((G)=>G.id===Q);if(U>=0){let G=q.learnings[U];q.learnings[U]={...G,timestamp:X,iteration:H.iteration}}else q.learnings.push(H);W1(Z,q)}),z.episodeBridge!==null&&(z.episodeBridge!==void 0||process.env.LOKI_AUTO_LEARNINGS_EPISODE==="1")){let q=z.episodeBridge??Q7,U=z.bridgeFailureLog??IK;try{let G=await q(K,{taskId:`learning-${Q}`,outcome:"failure",phase:"VERIFY",goal:`${$.trigger}: ${$.rootCause}`});if(G&&!G.stored){if(!new Set(["memory dir not initialized","stub"]).has(G.reason))U(`episode_bridge skipped: ${G.reason}`)}}catch(G){U(`episode_bridge threw: ${G.message}`)}}return H}function IK(K){process.stderr.write(`[learnings_writer] ${K}
430
+ `)}async function PK(K,$,z,Q={}){let X=`[${z.severity}] ${z.description}`;return V1(K,{iteration:$,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}},Q)}function l1(K){return W7(H7(K))}var AK;var E1=L(()=>{_1();X7();AK=Z7("state","relevant-learnings.json")});var U7={};b(U7,{runOverrideCouncil:()=>wK,recordOverrideOutcome:()=>SK,loadCounterEvidence:()=>FK,canonicalFindingId:()=>d1,DEFAULT_OVERRIDE_JUDGES:()=>q7});import{existsSync as LK,readFileSync as RK}from"fs";import{join as EK}from"path";function FK(K,$){let z=EK(K,"state",`counter-evidence-${$}.json`);if(!LK(z))return null;try{let Q=RK(z,"utf-8"),X=JSON.parse(Q);if(typeof X.iteration!=="number")return null;let H=Array.isArray(X.evidence)?X.evidence:[],Z=[];for(let V of H){if(typeof V!=="object"||V===null)continue;let q=V;if(typeof q.findingId!=="string")continue;if(typeof q.claim!=="string")continue;let U=q.proofType;if(typeof U!=="string"||!xK.has(U))continue;let G=U,B=Array.isArray(q.artifacts)?q.artifacts:[];Z.push({findingId:q.findingId,claim:q.claim,proofType:G,artifacts:B.filter((J)=>typeof J==="string")})}return{iteration:X.iteration,evidence:Z}}catch{return null}}async function wK(K,$,z,Q={}){let X=Q.judges??q7,H=new Set,Z=new Set,V={},q=new Map;for(let U of $.evidence)q.set(U.findingId,U);for(let U of K){let G=d1(U),B=q.get(G);if(!B){Z.add(G);continue}let J=await Promise.all(X.map((j)=>z({finding:U,evidence:B,judge:j})));if(V[G]=J,J.filter((j)=>j.verdict==="APPROVE_OVERRIDE").length>=2)H.add(G);else Z.add(G)}return{approvedFindingIds:H,rejectedFindingIds:Z,votes:V}}function d1(K){let $=K.raw.slice(0,80).replace(/\s+/g," ").trim();return`${K.reviewer}::${$}`}async function SK(K,$,z,Q,X={}){let H={episodeBridge:X.episodeBridge===void 0?null:X.episodeBridge};for(let Z of Q){let V=d1(Z);if(z.approvedFindingIds.has(V))await V1(K,{iteration:$,trigger:"override_approved",rootCause:`[${Z.severity}] ${Z.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:V,reviewId:Z.reviewId,file:Z.file??void 0,line:Z.line??void 0,severity:Z.severity,reviewer:Z.reviewer}},H);else if(z.rejectedFindingIds.has(V))await V1(K,{iteration:$,trigger:"override_rejected",rootCause:`[${Z.severity}] ${Z.description}`,fix:"override council rejected -- dev agent must fix the finding",preventInFuture:"address this finding in the next iteration",evidence:{findingId:V,reviewId:Z.reviewId,file:Z.file??void 0,line:Z.line??void 0,severity:Z.severity,reviewer:Z.reviewer}},H)}}var xK,q7;var J7=L(()=>{E1();xK=new Set(["file-exists","test-passes","grep-miss","reviewer-misread","duplicate-code-path","out-of-scope"]);q7=["judge-primary","judge-secondary","judge-tertiary"]});var M7={};b(M7,{writeEscalationHandoff:()=>uK,renderHandoff:()=>G7,readLatestHandoff:()=>pK});import{existsSync as NK,mkdirSync as kK,readdirSync as DK,readFileSync as CK,renameSync as hK,writeFileSync as bK}from"fs";import{dirname as yK,join as x1}from"path";function vK(){return new Date().toISOString()}function gK(K){let $=K.file?` (${K.file}${K.line!==null?":"+K.line:""})`:"";return` - [${K.severity}] ${K.description}${$} -- ${K.reviewer}`}function mK(K){let $=K.evidence,z=$.file?` ${$.file}${$.line!==void 0?":"+$.line:""}`:"";return` - **${K.trigger}** (iter ${K.iteration})${z}: ${K.rootCause}`}function G7(K,$,z){let Q=[];if(Q.push(`# Loki escalation handoff -- ${vK()}`),Q.push(""),Q.push(`Gate **${K.gateName}** has failed ${K.consecutiveFailures} consecutive times at iteration ${K.iteration}.`),Q.push(""),Q.push(`Reason: ${K.detail}`),Q.push(""),$.length>0){Q.push(`## Outstanding findings (${$.length})`),Q.push("");for(let X of $)Q.push(gK(X));Q.push("")}else Q.push("## Outstanding findings"),Q.push(""),Q.push("(no per-finding records captured -- gate failed without populating reviewer outputs)"),Q.push("");if(z.length>0){Q.push(`## Recent learnings (${Math.min(z.length,10)})`),Q.push("");for(let X of z.slice(-10))Q.push(mK(X));Q.push("")}return Q.push("## What the human must decide"),Q.push(""),Q.push("- Approve override? Write `.loki/state/counter-evidence-<iter>.json` with one entry per finding to dispute, then `rm .loki/PAUSE` to resume."),Q.push("- Disable a gate? Set `LOKI_GATE_<NAME>=false` in env (see skills/quality-gates.md)."),Q.push("- Tweak escalation? Set `LOKI_GATE_PAUSE_LIMIT` or `LOKI_GATE_ESCALATE_LIMIT`."),Q.push("- Roll back? Switch to `LOKI_LEGACY_BASH=1` and re-run; the bash route does not consult this handoff doc."),Q.push(""),Q.push("To resume: address the findings (or supply counter-evidence) and `rm .loki/PAUSE`."),Q.join(`
431
+ `)}function fK(K,$){kK(yK(K),{recursive:!0});let z=`${K}.tmp.${process.pid}.${++B7}`;bK(z,$),hK(z,K)}function uK(K,$,z={}){let Q=z.findings??p1(K,$.iteration).findings,X=z.learnings??l1(K).learnings,H=G7($,Q,X),Z=(z.now?.()??new Date).toISOString().replace(/[-:.]/g,""),V=x1(K,"escalations"),q=++B7,U=x1(V,`handoff-${Z}-${process.pid}-${q}-${$.gateName}.md`);return fK(U,H),{path:U,bytes:H.length}}function pK(K){let $=x1(K,"escalations");if(!NK($))return null;let z;try{z=DK($).filter((H)=>H.endsWith(".md"))}catch{return null}if(z.length===0)return null;z.sort();let Q=z[z.length-1];if(!Q)return null;let X=x1($,Q);try{return{path:X,body:CK(X,"utf-8")}}catch{return null}}var B7=0;var Y7=L(()=>{R1();E1()});var O7={};b(O7,{runInternalPhase1Hooks:()=>aK,_resolveForTests:()=>nK,_internalPhase1HooksHelp:()=>iK});import{existsSync as cK,mkdirSync as lK,readdirSync as dK,statSync as oK}from"fs";import{join as q1,resolve as nK}from"path";async function aK(K){let[$,...z]=K;switch($){case void 0:case"help":case"--help":case"-h":return process.stdout.write(o1),$===void 0?1:0;case"reflect":return sK(z);case"override":return rK(z);case"handoff":return tK(z);default:return process.stderr.write(`Unknown subcommand: ${$}
432
+ `),process.stderr.write(o1),2}}async function sK(K){let $=n1(K[0]);if($===null)return process.stderr.write(`reflect: missing or invalid <iter>
433
+ `),2;let z=P();try{let X=(await Promise.resolve().then(() => (R1(),c1))).loadPreviousFindings(z,$);if(X.findings.length===0)return process.stdout.write(`reflect: no findings for iter ${$} (nothing to do)
434
+ `),0;let H=q1(z,"state");lK(H,{recursive:!0}),W1(q1(H,`findings-${$}.json`),{review_id:X.reviewId,iteration:$,findings:X.findings});let Z=await Promise.resolve().then(() => (E1(),V7)),V=0;if(process.env.LOKI_AUTO_LEARNINGS!=="0"){for(let q of X.findings)if(q.severity==="Critical"||q.severity==="High")await Z.appendFromGateFailure(z,$,q,{episodeBridge:null}),V+=1}return process.stdout.write(`reflect: persisted ${X.findings.length} findings + ${V} learnings (iter ${$})
435
+ `),0}catch(Q){return process.stderr.write(`reflect: ${Q.message}
436
+ `),1}}async function rK(K){let $=n1(K[0]);if($===null)return process.stderr.write(`override: missing or invalid <iter>
437
+ `),2;let z=P();try{let Q=await Promise.resolve().then(() => (J7(),U7)),X=Q.loadCounterEvidence(z,$);if(X===null||X.evidence.length===0)return process.stdout.write(`override: no counter-evidence for iter ${$} (skip)
438
+ `),0;let Z=(await Promise.resolve().then(() => (R1(),c1))).loadPreviousFindings(z,$),V=Z.findings.filter((_)=>_.severity==="Critical"||_.severity==="High");if(V.length===0)return process.stdout.write(`override: no blocking findings for iter ${$} (skip)
439
+ `),0;let q=new Set(["duplicate-code-path","file-exists","test-passes","grep-miss","out-of-scope"]),U=async(_)=>{let C=q.has(_.evidence.proofType);return{judge:_.judge,verdict:C?"APPROVE_OVERRIDE":"REJECT_OVERRIDE",reasoning:C?`[stub] proofType=${_.evidence.proofType} trusted`:`[stub] proofType=${_.evidence.proofType} requires manual review`}},G=await Q.runOverrideCouncil(V,X,U);await Q.recordOverrideOutcome(z,$,G,V);let B=q1(z,"quality","reviews");if(cK(B))try{let _=dK(B).filter((g)=>g.startsWith("review-")).sort(),C=_[_.length-1];if(C&&oK(q1(B,C)).isDirectory())W1(q1(B,C,`override-${$}.json`),{review_id:Z.reviewId,iteration:$,approved_finding_ids:Array.from(G.approvedFindingIds),rejected_finding_ids:Array.from(G.rejectedFindingIds),votes:G.votes})}catch{}let J=G.approvedFindingIds.size,Y=G.rejectedFindingIds.size;if(Y===0&&J>0)process.stdout.write(`override: LIFTED -- ${J} approved, ${Y} rejected
440
+ `);else process.stdout.write(`override: BLOCKED -- ${J} approved, ${Y} rejected
441
+ `);return 0}catch(Q){return process.stderr.write(`override: ${Q.message}
442
+ `),1}}async function tK(K){let $=K[0],z=Number.parseInt(K[1]??"0",10),Q=n1(K[2]);if(!$||!Number.isFinite(z)||Q===null)return process.stderr.write(`handoff: usage: handoff <gate> <consecutive-failures> <iter>
443
+ `),2;let X=P();try{let Z=(await Promise.resolve().then(() => (Y7(),M7))).writeEscalationHandoff(X,{gateName:$,iteration:Q,consecutiveFailures:z,detail:`${$} hit PAUSE_LIMIT (${z} consecutive failures)`});return process.stdout.write(`handoff: wrote ${Z.path} (${Z.bytes}B)
444
+ `),0}catch(H){return process.stderr.write(`handoff: ${H.message}
445
+ `),1}}function n1(K){if(K===void 0)return null;let $=Number.parseInt(K,10);return Number.isFinite($)&&$>=0?$:null}var o1=`loki internal phase1-hooks <subcommand>
421
446
 
422
447
  Subcommands:
423
448
  reflect <iter> Persist structured findings + auto-learnings.
@@ -426,24 +451,24 @@ Subcommands:
426
451
 
427
452
  This command is invoked by autonomy/run.sh between iterations. Users
428
453
  should not run it directly -- run \`loki start\` instead.
429
- `,O5;var z6=w(()=>{v();T1();O5=c1});v();import{readFileSync as H6}from"fs";import{resolve as G6,dirname as V6}from"path";import{fileURLToPath as J6}from"url";var o=null;function s1(){if(o!==null)return o;let $="7.5.27";if(typeof $==="string"&&$.length>0)return o=$,o;try{let Q=V6(J6(import.meta.url)),z=F1(Q);o=H6(G6(z,"VERSION"),"utf-8").trim()}catch{o="unknown"}return o}function r1(){return process.stdout.write(`Loki Mode v${s1()}
430
- `),0}p();n();v();import{readFileSync as T6,existsSync as O6}from"fs";import{resolve as j6}from"path";var _6=["claude","codex","cline","aider"];function i1(){let $=j6(P(),"state","provider");if(!O6($))return"";try{return T6($,"utf-8").trim()}catch{return""}}function I6($,Q){return $||Q||process.env.LOKI_PROVIDER||"claude"}function L6($){let Q=i1(),z=I6($,Q);switch(process.stdout.write(`${D}Current Provider${U}
454
+ `,iK;var T7=L(()=>{y();_1();iK=o1});y();import{readFileSync as E7}from"fs";import{resolve as x7,dirname as F7}from"path";import{fileURLToPath as w7}from"url";var o=null;function i1(){if(o!==null)return o;let K="7.5.29";if(typeof K==="string"&&K.length>0)return o=K,o;try{let $=F7(w7(import.meta.url)),z=S1($);o=E7(x7(z,"VERSION"),"utf-8").trim()}catch{o="unknown"}return o}function e1(){return process.stdout.write(`Loki Mode v${i1()}
455
+ `),0}p();n();y();import{readFileSync as C7,existsSync as h7}from"fs";import{resolve as b7}from"path";var y7=["claude","codex","cline","aider"];function $0(){let K=b7(P(),"state","provider");if(!h7(K))return"";try{return C7(K,"utf-8").trim()}catch{return""}}function v7(K,$){return K||$||process.env.LOKI_PROVIDER||"claude"}function g7(K){let $=$0(),z=v7(K,$);switch(process.stdout.write(`${k}Current Provider${W}
431
456
  `),process.stdout.write(`
432
- `),process.stdout.write(`${A}Provider:${U} ${z}
433
- `),z){case"claude":process.stdout.write(`${C}Status:${U} Full features (subagents, parallel, MCP)
434
- `);break;case"cline":process.stdout.write(`${C}Status:${U} Near-full mode (subagents, MCP, 12+ providers)
435
- `);break;case"codex":case"aider":process.stdout.write(`${x}Status:${U} Degraded mode (sequential only)
436
- `);break;default:break}if(Q)process.stdout.write(`${R}(saved in .loki/state/provider)${U}
437
- `);else process.stdout.write(`${R}(default - not explicitly set)${U}
457
+ `),process.stdout.write(`${O}Provider:${W} ${z}
458
+ `),z){case"claude":process.stdout.write(`${D}Status:${W} Full features (subagents, parallel, MCP)
459
+ `);break;case"cline":process.stdout.write(`${D}Status:${W} Near-full mode (subagents, MCP, 12+ providers)
460
+ `);break;case"codex":case"aider":process.stdout.write(`${E}Status:${W} Degraded mode (sequential only)
461
+ `);break;default:break}if($)process.stdout.write(`${x}(saved in .loki/state/provider)${W}
462
+ `);else process.stdout.write(`${x}(default - not explicitly set)${W}
438
463
  `);return process.stdout.write(`
439
- `),process.stdout.write(`Switch provider: ${A}loki provider set <name>${U}
440
- `),process.stdout.write(`Available: ${A}loki provider list${U}
441
- `),0}async function P6(){let Q=i1()||process.env.LOKI_PROVIDER||"claude";process.stdout.write(`${D}Available Providers${U}
464
+ `),process.stdout.write(`Switch provider: ${O}loki provider set <name>${W}
465
+ `),process.stdout.write(`Available: ${O}loki provider list${W}
466
+ `),0}async function m7(){let $=$0()||process.env.LOKI_PROVIDER||"claude";process.stdout.write(`${k}Available Providers${W}
442
467
  `),process.stdout.write(`
443
- `);let z=await Promise.all(_6.map(async(K)=>[K,await b(K)!==null])),X=new Map;for(let[K,W]of z)X.set(K,W?`${C}installed${U}`:`${L}not installed${U}`);let Z=[["claude","claude - Claude Code (Anthropic) "],["codex","codex - Codex CLI (OpenAI) "],["cline","cline - Cline (multi-provider) "],["aider","aider - Aider (terminal pair prog) "]];for(let[K,W]of Z){let q=Q===K?` ${A}(current)${U}`:"";process.stdout.write(` ${W} ${X.get(K)}${q}
468
+ `);let z=await Promise.all(y7.map(async(H)=>[H,await h(H)!==null])),Q=new Map;for(let[H,Z]of z)Q.set(H,Z?`${D}installed${W}`:`${R}not installed${W}`);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[H,Z]of X){let V=$===H?` ${O}(current)${W}`:"";process.stdout.write(` ${Z} ${Q.get(H)}${V}
444
469
  `)}return process.stdout.write(`
445
- `),process.stdout.write(`Set provider: ${A}loki provider set <name>${U}
446
- `),0}function x6(){return process.stdout.write(`${D}Loki Mode Provider Management${U}
470
+ `),process.stdout.write(`Set provider: ${O}loki provider set <name>${W}
471
+ `),0}function f7(){return process.stdout.write(`${k}Loki Mode Provider Management${W}
447
472
  `),process.stdout.write(`
448
473
  `),process.stdout.write(`Usage: loki provider <command>
449
474
  `),process.stdout.write(`
@@ -461,17 +486,17 @@ should not run it directly -- run \`loki start\` instead.
461
486
  `),process.stdout.write(` loki provider list
462
487
  `),process.stdout.write(` loki provider info codex
463
488
  `),process.stdout.write(` loki provider models
464
- `),0}async function e1($){let Q=$[0]??"show",z=$.slice(1);switch(Q){case"show":case"current":return L6(z[0]);case"list":return P6();case"set":case"info":case"models":return R6(["provider",Q,...z]);default:return x6()}}async function R6($){let{run:Q}=await Promise.resolve().then(() => (p(),t1)),{resolve:z}=await import("path"),{REPO_ROOT:X}=await Promise.resolve().then(() => (v(),a1)),Z=z(X,"autonomy","loki"),K=await Q([Z,...$],{env:{LOKI_LEGACY_BASH:"1"},timeoutMs:3600000});return process.stdout.write(K.stdout),process.stderr.write(K.stderr),K.exitCode}n();v();X1();p();import{existsSync as $0,readFileSync as E6}from"fs";import{resolve as t}from"path";import{mkdir as w6}from"fs/promises";var Z1=t(E1(),"learnings");function S1($){if(!$0($))return 0;try{let Q=E6($,"utf-8"),z=0;for(let X of Q.split(`
465
- `))if(X.includes('"description"'))z++;return z}catch{return 0}}async function S6(){await w6(Z1,{recursive:!0});let $=S1(t(Z1,"patterns.jsonl")),Q=S1(t(Z1,"mistakes.jsonl")),z=S1(t(Z1,"successes.jsonl"));return process.stdout.write(`${D}Cross-Project Learnings${U}
489
+ `),0}async function z0(K){let $=K[0]??"show",z=K.slice(1);switch($){case"show":case"current":return g7(z[0]);case"list":return m7();case"set":case"info":case"models":return u7(["provider",$,...z]);default:return f7()}}async function u7(K){let{run:$}=await Promise.resolve().then(() => (p(),K0)),{resolve:z}=await import("path"),{REPO_ROOT:Q}=await Promise.resolve().then(() => (y(),t1)),X=z(Q,"autonomy","loki"),H=await $([X,...K],{env:{LOKI_LEGACY_BASH:"1"},timeoutMs:3600000});return process.stdout.write(H.stdout),process.stderr.write(H.stderr),H.exitCode}n();y();Q1();p();import{existsSync as Q0,readFileSync as c7}from"fs";import{resolve as t}from"path";import{mkdir as l7}from"fs/promises";var X1=t(N1(),"learnings");function D1(K){if(!Q0(K))return 0;try{let $=c7(K,"utf-8"),z=0;for(let Q of $.split(`
490
+ `))if(Q.includes('"description"'))z++;return z}catch{return 0}}async function d7(){await l7(X1,{recursive:!0});let K=D1(t(X1,"patterns.jsonl")),$=D1(t(X1,"mistakes.jsonl")),z=D1(t(X1,"successes.jsonl"));return process.stdout.write(`${k}Cross-Project Learnings${W}
466
491
  `),process.stdout.write(`
467
- `),process.stdout.write(` Patterns: ${C}${$}${U}
468
- `),process.stdout.write(` Mistakes: ${x}${Q}${U}
469
- `),process.stdout.write(` Successes: ${A}${z}${U}
492
+ `),process.stdout.write(` Patterns: ${D}${K}${W}
493
+ `),process.stdout.write(` Mistakes: ${E}${$}${W}
494
+ `),process.stdout.write(` Successes: ${O}${z}${W}
470
495
  `),process.stdout.write(`
471
- `),process.stdout.write(`Location: ${Z1}
496
+ `),process.stdout.write(`Location: ${X1}
472
497
  `),process.stdout.write(`
473
498
  `),process.stdout.write(`Use 'loki memory show <type>' to view entries
474
- `),0}async function N6($){if($){let X=`
499
+ `),0}async function o7(K){if(K){let Q=`
475
500
  try:
476
501
  from memory.layers import IndexLayer
477
502
  layer = IndexLayer('.loki/memory')
@@ -481,9 +506,9 @@ except ImportError:
481
506
  print('Error: memory.layers module not found')
482
507
  except Exception as e:
483
508
  print(f'Error: {e}')
484
- `.trim(),Z=await a(X,{cwd:u});return process.stdout.write(Z.stdout),0}let Q=t(P(),"memory","index.json");if(!$0(Q))return process.stdout.write(`No index found
485
- `),0;let z=await a(`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
486
- `),0;return process.stdout.write(z.stdout),0}async function z0($){switch($[0]??"list"){case"list":case"ls":return S6();case"index":return N6($[1]==="rebuild");default:{let z=t(u,"autonomy","loki"),X=await E([z,"memory",...$],{env:{LOKI_LEGACY_BASH:"1"},timeoutMs:3600000});return process.stdout.write(X.stdout),process.stderr.write(X.stderr),X.exitCode}}}var Q6=`Loki Mode (TypeScript port, Phase 2 of bash->Bun migration)
509
+ `.trim(),X=await a(Q,{cwd:u});return process.stdout.write(X.stdout),0}let $=t(P(),"memory","index.json");if(!Q0($))return process.stdout.write(`No index found
510
+ `),0;let z=await a(`import json, sys; sys.stdout.write(json.dumps(json.load(open(${JSON.stringify($)})), indent=4) + "\\n")`);if(z.exitCode!==0)return process.stdout.write(`No index found
511
+ `),0;return process.stdout.write(z.stdout),0}async function X0(K){switch(K[0]??"list"){case"list":case"ls":return d7();case"index":return o7(K[1]==="rebuild");default:{let z=t(u,"autonomy","loki"),Q=await w([z,"memory",...K],{env:{LOKI_LEGACY_BASH:"1"},timeoutMs:3600000});return process.stdout.write(Q.stdout),process.stderr.write(Q.stderr),Q.exitCode}}}var A7=`Loki Mode (TypeScript port, Phase 2 of bash->Bun migration)
487
512
 
488
513
  Usage: loki <command> [args...]
489
514
 
@@ -501,12 +526,12 @@ Phase 2 ported (Bun-native, fast):
501
526
 
502
527
  All other commands fall through to the bash CLI (autonomy/loki).
503
528
  Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
504
- `;function j5(){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.
505
- `)}async function _5($){j5();let Q=$[0],z=$.slice(1);switch(Q){case void 0:case"help":case"--help":case"-h":return process.stdout.write(Q6),0;case"version":case"--version":case"-v":return r1();case"provider":return e1(z);case"memory":return z0(z);case"status":{let{runStatus:X}=await Promise.resolve().then(() => (H0(),q0));return X(z)}case"stats":{let{runStats:X}=await Promise.resolve().then(() => (Y0(),B0));return X(z)}case"doctor":{let{runDoctor:X}=await Promise.resolve().then(() => (x0(),P0));return X(z)}case"rollback":{let{runRollback:X}=await Promise.resolve().then(() => (y0(),b0));return X(z)}case"internal":{let X=z[0];if(!X||X==="--help"||X==="-h"||X==="help"){let K=["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(`
506
- `);return process.stdout.write(`${K}
507
- `),0}if(X==="phase1-hooks"){let{runInternalPhase1Hooks:K}=await Promise.resolve().then(() => (z6(),$6));return K(z.slice(1))}return process.stderr.write(`Unknown internal subcommand: ${X}
529
+ `;function eK(){let K=process.env.LOKI_LEGACY_BASH;if(K===void 0)return;let $=K.trim().toLowerCase();if($!=="1"&&$!=="true"&&$!=="yes"&&$!=="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.
530
+ `)}async function K6(K){eK();let $=K[0],z=K.slice(1);switch($){case void 0:case"help":case"--help":case"-h":return process.stdout.write(A7),0;case"version":case"--version":case"-v":return e1();case"provider":return z0(z);case"memory":return X0(z);case"status":{let{runStatus:Q}=await Promise.resolve().then(() => (G0(),J0));return Q(z)}case"stats":{let{runStats:Q}=await Promise.resolve().then(() => (T0(),O0));return Q(z)}case"doctor":{let{runDoctor:Q}=await Promise.resolve().then(() => (F0(),x0));return Q(z)}case"kpis":{let{runKpis:Q}=await Promise.resolve().then(() => (f0(),m0));return Q(z)}case"rollback":{let{runRollback:Q}=await Promise.resolve().then(() => (t0(),r0));return Q(z)}case"internal":{let Q=z[0];if(!Q||Q==="--help"||Q==="-h"||Q==="help"){let H=["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(`
531
+ `);return process.stdout.write(`${H}
532
+ `),0}if(Q==="phase1-hooks"){let{runInternalPhase1Hooks:H}=await Promise.resolve().then(() => (T7(),O7));return H(z.slice(1))}return process.stderr.write(`Unknown internal subcommand: ${Q}
508
533
  `),process.stderr.write(`Run 'loki internal --help' for the supported list.
509
- `),2}default:return process.stderr.write(`Unknown command: ${Q}
510
- `),process.stderr.write(Q6),2}}process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var I5=await _5(Bun.argv.slice(2));process.exit(I5);
534
+ `),2}default:return process.stderr.write(`Unknown command: ${$}
535
+ `),process.stderr.write(A7),2}}process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var $6=await K6(Bun.argv.slice(2));process.exit($6);
511
536
 
512
- //# debugId=B969F5C49B8FCB5864756E2164756E21
537
+ //# debugId=296177BB08F8D57264756E2164756E21