loki-mode 7.84.0 → 7.86.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 +76 -0
- package/SKILL.md +4 -2
- package/VERSION +1 -1
- package/autonomy/lib/proof-generator.py +407 -13
- package/autonomy/lib/proof-template.html +309 -1
- package/autonomy/lib/proof-verify.py +483 -0
- package/autonomy/loki +32 -1
- package/autonomy/run.sh +26 -2
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +56 -0
- package/dashboard/static/index.html +93 -0
- package/docs/INSTALLATION.md +2 -2
- 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
|
@@ -204,6 +204,41 @@
|
|
|
204
204
|
font-weight: 500;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/* Verified-receipts badge: an honest trust signal next to the brand.
|
|
208
|
+
Counts are pulled live from /api/proofs/summary and reflect only real,
|
|
209
|
+
deterministic Evidence Receipts. Hidden until we have data; shows a muted
|
|
210
|
+
"No receipts yet" at zero; never a fabricated number. */
|
|
211
|
+
.receipts-badge {
|
|
212
|
+
display: none;
|
|
213
|
+
align-items: center;
|
|
214
|
+
gap: 5px;
|
|
215
|
+
margin-top: 6px;
|
|
216
|
+
padding: 3px 8px;
|
|
217
|
+
width: fit-content;
|
|
218
|
+
max-width: 100%;
|
|
219
|
+
border: 1px solid var(--loki-border);
|
|
220
|
+
border-radius: 999px;
|
|
221
|
+
background: var(--loki-bg-card);
|
|
222
|
+
font-family: 'Inter', system-ui, sans-serif;
|
|
223
|
+
font-size: 10px;
|
|
224
|
+
font-weight: 500;
|
|
225
|
+
line-height: 1.2;
|
|
226
|
+
color: var(--loki-text-secondary);
|
|
227
|
+
cursor: default;
|
|
228
|
+
}
|
|
229
|
+
.receipts-badge.show { display: inline-flex; }
|
|
230
|
+
.receipts-badge.empty { color: var(--loki-text-muted); }
|
|
231
|
+
.receipts-badge .receipts-dot {
|
|
232
|
+
width: 6px;
|
|
233
|
+
height: 6px;
|
|
234
|
+
border-radius: 50%;
|
|
235
|
+
background: var(--loki-success);
|
|
236
|
+
flex: 0 0 auto;
|
|
237
|
+
}
|
|
238
|
+
.receipts-badge.empty .receipts-dot { background: var(--loki-text-muted); }
|
|
239
|
+
.receipts-badge .receipts-verified { color: var(--loki-success); font-weight: 600; }
|
|
240
|
+
.receipts-badge.empty .receipts-verified { color: var(--loki-text-muted); font-weight: 500; }
|
|
241
|
+
|
|
207
242
|
/* Navigation: the only scrolling region. min-height:0 + overflow-y:auto so
|
|
208
243
|
a long grouped nav scrolls within the sidebar while the header + footer
|
|
209
244
|
stay pinned. */
|
|
@@ -851,6 +886,15 @@
|
|
|
851
886
|
</button>
|
|
852
887
|
<span class="logo-brand">Loki Mode</span>
|
|
853
888
|
<span class="logo-subtitle">powered by Autonomi</span>
|
|
889
|
+
<!-- Verified-receipts badge: honest trust signal. Populated at runtime
|
|
890
|
+
from /api/proofs/summary; hidden until data arrives, shows a muted
|
|
891
|
+
empty state at zero, and degrades silently if the endpoint is
|
|
892
|
+
unavailable. Every receipt is a deterministic, re-verifiable
|
|
893
|
+
Evidence Receipt (loki proof verify). -->
|
|
894
|
+
<span class="receipts-badge" id="receipts-badge" role="status">
|
|
895
|
+
<span class="receipts-dot" aria-hidden="true"></span>
|
|
896
|
+
<span id="receipts-badge-text"></span>
|
|
897
|
+
</span>
|
|
854
898
|
<!-- v7.84 single project switcher: ONE searchable <select> with two
|
|
855
899
|
<optgroup>s ("Running" and "All projects"), built at runtime from
|
|
856
900
|
/api/running-projects. A running-app count pill sits beside it; the
|
|
@@ -15250,6 +15294,55 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
15250
15294
|
} catch (err) { /* polling fallback still covers it */ }
|
|
15251
15295
|
})();
|
|
15252
15296
|
|
|
15297
|
+
// Verified-receipts badge: honest trust signal beside the brand. Fetches the
|
|
15298
|
+
// real aggregate from /api/proofs/summary and shows "N receipts - M
|
|
15299
|
+
// verified". At zero it shows a muted "No receipts yet"; if the endpoint is
|
|
15300
|
+
// unavailable it stays hidden (no error spew). We never display a number the
|
|
15301
|
+
// data does not support: "verified" here is the deterministic
|
|
15302
|
+
// honesty.headline == VERIFIED count, re-verifiable via loki proof verify.
|
|
15303
|
+
(function initReceiptsBadge() {
|
|
15304
|
+
var badge = document.getElementById('receipts-badge');
|
|
15305
|
+
var textEl = document.getElementById('receipts-badge-text');
|
|
15306
|
+
if (!badge || !textEl) return;
|
|
15307
|
+
|
|
15308
|
+
function plural(n, word) { return n + ' ' + word + (n === 1 ? '' : 's'); }
|
|
15309
|
+
|
|
15310
|
+
function render(s) {
|
|
15311
|
+
var total = (s && typeof s.total_receipts === 'number') ? s.total_receipts : 0;
|
|
15312
|
+
var verified = (s && typeof s.verified === 'number') ? s.verified : 0;
|
|
15313
|
+
if (total <= 0) {
|
|
15314
|
+
// Honest empty state: no fabricated number.
|
|
15315
|
+
badge.classList.add('empty');
|
|
15316
|
+
textEl.textContent = 'No receipts yet';
|
|
15317
|
+
badge.title = 'Evidence Receipts appear here once Loki completes a '
|
|
15318
|
+
+ 'verified run. Each is deterministic and re-verifiable with '
|
|
15319
|
+
+ '"loki proof verify".';
|
|
15320
|
+
badge.classList.add('show');
|
|
15321
|
+
return;
|
|
15322
|
+
}
|
|
15323
|
+
badge.classList.remove('empty');
|
|
15324
|
+
// "N receipts - M verified" with the verified count emphasized.
|
|
15325
|
+
textEl.innerHTML = plural(total, 'receipt') + ' - '
|
|
15326
|
+
+ '<span class="receipts-verified"></span> verified';
|
|
15327
|
+
var vEl = textEl.querySelector('.receipts-verified');
|
|
15328
|
+
if (vEl) vEl.textContent = String(verified);
|
|
15329
|
+
badge.title = plural(verified, 'receipt') + ' of ' + total
|
|
15330
|
+
+ ' verified by a deterministic Evidence Receipt (re-verifiable with '
|
|
15331
|
+
+ '"loki proof verify"). "Verified" means tests passed with real '
|
|
15332
|
+
+ 'exit-code evidence, not an LLM opinion.';
|
|
15333
|
+
badge.classList.add('show');
|
|
15334
|
+
}
|
|
15335
|
+
|
|
15336
|
+
function poll() {
|
|
15337
|
+
fetch('/api/proofs/summary', { headers: { 'Accept': 'application/json' } })
|
|
15338
|
+
.then(function (r) { return r.ok ? r.json() : null; })
|
|
15339
|
+
.then(function (d) { if (d) render(d); })
|
|
15340
|
+
.catch(function () { /* endpoint unavailable: leave badge hidden */ });
|
|
15341
|
+
}
|
|
15342
|
+
poll();
|
|
15343
|
+
setInterval(poll, 30000);
|
|
15344
|
+
})();
|
|
15345
|
+
|
|
15253
15346
|
// Mobile menu toggle
|
|
15254
15347
|
var mobileMenuBtn = document.getElementById('mobile-menu-btn');
|
|
15255
15348
|
var sidebar = document.getElementById('sidebar');
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -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:** v7.
|
|
5
|
+
**Version:** v7.86.0
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -395,7 +395,7 @@ provider works inside the container. Provide auth with your Anthropic API key:
|
|
|
395
395
|
# Run Loki Mode in Docker (Claude provider, API-key auth)
|
|
396
396
|
docker run --rm -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
|
|
397
397
|
-v $(pwd):/workspace -w /workspace \
|
|
398
|
-
asklokesh/loki-mode:7.
|
|
398
|
+
asklokesh/loki-mode:7.86.0 start ./my-spec.md
|
|
399
399
|
```
|
|
400
400
|
|
|
401
401
|
##### docker compose + .env (no host install)
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var QQ=Object.defineProperty;var ZQ=($)=>$;function zQ($,Q){this[$]=ZQ.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)QQ($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:zQ.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var q$=import.meta.require;var h1={};b(h1,{lokiDir:()=>P,homeLokiDir:()=>i$,findRepoRootForVersion:()=>t$,REPO_ROOT:()=>g});import{resolve as a,dirname as r$}from"path";import{fileURLToPath as XQ}from"url";import{existsSync as R$}from"fs";import{homedir as KQ}from"os";function qQ(){let $=b1;for(let Q=0;Q<6;Q++){if(R$(a($,"VERSION"))&&R$(a($,"autonomy/run.sh")))return $;let Z=r$($);if(Z===$)break;$=Z}return a(b1,"..","..","..")}function t$($){let Q=$;for(let Z=0;Z<6;Z++){if(R$(a(Q,"VERSION"))&&R$(a(Q,"autonomy/run.sh")))return Q;let z=r$(Q);if(z===Q)break;Q=z}return a($,"..","..","..")}function P(){return process.env.LOKI_DIR??a(process.cwd(),".loki")}function i$(){return a(KQ(),".loki")}var b1,g;var C=L(()=>{b1=r$(XQ(import.meta.url));g=qQ()});import{readFileSync as VQ}from"fs";import{resolve as JQ,dirname as UQ}from"path";import{fileURLToPath as WQ}from"url";function E$(){if(Q$!==null)return Q$;let $="7.
|
|
2
|
+
var QQ=Object.defineProperty;var ZQ=($)=>$;function zQ($,Q){this[$]=ZQ.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)QQ($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:zQ.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var q$=import.meta.require;var h1={};b(h1,{lokiDir:()=>P,homeLokiDir:()=>i$,findRepoRootForVersion:()=>t$,REPO_ROOT:()=>g});import{resolve as a,dirname as r$}from"path";import{fileURLToPath as XQ}from"url";import{existsSync as R$}from"fs";import{homedir as KQ}from"os";function qQ(){let $=b1;for(let Q=0;Q<6;Q++){if(R$(a($,"VERSION"))&&R$(a($,"autonomy/run.sh")))return $;let Z=r$($);if(Z===$)break;$=Z}return a(b1,"..","..","..")}function t$($){let Q=$;for(let Z=0;Z<6;Z++){if(R$(a(Q,"VERSION"))&&R$(a(Q,"autonomy/run.sh")))return Q;let z=r$(Q);if(z===Q)break;Q=z}return a($,"..","..","..")}function P(){return process.env.LOKI_DIR??a(process.cwd(),".loki")}function i$(){return a(KQ(),".loki")}var b1,g;var C=L(()=>{b1=r$(XQ(import.meta.url));g=qQ()});import{readFileSync as VQ}from"fs";import{resolve as JQ,dirname as UQ}from"path";import{fileURLToPath as WQ}from"url";function E$(){if(Q$!==null)return Q$;let $="7.86.0";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=UQ(WQ(import.meta.url)),Z=t$(Q);Q$=VQ(JQ(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var e$=L(()=>{C()});var g1={};b(g1,{runOrThrow:()=>HQ,run:()=>F,readStreamCapped:()=>m1,commandVersion:()=>BQ,commandExists:()=>f,ShellError:()=>$1,MAX_STDOUT_BYTES:()=>v1});async function m1($,Q=v1){let Z=$.getReader(),z=new TextDecoder,X="",q=0;try{while(q<Q){let{done:K,value:U}=await Z.read();if(K)break;if(!U)continue;if(q+=U.byteLength,q>Q){let J=U.byteLength-(q-Q);X+=z.decode(U.subarray(0,J),{stream:!0});break}X+=z.decode(U,{stream:!0})}X+=z.decode()}finally{try{await Z.cancel()}catch{}Z.releaseLock()}return X}async function F($,Q={}){let Z=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Q.env?{...process.env,...Q.env}:process.env,cwd:Q.cwd}),z,X;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[q,K,U]=await Promise.all([m1(Z.stdout),new Response(Z.stderr).text(),Z.exited]);return{stdout:q,stderr:K,exitCode:U}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function HQ($,Q={}){let Z=await F($,Q);if(Z.exitCode!==0)throw new $1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function f($){let Q=GQ($),Z=await F(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function GQ($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function BQ($,Q="--version"){if(!await f($))return null;let z=await F([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var v1=16777216,$1;var d=L(()=>{$1=class $1 extends Error{message;exitCode;stdout;stderr;constructor($,Q,Z,z){super($);this.message=$;this.exitCode=Q;this.stdout=Z;this.stderr=z;this.name="ShellError"}}});function s($){return YQ?"":$}var YQ,O,S,_,_Z,I,k,h,V;var c=L(()=>{YQ=(process.env.NO_COLOR??"").length>0;O=s("\x1B[0;31m"),S=s("\x1B[0;32m"),_=s("\x1B[1;33m"),_Z=s("\x1B[0;34m"),I=s("\x1B[0;36m"),k=s("\x1B[1m"),h=s("\x1B[2m"),V=s("\x1B[0m")});import{existsSync as jQ}from"fs";async function Z$(){if(Y$!==void 0)return Y$;let $="/opt/homebrew/bin/python3.12";if(jQ($))return Y$=$,$;let Q=await f("python3.12");if(Q)return Y$=Q,Q;let Z=await f("python3");return Y$=Z,Z}async function z$($,Q={}){let Z=await Z$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return F([Z,"-c",$],Q)}var Y$;var V$=L(()=>{d()});var X0={};b(X0,{runStatus:()=>oQ});import{existsSync as y,readFileSync as U$,readdirSync as r1,statSync as t1}from"fs";import{resolve as D,basename as vQ}from"path";import{homedir as mQ}from"os";function i1($){let Q=Math.trunc($);if(Q>=1e6)return`${(Math.trunc(Q/1e6*10)/10).toFixed(1)}M`;if(Q>=1000)return`${(Math.trunc(Q/1000*10)/10).toFixed(1)}K`;return String(Q)}function e1($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*N$/Q);if(X>N$)X=N$;let q=N$-X,K=S;if(z>=80)K=O;else if(z>=50)K=_;let U="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),J=i1($),W=i1(Q);return` ${k}${Z}${V} ${K}[${U}]${V} ${z}% (${J} / ${W})`}async function fQ(){if(await f("jq"))return!0;return process.stdout.write(`${O}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)
|
|
@@ -796,4 +796,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
796
796
|
`),2}default:return process.stderr.write(`Unknown command: ${Q}
|
|
797
797
|
`),process.stderr.write($Q),2}}s1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var qZ=await KZ(Bun.argv.slice(2));process.exit(qZ);
|
|
798
798
|
|
|
799
|
-
//# debugId=
|
|
799
|
+
//# debugId=5E11AD9E3DCEB72F64756E2164756E21
|
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": "7.
|
|
4
|
+
"version": "7.86.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": "7.
|
|
5
|
+
"version": "7.86.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",
|