loki-mode 9.22.11 → 9.22.12

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 CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v9.22.11
6
+ # Loki Mode v9.22.12
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -470,4 +470,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
470
470
 
471
471
  ---
472
472
 
473
- **v9.22.11 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
473
+ **v9.22.12 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 9.22.11
1
+ 9.22.12
@@ -17,7 +17,7 @@
17
17
  # Returns 0 on success, 1 only if the dir
18
18
  # cannot be created or the file cannot be
19
19
  # written.
20
- # loki_user_mcp_config_path -- emit absolute path to ~/.claude/mcp.json
20
+ # loki_user_mcp_config_path -- emit a bounded, current-schema ~/.claude/mcp.json
21
21
  # if present + readable, else empty. Always
22
22
  # returns 0.
23
23
  # loki_mcp_config_argv -- emit one space-separated string of paths
@@ -127,12 +127,35 @@ print(os.path.abspath(os.environ['_MCP_OUT']))
127
127
  }
128
128
 
129
129
  # ---------- User overlay path ----------
130
- # Echoes ~/.claude/mcp.json if it exists and is readable, else empty.
131
- # Always returns 0 -- a missing overlay is a normal state, not an error.
130
+ # Echoes ~/.claude/mcp.json only when it is valid JSON with the current Claude
131
+ # Code top-level `mcpServers` object. Older files using `servers` are not valid
132
+ # inputs to `claude --mcp-config`: passing one makes Claude refuse before the
133
+ # first provider turn. Ignore those files with an actionable warning so Loki's
134
+ # own valid bundle can still start the run.
135
+ # The 1 MiB bound prevents a local overlay from turning provider startup into an
136
+ # unbounded read. Always returns 0 -- a missing/invalid overlay is recoverable,
137
+ # not fatal.
132
138
  loki_user_mcp_config_path() {
133
139
  local user_path="${HOME}/.claude/mcp.json"
134
140
  if [ -f "$user_path" ] && [ -r "$user_path" ]; then
135
- printf '%s' "$user_path"
141
+ if _LOKI_USER_MCP="$user_path" python3 -c "
142
+ import json, os, sys
143
+ try:
144
+ path = os.environ['_LOKI_USER_MCP']
145
+ if os.path.getsize(path) > 1024 * 1024:
146
+ sys.exit(1)
147
+ with open(path, encoding='utf-8') as handle:
148
+ value = json.load(handle)
149
+ except (OSError, ValueError):
150
+ sys.exit(1)
151
+ sys.exit(0 if isinstance(value, dict) and isinstance(value.get('mcpServers'), dict) else 1)
152
+ " 2>/dev/null; then
153
+ printf '%s' "$user_path"
154
+ else
155
+ printf '%s\n' \
156
+ 'loki: ignoring ~/.claude/mcp.json: Claude Code requires a top-level "mcpServers" object; update or remove the legacy/invalid file.' \
157
+ >&2
158
+ fi
136
159
  fi
137
160
  return 0
138
161
  }
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "9.22.11"
10
+ __version__ = "9.22.12"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v9.22.11
5
+ **Version:** v9.22.12
6
6
 
7
7
  ---
8
8
 
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var Mf=Object.create;var{getPrototypeOf:Tf,defineProperty:Q$,getOwnPropertyNames:wf}=Object;var Cf=Object.prototype.hasOwnProperty;function Ff(Z){return this[Z]}var Df,Ef,Pf=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?Df??=new WeakMap:Ef??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?Mf(Tf(Z)):{};let K=X||!Z||!Z.__esModule?Q$(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of wf(Z))if(!Cf.call(K,$))Q$(K,$,{get:Ff.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var LQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var kf=(Z)=>Z;function xf(Z,X){this[Z]=kf.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)Q$(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:xf.bind(X,Q)})};var u=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var Z8=import.meta.require;var fO={};l0(fO,{lokiDir:()=>U0,homeLokiDir:()=>S4,findRepoRootForVersion:()=>J$,REPO_ROOT:()=>n0});import{resolve as s7,dirname as Y$}from"path";import{fileURLToPath as Sf}from"url";import{existsSync as AQ}from"fs";import{homedir as yf}from"os";function bf(){let Z=_O;for(let X=0;X<6;X++){if(AQ(s7(Z,"VERSION"))&&AQ(s7(Z,"autonomy/run.sh")))return Z;let Q=Y$(Z);if(Q===Z)break;Z=Q}return s7(_O,"..","..","..")}function J$(Z){let X=Z;for(let Q=0;Q<6;Q++){if(AQ(s7(X,"VERSION"))&&AQ(s7(X,"autonomy/run.sh")))return X;let Y=Y$(X);if(Y===X)break;X=Y}return s7(Z,"..","..","..")}function U0(){return process.env.LOKI_DIR??s7(process.cwd(),".loki")}function S4(){return s7(yf(),".loki")}var _O,n0;var z8=u(()=>{_O=Y$(Sf(import.meta.url));n0=bf()});import{readFileSync as _f}from"fs";import{resolve as ff,dirname as hf}from"path";import{fileURLToPath as vf}from"url";function v3(){if(v5!==null)return v5;let Z="9.22.11";if(typeof Z==="string"&&Z.length>0)return v5=Z,v5;try{let X=hf(vf(import.meta.url)),Q=J$(X);v5=_f(ff(Q,"VERSION"),"utf-8").trim()}catch{v5="unknown"}return v5}var v5=null;var jQ=u(()=>{z8()});var mO={};l0(mO,{runOrThrow:()=>Xh,run:()=>P0,readStreamCapped:()=>MQ,commandVersion:()=>Yh,commandExists:()=>X9,ShellError:()=>z$,MAX_STDOUT_BYTES:()=>gO});async function MQ(Z,X=gO){let Q=Z.getReader(),Y=new TextDecoder,J="",z=0;try{while(z<X){let{done:K,value:$}=await Q.read();if(K)break;if(!$)continue;if(z+=$.byteLength,z>X){let V=$.byteLength-(z-X);J+=Y.decode($.subarray(0,V),{stream:!0});break}J+=Y.decode($,{stream:!0})}J+=Y.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function P0(Z,X={}){let Q=Bun.spawn({cmd:[...Z],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),Y,J;if(X.timeoutMs&&X.timeoutMs>0)Y=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[z,K,$]=await Promise.all([MQ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:K,exitCode:$}}finally{if(Y)clearTimeout(Y);if(J)clearTimeout(J)}}async function Xh(Z,X={}){let Q=await P0(Z,X);if(Q.exitCode!==0)throw new z$(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function X9(Z){let X=Qh(Z),Q=await P0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Qh(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Yh(Z,X="--version"){if(!await X9(Z))return null;let Y=await P0([Z,X],{timeoutMs:5000});if(Y.exitCode!==0)return null;return((Y.stdout||Y.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var gO=16777216,z$;var x9=u(()=>{z$=class z$ extends Error{message;exitCode;stdout;stderr;constructor(Z,X,Q,Y){super(Z);this.message=Z;this.exitCode=X;this.stdout=Q;this.stderr=Y;this.name="ShellError"}}});function o7(Z){return Jh?"":Z}var Jh,j0,F8,h0,wq0,s0,W8,Q9,h;var _6=u(()=>{Jh=(process.env.NO_COLOR??"").length>0;j0=o7("\x1B[0;31m"),F8=o7("\x1B[0;32m"),h0=o7("\x1B[1;33m"),wq0=o7("\x1B[0;34m"),s0=o7("\x1B[0;36m"),W8=o7("\x1B[1m"),Q9=o7("\x1B[2m"),h=o7("\x1B[0m")});import{existsSync as Bh}from"fs";async function P7(){if(b4!==void 0)return b4;let Z="/opt/homebrew/bin/python3.12";if(Bh(Z))return b4=Z,Z;let X=await X9("python3.12");if(X)return b4=X,X;let Q=await X9("python3");return b4=Q,Q}async function K7(Z,X={}){let Q=await P7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return P0([Q,"-c",Z],X)}var b4;var r7=u(()=>{x9()});var KL={};l0(KL,{runStatus:()=>gh});import{existsSync as Y9,readFileSync as m3,readdirSync as tO,statSync as eO}from"fs";import{resolve as h8,basename as kh}from"path";import{homedir as xh}from"os";function ZL(Z){let X=Math.trunc(Z);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function XL(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*wQ/X);if(J>wQ)J=wQ;let z=wQ-J,K=F8;if(Y>=80)K=j0;else if(Y>=50)K=h0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),V=ZL(Z),W=ZL(X);return` ${W8}${Q}${h} ${K}[${$}]${h} ${Y}% (${V} / ${W})`}async function yh(){if(await X9("jq"))return!0;return process.stdout.write(`${j0}Error: jq is required but not installed.${h}
2
+ var Mf=Object.create;var{getPrototypeOf:Tf,defineProperty:Q$,getOwnPropertyNames:wf}=Object;var Cf=Object.prototype.hasOwnProperty;function Ff(Z){return this[Z]}var Df,Ef,Pf=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?Df??=new WeakMap:Ef??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?Mf(Tf(Z)):{};let K=X||!Z||!Z.__esModule?Q$(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of wf(Z))if(!Cf.call(K,$))Q$(K,$,{get:Ff.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var LQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var kf=(Z)=>Z;function xf(Z,X){this[Z]=kf.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)Q$(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:xf.bind(X,Q)})};var u=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var Z8=import.meta.require;var fO={};l0(fO,{lokiDir:()=>U0,homeLokiDir:()=>S4,findRepoRootForVersion:()=>J$,REPO_ROOT:()=>n0});import{resolve as s7,dirname as Y$}from"path";import{fileURLToPath as Sf}from"url";import{existsSync as AQ}from"fs";import{homedir as yf}from"os";function bf(){let Z=_O;for(let X=0;X<6;X++){if(AQ(s7(Z,"VERSION"))&&AQ(s7(Z,"autonomy/run.sh")))return Z;let Q=Y$(Z);if(Q===Z)break;Z=Q}return s7(_O,"..","..","..")}function J$(Z){let X=Z;for(let Q=0;Q<6;Q++){if(AQ(s7(X,"VERSION"))&&AQ(s7(X,"autonomy/run.sh")))return X;let Y=Y$(X);if(Y===X)break;X=Y}return s7(Z,"..","..","..")}function U0(){return process.env.LOKI_DIR??s7(process.cwd(),".loki")}function S4(){return s7(yf(),".loki")}var _O,n0;var z8=u(()=>{_O=Y$(Sf(import.meta.url));n0=bf()});import{readFileSync as _f}from"fs";import{resolve as ff,dirname as hf}from"path";import{fileURLToPath as vf}from"url";function v3(){if(v5!==null)return v5;let Z="9.22.12";if(typeof Z==="string"&&Z.length>0)return v5=Z,v5;try{let X=hf(vf(import.meta.url)),Q=J$(X);v5=_f(ff(Q,"VERSION"),"utf-8").trim()}catch{v5="unknown"}return v5}var v5=null;var jQ=u(()=>{z8()});var mO={};l0(mO,{runOrThrow:()=>Xh,run:()=>P0,readStreamCapped:()=>MQ,commandVersion:()=>Yh,commandExists:()=>X9,ShellError:()=>z$,MAX_STDOUT_BYTES:()=>gO});async function MQ(Z,X=gO){let Q=Z.getReader(),Y=new TextDecoder,J="",z=0;try{while(z<X){let{done:K,value:$}=await Q.read();if(K)break;if(!$)continue;if(z+=$.byteLength,z>X){let V=$.byteLength-(z-X);J+=Y.decode($.subarray(0,V),{stream:!0});break}J+=Y.decode($,{stream:!0})}J+=Y.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function P0(Z,X={}){let Q=Bun.spawn({cmd:[...Z],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),Y,J;if(X.timeoutMs&&X.timeoutMs>0)Y=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[z,K,$]=await Promise.all([MQ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:K,exitCode:$}}finally{if(Y)clearTimeout(Y);if(J)clearTimeout(J)}}async function Xh(Z,X={}){let Q=await P0(Z,X);if(Q.exitCode!==0)throw new z$(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function X9(Z){let X=Qh(Z),Q=await P0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Qh(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Yh(Z,X="--version"){if(!await X9(Z))return null;let Y=await P0([Z,X],{timeoutMs:5000});if(Y.exitCode!==0)return null;return((Y.stdout||Y.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var gO=16777216,z$;var x9=u(()=>{z$=class z$ extends Error{message;exitCode;stdout;stderr;constructor(Z,X,Q,Y){super(Z);this.message=Z;this.exitCode=X;this.stdout=Q;this.stderr=Y;this.name="ShellError"}}});function o7(Z){return Jh?"":Z}var Jh,j0,F8,h0,wq0,s0,W8,Q9,h;var _6=u(()=>{Jh=(process.env.NO_COLOR??"").length>0;j0=o7("\x1B[0;31m"),F8=o7("\x1B[0;32m"),h0=o7("\x1B[1;33m"),wq0=o7("\x1B[0;34m"),s0=o7("\x1B[0;36m"),W8=o7("\x1B[1m"),Q9=o7("\x1B[2m"),h=o7("\x1B[0m")});import{existsSync as Bh}from"fs";async function P7(){if(b4!==void 0)return b4;let Z="/opt/homebrew/bin/python3.12";if(Bh(Z))return b4=Z,Z;let X=await X9("python3.12");if(X)return b4=X,X;let Q=await X9("python3");return b4=Q,Q}async function K7(Z,X={}){let Q=await P7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return P0([Q,"-c",Z],X)}var b4;var r7=u(()=>{x9()});var KL={};l0(KL,{runStatus:()=>gh});import{existsSync as Y9,readFileSync as m3,readdirSync as tO,statSync as eO}from"fs";import{resolve as h8,basename as kh}from"path";import{homedir as xh}from"os";function ZL(Z){let X=Math.trunc(Z);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function XL(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*wQ/X);if(J>wQ)J=wQ;let z=wQ-J,K=F8;if(Y>=80)K=j0;else if(Y>=50)K=h0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),V=ZL(Z),W=ZL(X);return` ${W8}${Q}${h} ${K}[${$}]${h} ${Y}% (${V} / ${W})`}async function yh(){if(await X9("jq"))return!0;return process.stdout.write(`${j0}Error: jq is required but not installed.${h}
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)
@@ -832,7 +832,7 @@ new Anthropic({ apiKey, dangerouslyAllowBrowser: true });
832
832
  `),z.verdict==="accepted"?0:2}}catch(J){let z=J instanceof Error?J.message:String(J);return process.stderr.write(`exec-manifest: ${z}
833
833
  `),2}return process.stderr.write(`exec-manifest: unknown action "${X}"
834
834
  `),2}var Hw=u(()=>{Ww()});var Uw;var Bw=u(()=>{Uw={now:()=>Date.now(),sleep:(Z)=>new Promise((X)=>setTimeout(X,Z))}});import{resolve as Qc,join as Xq}from"path";import{existsSync as Qq,mkdirSync as Yc}from"fs";function Jc(){return Qc(n0,"autonomy","lib","proof-generator.py")}function zc(){let Z=new Date().toISOString().replace(/[-:T]/g,"").slice(0,14),X=Math.floor(Math.random()*32768);return`proof-${Z}-${process.pid}-${X}`}async function Nw(Z){try{if(process.env.LOKI_PROOF==="0")return!1;let X=Jc();if(!Qq(X))return!1;if(!Qq(Z.lokiDir))return!1;let Q=await P7();if(!Q)return!1;let Y="unknown";try{Y=v3()}catch{}let J=zc(),z=[X,"--loki-dir",Z.lokiDir,"--loki-version",Y,"--provider",Z.provider,"--run-id",J,"--quiet"],K={ITERATION_COUNT:String(Z.iterationCount),PROVIDER_NAME:Z.provider};if(Z.prdPath)K.PRD_PATH=Z.prdPath;await P0([Q,...z],{cwd:Z.cwd,env:K,timeoutMs:30000});let $=Xq(Z.lokiDir,"proofs",J,"proof.json");if(Qq($))try{let V=Xq(Z.lokiDir,"state");Yc(V,{recursive:!0}),H6(Xq(V,"last-proof-id.txt"),J)}catch{}return!0}catch(X){try{Z.log(`[runner] proof-of-run generation skipped: ${X.message}`)}catch{}return!1}}var Ow=u(()=>{z8();r7();x9();jQ();$7()});import{existsSync as Lw,readFileSync as Aw,writeFileSync as Kc,mkdirSync as $c,statSync as jw}from"fs";import{resolve as Vc,join as Yq,delimiter as Wc}from"path";function Gc(){let Z=process.env.PATH??"";if(!Z)return!1;let X=Z.split(Wc).filter((Q)=>Q.length>0);for(let Q of qc)for(let Y of X){let J=Yq(Y,Q);try{if(jw(J).isFile())return!0}catch{}}return!1}function Hc(Z){let X={"loki-mode":{command:"python3",args:["-m","mcp.server"]}};if(Z)X["lsp-proxy"]={command:"python3",args:["-m","mcp.lsp_proxy"]};return{mcpServers:X}}function Uc(Z){return JSON.stringify(Z,null,2)+`
835
- `}function Jq(Z){let X=Vc(Z,".loki"),Q=Yq(X,"mcp-config.json"),Y=Uc(Hc(Gc())),J=null;if(Lw(Q))try{J=Aw(Q,"utf8")}catch{J=null}if(J===Y)return Q;return $c(X,{recursive:!0}),Kc(Q,Y,"utf8"),Q}function Bc(){let Z=process.env.HOME;if(!Z)return null;let X=Yq(Z,".claude","mcp.json");if(!Lw(X))return null;try{if(!jw(X).isFile())return null;return Aw(X,"utf8"),X}catch{return null}}function Mw(Z){let Q=["--mcp-config",Jq(Z)],Y=Bc();if(Y!==null)Q.push(Y);return Q}var qc;var zq=u(()=>{qc=["typescript-language-server","pylsp","gopls","rust-analyzer"]});import{existsSync as Fw,readFileSync as Kq}from"fs";import{resolve as Dw,dirname as Nc}from"path";import{fileURLToPath as Oc}from"url";import{createHash as Lc}from"crypto";function E2(Z,X){let Q;switch(Z){case"planning":case"best":Q="xhigh";break;case"development":case"balanced":Q="high";break;case"fast":Q="medium";break;case"cheap":Q="low";break;default:Q="high";break}if((X??process.env.LOKI_COMPLEXITY??"standard")==="complex")switch(Q){case"low":Q="medium";break;case"medium":Q="high";break;case"high":Q="xhigh";break}return Q}function Tw(...Z){return Z.some((X)=>{let Q=process.env[X];return Q!==void 0&&Q!==""})}function $q(Z,X){if(process.env.LOKI_TIER_ROUTING!=="1")return X;let Q=process.env.LOKI_COMPLEXITY??"standard";switch(Z){case"planning":if(Q==="complex"&&!Tw("LOKI_CLAUDE_MODEL_PLANNING","LOKI_MODEL_PLANNING"))return"opus";return X;case"fast":if(Q==="simple"&&process.env.LOKI_ALLOW_HAIKU==="true"&&!Tw("LOKI_CLAUDE_MODEL_FAST","LOKI_MODEL_FAST"))return"haiku";return X;default:return X}}function Vq(Z){let X=process.env.LOKI_BUDGET_LIMIT;if(!X)return null;let Q=parseFloat(X);if(!Number.isFinite(Q)||Q<=0)return null;let Y=Z??process.env.TARGET_DIR??".",J=Dw(Y,".loki","metrics","budget.json"),z=0;if(Fw(J))try{let V=JSON.parse(Kq(J,"utf8")).current_spend;if(typeof V==="number"&&Number.isFinite(V))z=V;else if(typeof V==="string"){let W=parseFloat(V);if(Number.isFinite(W))z=W}}catch{z=0}let K=Q-z;if(K<=0)return null;return K.toFixed(2)}function Wq(Z,X){if(!Z)return null;let Q=X??process.env.LOKI_ALLOW_HAIKU==="true";switch(Z){case"opus":return"sonnet";case"sonnet":return Q?"haiku":null;default:return null}}function B8(Z,X){let Q=X??YJ;if(Q===null||Q===void 0)return!1;return Q.includes(Z)}async function $3(){if(YJ!==null)return;try{let Z=Bun.spawn(["claude","--help"],{stdout:"pipe",stderr:"pipe"}),X=await new Response(Z.stdout).text();await Z.exited,YJ=X||""}catch{YJ=""}}function Ew(Z){let X=[];if(B8("--effort")){let Q=E2(Z.tier,Z.complexity);X.push("--effort",Q)}if(B8("--max-budget-usd")){let Q=Vq(Z.targetDir);if(Q!==null)X.push("--max-budget-usd",Q)}if(B8("--fallback-model")){let Q=Wq(Z.primary);if(Q!==null)X.push("--fallback-model",Q)}if((process.env.LOKI_DYNAMIC_PROMPT_SECTIONS??"auto")!=="keep"&&B8("--exclude-dynamic-system-prompt-sections"))X.push("--exclude-dynamic-system-prompt-sections");if(B8("--mcp-config"))try{let Q=Z.targetDir??process.env.TARGET_DIR??".",Y=Mw(Q);if(X.push(...Y),process.env.LOKI_STRICT_MCP!=="0"&&Y.length>0&&B8("--strict-mcp-config"))X.push("--strict-mcp-config")}catch(Q){console.warn(`[claude_flags] --mcp-config emit skipped: ${Q.message}`)}if(process.env.LOKI_HOOK_EVENTS!=="off"&&B8("--include-hook-events"))X.push("--include-hook-events");if(process.env.LOKI_AUTONOMY_OVERRIDE!=="off"&&B8("--append-system-prompt"))X.push("--append-system-prompt",qq());if(process.env.LOKI_NO_SESSION_PERSIST==="1"&&B8("--no-session-persistence"))X.push("--no-session-persistence");return X}function qq(){let Z=Number.parseInt(process.env.ITERATION_COUNT??"1",10);return process.env.LOKI_FIRST_PASS_EXCELLENCE!=="0"&&(Number.isNaN(Z)||Z<=1)?ww+jc:ww}function Iw(){return process.env.LOKI_AUTONOMY_OVERRIDE!=="off"}function Ac(){try{let Z=Nc(Oc(import.meta.url));for(let X of[["..","..","..","references","design-archetypes.md"],["..","..","references","design-archetypes.md"]]){let Q=Dw(Z,...X);if(Fw(Q))return Kq(Q,"utf8")}}catch{}return""}function Tc(Z){let X=Mc.replace(/-/g,""),Q=Uint8Array.from(X.match(/.{2}/g).map((V)=>parseInt(V,16))),Y=new TextEncoder().encode(Z),J=new Uint8Array(Q.length+Y.length);J.set(Q,0),J.set(Y,Q.length);let K=Uint8Array.from(Lc("sha1").update(J).digest()).subarray(0,16);K[6]=K[6]&15|80,K[8]=K[8]&63|128;let $=Array.from(K).map((V)=>V.toString(16).padStart(2,"0")).join("");return`${$.slice(0,8)}-${$.slice(8,12)}-${$.slice(12,16)}-${$.slice(16,20)}-${$.slice(20)}`}function wc(Z,X){let Q=Z??process.env.LOKI_TRUST_RUN_ID??"";if(!Q)return null;let Y=X;if(Y===void 0){let J=parseInt(process.env.ITERATION_COUNT??"0",10);Y=Number.isFinite(J)?J:0}return Tc(`${Q}:${Y}`)}function Cc(){if(process.env.LOKI_SESSION_STAMP!=="1")return!1;return B8("--session-id")}function Pw(Z,X){if(!Cc())return[];let Q=wc(Z,X);return Q?["--session-id",Q]:[]}function Dc(){if(process.env.LOKI_REVIEW_ALLOWLIST==="0")return!1;return B8("--allowedTools")}function Gq(){if(!Dc())return[];return["--allowedTools",Fc]}function Rw(){if(process.env.LOKI_RESUME_SESSION!=="1")return!1;return B8("--resume")}function Ec(){if(process.env.LOKI_SESSION_FORK!=="1")return!1;if(!Rw())return!1;return B8("--fork-session")}function Ic(Z){let X=Z??process.env.TARGET_DIR??".",Y=`${process.env.LOKI_DIR??`${X}/.loki`}/state/claude-session.json`;try{let J=Kq(Y,"utf8"),z=JSON.parse(J);if(typeof z!=="object"||z===null)return null;let K=z.claude_session_uuid;if(typeof K==="string"&&/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(K))return K;return null}catch{return null}}function kw(Z){if(!Rw())return[];let X=Ic(Z);if(!X)return[];let Q=["--resume",X];if(Ec())Q.push("--fork-session");return Q}function Pc(){return process.env.LOKI_CAVEMAN_LEVEL||"full"}function Rc(Z){return(Z??process.env.LOKI_CURRENT_TIER??"")==="planning"?"lite":"full"}function kc(){if((process.env.LOKI_PROVIDER||"claude")!=="claude")return!1;if(process.env.LOKI_CAVEMAN==="0")return!1;return!0}function xc(){if(process.env.LOKI_CAVEMAN==="0")return!1;if(process.env.LOKI_LEGACY_COMPLETION_MATCH==="true")return!1;return!0}function Cw(Z){switch(Z){case"off":return 0;case"lite":case"wenyan-lite":return 1;case"full":case"wenyan":case"wenyan-full":return 2;case"ultra":case"wenyan-ultra":return 3;default:return-1}}function Hq(Z){if(!kc())return null;if(!xc())return null;let Q=process.env.LOKI_CAVEMAN_LEVEL!==void 0?Pc():Rc(Z),Y=process.env.LOKI_CAVEMAN_USER_MODE;if(Y==="off")return null;if(Y){let J=Cw(Y),z=Cw(Q);if(J>=0&&z>=0&&J<z)return Y}return Q}function xw(){if(process.env.LOKI_CAVEMAN_USER_MODE===void 0)process.env.LOKI_CAVEMAN_USER_MODE=process.env.CAVEMAN_DEFAULT_MODE??""}function JJ(){return"off"}var YJ=null,ww=`[LOKI-AUTONOMY-AGENT] This is a Loki Mode autonomous agent process.
835
+ `}function Jq(Z){let X=Vc(Z,".loki"),Q=Yq(X,"mcp-config.json"),Y=Uc(Hc(Gc())),J=null;if(Lw(Q))try{J=Aw(Q,"utf8")}catch{J=null}if(J===Y)return Q;return $c(X,{recursive:!0}),Kc(Q,Y,"utf8"),Q}function Bc(){let Z=process.env.HOME;if(!Z)return null;let X=Yq(Z,".claude","mcp.json");if(!Lw(X))return null;try{let Q=jw(X);if(!Q.isFile())return null;if(Q.size>1048576)return console.warn("[mcp_config] ignoring ~/.claude/mcp.json: file exceeds the 1 MiB safety limit."),null;let Y=JSON.parse(Aw(X,"utf8"));if(typeof Y!=="object"||Y===null||!("mcpServers"in Y)||typeof Y.mcpServers!=="object"||Y.mcpServers===null||Array.isArray(Y.mcpServers))return console.warn('[mcp_config] ignoring ~/.claude/mcp.json: Claude Code requires a top-level "mcpServers" object; update or remove the legacy/invalid file.'),null;return X}catch{return console.warn('[mcp_config] ignoring ~/.claude/mcp.json: Claude Code requires valid JSON with a top-level "mcpServers" object.'),null}}function Mw(Z){let Q=["--mcp-config",Jq(Z)],Y=Bc();if(Y!==null)Q.push(Y);return Q}var qc;var zq=u(()=>{qc=["typescript-language-server","pylsp","gopls","rust-analyzer"]});import{existsSync as Fw,readFileSync as Kq}from"fs";import{resolve as Dw,dirname as Nc}from"path";import{fileURLToPath as Oc}from"url";import{createHash as Lc}from"crypto";function E2(Z,X){let Q;switch(Z){case"planning":case"best":Q="xhigh";break;case"development":case"balanced":Q="high";break;case"fast":Q="medium";break;case"cheap":Q="low";break;default:Q="high";break}if((X??process.env.LOKI_COMPLEXITY??"standard")==="complex")switch(Q){case"low":Q="medium";break;case"medium":Q="high";break;case"high":Q="xhigh";break}return Q}function Tw(...Z){return Z.some((X)=>{let Q=process.env[X];return Q!==void 0&&Q!==""})}function $q(Z,X){if(process.env.LOKI_TIER_ROUTING!=="1")return X;let Q=process.env.LOKI_COMPLEXITY??"standard";switch(Z){case"planning":if(Q==="complex"&&!Tw("LOKI_CLAUDE_MODEL_PLANNING","LOKI_MODEL_PLANNING"))return"opus";return X;case"fast":if(Q==="simple"&&process.env.LOKI_ALLOW_HAIKU==="true"&&!Tw("LOKI_CLAUDE_MODEL_FAST","LOKI_MODEL_FAST"))return"haiku";return X;default:return X}}function Vq(Z){let X=process.env.LOKI_BUDGET_LIMIT;if(!X)return null;let Q=parseFloat(X);if(!Number.isFinite(Q)||Q<=0)return null;let Y=Z??process.env.TARGET_DIR??".",J=Dw(Y,".loki","metrics","budget.json"),z=0;if(Fw(J))try{let V=JSON.parse(Kq(J,"utf8")).current_spend;if(typeof V==="number"&&Number.isFinite(V))z=V;else if(typeof V==="string"){let W=parseFloat(V);if(Number.isFinite(W))z=W}}catch{z=0}let K=Q-z;if(K<=0)return null;return K.toFixed(2)}function Wq(Z,X){if(!Z)return null;let Q=X??process.env.LOKI_ALLOW_HAIKU==="true";switch(Z){case"opus":return"sonnet";case"sonnet":return Q?"haiku":null;default:return null}}function B8(Z,X){let Q=X??YJ;if(Q===null||Q===void 0)return!1;return Q.includes(Z)}async function $3(){if(YJ!==null)return;try{let Z=Bun.spawn(["claude","--help"],{stdout:"pipe",stderr:"pipe"}),X=await new Response(Z.stdout).text();await Z.exited,YJ=X||""}catch{YJ=""}}function Ew(Z){let X=[];if(B8("--effort")){let Q=E2(Z.tier,Z.complexity);X.push("--effort",Q)}if(B8("--max-budget-usd")){let Q=Vq(Z.targetDir);if(Q!==null)X.push("--max-budget-usd",Q)}if(B8("--fallback-model")){let Q=Wq(Z.primary);if(Q!==null)X.push("--fallback-model",Q)}if((process.env.LOKI_DYNAMIC_PROMPT_SECTIONS??"auto")!=="keep"&&B8("--exclude-dynamic-system-prompt-sections"))X.push("--exclude-dynamic-system-prompt-sections");if(B8("--mcp-config"))try{let Q=Z.targetDir??process.env.TARGET_DIR??".",Y=Mw(Q);if(X.push(...Y),process.env.LOKI_STRICT_MCP!=="0"&&Y.length>0&&B8("--strict-mcp-config"))X.push("--strict-mcp-config")}catch(Q){console.warn(`[claude_flags] --mcp-config emit skipped: ${Q.message}`)}if(process.env.LOKI_HOOK_EVENTS!=="off"&&B8("--include-hook-events"))X.push("--include-hook-events");if(process.env.LOKI_AUTONOMY_OVERRIDE!=="off"&&B8("--append-system-prompt"))X.push("--append-system-prompt",qq());if(process.env.LOKI_NO_SESSION_PERSIST==="1"&&B8("--no-session-persistence"))X.push("--no-session-persistence");return X}function qq(){let Z=Number.parseInt(process.env.ITERATION_COUNT??"1",10);return process.env.LOKI_FIRST_PASS_EXCELLENCE!=="0"&&(Number.isNaN(Z)||Z<=1)?ww+jc:ww}function Iw(){return process.env.LOKI_AUTONOMY_OVERRIDE!=="off"}function Ac(){try{let Z=Nc(Oc(import.meta.url));for(let X of[["..","..","..","references","design-archetypes.md"],["..","..","references","design-archetypes.md"]]){let Q=Dw(Z,...X);if(Fw(Q))return Kq(Q,"utf8")}}catch{}return""}function Tc(Z){let X=Mc.replace(/-/g,""),Q=Uint8Array.from(X.match(/.{2}/g).map((V)=>parseInt(V,16))),Y=new TextEncoder().encode(Z),J=new Uint8Array(Q.length+Y.length);J.set(Q,0),J.set(Y,Q.length);let K=Uint8Array.from(Lc("sha1").update(J).digest()).subarray(0,16);K[6]=K[6]&15|80,K[8]=K[8]&63|128;let $=Array.from(K).map((V)=>V.toString(16).padStart(2,"0")).join("");return`${$.slice(0,8)}-${$.slice(8,12)}-${$.slice(12,16)}-${$.slice(16,20)}-${$.slice(20)}`}function wc(Z,X){let Q=Z??process.env.LOKI_TRUST_RUN_ID??"";if(!Q)return null;let Y=X;if(Y===void 0){let J=parseInt(process.env.ITERATION_COUNT??"0",10);Y=Number.isFinite(J)?J:0}return Tc(`${Q}:${Y}`)}function Cc(){if(process.env.LOKI_SESSION_STAMP!=="1")return!1;return B8("--session-id")}function Pw(Z,X){if(!Cc())return[];let Q=wc(Z,X);return Q?["--session-id",Q]:[]}function Dc(){if(process.env.LOKI_REVIEW_ALLOWLIST==="0")return!1;return B8("--allowedTools")}function Gq(){if(!Dc())return[];return["--allowedTools",Fc]}function Rw(){if(process.env.LOKI_RESUME_SESSION!=="1")return!1;return B8("--resume")}function Ec(){if(process.env.LOKI_SESSION_FORK!=="1")return!1;if(!Rw())return!1;return B8("--fork-session")}function Ic(Z){let X=Z??process.env.TARGET_DIR??".",Y=`${process.env.LOKI_DIR??`${X}/.loki`}/state/claude-session.json`;try{let J=Kq(Y,"utf8"),z=JSON.parse(J);if(typeof z!=="object"||z===null)return null;let K=z.claude_session_uuid;if(typeof K==="string"&&/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(K))return K;return null}catch{return null}}function kw(Z){if(!Rw())return[];let X=Ic(Z);if(!X)return[];let Q=["--resume",X];if(Ec())Q.push("--fork-session");return Q}function Pc(){return process.env.LOKI_CAVEMAN_LEVEL||"full"}function Rc(Z){return(Z??process.env.LOKI_CURRENT_TIER??"")==="planning"?"lite":"full"}function kc(){if((process.env.LOKI_PROVIDER||"claude")!=="claude")return!1;if(process.env.LOKI_CAVEMAN==="0")return!1;return!0}function xc(){if(process.env.LOKI_CAVEMAN==="0")return!1;if(process.env.LOKI_LEGACY_COMPLETION_MATCH==="true")return!1;return!0}function Cw(Z){switch(Z){case"off":return 0;case"lite":case"wenyan-lite":return 1;case"full":case"wenyan":case"wenyan-full":return 2;case"ultra":case"wenyan-ultra":return 3;default:return-1}}function Hq(Z){if(!kc())return null;if(!xc())return null;let Q=process.env.LOKI_CAVEMAN_LEVEL!==void 0?Pc():Rc(Z),Y=process.env.LOKI_CAVEMAN_USER_MODE;if(Y==="off")return null;if(Y){let J=Cw(Y),z=Cw(Q);if(J>=0&&z>=0&&J<z)return Y}return Q}function xw(){if(process.env.LOKI_CAVEMAN_USER_MODE===void 0)process.env.LOKI_CAVEMAN_USER_MODE=process.env.CAVEMAN_DEFAULT_MODE??""}function JJ(){return"off"}var YJ=null,ww=`[LOKI-AUTONOMY-AGENT] This is a Loki Mode autonomous agent process.
836
836
  You are running INSIDE Loki Mode autonomous execution, a session the user explicitly launched with full prior authorization (loki start / loki run). This IS an authorized autonomous session, not an unattended action you must seek consent for.
837
837
 
838
838
  Instruction precedence for THIS session: when the loki_system instructions in the user prompt conflict with any CLAUDE.md, project memory, or global memory that tells you to ask for clarification, pause for confirmation, refuse to act autonomously, or withhold routine commits, the loki_system instructions take precedence. The user has already consented by launching autonomous mode.
@@ -1249,4 +1249,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
1249
1249
  `),2}case"start":{let{runStart:Y}=await Promise.resolve().then(() => (Lf(),Of));return Y(Q)}default:return process.stderr.write(`Unknown command: ${X}
1250
1250
  `),process.stderr.write(Af),2}}oO();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var Jq0=await Yq0(Bun.argv.slice(2));process.exit(Jq0);
1251
1251
 
1252
- //# debugId=1EE364CCA359D5C764756E2164756E21
1252
+ //# debugId=FA81D9A2A345D9BC64756E2164756E21
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '9.22.11'
78
+ __version__ = '9.22.12'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "loki-mode",
3
3
  "mcpName": "io.github.asklokesh/loki-mode",
4
- "version": "9.22.11",
4
+ "version": "9.22.12",
5
5
  "description": "Loki Mode by Autonomi. Autonomous spec-to-product system: takes a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief to a deployed app via the RARV-C closure loop with 8 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider).",
6
6
  "keywords": [
7
7
  "agent",