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