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