loki-mode 8.3.3 → 8.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -5
- package/VERSION +1 -1
- package/autonomy/run.sh +29 -0
- package/dashboard/__init__.py +1 -1
- package/docs/EVALUATING.md +50 -5
- package/loki-ts/dist/loki.js +2 -2
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ _The free, source-available autonomous coding agent by [Autonomi](https://www.au
|
|
|
15
15
|
|
|
16
16
|
[Website](https://www.autonomi.dev/) | [Documentation](wiki/Home.md) | [Installation](docs/INSTALLATION.md) | [Changelog](CHANGELOG.md) | [Purple Lab -- deprecated v7.44.0](#purple-lab)
|
|
17
17
|
|
|
18
|
-
**Current release: v8.
|
|
18
|
+
**Current release: v8.4.0**
|
|
19
19
|
|
|
20
20
|
</div>
|
|
21
21
|
|
|
@@ -63,10 +63,15 @@ does not execute functions"
|
|
|
63
63
|
([continue#5696](https://github.com/continuedev/continue/issues/5696)). None of
|
|
64
64
|
those seven publishes a machine-checkable completion artifact.
|
|
65
65
|
|
|
66
|
-
We
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
We measured every named competitor that ships a local CLI -- opencode 1.18.9,
|
|
67
|
+
aider 0.86.2, codex-cli 0.146.0, Claude Code 2.1.220, cursor-agent -- and none
|
|
68
|
+
exposes a command that verifies the agent's own output. Rerun it yourself with
|
|
69
|
+
`bash tests/test-competitor-verify-surface.sh`.
|
|
70
|
+
|
|
71
|
+
That is a measurement of the CLI surface, not of whole products: a web UI or an
|
|
72
|
+
API could expose something `--help` does not, and Devin and Replit Agent ship no
|
|
73
|
+
local CLI so they are not covered. The receipt stands on its own either way:
|
|
74
|
+
run the tour and check the hash.
|
|
70
75
|
|
|
71
76
|
**Evaluating this against something else?** [docs/EVALUATING.md](docs/EVALUATING.md)
|
|
72
77
|
puts a runnable command next to every claim we make, and states plainly what we
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
8.
|
|
1
|
+
8.4.0
|
package/autonomy/run.sh
CHANGED
|
@@ -3971,6 +3971,30 @@ except Exception:
|
|
|
3971
3971
|
print('')" "$_app_state_file" 2>/dev/null)"
|
|
3972
3972
|
fi
|
|
3973
3973
|
|
|
3974
|
+
# Time to first preview: how long until the user could SEE something running.
|
|
3975
|
+
#
|
|
3976
|
+
# WRITTEN BUT NEVER READ, until now. app-runner.sh:177 has recorded
|
|
3977
|
+
# seconds_to_first_preview since v8, write-once and atomically, and NOTHING
|
|
3978
|
+
# consumed it -- not this summary, not the receipt, not the dashboard. A
|
|
3979
|
+
# measurement nobody surfaces cannot influence anything, so the number that
|
|
3980
|
+
# research identifies as the delight peak of this whole category (a working
|
|
3981
|
+
# preview at roughly four minutes) was invisible to the person who waited for
|
|
3982
|
+
# it and to us.
|
|
3983
|
+
#
|
|
3984
|
+
# Read-only and best-effort by design: absent file means the app never
|
|
3985
|
+
# previewed (or the run predates the writer), and we render nothing rather
|
|
3986
|
+
# than a zero. A fabricated "0s to preview" would be worse than silence.
|
|
3987
|
+
local first_preview_s=""
|
|
3988
|
+
local _fp_file="$loki_dir/app-runner/first-preview.json"
|
|
3989
|
+
if [ -f "$_fp_file" ]; then
|
|
3990
|
+
first_preview_s="$(python3 -c "import json,sys
|
|
3991
|
+
try:
|
|
3992
|
+
v=json.load(open(sys.argv[1])).get('seconds_to_first_preview')
|
|
3993
|
+
print(int(v) if isinstance(v,(int,float)) and v>=0 else '')
|
|
3994
|
+
except Exception:
|
|
3995
|
+
print('')" "$_fp_file" 2>/dev/null)"
|
|
3996
|
+
fi
|
|
3997
|
+
|
|
3974
3998
|
# Branch + diff stats vs the run-start SHA (best-effort; non-git or empty
|
|
3975
3999
|
# baseline yields empty values, which we render as "unknown"/"0").
|
|
3976
4000
|
local start_sha="${_LOKI_RUN_START_SHA:-}"
|
|
@@ -4100,6 +4124,11 @@ except Exception:
|
|
|
4100
4124
|
fi
|
|
4101
4125
|
printf '%-14s %s\n' "Branch:" "$branch"
|
|
4102
4126
|
printf '%-14s %s\n' "Files:" "$files_changed (+$insertions / -$deletions)"
|
|
4127
|
+
# Only rendered when the app actually previewed. Silence beats a
|
|
4128
|
+
# fabricated zero for a run where nothing ever came up.
|
|
4129
|
+
if [ -n "$first_preview_s" ]; then
|
|
4130
|
+
printf '%-14s %ss\n' "First preview:" "$first_preview_s"
|
|
4131
|
+
fi
|
|
4103
4132
|
printf '%-14s %s\n' "Finished:" "$ts"
|
|
4104
4133
|
if [ -n "$delegate_branch" ]; then
|
|
4105
4134
|
printf '%-14s %s\n' "Delegate:" "$delegate_branch"
|
package/dashboard/__init__.py
CHANGED
package/docs/EVALUATING.md
CHANGED
|
@@ -114,6 +114,48 @@ check you run at the end and a check something else can call as a dependency.
|
|
|
114
114
|
|
|
115
115
|
---
|
|
116
116
|
|
|
117
|
+
## 6. Head to head, on this machine, in ten seconds
|
|
118
|
+
|
|
119
|
+
The one competitive comparison we will publish, because you can rerun it:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
bash tests/test-competitor-verify-surface.sh
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
It runs `--help` on whatever agent CLIs are installed and checks whether any of
|
|
126
|
+
them exposes a command that verifies the agent's OWN output.
|
|
127
|
+
|
|
128
|
+
Measured 2026-07-30 against every one of the six named competitors that ships
|
|
129
|
+
a local CLI:
|
|
130
|
+
|
|
131
|
+
| CLI | Verifies its own output |
|
|
132
|
+
| --- | --- |
|
|
133
|
+
| opencode 1.18.9 | no |
|
|
134
|
+
| aider 0.86.2 | no |
|
|
135
|
+
| codex-cli 0.146.0 | no |
|
|
136
|
+
| Claude Code 2.1.220 | no |
|
|
137
|
+
| cursor-agent 2026.05.24 | no |
|
|
138
|
+
| loki-mode 8.3.3 | yes (`loki proof verify`) |
|
|
139
|
+
|
|
140
|
+
Devin and Replit Agent ship no local CLI, so they are not covered and no claim
|
|
141
|
+
is made about them.
|
|
142
|
+
|
|
143
|
+
**The detail that makes this honest.** aider matches eight times on
|
|
144
|
+
verify/proof/attest terms. All eight are `--verify-ssl` (TLS certificate
|
|
145
|
+
validation) and `--git-commit-verify` (git pre-commit hooks). Neither verifies
|
|
146
|
+
the agent's output. A count-based comparison would have scored aider 8 against
|
|
147
|
+
our 2 and concluded the opposite of the truth, so the test reads every hit
|
|
148
|
+
instead of counting them.
|
|
149
|
+
|
|
150
|
+
**Scope.** This inspects the CLI surface of locally installed tools. Devin and
|
|
151
|
+
Replit Agent ship no local CLI and are not covered. Absence from a `--help`
|
|
152
|
+
listing is also not proof of absence from a product: a web UI or an API could
|
|
153
|
+
expose something the CLI does not. If a competitor does ship output
|
|
154
|
+
verification, this test is how we would find out, and the claim above would be
|
|
155
|
+
corrected rather than defended.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
117
159
|
## What we do not have
|
|
118
160
|
|
|
119
161
|
Stating this plainly, because you will find it out anyway and it is cheaper for
|
|
@@ -124,11 +166,14 @@ both of us if you find it here.
|
|
|
124
166
|
- **No independent third-party benchmark placement.** The SWE-bench Verified
|
|
125
167
|
leaderboard is months stale and every entry on it is self-reported, ours would
|
|
126
168
|
be too.
|
|
127
|
-
- **
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
169
|
+
- **Only the CLI surface is audited, not whole products.** Section 6 measures
|
|
170
|
+
every named competitor that ships a local CLI (opencode, aider, codex, Claude
|
|
171
|
+
Code, cursor-agent) and none exposes output verification. That is a real
|
|
172
|
+
measurement you can rerun, but it is a measurement of `--help`, not of a
|
|
173
|
+
product: a web UI or an API could expose something the CLI does not. Devin and
|
|
174
|
+
Replit Agent ship no local CLI and are not covered at all. Treat this as
|
|
175
|
+
"unclaimed on every surface we can reach", which is stronger than the earlier
|
|
176
|
+
"unclaimed as far as we can verify" and still short of a proven first.
|
|
132
177
|
- **Generation is not air-gapped.** See section 2.
|
|
133
178
|
|
|
134
179
|
---
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var S_=Object.create;var{getPrototypeOf:y_,defineProperty:oK,getOwnPropertyNames:b_}=Object;var __=Object.prototype.hasOwnProperty;function f_(Z){return this[Z]}var h_,v_,g_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?h_??=new WeakMap:v_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?S_(y_(Z)):{};let K=X||!Z||!Z.__esModule?oK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of b_(Z))if(!__.call(K,$))oK(K,$,{get:f_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var VQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var m_=(Z)=>Z;function u_(Z,X){this[Z]=m_.bind(null,X)}var c0=(Z,X)=>{for(var Q in X)oK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:u_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var t0=import.meta.require;var IO={};c0(IO,{lokiDir:()=>j0,homeLokiDir:()=>I4,findRepoRootForVersion:()=>tK,REPO_ROOT:()=>Q8});import{resolve as s7,dirname as rK}from"path";import{fileURLToPath as p_}from"url";import{existsSync as qQ}from"fs";import{homedir as d_}from"os";function c_(){let Z=EO;for(let X=0;X<6;X++){if(qQ(s7(Z,"VERSION"))&&qQ(s7(Z,"autonomy/run.sh")))return Z;let Q=rK(Z);if(Q===Z)break;Z=Q}return s7(EO,"..","..","..")}function tK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(qQ(s7(X,"VERSION"))&&qQ(s7(X,"autonomy/run.sh")))return X;let Y=rK(X);if(Y===X)break;X=Y}return s7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??s7(process.cwd(),".loki")}function I4(){return s7(d_(),".loki")}var EO,Q8;var G8=p(()=>{EO=rK(p_(import.meta.url));Q8=c_()});import{readFileSync as l_}from"fs";import{resolve as i_,dirname as a_}from"path";import{fileURLToPath as s_}from"url";function _3(){if(f5!==null)return f5;let Z="8.
|
|
2
|
+
var S_=Object.create;var{getPrototypeOf:y_,defineProperty:oK,getOwnPropertyNames:b_}=Object;var __=Object.prototype.hasOwnProperty;function f_(Z){return this[Z]}var h_,v_,g_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?h_??=new WeakMap:v_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?S_(y_(Z)):{};let K=X||!Z||!Z.__esModule?oK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of b_(Z))if(!__.call(K,$))oK(K,$,{get:f_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var VQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var m_=(Z)=>Z;function u_(Z,X){this[Z]=m_.bind(null,X)}var c0=(Z,X)=>{for(var Q in X)oK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:u_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var t0=import.meta.require;var IO={};c0(IO,{lokiDir:()=>j0,homeLokiDir:()=>I4,findRepoRootForVersion:()=>tK,REPO_ROOT:()=>Q8});import{resolve as s7,dirname as rK}from"path";import{fileURLToPath as p_}from"url";import{existsSync as qQ}from"fs";import{homedir as d_}from"os";function c_(){let Z=EO;for(let X=0;X<6;X++){if(qQ(s7(Z,"VERSION"))&&qQ(s7(Z,"autonomy/run.sh")))return Z;let Q=rK(Z);if(Q===Z)break;Z=Q}return s7(EO,"..","..","..")}function tK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(qQ(s7(X,"VERSION"))&&qQ(s7(X,"autonomy/run.sh")))return X;let Y=rK(X);if(Y===X)break;X=Y}return s7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??s7(process.cwd(),".loki")}function I4(){return s7(d_(),".loki")}var EO,Q8;var G8=p(()=>{EO=rK(p_(import.meta.url));Q8=c_()});import{readFileSync as l_}from"fs";import{resolve as i_,dirname as a_}from"path";import{fileURLToPath as s_}from"url";function _3(){if(f5!==null)return f5;let Z="8.4.0";if(typeof Z==="string"&&Z.length>0)return f5=Z,f5;try{let X=a_(s_(import.meta.url)),Q=tK(X);f5=l_(i_(Q,"VERSION"),"utf-8").trim()}catch{f5="unknown"}return f5}var f5=null;var GQ=p(()=>{G8()});var xO={};c0(xO,{runOrThrow:()=>qf,run:()=>E0,readStreamCapped:()=>HQ,commandVersion:()=>Hf,commandExists:()=>X9,ShellError:()=>eK,MAX_STDOUT_BYTES:()=>kO});async function HQ(Z,X=kO){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([HQ(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 qf(Z,X={}){let Q=await E0(Z,X);if(Q.exitCode!==0)throw new eK(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function X9(Z){let X=Gf(Z),Q=await E0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Gf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Hf(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 kO=16777216,eK;var k9=p(()=>{eK=class eK 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 n7(Z){return Uf?"":Z}var Uf,M0,k8,l0,dW0,a0,H8,Q9,g;var S6=p(()=>{Uf=(process.env.NO_COLOR??"").length>0;M0=n7("\x1B[0;31m"),k8=n7("\x1B[0;32m"),l0=n7("\x1B[1;33m"),dW0=n7("\x1B[0;34m"),a0=n7("\x1B[0;36m"),H8=n7("\x1B[1m"),Q9=n7("\x1B[2m"),g=n7("\x1B[0m")});import{existsSync as Ff}from"fs";async function F7(){if(R4!==void 0)return R4;let Z="/opt/homebrew/bin/python3.12";if(Ff(Z))return R4=Z,Z;let X=await X9("python3.12");if(X)return R4=X,X;let Q=await X9("python3");return R4=Q,Q}async function D7(Z,X={}){let Q=await F7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return E0([Q,"-c",Z],X)}var R4;var o7=p(()=>{k9()});var rO={};c0(rO,{runStatus:()=>tf});import{existsSync as Y9,readFileSync as h3,readdirSync as dO,statSync as cO}from"fs";import{resolve as h8,basename as pf}from"path";import{homedir as df}from"os";function lO(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 iO(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*BQ/X);if(J>BQ)J=BQ;let z=BQ-J,K=k8;if(Y>=80)K=M0;else if(Y>=50)K=l0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),W=lO(Z),V=lO(X);return` ${H8}${Q}${g} ${K}[${$}]${g} ${Y}% (${W} / ${V})`}async function lf(){if(await X9("jq"))return!0;return process.stdout.write(`${M0}Error: jq is required but not installed.${g}
|
|
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)
|
|
@@ -1206,4 +1206,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
1206
1206
|
`),2}case"start":{let{runStart:Y}=await Promise.resolve().then(() => (R_(),P_));return Y(Q)}default:return process.stderr.write(`Unknown command: ${X}
|
|
1207
1207
|
`),process.stderr.write(k_),2}}uO();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var DW0=await FW0(Bun.argv.slice(2));process.exit(DW0);
|
|
1208
1208
|
|
|
1209
|
-
//# debugId=
|
|
1209
|
+
//# debugId=8285CFE544C8109D64756E2164756E21
|
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.4.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.4.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",
|