loki-mode 8.13.1 → 8.14.1
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 +47 -0
- package/autonomy/run.sh +32 -0
- package/dashboard/__init__.py +1 -1
- package/loki-ts/dist/loki.js +2 -2
- 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.14.1
|
|
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.14.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
8.
|
|
1
|
+
8.14.1
|
package/autonomy/loki
CHANGED
|
@@ -4059,6 +4059,7 @@ WHYJSON
|
|
|
4059
4059
|
_LOKI_WHY_HEAD_SHA="$_why_head_sha" \
|
|
4060
4060
|
_LOKI_WHY_LAST_ERROR="$loki_dir/state/LAST_ERROR.json" \
|
|
4061
4061
|
_LOKI_WHY_UNCERTAINTY="$loki_dir/signals/UNCERTAINTY_ESCALATION" \
|
|
4062
|
+
_LOKI_WHY_EFFICIENCY="$loki_dir/metrics/efficiency" \
|
|
4062
4063
|
_LOKI_WHY_CONVERGENCE="$loki_dir/council/convergence.log" \
|
|
4063
4064
|
_LOKI_WHY_GATE="$loki_dir/signals/GATE_ESCALATION.json" \
|
|
4064
4065
|
_LOKI_WHY_TARGET="${TARGET_DIR:-$(dirname "$loki_dir")}" \
|
|
@@ -4128,6 +4129,52 @@ GUIDE = {
|
|
|
4128
4129
|
meaning, action = GUIDE.get(status, ("No diagnosis mapping for this status; see the raw fields below.",
|
|
4129
4130
|
"Check loki status and .loki/logs/ for detail."))
|
|
4130
4131
|
|
|
4132
|
+
# Rework-aware advice for the iteration cap. The static line said "raise
|
|
4133
|
+
# LOKI_MAX_ITERATIONS", which is right for a run that was CONVERGING and wrong
|
|
4134
|
+
# for one that was THRASHING -- there, a higher cap buys more thrashing at full
|
|
4135
|
+
# price. The completion summary already splits those cases; this command is
|
|
4136
|
+
# where v8.14.0 sends the user, so it must not contradict it.
|
|
4137
|
+
#
|
|
4138
|
+
# Reads the same attribution the summary and the prompt trend use, so all three
|
|
4139
|
+
# surfaces cannot disagree about one run. Falls back to the static line when
|
|
4140
|
+
# the split is unknown: guessing which case applies would be worse than the
|
|
4141
|
+
# generic advice.
|
|
4142
|
+
if status == "max_iterations_reached":
|
|
4143
|
+
try:
|
|
4144
|
+
import glob as _glob
|
|
4145
|
+
_prog = _rew = 0
|
|
4146
|
+
_rcost = 0.0
|
|
4147
|
+
_effdir = os.environ.get("_LOKI_WHY_EFFICIENCY", "")
|
|
4148
|
+
for _f in (_glob.glob(os.path.join(_effdir, "iteration-*.json")) if _effdir else []):
|
|
4149
|
+
try:
|
|
4150
|
+
_d = json.load(open(_f))
|
|
4151
|
+
except Exception:
|
|
4152
|
+
continue
|
|
4153
|
+
_st = str(_d.get("status", "")).lower()
|
|
4154
|
+
if _st in ("completed", "ok", "success"):
|
|
4155
|
+
_prog += 1
|
|
4156
|
+
elif _st in ("failed", "error", "blocked"):
|
|
4157
|
+
_rew += 1
|
|
4158
|
+
_rcost += float(_d.get("cost_usd") or 0)
|
|
4159
|
+
if _prog + _rew > 0:
|
|
4160
|
+
_tot = _prog + _rew
|
|
4161
|
+
if _rew * 2 >= _tot:
|
|
4162
|
+
action = (
|
|
4163
|
+
f"{_rew} of {_tot} iterations redid earlier work"
|
|
4164
|
+
+ (f" (${_rcost:.2f})" if _rcost > 0 else "")
|
|
4165
|
+
+ ". Raising LOKI_MAX_ITERATIONS buys more of the same at full price. "
|
|
4166
|
+
"Read the last reviewer findings in .loki/quality/reviews/ and fix the "
|
|
4167
|
+
"blocker, or narrow the spec."
|
|
4168
|
+
)
|
|
4169
|
+
else:
|
|
4170
|
+
action = (
|
|
4171
|
+
f"Converging: {_prog} of {_tot} iterations made progress"
|
|
4172
|
+
+ (f", {_rew} redid work (${_rcost:.2f})" if _rew else "")
|
|
4173
|
+
+ ". Raise LOKI_MAX_ITERATIONS and resume."
|
|
4174
|
+
)
|
|
4175
|
+
except Exception:
|
|
4176
|
+
pass
|
|
4177
|
+
|
|
4131
4178
|
# The completion.json branch/changes/PR belong to the LAST COMPLETED run. When
|
|
4132
4179
|
# the live state shows a build that is still running or crashed mid-iteration
|
|
4133
4180
|
# (running/exited), or when the completion record's head_sha no longer matches
|
package/autonomy/run.sh
CHANGED
|
@@ -4490,6 +4490,38 @@ except Exception:
|
|
|
4490
4490
|
echo "$_LOKI_REWORK_LINE"
|
|
4491
4491
|
echo ""
|
|
4492
4492
|
fi
|
|
4493
|
+
# What to DO about it. A terminal that names a bound without naming the
|
|
4494
|
+
# lever leaves the user to guess which knob applies, and the wrong guess
|
|
4495
|
+
# is expensive: raising an iteration cap on a run that was thrashing
|
|
4496
|
+
# buys more thrashing at full price.
|
|
4497
|
+
#
|
|
4498
|
+
# The rework split above already distinguishes the two cases, so this
|
|
4499
|
+
# points at the lever that actually matches the outcome rather than
|
|
4500
|
+
# listing every environment variable.
|
|
4501
|
+
case "$outcome" in
|
|
4502
|
+
max_iterations)
|
|
4503
|
+
echo "Next: this run hit its iteration ceiling, not a verdict."
|
|
4504
|
+
echo " Converging (low rework above)? Raise it: LOKI_MAX_ITERATIONS=<n>"
|
|
4505
|
+
echo " Thrashing (high rework above)? Raising the cap buys more"
|
|
4506
|
+
echo " of the same. Read the last reviewer findings first:"
|
|
4507
|
+
echo " loki why"
|
|
4508
|
+
echo ""
|
|
4509
|
+
;;
|
|
4510
|
+
budget_exceeded)
|
|
4511
|
+
echo "Next: the spend cap stopped this run, not a failed gate."
|
|
4512
|
+
echo " Raise it with LOKI_BUDGET_LIMIT=<usd>, or check the cache"
|
|
4513
|
+
echo " hit ratio first -- a cold cache is the usual cause of a"
|
|
4514
|
+
echo " surprising bill:"
|
|
4515
|
+
echo " loki memory economics"
|
|
4516
|
+
echo ""
|
|
4517
|
+
;;
|
|
4518
|
+
force_stopped)
|
|
4519
|
+
echo "Next: the council stopped this run WITHOUT approving it."
|
|
4520
|
+
echo " The work is not verified complete. See what blocked it:"
|
|
4521
|
+
echo " loki why"
|
|
4522
|
+
echo ""
|
|
4523
|
+
;;
|
|
4524
|
+
esac
|
|
4493
4525
|
if [ -n "$evidence_inconclusive_line" ]; then
|
|
4494
4526
|
echo "$evidence_inconclusive_line"
|
|
4495
4527
|
echo ""
|
package/dashboard/__init__.py
CHANGED
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var h_=Object.create;var{getPrototypeOf:v_,defineProperty:rK,getOwnPropertyNames:g_}=Object;var m_=Object.prototype.hasOwnProperty;function u_(Z){return this[Z]}var p_,d_,c_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?p_??=new WeakMap:d_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?h_(v_(Z)):{};let K=X||!Z||!Z.__esModule?rK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of g_(Z))if(!m_.call(K,$))rK(K,$,{get:u_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var qQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var l_=(Z)=>Z;function i_(Z,X){this[Z]=l_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)rK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:i_.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:()=>P4,findRepoRootForVersion:()=>eK,REPO_ROOT:()=>r0});import{resolve as n7,dirname as tK}from"path";import{fileURLToPath as a_}from"url";import{existsSync as GQ}from"fs";import{homedir as s_}from"os";function n_(){let Z=RO;for(let X=0;X<6;X++){if(GQ(n7(Z,"VERSION"))&&GQ(n7(Z,"autonomy/run.sh")))return Z;let Q=tK(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function eK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(GQ(n7(X,"VERSION"))&&GQ(n7(X,"autonomy/run.sh")))return X;let Y=tK(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function P4(){return n7(s_(),".loki")}var RO,r0;var G8=p(()=>{RO=tK(a_(import.meta.url));r0=n_()});import{readFileSync as o_}from"fs";import{resolve as r_,dirname as t_}from"path";import{fileURLToPath as e_}from"url";function f3(){if(h5!==null)return h5;let Z="8.
|
|
2
|
+
var h_=Object.create;var{getPrototypeOf:v_,defineProperty:rK,getOwnPropertyNames:g_}=Object;var m_=Object.prototype.hasOwnProperty;function u_(Z){return this[Z]}var p_,d_,c_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?p_??=new WeakMap:d_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?h_(v_(Z)):{};let K=X||!Z||!Z.__esModule?rK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of g_(Z))if(!m_.call(K,$))rK(K,$,{get:u_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var qQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var l_=(Z)=>Z;function i_(Z,X){this[Z]=l_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)rK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:i_.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:()=>P4,findRepoRootForVersion:()=>eK,REPO_ROOT:()=>r0});import{resolve as n7,dirname as tK}from"path";import{fileURLToPath as a_}from"url";import{existsSync as GQ}from"fs";import{homedir as s_}from"os";function n_(){let Z=RO;for(let X=0;X<6;X++){if(GQ(n7(Z,"VERSION"))&&GQ(n7(Z,"autonomy/run.sh")))return Z;let Q=tK(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function eK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(GQ(n7(X,"VERSION"))&&GQ(n7(X,"autonomy/run.sh")))return X;let Y=tK(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function P4(){return n7(s_(),".loki")}var RO,r0;var G8=p(()=>{RO=tK(a_(import.meta.url));r0=n_()});import{readFileSync as o_}from"fs";import{resolve as r_,dirname as t_}from"path";import{fileURLToPath as e_}from"url";function f3(){if(h5!==null)return h5;let Z="8.14.1";if(typeof Z==="string"&&Z.length>0)return h5=Z,h5;try{let X=t_(e_(import.meta.url)),Q=eK(X);h5=o_(r_(Q,"VERSION"),"utf-8").trim()}catch{h5="unknown"}return h5}var h5=null;var HQ=p(()=>{G8()});var bO={};l0(bO,{runOrThrow:()=>Of,run:()=>E0,readStreamCapped:()=>UQ,commandVersion:()=>Af,commandExists:()=>X9,ShellError:()=>Z$,MAX_STDOUT_BYTES:()=>yO});async function UQ(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([UQ(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 Of(Z,X={}){let Q=await E0(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=Lf(Z),Q=await E0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Lf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Af(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,Z$;var x9=p(()=>{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 jf?"":Z}var jf,L0,k8,p0,ZV0,i0,H8,Q9,v;var S6=p(()=>{jf=(process.env.NO_COLOR??"").length>0;L0=o7("\x1B[0;31m"),k8=o7("\x1B[0;32m"),p0=o7("\x1B[1;33m"),ZV0=o7("\x1B[0;34m"),i0=o7("\x1B[0;36m"),H8=o7("\x1B[1m"),Q9=o7("\x1B[2m"),v=o7("\x1B[0m")});import{existsSync as xf}from"fs";async function E7(){if(k4!==void 0)return k4;let Z="/opt/homebrew/bin/python3.12";if(xf(Z))return k4=Z,Z;let X=await X9("python3.12");if(X)return k4=X,X;let Q=await X9("python3");return k4=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 k4;var r7=p(()=>{x9()});var ZL={};l0(ZL,{runStatus:()=>Yh});import{existsSync as Y9,readFileSync as v3,readdirSync as iO,statSync as aO}from"fs";import{resolve as h8,basename as sf}from"path";import{homedir as nf}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*NQ/X);if(J>NQ)J=NQ;let z=NQ-J,K=k8;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` ${H8}${Q}${v} ${K}[${$}]${v} ${Y}% (${W} / ${V})`}async function rf(){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)
|
|
@@ -1222,4 +1222,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
1222
1222
|
`),2}case"start":{let{runStart:Y}=await Promise.resolve().then(() => (b_(),y_));return Y(Q)}default:return process.stderr.write(`Unknown command: ${X}
|
|
1223
1223
|
`),process.stderr.write(__),2}}cO();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var fW0=await _W0(Bun.argv.slice(2));process.exit(fW0);
|
|
1224
1224
|
|
|
1225
|
-
//# debugId=
|
|
1225
|
+
//# debugId=459E40D2ADB11B2D64756E2164756E21
|
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.14.1",
|
|
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.14.1",
|
|
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",
|