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.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/project-graph.sh +24 -14
- package/autonomy/loki +50 -18
- package/bin/loki +2 -1
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/MERGE-DEDUP-MAP.md +420 -0
- package/docs/MERGE-ROUTE-MAP.md +139 -0
- package/docs/MERGE3-PLAN.md +119 -0
- package/loki-ts/dist/loki.js +196 -171
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/web-app/dist/assets/{AdminPage-DwVUK4v9.js → AdminPage-CKUOsWZW.js} +3 -3
- package/web-app/dist/assets/{Avatar-B7gqhcg3.js → Avatar-CL9Id9Hi.js} +1 -1
- package/web-app/dist/assets/{Badge-DA3xNJAS.js → Badge-B12zwlD7.js} +1 -1
- package/web-app/dist/assets/{Button-BPXURLaK.js → Button-CFLVoduT.js} +1 -1
- package/web-app/dist/assets/{ComparePage-B0JQMhKG.js → ComparePage-Dg0UdZAk.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-D38-fy29.js → GitHubIssuesPanel-CSitxtAX.js} +2 -2
- package/web-app/dist/assets/{GitHubPRsPanel-DLPcW3N0.js → GitHubPRsPanel-BIT06FRo.js} +1 -1
- package/web-app/dist/assets/HomePage-pU_0fGny.js +28 -0
- package/web-app/dist/assets/{LoginPage-DqCzxsfx.js → LoginPage-DTZtt2Yb.js} +1 -1
- package/web-app/dist/assets/MagicPage-10zfra8o.js +31 -0
- package/web-app/dist/assets/{MetricsPage-CPYQR0zr.js → MetricsPage-C-wiKUkv.js} +1 -1
- package/web-app/dist/assets/NotFoundPage-BDkcmhYe.js +1 -0
- package/web-app/dist/assets/{ProjectPage-DNujSl6j.js → ProjectPage-CiCavQ8n.js} +71 -71
- package/web-app/dist/assets/ProjectsPage-BLCXQwwC.js +6 -0
- package/web-app/dist/assets/{SettingsPage-BaQJbOgL.js → SettingsPage-PkxtaMyg.js} +3 -3
- package/web-app/dist/assets/{ShowcasePage-DQR_e-kg.js → ShowcasePage-iECp8Tha.js} +1 -1
- package/web-app/dist/assets/SystemSettingsPage-DS6Anno1.js +6 -0
- package/web-app/dist/assets/{TeamsPage-DOFErDqX.js → TeamsPage-ls6h6bNL.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-Ty72hILN.js → TemplatesPage-Bk0QzlPt.js} +3 -3
- package/web-app/dist/assets/{TerminalOutput-DqOVnR1p.js → TerminalOutput-4-1hWCtZ.js} +1 -1
- package/web-app/dist/assets/{activity-BgBZ4s4c.js → activity-DH3ih2nS.js} +1 -1
- package/web-app/dist/assets/{bell-C-UezVWi.js → bell-Gn17S6uv.js} +1 -1
- package/web-app/dist/assets/{bot-D70fEnm5.js → bot-Cbycc3VE.js} +1 -1
- package/web-app/dist/assets/{check-CBohulxQ.js → check-nIAqa-kf.js} +1 -1
- package/web-app/dist/assets/{chevron-left-C-emzUhB.js → chevron-left-D2jcWDll.js} +1 -1
- package/web-app/dist/assets/{circle-alert-8SRY0_GX.js → circle-alert-CpL4Bhvt.js} +1 -1
- package/web-app/dist/assets/{clock-mfq4XnPQ.js → clock-IW4Wq86N.js} +1 -1
- package/web-app/dist/assets/{cloud-DpRM7T8t.js → cloud-Cn8nNuH2.js} +1 -1
- package/web-app/dist/assets/{code-xml-1N2Ui-4c.js → code-xml-BiJBteXf.js} +1 -1
- package/web-app/dist/assets/{copy-LXquTgzI.js → copy-CnqkyNsi.js} +1 -1
- package/web-app/dist/assets/{database-S1dyXnuT.js → database-CKSReqa5.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-CRqk0dW5.js → dollar-sign-CDzDY64R.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-B99CwY_6.js → file-code-corner-Box4IwG1.js} +1 -1
- package/web-app/dist/assets/{file-plus-DZ5qnz5b.js → file-plus-DpGqlXF8.js} +1 -1
- package/web-app/dist/assets/{folder-open-DBCm7yuF.js → folder-open-B57dAoBv.js} +1 -1
- package/web-app/dist/assets/{git-commit-horizontal-DM1ERuNd.js → git-commit-horizontal-BVbucmO5.js} +1 -1
- package/web-app/dist/assets/{globe-B7xEJSL_.js → globe-BkOnKl4x.js} +1 -1
- package/web-app/dist/assets/{hammer-Cgi3LTuS.js → hammer-DRbIQ4QU.js} +1 -1
- package/web-app/dist/assets/{index-BN52-GQT.js → index-CM_b_EhP.js} +77 -77
- package/web-app/dist/assets/{layers-Bi8RPIBC.js → layers-B78BiFiU.js} +1 -1
- package/web-app/dist/assets/{lightbulb-Doc_n8JX.js → lightbulb-B-Itbm9g.js} +1 -1
- package/web-app/dist/assets/{loader-circle-BB932A7A.js → loader-circle-Oq6NQhW2.js} +1 -1
- package/web-app/dist/assets/{lock-Bt6gpMrs.js → lock-DbJ9zxbw.js} +1 -1
- package/web-app/dist/assets/{mail-BuzAu1IP.js → mail-CzMRod6m.js} +1 -1
- package/web-app/dist/assets/{package-BE5FHxQ8.js → package-WZ5osvej.js} +1 -1
- package/web-app/dist/assets/{plus-CNqABexN.js → plus-j08lFR-K.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-34B13ztx.js → refresh-cw-CIr7E-g2.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-CrD2QB29.js → rotate-ccw-gwoXxDeE.js} +1 -1
- package/web-app/dist/assets/{save-DsJcqdnI.js → save-B8fV_ZpE.js} +1 -1
- package/web-app/dist/assets/{server-BcgRMArA.js → server-D5dO1paz.js} +1 -1
- package/web-app/dist/assets/{shield-alert-DLYLdVJ0.js → shield-alert-Du08zhdg.js} +1 -1
- package/web-app/dist/assets/{trash-2-Cc-VTvzt.js → trash-2-DEKSVae5.js} +1 -1
- package/web-app/dist/assets/{trending-down-CrDpO2a_.js → trending-down-DBiXUtxJ.js} +1 -1
- package/web-app/dist/assets/{trending-up-CNVsmM3G.js → trending-up-BgmK_tHq.js} +1 -1
- package/web-app/dist/assets/{upload-LuDuB7Wc.js → upload-IaViyeVD.js} +1 -1
- package/web-app/dist/assets/{usePolling-C8rvc-CG.js → usePolling-PiRLqNu6.js} +1 -1
- package/web-app/dist/assets/{user-BT79cI-o.js → user-BB5J8wAF.js} +1 -1
- package/web-app/dist/index.html +2 -3
- package/web-app/server.py +45 -7
- package/web-app/dist/assets/HomePage-CzeoS2V_.js +0 -28
- package/web-app/dist/assets/MagicPage-CBLqpa55.js +0 -31
- package/web-app/dist/assets/NotFoundPage-B62u4iCs.js +0 -1
- package/web-app/dist/assets/ProjectsPage-uHG7kxB-.js +0 -6
- package/web-app/dist/assets/SystemSettingsPage-C_Q_1WK4.js +0 -6
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
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
|
|
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(`${
|
|
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(`${
|
|
17
|
-
`),0;process.stdout.write(`${
|
|
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
|
|
20
|
-
`),process.stdout.write(`${
|
|
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
|
|
23
|
-
`);for(let
|
|
24
|
-
`);else process.stdout.write(` ${
|
|
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(`${
|
|
27
|
-
`),process.stdout.write(`${
|
|
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(
|
|
30
|
-
`),process.stdout.write(`${
|
|
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(
|
|
33
|
-
`),process.stdout.write(`${
|
|
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
|
|
36
|
-
`);try{process.stdout.write(
|
|
37
|
-
`)}let
|
|
38
|
-
`);let
|
|
39
|
-
`)}let
|
|
40
|
-
`)}let
|
|
41
|
-
`);else process.stdout.write(`${
|
|
42
|
-
`)}let
|
|
43
|
-
`)}let B=F(
|
|
44
|
-
`)}}return await
|
|
45
|
-
`),process.stdout.write(`${
|
|
46
|
-
`),process.stdout.write(`${
|
|
47
|
-
`),0}async function
|
|
48
|
-
${
|
|
49
|
-
`),
|
|
50
|
-
`)}}if(
|
|
51
|
-
`)}}if(
|
|
52
|
-
`)}}function
|
|
53
|
-
`),1;let
|
|
54
|
-
`),1;return process.stdout.write(
|
|
55
|
-
`),0;return process.stdout.write(`${
|
|
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
|
|
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
|
|
265
|
-
`)}function
|
|
266
|
-
Start a session with: loki start <prd>`}}let
|
|
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
|
|
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
|
|
280
|
-
`);for(let
|
|
281
|
-
`),Y1(
|
|
282
|
-
`),process.stdout.write(`${
|
|
283
|
-
`);let
|
|
284
|
-
`),Y1(
|
|
285
|
-
`),process.stdout.write(` ${
|
|
286
|
-
`)
|
|
287
|
-
`),process.stdout.write(`${
|
|
288
|
-
`);let
|
|
289
|
-
`)
|
|
290
|
-
`);if(
|
|
291
|
-
`)
|
|
292
|
-
`);if(
|
|
293
|
-
`)
|
|
294
|
-
`)
|
|
295
|
-
`)
|
|
296
|
-
`),process.stdout.write(`${
|
|
297
|
-
`);for(let
|
|
298
|
-
`)
|
|
299
|
-
`),process.stdout.write(` ${
|
|
300
|
-
`)
|
|
301
|
-
`)
|
|
302
|
-
`),process.stdout.write(`${
|
|
303
|
-
`);let[
|
|
304
|
-
`)
|
|
305
|
-
`)
|
|
306
|
-
`)
|
|
307
|
-
`)
|
|
308
|
-
`)
|
|
309
|
-
`)
|
|
310
|
-
`)
|
|
311
|
-
`)
|
|
312
|
-
`)
|
|
313
|
-
`)
|
|
314
|
-
`)
|
|
315
|
-
`)
|
|
316
|
-
`)
|
|
317
|
-
`)
|
|
318
|
-
`),process.stdout.write(`${
|
|
319
|
-
`);let
|
|
320
|
-
`),Y1(
|
|
321
|
-
`),Y1(
|
|
322
|
-
`)
|
|
323
|
-
`)
|
|
324
|
-
`)
|
|
325
|
-
`)
|
|
326
|
-
`),process.stdout.write(`${
|
|
327
|
-
`);let
|
|
328
|
-
`),process.env.LOKI_LEGACY_BASH==="1"||process.env.LOKI_LEGACY_BASH==="true")process.stdout.write(` ${
|
|
329
|
-
`);if(process.env.LOKI_TS_ENTRY)process.stdout.write(` ${
|
|
330
|
-
`);if(process.env.BUN_FROM_SOURCE==="1"||process.env.BUN_FROM_SOURCE==="true")process.stdout.write(` ${
|
|
331
|
-
`);let
|
|
332
|
-
`);else if(N)process.stdout.write(` ${
|
|
333
|
-
`);else process.stdout.write(` ${
|
|
334
|
-
`)}else process.stdout.write(` ${
|
|
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(`${
|
|
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
|
-
`)
|
|
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(
|
|
341
|
-
`),0;return process.stdout.write(`${
|
|
342
|
-
`),0}async function
|
|
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(
|
|
345
|
-
`),0}return
|
|
346
|
-
`)
|
|
347
|
-
|
|
348
|
-
`)
|
|
349
|
-
|
|
350
|
-
`),
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
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
|
|
377
|
-
`)}function
|
|
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:
|
|
405
|
-
`)}async function
|
|
406
|
-
`)}function
|
|
407
|
-
`),process.stderr.write(
|
|
408
|
-
`),2;let z=P();try{let
|
|
409
|
-
`),0;let
|
|
410
|
-
`),0}catch(
|
|
411
|
-
`),1}}async function
|
|
412
|
-
`),2;let z=P();try{let
|
|
413
|
-
`),0;let
|
|
414
|
-
`),0;let
|
|
415
|
-
`);else process.stdout.write(`override: BLOCKED -- ${
|
|
416
|
-
`);return 0}catch(
|
|
417
|
-
`),1}}async function
|
|
418
|
-
`),2;let
|
|
419
|
-
`),0}catch(
|
|
420
|
-
`),1}}function
|
|
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
|
-
`,
|
|
430
|
-
`),0}p();n();
|
|
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(`${
|
|
433
|
-
`),z){case"claude":process.stdout.write(`${
|
|
434
|
-
`);break;case"cline":process.stdout.write(`${
|
|
435
|
-
`);break;case"codex":case"aider":process.stdout.write(`${
|
|
436
|
-
`);break;default:break}if(
|
|
437
|
-
`);else process.stdout.write(`${
|
|
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: ${
|
|
440
|
-
`),process.stdout.write(`Available: ${
|
|
441
|
-
`),0}async function
|
|
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(
|
|
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: ${
|
|
446
|
-
`),0}function
|
|
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
|
|
465
|
-
`))if(
|
|
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: ${
|
|
468
|
-
`),process.stdout.write(` Mistakes: ${
|
|
469
|
-
`),process.stdout.write(` Successes: ${
|
|
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: ${
|
|
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
|
|
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(),
|
|
485
|
-
`),0;let z=await a(`import json, sys; sys.stdout.write(json.dumps(json.load(open(${JSON.stringify(
|
|
486
|
-
`),0;return process.stdout.write(z.stdout),0}async function
|
|
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
|
|
505
|
-
`)}async function
|
|
506
|
-
`);return process.stdout.write(`${
|
|
507
|
-
`),0}if(
|
|
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: ${
|
|
510
|
-
`),process.stderr.write(
|
|
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=
|
|
537
|
+
//# debugId=296177BB08F8D57264756E2164756E21
|