loki-mode 8.81.0 → 8.83.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 +17 -1
- package/completions/_loki +1 -1
- package/completions/loki.bash +1 -1
- package/dashboard/__init__.py +1 -1
- package/loki-ts/dist/loki.js +5 -5
- package/magic/core/debate.py +9 -4
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
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 v8.
|
|
6
|
+
# Loki Mode v8.83.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -469,4 +469,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
469
469
|
|
|
470
470
|
---
|
|
471
471
|
|
|
472
|
-
**v8.
|
|
472
|
+
**v8.83.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
8.
|
|
1
|
+
8.83.0
|
package/autonomy/loki
CHANGED
|
@@ -5667,6 +5667,7 @@ cmd_provider_list() {
|
|
|
5667
5667
|
local codex_status="${RED}not installed${NC}"
|
|
5668
5668
|
local cline_status="${RED}not installed${NC}"
|
|
5669
5669
|
local aider_status="${RED}not installed${NC}"
|
|
5670
|
+
local opencode_status="${RED}not installed${NC}"
|
|
5670
5671
|
|
|
5671
5672
|
if command -v claude &> /dev/null; then
|
|
5672
5673
|
claude_status="${GREEN}installed${NC}"
|
|
@@ -5680,6 +5681,9 @@ cmd_provider_list() {
|
|
|
5680
5681
|
if command -v aider &> /dev/null; then
|
|
5681
5682
|
aider_status="${GREEN}installed${NC}"
|
|
5682
5683
|
fi
|
|
5684
|
+
if command -v opencode &> /dev/null; then
|
|
5685
|
+
opencode_status="${GREEN}installed${NC}"
|
|
5686
|
+
fi
|
|
5683
5687
|
|
|
5684
5688
|
# Display providers
|
|
5685
5689
|
local marker=""
|
|
@@ -5698,6 +5702,14 @@ cmd_provider_list() {
|
|
|
5698
5702
|
[ "$current" = "aider" ] && marker=" ${CYAN}(current)${NC}"
|
|
5699
5703
|
echo -e " aider - Aider (terminal pair prog) $aider_status$marker"
|
|
5700
5704
|
|
|
5705
|
+
# opencode was absent here while auto_detect_provider() has selected it
|
|
5706
|
+
# since v8.64.0, so `loki provider list` under-reported a provider the
|
|
5707
|
+
# runner will happily choose -- the same drift that blocked opencode-only
|
|
5708
|
+
# machines outright until v8.76.0.
|
|
5709
|
+
marker=""
|
|
5710
|
+
[ "$current" = "opencode" ] && marker=" ${CYAN}(current)${NC}"
|
|
5711
|
+
echo -e " opencode - opencode (multi-provider) $opencode_status$marker"
|
|
5712
|
+
|
|
5701
5713
|
echo ""
|
|
5702
5714
|
echo -e "Set provider: ${CYAN}loki provider set <name>${NC}"
|
|
5703
5715
|
}
|
|
@@ -14646,7 +14658,11 @@ ENDGITIGNORE
|
|
|
14646
14658
|
|
|
14647
14659
|
# Check if an AI provider CLI is available
|
|
14648
14660
|
local _has_provider=false
|
|
14649
|
-
|
|
14661
|
+
# Must match auto_detect_provider() in providers/loader.sh. Omitting
|
|
14662
|
+
# opencode here made `loki provider list` under-report a provider the
|
|
14663
|
+
# runner will happily select -- the same drift that blocked
|
|
14664
|
+
# opencode-only machines entirely until v8.76.0.
|
|
14665
|
+
for _pcli in claude cline codex aider opencode; do
|
|
14650
14666
|
if command -v "$_pcli" &>/dev/null; then
|
|
14651
14667
|
_has_provider=true
|
|
14652
14668
|
break
|
package/completions/_loki
CHANGED
|
@@ -241,7 +241,7 @@ function _loki_commands {
|
|
|
241
241
|
|
|
242
242
|
function _loki_start {
|
|
243
243
|
_arguments \
|
|
244
|
-
'--provider[AI provider]:provider name:(claude codex
|
|
244
|
+
'--provider[AI provider]:provider name:(claude cline codex aider opencode)' \
|
|
245
245
|
'--parallel[Parallel mode]' \
|
|
246
246
|
'--background[Background mode]' \
|
|
247
247
|
'--bg[Background mode]' \
|
package/completions/loki.bash
CHANGED
|
@@ -21,7 +21,7 @@ _loki_completion() {
|
|
|
21
21
|
# Active providers (loki rejects gemini since v7.5.18; cline/aider
|
|
22
22
|
# are supported). Keep in sync with providers/loader.sh
|
|
23
23
|
# SUPPORTED_PROVIDERS.
|
|
24
|
-
COMPREPLY=( $(compgen -W "claude codex
|
|
24
|
+
COMPREPLY=( $(compgen -W "claude cline codex aider opencode" -- "$cur") )
|
|
25
25
|
return 0
|
|
26
26
|
fi
|
|
27
27
|
|
package/dashboard/__init__.py
CHANGED
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var m_=Object.create;var{getPrototypeOf:u_,defineProperty:eK,getOwnPropertyNames:p_}=Object;var d_=Object.prototype.hasOwnProperty;function c_(Z){return this[Z]}var l_,i_,a_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?l_??=new WeakMap:i_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?m_(u_(Z)):{};let K=X||!Z||!Z.__esModule?eK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of p_(Z))if(!d_.call(K,$))eK(K,$,{get:c_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var HQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var s_=(Z)=>Z;function n_(Z,X){this[Z]=s_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)eK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:n_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var e0=import.meta.require;var kO={};l0(kO,{lokiDir:()=>j0,homeLokiDir:()=>R4,findRepoRootForVersion:()=>X$,REPO_ROOT:()=>i0});import{resolve as n7,dirname as Z$}from"path";import{fileURLToPath as o_}from"url";import{existsSync as UQ}from"fs";import{homedir as r_}from"os";function t_(){let Z=RO;for(let X=0;X<6;X++){if(UQ(n7(Z,"VERSION"))&&UQ(n7(Z,"autonomy/run.sh")))return Z;let Q=Z$(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function X$(Z){let X=Z;for(let Q=0;Q<6;Q++){if(UQ(n7(X,"VERSION"))&&UQ(n7(X,"autonomy/run.sh")))return X;let Y=Z$(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function R4(){return n7(r_(),".loki")}var RO,i0;var H8=p(()=>{RO=Z$(o_(import.meta.url));i0=t_()});import{readFileSync as e_}from"fs";import{resolve as Zf,dirname as Xf}from"path";import{fileURLToPath as Qf}from"url";function h3(){if(h5!==null)return h5;let Z="8.
|
|
2
|
+
var m_=Object.create;var{getPrototypeOf:u_,defineProperty:eK,getOwnPropertyNames:p_}=Object;var d_=Object.prototype.hasOwnProperty;function c_(Z){return this[Z]}var l_,i_,a_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?l_??=new WeakMap:i_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?m_(u_(Z)):{};let K=X||!Z||!Z.__esModule?eK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of p_(Z))if(!d_.call(K,$))eK(K,$,{get:c_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var HQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var s_=(Z)=>Z;function n_(Z,X){this[Z]=s_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)eK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:n_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var e0=import.meta.require;var kO={};l0(kO,{lokiDir:()=>j0,homeLokiDir:()=>R4,findRepoRootForVersion:()=>X$,REPO_ROOT:()=>i0});import{resolve as n7,dirname as Z$}from"path";import{fileURLToPath as o_}from"url";import{existsSync as UQ}from"fs";import{homedir as r_}from"os";function t_(){let Z=RO;for(let X=0;X<6;X++){if(UQ(n7(Z,"VERSION"))&&UQ(n7(Z,"autonomy/run.sh")))return Z;let Q=Z$(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function X$(Z){let X=Z;for(let Q=0;Q<6;Q++){if(UQ(n7(X,"VERSION"))&&UQ(n7(X,"autonomy/run.sh")))return X;let Y=Z$(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function R4(){return n7(r_(),".loki")}var RO,i0;var H8=p(()=>{RO=Z$(o_(import.meta.url));i0=t_()});import{readFileSync as e_}from"fs";import{resolve as Zf,dirname as Xf}from"path";import{fileURLToPath as Qf}from"url";function h3(){if(h5!==null)return h5;let Z="8.83.0";if(typeof Z==="string"&&Z.length>0)return h5=Z,h5;try{let X=Xf(Qf(import.meta.url)),Q=X$(X);h5=e_(Zf(Q,"VERSION"),"utf-8").trim()}catch{h5="unknown"}return h5}var h5=null;var BQ=p(()=>{H8()});var bO={};l0(bO,{runOrThrow:()=>jf,run:()=>E0,readStreamCapped:()=>NQ,commandVersion:()=>Tf,commandExists:()=>X9,ShellError:()=>Q$,MAX_STDOUT_BYTES:()=>yO});async function NQ(Z,X=yO){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 W=$.byteLength-(z-X);J+=Y.decode($.subarray(0,W),{stream:!0});break}J+=Y.decode($,{stream:!0})}J+=Y.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function E0(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([NQ(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 jf(Z,X={}){let Q=await E0(Z,X);if(Q.exitCode!==0)throw new Q$(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function X9(Z){let X=Mf(Z),Q=await E0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Mf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Tf(Z,X="--version"){if(!await X9(Z))return null;let Y=await E0([Z,X],{timeoutMs:5000});if(Y.exitCode!==0)return null;return((Y.stdout||Y.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var yO=16777216,Q$;var x9=p(()=>{Q$=class Q$ 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 wf?"":Z}var wf,L0,F8,p0,zV0,a0,W8,Q9,v;var S6=p(()=>{wf=(process.env.NO_COLOR??"").length>0;L0=o7("\x1B[0;31m"),F8=o7("\x1B[0;32m"),p0=o7("\x1B[1;33m"),zV0=o7("\x1B[0;34m"),a0=o7("\x1B[0;36m"),W8=o7("\x1B[1m"),Q9=o7("\x1B[2m"),v=o7("\x1B[0m")});import{existsSync as bf}from"fs";async function E7(){if(x4!==void 0)return x4;let Z="/opt/homebrew/bin/python3.12";if(bf(Z))return x4=Z,Z;let X=await X9("python3.12");if(X)return x4=X,X;let Q=await X9("python3");return x4=Q,Q}async function Y7(Z,X={}){let Q=await E7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return E0([Q,"-c",Z],X)}var x4;var r7=p(()=>{x9()});var ZL={};l0(ZL,{runStatus:()=>Kh});import{existsSync as Y9,readFileSync as g3,readdirSync as iO,statSync as aO}from"fs";import{resolve as h8,basename as rf}from"path";import{homedir as tf}from"os";function sO(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 nO(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*LQ/X);if(J>LQ)J=LQ;let z=LQ-J,K=F8;if(Y>=80)K=L0;else if(Y>=50)K=p0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),W=sO(Z),V=sO(X);return` ${W8}${Q}${v} ${K}[${$}]${v} ${Y}% (${W} / ${V})`}async function Zh(){if(await X9("jq"))return!0;return process.stdout.write(`${L0}Error: jq is required but not installed.${v}
|
|
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)
|
|
@@ -844,7 +844,7 @@ Deliver the finished, self-verified, genuinely-designed result in THIS pass. Add
|
|
|
844
844
|
`)?Z:`${Z}
|
|
845
845
|
`;return S7(Y,J),Y}var zw,Kw,$w,rY,yd=120000,bd=5000,vd;var qZ=p(()=>{H8();J7();zw=Vq,Kw=Yw,$w=Jw,rY=eY;vd=new Set(["failed","max_iterations_reached","max_retries_exceeded","exited","council_approved","council_force_approved","completion_promise_fulfilled","running"])});import{copyFileSync as ld,existsSync as E2,mkdirSync as Hw,readFileSync as Uq,renameSync as id,statSync as ad}from"fs";import{createHash as sd}from"crypto";import{spawnSync as Hq}from"child_process";import{resolve as K3}from"path";function Bq(Z){return sd("sha256").update(Z).digest("hex").slice(0,16)}function nd(Z){let X=Z.cwd??process.cwd();if(Z.lokiDirOverride)return Z.lokiDirOverride;return process.env.LOKI_DIR??K3(X,".loki")}function ZJ(Z){return K3(Z,"generated-prd.md")}function Uw(Z){return K3(Z,"generated-prd.json")}function Bw(Z){return K3(Z,"state","prd-signature.json")}function Nw(Z){return E2(ZJ(Z))||E2(Uw(Z))}function od(Z){let X=ZJ(Z),Q=Uw(Z),Y="";if(E2(X))Y=X;else if(E2(Q))Y=Q;if(!Y)return"";try{return Bq(Uq(Y))}catch{return""}}function Ow(Z){try{let X=Hq("git",["rev-parse","--is-inside-work-tree"],{cwd:Z,encoding:"utf8"});if(X.status===0&&(X.stdout||"").trim()==="true"){let Q=Hq("git",["rev-parse","HEAD"],{cwd:Z,encoding:"utf8"}),Y=Q.status===0&&(Q.stdout||"").trim()?(Q.stdout||"").trim():"nohead",z=(Hq("git",["status","--porcelain"],{cwd:Z,encoding:"utf8"}).stdout||"").split(`
|
|
846
846
|
`).filter(($)=>{if($==="")return!1;if(/^...?\.loki\//.test($))return!1;if(/\/\.loki\//.test($))return!1;if(/ \.loki\//.test($))return!1;if(/\.git\//.test($))return!1;return!0}).join(`
|
|
847
|
-
`),K=z===""?"clean":Bq(z);return`git:${Y}:${K}`}}catch{}return"files-bun:0000000000000000"}function rd(Z){let X=Bw(Z);if(!E2(X))return null;try{let Q=JSON.parse(Uq(X,"utf8"));if(Q&&typeof Q==="object")return Q;return null}catch{return null}}function td(){return process.env.LOKI_PRD_REGEN==="1"}function ed(Z){let X=Z.cwd??process.cwd(),Q=Z.lokiDirOverride??K3(X,".loki");if(td())return"generate";if(!Nw(Q))return"generate";let Y=rd(Q);if(Y&&Y.source==="user")return"user_owned";if(!Y)return"update";let J=typeof Y.signature==="string"?Y.signature:"";if(J==="")return"update";let z=typeof Y.prd_sha==="string"?Y.prd_sha:"";if(z!==""){let $=od(Q);if($!==""&&$!==z)return"user_owned"}let K=Ow(X);if(J===K)return"reuse";return"update"}function Zc(Z,X,Q,Y){Hw(X,{recursive:!0}),Hw(K3(X,"state"),{recursive:!0});let J=ZJ(X),z=`${J}.tmp.${process.pid}`;ld(Z,z);let K=Uq(z);id(z,J);let $=Bq(K),W=Ow(Q),V=W.startsWith("git:")?"git":"files",q=new Date().toISOString().replace(/\.\d{3}Z$/,"Z"),G={signature:W,generated_at:q,prd_path:".loki/generated-prd.md",prd_sha:$,mode:V,source:"user",origin_path:Z};return S7(Bw(X),JSON.stringify(G)),Y("[runner] PRD: persisted user file -> .loki/generated-prd.md (source=user)"),J}function Lw(Z){let X=Z.log??(()=>{}),Q=Z.cwd??process.cwd(),Y=nd(Z),J=ZJ(Y);try{let z=Z.prdPath;if(typeof z==="string"&&z!==""){if(!(K3(Q,z)===J||z===J||z.endsWith(".loki/generated-prd.md"))&&E2(z)&&ad(z).isFile())return{prdPath:Zc(z,Y,Q,X),action:"user_persist"};return{prdPath:z,action:"none"}}if(Nw(Y)){let $=ed({cwd:Q,lokiDirOverride:Y});if($==="generate")return X("[runner] PRD: regenerating (action=generate)"),{prdPath:void 0,action:$};return X(`[runner] PRD: reusing .loki/generated-prd.md (action=${$})`),{prdPath:J,action:$}}return{prdPath:void 0,action:"none"}}catch(z){return X(`[runner] PRD reuse resolution failed (non-fatal): ${z.message}`),{prdPath:Z.prdPath,action:"none"}}}var Aw=p(()=>{qZ()});function jw(Z){let X=Z??"";if(X.trim()==="")return{klass:"transient",reason:"empty_output"};if(Qc.test(X))return{klass:"transient",reason:"transient_marker"};for(let[Q,Y]of Xc)if(Y.test(X))return{klass:"non_retryable",reason:Q};return{klass:"transient",reason:"unrecognized"}}function Mw(Z,X=process.env){if(X.LOKI_SMART_RETRY==="0")return!1;return Z.klass==="non_retryable"}var Xc,Qc;var Tw=p(()=>{Xc=[["auth",/\b(?:invalid[_ -]?api[_ -]?key|unauthorized|authentication[_ -]?(?:failed|error)|401\b|invalid[_ -]?x-api-key|permission[_ -]?denied|403\b)/i],["unknown_model",/\b(?:model[_ -]?not[_ -]?found|unknown[_ -]?model|invalid[_ -]?model|does not exist.{0,20}model)/i],["bad_request",/\b(?:invalid[_ -]?request[_ -]?error|malformed[_ -]?request|400\b.{0,40}invalid)/i],["quota_exhausted",/\b(?:insufficient[_ -]?(?:quota|credit|funds)|billing[_ -]?(?:hard[_ -]?limit|issue)|credit[_ -]?balance[_ -]?(?:is[_ -]?)?too[_ -]?low|payment[_ -]?required|402\b)/i]],Qc=/\b(?:rate[_ -]?limit|429\b|overloaded|please try again|temporarily unavailable|timeout|timed out|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|socket hang up|502\b|503\b|504\b|service unavailable)/i});var Oq={};l0(Oq,{getRarvTier:()=>Uc,getRarvPhaseName:()=>Bc,getProviderTierParam:()=>Nc,detectComplexity:()=>Nq});import{existsSync as GZ,readdirSync as Yc,readFileSync as Jc,statSync as zc,openSync as Kc,readSync as $c,closeSync as Wc}from"fs";import{extname as Vc,join as XJ,relative as qc}from"path";function Gc(Z){switch((Math.trunc(Z)%4+4)%4){case 0:return"planning";case 1:return"development";case 2:return"development";case 3:return"fast";default:return"development"}}function Hc(Z){switch(Z){case"opus":return"planning";case"sonnet":return"development";case"haiku":return"fast";case"fable":return"fable";case"planning":case"development":case"fast":return Z;default:return"development"}}function Uc(Z,X={}){if(X.legacy??process.env.LOKI_LEGACY_TIER_SWITCHING==="true")return Gc(Z);let Y=X.sessionModel??process.env.LOKI_SESSION_MODEL??"sonnet";return Hc(Y)}function Bc(Z){switch((Math.trunc(Z)%4+4)%4){case 0:return"REASON";case 1:return"ACT";case 2:return"REFLECT";case 3:return"VERIFY";default:return"REASON"}}function Nc(Z,X){switch(X){case"claude":switch(Z){case"planning":return process.env.PROVIDER_MODEL_PLANNING??"sonnet";case"development":return process.env.PROVIDER_MODEL_DEVELOPMENT??"sonnet";case"fast":return process.env.PROVIDER_MODEL_FAST??"sonnet";case"fable":return"opus";default:return"sonnet"}case"codex":switch(Z){case"planning":return process.env.PROVIDER_EFFORT_PLANNING??"xhigh";case"development":return process.env.PROVIDER_EFFORT_DEVELOPMENT??"high";case"fast":return process.env.PROVIDER_EFFORT_FAST??"low";default:return"high"}case"cline":return process.env.CLINE_DEFAULT_MODEL??process.env.LOKI_CLINE_MODEL??"default";case"aider":return process.env.AIDER_DEFAULT_MODEL??process.env.LOKI_AIDER_MODEL??"claude-opus-4-7";default:return"development"}}function Mc(Z){let X=0,Q=!1,Y=[Z];while(Y.length>0){let J=Y.pop(),z;try{z=Yc(J)}catch{continue}for(let K of z){let $=XJ(J,K),W;try{W=zc($)}catch{continue}if(W.isDirectory()){if(Lc.has(K))continue;Y.push($);continue}if(!W.isFile())continue;let V=Vc(K).toLowerCase();if(Oc.has(V))X+=1;if(!Q&&jc.has(V))try{let q=Kc($,"r");try{let H=Buffer.alloc(262144),B=$c(q,H,0,262144,0),O=H.subarray(0,B).toString("utf8");if(Ac.test(O))Q=!0}finally{Wc(q)}}catch{}}}return{fileCount:X,hasExternal:Q}}function Tc(Z){let X="standard";if(!GZ(Z))return{prdComplexity:X};let Q;try{Q=Jc(Z,"utf8")}catch{return{prdComplexity:X}}let Y=Z.toLowerCase().endsWith(".json"),J=Q.trim().length===0?0:Q.trim().split(/\s+/).length,z=0,K=0;if(Y)try{let $=JSON.parse(Q);if($&&typeof $==="object"){let W=$;for(let V of["features","requirements","tasks","user_stories","epics"]){let q=W[V];if(Array.isArray(q))z+=q.length}}}catch{let $=Q.match(/"title"|"name"|"feature"|"requirement"/g);z=$?$.length:0}else{let $=Q.match(/^(##|- \[)/gm);z=$?$.length:0;let W=Q.match(/^(##|###)/gm);K=W?W.length:0}if(J<200&&z<5&&K<3)X="simple";else if(J>1000||z>15||K>10)X="complex";else X="standard";return{prdComplexity:X}}function Nq(Z={}){let X=Z.override??(process.env.COMPLEXITY_TIER&&process.env.COMPLEXITY_TIER!=="auto"?process.env.COMPLEXITY_TIER:void 0)??process.env.LOKI_COMPLEXITY;if(X&&X!=="auto"){if(X==="simple"||X==="standard"||X==="complex")return{complexity:X,fileCount:0,prdComplexity:"standard",hasExternal:!1,hasMicroservices:!1}}let Q=Z.filesGlob??process.env.TARGET_DIR??process.cwd(),Y=0,J=!1;if(GZ(Q)){let W=Mc(Q);Y=W.fileCount,J=W.hasExternal}let z=GZ(XJ(Q,"docker-compose.yml"))||GZ(XJ(Q,"docker-compose.yaml"))||GZ(XJ(Q,"k8s")),K="standard";if(Z.prdPath)K=Tc(Z.prdPath).prdComplexity;let $;if(Y<=5&&K==="simple"&&!J&&!z)$="simple";else if(Y>50||z||J||K==="complex")$="complex";else $="standard";return{complexity:$,fileCount:Y,prdComplexity:K,hasExternal:J,hasMicroservices:z}}var Oc,Lc,Ac,jc;var QJ=p(()=>{Oc=new Set([".ts",".tsx",".js",".jsx",".py",".go",".rs",".java",".rb",".php",".swift",".kt"]),Lc=new Set(["node_modules",".git","vendor","dist","build","__pycache__"]),Ac=/oauth|SAML|OIDC|stripe|twilio|aws-sdk|@google-cloud|azure/i,jc=new Set([".json",".ts",".js"])});function Ic(Z){let X=(Z??"").trim();if(X==="")return{score:0,dimensions:[],vagueOnly:!1,rationale:"Empty goal: nothing to measure."};let Q=[];for(let[K,$]of ww)if($.test(X))Q.push(K);let Y=Q.length/ww.length,J=Q.length===0&&Ec.test(X),z;if(Q.length===0)z=J?"Subjective goal with no measurable target: every iteration can claim progress and none can be verified. Add a number, a comparison, or a concrete artifact to check.":"No measurable target detected: the loop has no gradient to climb. Add an explicit success threshold.";else if(Y<0.5)z=`Partially measurable (${Q.join(", ")}): usable, but a concrete threshold would make progress checkable each iteration.`;else z=`Measurable (${Q.join(", ")}): each iteration can be checked against this.`;return{score:Y,dimensions:Q,vagueOnly:J,rationale:z}}function Pc(Z,X=process.env){if(X.LOKI_GOAL_SCORING==="0")return!1;if(Z.rationale.startsWith("Empty goal"))return!1;return Z.score===0}function Cw(Z,X=process.env){if((Z??"").trim()==="")return"";let Q=Ic(Z);if(!Pc(Q,X))return"";return`GOAL_MEASURABILITY: the stated goal is not currently hill-climbable. ${Q.rationale} Before implementing, restate it with at least one checkable success condition (a number with a unit, a comparison threshold, or a concrete artifact such as a passing test or an endpoint returning a specific status), and record that restatement so each iteration can be measured against it. Do NOT silently substitute your own easier goal -- if the goal cannot be sharpened from the spec alone, say so explicitly and state the assumption you are proceeding under.`}var wc,Cc,Fc,Dc,Ec,ww;var Fw=p(()=>{wc=/\b\d+(?:\.\d+)?\s*(?:%|ms|s\b|sec|second|min|minute|hour|day|kb|mb|gb|rps|qps|req|x\b|users?|items?|rows?)/i,Cc=/\b(?:under|below|less than|no more than|at most|over|above|greater than|at least|within|between|<=?|>=?)\b/i,Fc=/\b(?:latency|throughput|p50|p95|p99|uptime|error rate|conversion|coverage|score|accuracy|precision|recall|bundle size|load time|response time|memory|cpu|cost)\b/i,Dc=/\b(?:tests? pass|builds? clean|endpoint|returns? \d{3}|exit code|schema|migration|deploys?|renders?|compiles?)\b/i,Ec=/\b(?:fast|slow|good|bad|nice|clean|better|best|modern|beautiful|intuitive|robust|scalable|user-friendly|production-ready|polished|seamless)\b/i,ww=[["numeric_target",wc],["comparator",Cc],["named_metric",Fc],["verifiable_artifact",Dc]]});var ew={};l0(ew,{useClaudeWorkflowsForAnalysis:()=>kq,buildPromptForRunner:()=>nc,buildPrompt:()=>tw,_internals:()=>sc});import{existsSync as J9,readFileSync as Eq,readdirSync as Iq,statSync as Iw,writeFileSync as Rc,renameSync as kc,rmSync as xc}from"fs";import{resolve as n0,dirname as Pq}from"path";function UZ(Z,X){return Z[X]==="true"}function q3(Z,X,Q=""){let Y=Z[X];return Y===void 0||Y===null?Q:Y}function Lq(Z,X,Q){let Y=Z[X];if(Y===void 0||Y==="")return Q;let J=Number.parseInt(Y,10);return Number.isFinite(J)?J:Q}function t9(Z){try{if(!J9(Z))return null;return Eq(Z,"utf8")}catch{return null}}function Pw(Z){return Z.replace(/\n+$/,"")}function NZ(Z,X){let Q=Sc(Z);if(Q===null)return null;let Y=Q.byteLength<=X?Q:Q.subarray(0,X),J=Y;if(Y.includes(0)){let K=[];for(let $ of Y)if($!==0)K.push($);J=Buffer.from(K)}let z=J.toString("utf8");return Pw(z)}function Sc(Z){try{if(!J9(Z))return null;return Eq(Z)}catch{return null}}function Rw(Z,X){let Q=t9(Z);if(Q===null)return null;let Y=Q.split(`
|
|
847
|
+
`),K=z===""?"clean":Bq(z);return`git:${Y}:${K}`}}catch{}return"files-bun:0000000000000000"}function rd(Z){let X=Bw(Z);if(!E2(X))return null;try{let Q=JSON.parse(Uq(X,"utf8"));if(Q&&typeof Q==="object")return Q;return null}catch{return null}}function td(){return process.env.LOKI_PRD_REGEN==="1"}function ed(Z){let X=Z.cwd??process.cwd(),Q=Z.lokiDirOverride??K3(X,".loki");if(td())return"generate";if(!Nw(Q))return"generate";let Y=rd(Q);if(Y&&Y.source==="user")return"user_owned";if(!Y)return"update";let J=typeof Y.signature==="string"?Y.signature:"";if(J==="")return"update";let z=typeof Y.prd_sha==="string"?Y.prd_sha:"";if(z!==""){let $=od(Q);if($!==""&&$!==z)return"user_owned"}let K=Ow(X);if(J===K)return"reuse";return"update"}function Zc(Z,X,Q,Y){Hw(X,{recursive:!0}),Hw(K3(X,"state"),{recursive:!0});let J=ZJ(X),z=`${J}.tmp.${process.pid}`;ld(Z,z);let K=Uq(z);id(z,J);let $=Bq(K),W=Ow(Q),V=W.startsWith("git:")?"git":"files",q=new Date().toISOString().replace(/\.\d{3}Z$/,"Z"),G={signature:W,generated_at:q,prd_path:".loki/generated-prd.md",prd_sha:$,mode:V,source:"user",origin_path:Z};return S7(Bw(X),JSON.stringify(G)),Y("[runner] PRD: persisted user file -> .loki/generated-prd.md (source=user)"),J}function Lw(Z){let X=Z.log??(()=>{}),Q=Z.cwd??process.cwd(),Y=nd(Z),J=ZJ(Y);try{let z=Z.prdPath;if(typeof z==="string"&&z!==""){if(!(K3(Q,z)===J||z===J||z.endsWith(".loki/generated-prd.md"))&&E2(z)&&ad(z).isFile())return{prdPath:Zc(z,Y,Q,X),action:"user_persist"};return{prdPath:z,action:"none"}}if(Nw(Y)){let $=ed({cwd:Q,lokiDirOverride:Y});if($==="generate")return X("[runner] PRD: regenerating (action=generate)"),{prdPath:void 0,action:$};return X(`[runner] PRD: reusing .loki/generated-prd.md (action=${$})`),{prdPath:J,action:$}}return{prdPath:void 0,action:"none"}}catch(z){return X(`[runner] PRD reuse resolution failed (non-fatal): ${z.message}`),{prdPath:Z.prdPath,action:"none"}}}var Aw=p(()=>{qZ()});function jw(Z){let X=Z??"";if(X.trim()==="")return{klass:"transient",reason:"empty_output"};if(Qc.test(X))return{klass:"transient",reason:"transient_marker"};for(let[Q,Y]of Xc)if(Y.test(X))return{klass:"non_retryable",reason:Q};return{klass:"transient",reason:"unrecognized"}}function Mw(Z,X=process.env){if(X.LOKI_SMART_RETRY==="0")return!1;return Z.klass==="non_retryable"}var Xc,Qc;var Tw=p(()=>{Xc=[["auth",/\b(?:invalid[_ -]?api[_ -]?key|invalid[_ -]?x-api-key|authentication[_ -]?(?:failed|error))/i],["unknown_model",/\b(?:model[_ -]?not[_ -]?found|unknown[_ -]?model|does not exist.{0,20}model)/i],["bad_request",/\b(?:invalid[_ -]?request[_ -]?error|malformed[_ -]?request)/i],["quota_exhausted",/\b(?:insufficient[_ -]?(?:quota|credit|funds)|billing[_ -]?(?:hard[_ -]?limit|issue)|credit[_ -]?balance[_ -]?(?:is[_ -]?)?too[_ -]?low)/i]],Qc=/\b(?:rate[_ -]?limit|429\b|overloaded|please try again|temporarily unavailable|timeout|timed out|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|socket hang up|502\b|503\b|504\b|service unavailable)/i});var Oq={};l0(Oq,{getRarvTier:()=>Uc,getRarvPhaseName:()=>Bc,getProviderTierParam:()=>Nc,detectComplexity:()=>Nq});import{existsSync as GZ,readdirSync as Yc,readFileSync as Jc,statSync as zc,openSync as Kc,readSync as $c,closeSync as Wc}from"fs";import{extname as Vc,join as XJ,relative as qc}from"path";function Gc(Z){switch((Math.trunc(Z)%4+4)%4){case 0:return"planning";case 1:return"development";case 2:return"development";case 3:return"fast";default:return"development"}}function Hc(Z){switch(Z){case"opus":return"planning";case"sonnet":return"development";case"haiku":return"fast";case"fable":return"fable";case"planning":case"development":case"fast":return Z;default:return"development"}}function Uc(Z,X={}){if(X.legacy??process.env.LOKI_LEGACY_TIER_SWITCHING==="true")return Gc(Z);let Y=X.sessionModel??process.env.LOKI_SESSION_MODEL??"sonnet";return Hc(Y)}function Bc(Z){switch((Math.trunc(Z)%4+4)%4){case 0:return"REASON";case 1:return"ACT";case 2:return"REFLECT";case 3:return"VERIFY";default:return"REASON"}}function Nc(Z,X){switch(X){case"claude":switch(Z){case"planning":return process.env.PROVIDER_MODEL_PLANNING??"sonnet";case"development":return process.env.PROVIDER_MODEL_DEVELOPMENT??"sonnet";case"fast":return process.env.PROVIDER_MODEL_FAST??"sonnet";case"fable":return"opus";default:return"sonnet"}case"codex":switch(Z){case"planning":return process.env.PROVIDER_EFFORT_PLANNING??"xhigh";case"development":return process.env.PROVIDER_EFFORT_DEVELOPMENT??"high";case"fast":return process.env.PROVIDER_EFFORT_FAST??"low";default:return"high"}case"cline":return process.env.CLINE_DEFAULT_MODEL??process.env.LOKI_CLINE_MODEL??"default";case"aider":return process.env.AIDER_DEFAULT_MODEL??process.env.LOKI_AIDER_MODEL??"claude-opus-4-7";default:return"development"}}function Mc(Z){let X=0,Q=!1,Y=[Z];while(Y.length>0){let J=Y.pop(),z;try{z=Yc(J)}catch{continue}for(let K of z){let $=XJ(J,K),W;try{W=zc($)}catch{continue}if(W.isDirectory()){if(Lc.has(K))continue;Y.push($);continue}if(!W.isFile())continue;let V=Vc(K).toLowerCase();if(Oc.has(V))X+=1;if(!Q&&jc.has(V))try{let q=Kc($,"r");try{let H=Buffer.alloc(262144),B=$c(q,H,0,262144,0),O=H.subarray(0,B).toString("utf8");if(Ac.test(O))Q=!0}finally{Wc(q)}}catch{}}}return{fileCount:X,hasExternal:Q}}function Tc(Z){let X="standard";if(!GZ(Z))return{prdComplexity:X};let Q;try{Q=Jc(Z,"utf8")}catch{return{prdComplexity:X}}let Y=Z.toLowerCase().endsWith(".json"),J=Q.trim().length===0?0:Q.trim().split(/\s+/).length,z=0,K=0;if(Y)try{let $=JSON.parse(Q);if($&&typeof $==="object"){let W=$;for(let V of["features","requirements","tasks","user_stories","epics"]){let q=W[V];if(Array.isArray(q))z+=q.length}}}catch{let $=Q.match(/"title"|"name"|"feature"|"requirement"/g);z=$?$.length:0}else{let $=Q.match(/^(##|- \[)/gm);z=$?$.length:0;let W=Q.match(/^(##|###)/gm);K=W?W.length:0}if(J<200&&z<5&&K<3)X="simple";else if(J>1000||z>15||K>10)X="complex";else X="standard";return{prdComplexity:X}}function Nq(Z={}){let X=Z.override??(process.env.COMPLEXITY_TIER&&process.env.COMPLEXITY_TIER!=="auto"?process.env.COMPLEXITY_TIER:void 0)??process.env.LOKI_COMPLEXITY;if(X&&X!=="auto"){if(X==="simple"||X==="standard"||X==="complex")return{complexity:X,fileCount:0,prdComplexity:"standard",hasExternal:!1,hasMicroservices:!1}}let Q=Z.filesGlob??process.env.TARGET_DIR??process.cwd(),Y=0,J=!1;if(GZ(Q)){let W=Mc(Q);Y=W.fileCount,J=W.hasExternal}let z=GZ(XJ(Q,"docker-compose.yml"))||GZ(XJ(Q,"docker-compose.yaml"))||GZ(XJ(Q,"k8s")),K="standard";if(Z.prdPath)K=Tc(Z.prdPath).prdComplexity;let $;if(Y<=5&&K==="simple"&&!J&&!z)$="simple";else if(Y>50||z||J||K==="complex")$="complex";else $="standard";return{complexity:$,fileCount:Y,prdComplexity:K,hasExternal:J,hasMicroservices:z}}var Oc,Lc,Ac,jc;var QJ=p(()=>{Oc=new Set([".ts",".tsx",".js",".jsx",".py",".go",".rs",".java",".rb",".php",".swift",".kt"]),Lc=new Set(["node_modules",".git","vendor","dist","build","__pycache__"]),Ac=/oauth|SAML|OIDC|stripe|twilio|aws-sdk|@google-cloud|azure/i,jc=new Set([".json",".ts",".js"])});function Ic(Z){let X=(Z??"").trim();if(X==="")return{score:0,dimensions:[],vagueOnly:!1,rationale:"Empty goal: nothing to measure."};let Q=[];for(let[K,$]of ww)if($.test(X))Q.push(K);let Y=Q.length/ww.length,J=Q.length===0&&Ec.test(X),z;if(Q.length===0)z=J?"Subjective goal with no measurable target: every iteration can claim progress and none can be verified. Add a number, a comparison, or a concrete artifact to check.":"No measurable target detected: the loop has no gradient to climb. Add an explicit success threshold.";else if(Y<0.5)z=`Partially measurable (${Q.join(", ")}): usable, but a concrete threshold would make progress checkable each iteration.`;else z=`Measurable (${Q.join(", ")}): each iteration can be checked against this.`;return{score:Y,dimensions:Q,vagueOnly:J,rationale:z}}function Pc(Z,X=process.env){if(X.LOKI_GOAL_SCORING==="0")return!1;if(Z.rationale.startsWith("Empty goal"))return!1;return Z.score===0}function Cw(Z,X=process.env){if((Z??"").trim()==="")return"";let Q=Ic(Z);if(!Pc(Q,X))return"";return`GOAL_MEASURABILITY: the stated goal is not currently hill-climbable. ${Q.rationale} Before implementing, restate it with at least one checkable success condition (a number with a unit, a comparison threshold, or a concrete artifact such as a passing test or an endpoint returning a specific status), and record that restatement so each iteration can be measured against it. Do NOT silently substitute your own easier goal -- if the goal cannot be sharpened from the spec alone, say so explicitly and state the assumption you are proceeding under.`}var wc,Cc,Fc,Dc,Ec,ww;var Fw=p(()=>{wc=/\b\d+(?:\.\d+)?\s*(?:%|ms|s\b|sec|second|min|minute|hour|day|kb|mb|gb|rps|qps|req|x\b|users?|items?|rows?)/i,Cc=/\b(?:under|below|less than|no more than|at most|over|above|greater than|at least|within|between|<=?|>=?)\b/i,Fc=/\b(?:latency|throughput|p50|p95|p99|uptime|error rate|conversion|coverage|score|accuracy|precision|recall|bundle size|load time|response time|memory|cpu|cost)\b/i,Dc=/\b(?:tests? pass|builds? clean|endpoint|returns? \d{3}|exit code|schema|migration|deploys?|renders?|compiles?)\b/i,Ec=/\b(?:fast|slow|good|bad|nice|clean|better|best|modern|beautiful|intuitive|robust|scalable|user-friendly|production-ready|polished|seamless)\b/i,ww=[["numeric_target",wc],["comparator",Cc],["named_metric",Fc],["verifiable_artifact",Dc]]});var ew={};l0(ew,{useClaudeWorkflowsForAnalysis:()=>kq,buildPromptForRunner:()=>nc,buildPrompt:()=>tw,_internals:()=>sc});import{existsSync as J9,readFileSync as Eq,readdirSync as Iq,statSync as Iw,writeFileSync as Rc,renameSync as kc,rmSync as xc}from"fs";import{resolve as n0,dirname as Pq}from"path";function UZ(Z,X){return Z[X]==="true"}function q3(Z,X,Q=""){let Y=Z[X];return Y===void 0||Y===null?Q:Y}function Lq(Z,X,Q){let Y=Z[X];if(Y===void 0||Y==="")return Q;let J=Number.parseInt(Y,10);return Number.isFinite(J)?J:Q}function t9(Z){try{if(!J9(Z))return null;return Eq(Z,"utf8")}catch{return null}}function Pw(Z){return Z.replace(/\n+$/,"")}function NZ(Z,X){let Q=Sc(Z);if(Q===null)return null;let Y=Q.byteLength<=X?Q:Q.subarray(0,X),J=Y;if(Y.includes(0)){let K=[];for(let $ of Y)if($!==0)K.push($);J=Buffer.from(K)}let z=J.toString("utf8");return Pw(z)}function Sc(Z){try{if(!J9(Z))return null;return Eq(Z)}catch{return null}}function Rw(Z,X){let Q=t9(Z);if(Q===null)return null;let Y=Q.split(`
|
|
848
848
|
`),J=Math.min(X,Y.length),z=Y.slice(0,J);return Pw(z.join(`
|
|
849
849
|
`))}function kw(Z){let X=[];for(let Q of yc)if(UZ(Z,`PHASE_${Q}`))X.push(Q);return X.join(",")}function xw(Z,X){let Q=`RALPH WIGGUM MODE ACTIVE. Use Reason-Act-Reflect-VERIFY cycle: 1) REASON - READ .loki/CONTINUITY.md including 'Mistakes & Learnings' section to avoid past errors. CHECK .loki/state/relevant-learnings.json for cross-project learnings from previous projects (mistakes to avoid, patterns to apply). Check .loki/state/ and .loki/queue/, identify next task. CHECK .loki/state/resources.json for system resource warnings - if CPU or memory is high, reduce parallel agent spawning or pause non-critical tasks. Limit to MAX_PARALLEL_AGENTS=${Z}. If queue empty, find new improvements. 2) ACT - Execute task, write code, commit changes atomically (git checkpoint). 3) REFLECT - Update .loki/CONTINUITY.md with progress, update state, identify NEXT improvement. Save valuable learnings for future projects. 4) VERIFY - Run automated tests (unit, integration, E2E), check compilation/build, verify against spec. IF VERIFICATION FAILS: a) Capture error details (stack trace, logs), b) Analyze root cause, c) UPDATE 'Mistakes & Learnings' in CONTINUITY.md with what failed, why, and how to prevent, d) Rollback to last good git checkpoint if needed, e) Apply learning and RETRY from REASON. If verification passes, mark task complete and continue.`;if(X)return`${Q} CRITICAL: There is NEVER a 'finished' state - always find the next improvement, optimization, test, or feature.`;return`${Q} When the PRD requirements are implemented and completion gates pass, claim done via loki_complete_task and STOP; do not add unrequested improvements. Verify once -- the completion gates (tests, checklist, evidence) are the authority on done; do not re-verify redundantly.`}function Sw(Z,X,Q){if(Z.length>0)return`COMPLETION_PROMISE: [${Z}]. When all PRD requirements are implemented, tests pass, and the PRD checklist is at or near 100%, invoke the loki_complete_task MCP tool with your completion_statement and evidence (cite tests that passed, checklist items verified, files created/modified). Do NOT emit a completion string in prose -- use the tool call. FALLBACK: if the loki_complete_task tool is not available in your environment, instead run \`touch .loki/signals/COMPLETION_REQUESTED\` (optionally write a one-line statement to that file via \`echo 'statement' > .loki/signals/COMPLETION_REQUESTED\`); the runner detects this file and treats it as a completion claim.`;return`NO COMPLETION PROMISE SET. Continue finding improvements. The Completion Council will evaluate your progress periodically. Iteration ${X} of max ${Q}. If you do decide the task is complete, invoke the loki_complete_task MCP tool with a structured statement and evidence rather than emitting prose. FALLBACK if that tool is unavailable: \`touch .loki/signals/COMPLETION_REQUESTED\`.`}function yw(Z,X){if(Z)return"CRITICAL AUTONOMY RULES: 1) NEVER ask questions - just decide. 2) NEVER wait for confirmation - just act. 3) NEVER say 'done' or 'complete' - there's always more to improve. 4) NEVER stop voluntarily - if out of tasks, create new ones (add tests, optimize, refactor, add features). 5) Work continues PERPETUALLY. Even if PRD is implemented, find bugs, add tests, improve UX, optimize performance.";return`CRITICAL AUTONOMY RULES: 1) NEVER ask questions - just decide. 2) NEVER wait for confirmation - just act. 3) When all PRD requirements are implemented and tests pass, invoke the loki_complete_task MCP tool (completion_statement='${X}' plus evidence + confidence). Do not emit completion prose. 4) If out of tasks but PRD is not fully implemented, continue working on remaining requirements. 5) Focus on completing PRD scope, not endless improvements.`}function bw(Z){return`SDLC_PHASES_ENABLED: [${Z}]. Execute ALL enabled phases. Log results to .loki/logs/. See .loki/SKILL.md for phase details. Skill modules at .loki/skills/.`}function _c(Z,X){let Q=Z.DETECTED_COMPLEXITY;if(Q!==void 0&&Q!=="")return Q;let Y=X??process.env.TARGET_DIR??process.cwd();if(HZ&&HZ.dir===Y)return HZ.complexity;let J=Nq({filesGlob:Y}).complexity;return HZ={dir:Y,complexity:J},J}function Rq(Z,X){if(q3(Z,"LOKI_PROVIDER","claude")!=="claude")return{useWorkflow:!1,autonomous:!1};if(UZ(Z,"PROVIDER_DEGRADED"))return{useWorkflow:!1,autonomous:!1};let Y=Z.LOKI_USE_CLAUDE_WORKFLOWS;if(Y==="0")return{useWorkflow:!1,autonomous:!1};if(Y==="1")return{useWorkflow:!0,autonomous:!1};if(Y===void 0&&_c(Z,X)==="complex")return{useWorkflow:!0,autonomous:!0};return{useWorkflow:!1,autonomous:!1}}function kq(Z,X){return Rq(Z,X).useWorkflow}function fc(){jq=!1,HZ=null}function Mq(Z,X,Q){if(jq)return;if(!Rq(Z,X).autonomous)return;jq=!0;let Y="Loki: no PRD found and this repo looks complex (complexity=complex), so the codebase-analysis pass is dispatching a Claude Code Dynamic Workflow (parallel fan-out). Workflows are more thorough but cost meaningfully more than the default three-pass analysis. Set LOKI_USE_CLAUDE_WORKFLOWS=0 to keep the cheaper three-pass pass.";if(Q)Q(Y);else console.error(Y)}function Tq(Z,X){if(kq(Z,X))return bc+Aq;return Aq}function Cq(Z){return Z.DETECTED_COMPLEXITY==="simple"?_w:fw}function hw(Z){let X=n0(Z,".loki/memory/ledgers");if(!J9(X))return"";let Q;try{Q=Iq(X).filter((J)=>J.startsWith("LEDGER-")&&J.endsWith(".md"))}catch{return""}if(Q.length===0)return"";let Y=null;for(let J of Q){let z=n0(X,J);try{let K=Iw(z);if(Y===null||K.mtimeMs>Y.mtimeMs)Y={path:z,mtimeMs:K.mtimeMs}}catch{}}if(Y===null)return"";return Rw(Y.path,100)??""}async function vw(Z){let X=n0(Z,".loki/memory/handoffs");if(!J9(X))return"";let Q;try{Q=Iq(X)}catch{return""}let Y=(K)=>{let $=null;for(let W of Q){if(!W.endsWith(K))continue;let V=n0(X,W);try{let q=Iw(V);if($===null||q.mtimeMs>$.mtimeMs)$={path:V,mtimeMs:q.mtimeMs}}catch{}}return $===null?null:$.path},J=Y(".json");if(J!==null){let K=t9(J);if(K===null)return"";try{let $=JSON.parse(K),W=[],V=String($.timestamp??"unknown"),q=String($.reason??"unknown");W.push(`Handoff from ${V} (reason: ${q})`),W.push(`Iteration: ${String($.iteration??0)}`);let G=$.files_modified;if(Array.isArray(G)&&G.length>0)W.push(`Modified files: ${G.slice(0,10).map(String).join(", ")}`);let H=$.task_status??{};W.push(`Tasks - pending: ${String(H.pending??0)}, completed: ${String(H.completed??0)}`);let B=$.open_questions;if(Array.isArray(B))for(let A of B)W.push(`Open question: ${String(A)}`);let O=$.blockers;if(Array.isArray(O))for(let A of O)W.push(`Blocker: ${String(A)}`);return W.join(" | ")}catch{return""}}let z=Y(".md");if(z!==null)return Rw(z,80)??"";return""}function gw(){let Z=process.env.LOKI_SKIP_MEMORY;return Z==="true"||Z==="1"}function mw(Z){if(gw())return"";let X=n0(Z,".loki/state/memory-context.json"),Q=t9(X);if(Q===null)return"";try{let Y=JSON.parse(Q);if(typeof Y!=="object"||Y===null)return"";if(typeof Y.memory_count!=="number")return"";let J=Y.memories;if(!Array.isArray(J)||J.length===0)return"";let z=["STARTUP LEARNINGS (pre-loaded):"];for(let K of J.slice(0,5)){if(typeof K!=="object"||K===null)continue;let $=K,W=String($.source??"unknown"),q=String($.summary??"").slice(0,100),G=$.score??0;if(q.length>0)z.push(`- [${W}|${String(G)}] ${q}`)}return z.join(`
|
|
850
850
|
`)}catch{return""}}function hc(Z){if(gw())return"";let X=n0(Z,".loki/memory/index.json");if(!J9(X))return"";return""}function Dw(Z,X){let Q=t9(Z);if(Q===null)return"";let Y;try{Y=JSON.parse(Q)}catch{return""}let J;if(Array.isArray(Y))J=Y;else if(Y!==null&&typeof Y==="object"&&Object.prototype.hasOwnProperty.call(Y,"tasks"))J=Y.tasks;else J=Y;if(!Array.isArray(J))return"";let z=[],K=J.slice(0,3);for(let $=0;$<K.length;$++){let W=K[$];if(W===null||typeof W!=="object")continue;let V=W,q=String(V.id??"unknown");if(String(V.source??"")==="prd"||q.startsWith("prd-")){let H=String(V.title??"Task"),B=[`${X}[${$+1}] ${q}: ${H}`],O=String(V.description??"");if(O.length>0&&O!==H){let N=O.replace(/\n/g," ").replace(/\r/g,"").slice(0,300);if(O.length>300)N+="...";B.push(` Description: ${N}`)}let A=V.acceptance_criteria;if(Array.isArray(A)&&A.length>0){let N=A.slice(0,5).map((j)=>String(j)).join("; ");B.push(` Acceptance: ${N}`)}let L=String(V.user_story??"");if(L.length>0)B.push(` User Story: ${L}`);z.push(B.join(`
|
|
@@ -1142,7 +1142,7 @@ If you believe the lock is stale, remove '${X}' manually.`;throw Z.log(`[runner]
|
|
|
1142
1142
|
--sandbox and other orchestration flags run on the bash route automatically.)
|
|
1143
1143
|
`;var h_=p(()=>{S_=new Set(["--max-iterations","--max-retries","--budget-limit","--budget","--provider","--session-model","--completion-promise","--base-wait","--max-wait","--prd","--brief","--aider-model","--aider-flags","--cline-model"]),y_=new Map([["--allow-haiku",["LOKI_ALLOW_HAIKU","true"]],["--simple",["LOKI_COMPLEXITY","simple"]],["--complex",["LOKI_COMPLEXITY","complex"]],["--regen-prd",["LOKI_PRD_REGEN","1"]],["--regenerate-prd",["LOKI_PRD_REGEN","1"]],["--regen",["LOKI_PRD_REGEN","1"]],["--fresh-prd",["LOKI_PRD_REGEN","1"]],["--skip-memory",["LOKI_SKIP_MEMORY","true"]]]),b_=new Set(["--yes","-y","--no-plan","--no-mirofish","--no-dashboard"]),bW0=new Set(["claude","codex","cline","aider"]),_W0=new Set(["planning","development","fast"]),fW0={small:"fast",medium:"development",high:"planning"}});BQ();H8();import{mkdirSync as Yf,readFileSync as Jf,writeFileSync as zf}from"fs";import{dirname as Kf,resolve as $f}from"path";var Wf="https://registry.npmjs.org/loki-mode/latest",Vf=86400000,qf=1500;function Gf(){return $f(R4(),"cache","update-check.json")}function k4(Z){let X=/^(\d+)\.(\d+)\.(\d+)$/.exec(Z.trim());if(!X)return null;return[Number(X[1]),Number(X[2]),Number(X[3])]}function Hf(Z,X){let Q=k4(Z),Y=k4(X);if(!Q||!Y)return!1;let[J,z,K]=Q,[$,W,V]=Y;if(J!==$)return J>$;if(z!==W)return z>W;return K>V}function Uf(){if(process.env.LOKI_NO_UPDATE_CHECK==="1")return!0;if(process.env.CI)return!0;if(!process.stdout.isTTY)return!0;return!1}function Bf(Z){try{let X=Jf(Z,"utf-8"),Q=JSON.parse(X);if(typeof Q.checkedAt==="number"&&typeof Q.latest==="string"&&k4(Q.latest)!==null)return{checkedAt:Q.checkedAt,latest:Q.latest}}catch{}return null}function Of(Z,X){try{Yf(Kf(Z),{recursive:!0}),zf(Z,JSON.stringify(X),"utf-8")}catch{}}async function Lf(){try{let Z=await fetch(Wf,{signal:AbortSignal.timeout(qf),headers:{accept:"application/json"}});if(!Z.ok)return null;let X=await Z.json();if(typeof X.version==="string"&&k4(X.version)!==null)return X.version}catch{}return null}async function Af(Z=Date.now(),X=Lf,Q=Gf()){let Y=Bf(Q);if(Y&&Z-Y.checkedAt<Vf)return Y.latest;let J=await X();if(J===null)return null;return Of(Q,{checkedAt:Z,latest:J}),J}async function xO(Z,X={}){try{if(Uf())return;if(k4(Z)===null)return;let Q=await Af(X.now,X.fetcher,X.cacheFile);if(Q===null)return;if(!Hf(Q,Z))return;(X.write??((J)=>process.stderr.write(J)))(`A newer Loki Mode is available: ${Q} (you have ${Z}). Update: bun install -g loki-mode (or npm i -g loki-mode)
|
|
1144
1144
|
`)}catch{}}async function SO(){let Z=h3();return process.stdout.write(`Loki Mode v${Z}
|
|
1145
|
-
`),await xO(Z),0}x9();S6();H8();import{readFileSync as Cf,existsSync as Ff}from"fs";import{resolve as Df}from"path";var Ef=["claude","
|
|
1145
|
+
`),await xO(Z),0}x9();S6();H8();import{readFileSync as Cf,existsSync as Ff}from"fs";import{resolve as Df}from"path";var Ef=["claude","cline","codex","aider","opencode"];function _O(){let Z=Df(j0(),"state","provider");if(!Ff(Z))return"";try{return Cf(Z,"utf-8").trim()}catch{return""}}function Pf(Z,X){return Z||X||process.env.LOKI_PROVIDER||"claude"}function kf(Z){let X=_O(),Q=Pf(Z,X);switch(process.stdout.write(`${W8}Current Provider${v}
|
|
1146
1146
|
`),process.stdout.write(`
|
|
1147
1147
|
`),process.stdout.write(`${a0}Provider:${v} ${Q}
|
|
1148
1148
|
`),Q){case"claude":process.stdout.write(`${F8}Status:${v} Full features (subagents, parallel, MCP)
|
|
@@ -1155,7 +1155,7 @@ If you believe the lock is stale, remove '${X}' manually.`;throw Z.log(`[runner]
|
|
|
1155
1155
|
`),process.stdout.write(`Available: ${a0}loki provider list${v}
|
|
1156
1156
|
`),0}async function xf(){let X=_O()||process.env.LOKI_PROVIDER||"claude";process.stdout.write(`${W8}Available Providers${v}
|
|
1157
1157
|
`),process.stdout.write(`
|
|
1158
|
-
`);let Q=await Promise.all(Ef.map(async(z)=>[z,await X9(z)!==null])),Y=new Map;for(let[z,K]of Q)Y.set(z,K?`${F8}installed${v}`:`${L0}not installed${v}`);let J=[["claude","claude - Claude Code (Anthropic) "],["codex","codex - Codex CLI (OpenAI) "],["cline","cline - Cline (multi-provider) "],["aider","aider - Aider (terminal pair prog) "]];for(let[z,K]of J){let $=X===z?` ${a0}(current)${v}`:"";process.stdout.write(` ${K} ${Y.get(z)}${$}
|
|
1158
|
+
`);let Q=await Promise.all(Ef.map(async(z)=>[z,await X9(z)!==null])),Y=new Map;for(let[z,K]of Q)Y.set(z,K?`${F8}installed${v}`:`${L0}not installed${v}`);let J=[["claude","claude - Claude Code (Anthropic) "],["codex","codex - Codex CLI (OpenAI) "],["cline","cline - Cline (multi-provider) "],["aider","aider - Aider (terminal pair prog) "],["opencode","opencode - opencode (multi-provider) "]];for(let[z,K]of J){let $=X===z?` ${a0}(current)${v}`:"";process.stdout.write(` ${K} ${Y.get(z)}${$}
|
|
1159
1159
|
`)}return process.stdout.write(`
|
|
1160
1160
|
`),process.stdout.write(`Set provider: ${a0}loki provider set <name>${v}
|
|
1161
1161
|
`),0}function Sf(){return process.stdout.write(`${W8}Loki Mode Provider Management${v}
|
|
@@ -1232,4 +1232,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
1232
1232
|
`),2}case"start":{let{runStart:Y}=await Promise.resolve().then(() => (h_(),f_));return Y(Q)}default:return process.stderr.write(`Unknown command: ${X}
|
|
1233
1233
|
`),process.stderr.write(v_),2}}cO();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var uW0=await mW0(Bun.argv.slice(2));process.exit(uW0);
|
|
1234
1234
|
|
|
1235
|
-
//# debugId=
|
|
1235
|
+
//# debugId=89896C957C47360064756E2164756E21
|
package/magic/core/debate.py
CHANGED
|
@@ -682,16 +682,21 @@ class DebateRunner:
|
|
|
682
682
|
def _critique_from_error(persona: str, exc: Exception) -> Critique:
|
|
683
683
|
"""Build a fail-safe Critique when a persona invocation errors.
|
|
684
684
|
|
|
685
|
-
The debate must continue even if one persona goes down
|
|
686
|
-
|
|
687
|
-
|
|
685
|
+
The debate must continue even if one persona goes down, but a
|
|
686
|
+
persona that never ran has NOT approved anything. approves=False
|
|
687
|
+
keeps a failed invocation out of the consensus tally: "the review
|
|
688
|
+
did not happen" and "the review passed" are opposite facts, and a
|
|
689
|
+
machine caller reads consensus as a gate verdict. The persona is
|
|
690
|
+
not a dissenter either, so severity stays 'info' (never 'block')
|
|
691
|
+
and parse_error carries the reason so callers can tell an
|
|
692
|
+
infrastructure failure from a genuine objection.
|
|
688
693
|
"""
|
|
689
694
|
return Critique(
|
|
690
695
|
persona=persona,
|
|
691
696
|
severity="info",
|
|
692
697
|
issues=[],
|
|
693
698
|
suggestions=[],
|
|
694
|
-
approves=
|
|
699
|
+
approves=False,
|
|
695
700
|
raw_response="",
|
|
696
701
|
parse_error=f"{type(exc).__name__}: {exc}",
|
|
697
702
|
)
|
package/mcp/__init__.py
CHANGED
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": "8.
|
|
4
|
+
"version": "8.83.0",
|
|
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",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "loki-mode",
|
|
4
4
|
"displayName": "Loki Mode",
|
|
5
|
-
"version": "8.
|
|
5
|
+
"version": "8.83.0",
|
|
6
6
|
"description": "Autonomous spec-to-product build system with a built-in trust layer (RARV-C closure loop, 8 quality gates, completion council). Ships Loki's spec-hardening, drift-detection, and deterministic PR verification commands plus the Loki MCP server.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Autonomi",
|