loki-mode 7.97.0 → 7.98.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 +2 -2
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +44 -4
- package/autonomy/run.sh +42 -5
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +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/README.md
CHANGED
|
@@ -197,7 +197,7 @@ loki quick "build a landing page with a signup form"
|
|
|
197
197
|
| **Bun (recommended)** | `bun install -g loki-mode` | Fastest startup for CLI commands. |
|
|
198
198
|
| **Homebrew** | `brew tap asklokesh/tap && brew install loki-mode` | Auto-installs Bun as a dep |
|
|
199
199
|
| **Docker (easiest)** | `loki docker start prd.md` | Host wrapper: runs loki in the published image with zero config. Bind-mounts the current folder so `.loki` state, resume, and continuity work exactly like local. Auto-detects auth (`ANTHROPIC_API_KEY`, else your host Claude Code login). Needs loki + Docker on the host. See DOCKER_README.md |
|
|
200
|
-
| **Docker (raw)** | `docker pull asklokesh/loki-mode:
|
|
200
|
+
| **Docker (raw)** | `docker pull asklokesh/loki-mode:latest && docker run --rm -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" asklokesh/loki-mode:latest start prd.md` | Bun + Claude CLI pre-installed; needs an API key, or use docker compose with a .env file, see DOCKER_README.md |
|
|
201
201
|
| **npm (compat)** | `npm install -g loki-mode` | Works without Bun (bash fallback). Migrate any time with `loki self-update --to bun`. |
|
|
202
202
|
|
|
203
203
|
**Upgrading:**
|
|
@@ -257,7 +257,7 @@ The next major release sunsets the Bash runtime entirely. There is no firm calen
|
|
|
257
257
|
| Method | Command |
|
|
258
258
|
|--------|---------|
|
|
259
259
|
| **Homebrew** | `brew tap asklokesh/tap && brew install loki-mode` |
|
|
260
|
-
| **Docker** | `docker pull asklokesh/loki-mode:
|
|
260
|
+
| **Docker** | `docker pull asklokesh/loki-mode:latest` |
|
|
261
261
|
| **Inside Claude Code** | `claude --dangerously-skip-permissions` then type "Loki Mode" |
|
|
262
262
|
| **Git clone** | `git clone https://github.com/asklokesh/loki-mode.git` |
|
|
263
263
|
|
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 v7.
|
|
6
|
+
# Loki Mode v7.98.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -408,4 +408,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
408
408
|
|
|
409
409
|
---
|
|
410
410
|
|
|
411
|
-
**v7.
|
|
411
|
+
**v7.98.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.98.0
|
|
@@ -44,7 +44,37 @@
|
|
|
44
44
|
# Council configuration
|
|
45
45
|
COUNCIL_ENABLED=${LOKI_COUNCIL_ENABLED:-true}
|
|
46
46
|
COUNCIL_SIZE=${LOKI_COUNCIL_SIZE:-3}
|
|
47
|
+
# Guard COUNCIL_SIZE: a non-positive/non-numeric size would make the 2/3 floor 0
|
|
48
|
+
# and let an empty council "approve" by default (fake-green). Force a sane floor.
|
|
49
|
+
case "$COUNCIL_SIZE" in
|
|
50
|
+
''|*[!0-9]*) COUNCIL_SIZE=3 ;;
|
|
51
|
+
esac
|
|
52
|
+
[ "$COUNCIL_SIZE" -lt 1 ] 2>/dev/null && COUNCIL_SIZE=3
|
|
47
53
|
COUNCIL_THRESHOLD=${LOKI_COUNCIL_THRESHOLD:-2}
|
|
54
|
+
|
|
55
|
+
# Effective completion threshold: the operator's COUNCIL_THRESHOLD may only ever
|
|
56
|
+
# TIGHTEN the gate, never weaken it below the 2/3-majority safety floor. Before
|
|
57
|
+
# this, the operator's COUNCIL_THRESHOLD was silently ignored by the vote (a
|
|
58
|
+
# hardcoded 2/3 formula was used), so an operator who set a stricter threshold
|
|
59
|
+
# got a no-op while the logs claimed it was active. We honor it as a floor-raise
|
|
60
|
+
# only: effective = max(ceil(2/3*size), operator_threshold), clamped to size.
|
|
61
|
+
_council_effective_threshold() {
|
|
62
|
+
# Optional $1 = the size to compute against (e.g. the actual number of voters
|
|
63
|
+
# present in this round); defaults to COUNCIL_SIZE. The 2/3 floor + the
|
|
64
|
+
# operator clamp are both relative to this size, so the helper works for both
|
|
65
|
+
# the configured council size and a per-round member count.
|
|
66
|
+
local _size="${1:-$COUNCIL_SIZE}"
|
|
67
|
+
case "$_size" in ''|*[!0-9]*) _size="$COUNCIL_SIZE" ;; esac
|
|
68
|
+
[ "$_size" -lt 1 ] 2>/dev/null && _size=1
|
|
69
|
+
local _floor=$(( (_size * 2 + 2) / 3 ))
|
|
70
|
+
local _op="${COUNCIL_THRESHOLD:-0}"
|
|
71
|
+
case "$_op" in ''|*[!0-9]*) _op=0 ;; esac
|
|
72
|
+
local _eff="$_floor"
|
|
73
|
+
[ "$_op" -gt "$_eff" ] 2>/dev/null && _eff="$_op"
|
|
74
|
+
[ "$_eff" -gt "$_size" ] 2>/dev/null && _eff="$_size"
|
|
75
|
+
[ "$_eff" -lt 1 ] 2>/dev/null && _eff=1
|
|
76
|
+
printf '%s' "$_eff"
|
|
77
|
+
}
|
|
48
78
|
COUNCIL_CHECK_INTERVAL=${LOKI_COUNCIL_CHECK_INTERVAL:-5}
|
|
49
79
|
# Guard against invalid interval (must be positive integer)
|
|
50
80
|
if ! [[ "$COUNCIL_CHECK_INTERVAL" =~ ^[1-9][0-9]*$ ]]; then
|
|
@@ -608,8 +638,11 @@ council_vote() {
|
|
|
608
638
|
log_header "COMPLETION COUNCIL - Iteration $ITERATION_COUNT"
|
|
609
639
|
log_info "Convening ${COUNCIL_SIZE}-member council..."
|
|
610
640
|
|
|
611
|
-
#
|
|
612
|
-
|
|
641
|
+
# Effective threshold honors the operator's COUNCIL_THRESHOLD as a floor-raise
|
|
642
|
+
# over the 2/3-majority safety floor (tighten-only); see
|
|
643
|
+
# _council_effective_threshold.
|
|
644
|
+
local effective_threshold
|
|
645
|
+
effective_threshold=$(_council_effective_threshold)
|
|
613
646
|
|
|
614
647
|
# Gather evidence for council members
|
|
615
648
|
local evidence_file="$vote_dir/evidence.md"
|
|
@@ -2604,7 +2637,13 @@ print(json.dumps(out))
|
|
|
2604
2637
|
" 2>/dev/null || echo "[]")
|
|
2605
2638
|
|
|
2606
2639
|
# Calculate threshold: 2/3 majority
|
|
2607
|
-
|
|
2640
|
+
# Effective threshold honors the operator's COUNCIL_THRESHOLD as a tighten-only
|
|
2641
|
+
# floor-raise over the 2/3 ceiling, computed against the actual member count.
|
|
2642
|
+
# This is the PRIMARY completion-decision path (council_should_stop ->
|
|
2643
|
+
# council_evaluate -> council_aggregate_votes), so it must use the same helper
|
|
2644
|
+
# as council_vote, not a separate hardcoded formula.
|
|
2645
|
+
local threshold
|
|
2646
|
+
threshold=$(_council_effective_threshold "$total_members")
|
|
2608
2647
|
local verdict="CONTINUE"
|
|
2609
2648
|
if [ "$complete_count" -ge "$threshold" ]; then
|
|
2610
2649
|
verdict="COMPLETE"
|
|
@@ -2833,7 +2872,8 @@ council_evaluate() {
|
|
|
2833
2872
|
fi
|
|
2834
2873
|
|
|
2835
2874
|
# Compute threshold using the same ceiling(2/3) formula as council_vote and council_aggregate_votes
|
|
2836
|
-
local _eval_threshold
|
|
2875
|
+
local _eval_threshold
|
|
2876
|
+
_eval_threshold=$(_council_effective_threshold)
|
|
2837
2877
|
|
|
2838
2878
|
# Step 1: Aggregate votes from all members.
|
|
2839
2879
|
# Phase C (v7.5.20): try the Claude `--agents <json>` + `--json-schema`
|
package/autonomy/run.sh
CHANGED
|
@@ -2058,6 +2058,25 @@ validate_api_keys() {
|
|
|
2058
2058
|
return 1
|
|
2059
2059
|
fi
|
|
2060
2060
|
|
|
2061
|
+
# Zero-friction auth preflight for LOCAL runs (must run BEFORE the early
|
|
2062
|
+
# return below, which exits for non-Docker/K8s envs). When claude is the
|
|
2063
|
+
# provider, the claude CLI is on PATH, there is no ANTHROPIC_API_KEY, and no
|
|
2064
|
+
# OAuth credentials file exists (the user installed claude but never ran
|
|
2065
|
+
# `claude login`), the build would otherwise enter, make a failing call, and
|
|
2066
|
+
# 401 -- the worst first impression -- forcing the user to run `loki why`.
|
|
2067
|
+
# Fail fast with the one-step fix instead. Opt out with LOKI_SKIP_AUTH_PREFLIGHT=1.
|
|
2068
|
+
if [[ "$provider" == "claude" && "${LOKI_SKIP_AUTH_PREFLIGHT:-}" != "1" && -z "${ANTHROPIC_API_KEY:-}" ]] \
|
|
2069
|
+
&& command -v claude >/dev/null 2>&1; then
|
|
2070
|
+
local _local_creds="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/.credentials.json"
|
|
2071
|
+
if [[ ! -s "$_local_creds" ]]; then
|
|
2072
|
+
log_error "Claude Code is installed but not logged in -- the build would stall instead of running."
|
|
2073
|
+
log_error "Log in once, then retry:"
|
|
2074
|
+
log_error " claude login"
|
|
2075
|
+
log_error "(or set ANTHROPIC_API_KEY, or LOKI_SKIP_AUTH_PREFLIGHT=1 to bypass this check)"
|
|
2076
|
+
return 1
|
|
2077
|
+
fi
|
|
2078
|
+
fi
|
|
2079
|
+
|
|
2061
2080
|
# CLI tools (claude, codex, cline, aider) use their own login sessions.
|
|
2062
2081
|
# Only require API keys inside Docker/K8s where CLI login isn't available.
|
|
2063
2082
|
if [[ ! -f "/.dockerenv" ]] && [[ -z "${KUBERNETES_SERVICE_HOST:-}" ]]; then
|
|
@@ -2162,6 +2181,9 @@ except Exception:
|
|
|
2162
2181
|
return 1
|
|
2163
2182
|
fi
|
|
2164
2183
|
fi
|
|
2184
|
+
# NOTE: the never-logged-in (no credentials file) case is handled earlier,
|
|
2185
|
+
# BEFORE the local early-return, so it covers local runs too (this Docker/
|
|
2186
|
+
# K8s-only block would otherwise be unreachable for that case).
|
|
2165
2187
|
fi
|
|
2166
2188
|
|
|
2167
2189
|
return 0
|
|
@@ -12224,16 +12246,31 @@ check_task_completion_signal() {
|
|
|
12224
12246
|
local fb_statement="${fb_content:-All PRD requirements implemented and tests passing}"
|
|
12225
12247
|
# Build minimal JSON payload
|
|
12226
12248
|
signal_file="$fallback_file"
|
|
12227
|
-
#
|
|
12228
|
-
#
|
|
12229
|
-
python3
|
|
12249
|
+
# Synthesize the payload into a TEMP file then atomically move it into
|
|
12250
|
+
# place, so the signal file is never observed truncated/empty/malformed:
|
|
12251
|
+
# a bare `python3 ... > "$fallback_file"` truncates the file BEFORE python
|
|
12252
|
+
# runs, so a python crash (or missing interpreter) mid-write would leave
|
|
12253
|
+
# an empty/partial file that downstream json.loads then silently drops.
|
|
12254
|
+
local _fb_tmp="${fallback_file}.tmp.$$"
|
|
12255
|
+
if python3 -c "
|
|
12230
12256
|
import json, sys
|
|
12231
|
-
|
|
12257
|
+
sys.stdout.write(json.dumps({
|
|
12232
12258
|
'statement': sys.argv[1][:1000],
|
|
12233
12259
|
'evidence': 'file-based completion via COMPLETION_REQUESTED fallback',
|
|
12234
12260
|
'confidence': 'medium',
|
|
12235
12261
|
'source': 'completion_requested_file_fallback'
|
|
12236
|
-
}))" "$fb_statement" > "$
|
|
12262
|
+
}))" "$fb_statement" > "$_fb_tmp" 2>/dev/null && [ -s "$_fb_tmp" ]; then
|
|
12263
|
+
mv -f "$_fb_tmp" "$fallback_file" 2>/dev/null || rm -f "$_fb_tmp" 2>/dev/null
|
|
12264
|
+
else
|
|
12265
|
+
# python unavailable or produced nothing: write a hand-built minimal
|
|
12266
|
+
# valid JSON (statement embedded with a conservative escape) atomically.
|
|
12267
|
+
rm -f "$_fb_tmp" 2>/dev/null
|
|
12268
|
+
local _fb_esc
|
|
12269
|
+
_fb_esc=$(printf '%s' "$fb_statement" | tr -d '"\\\n\r' | cut -c1-1000)
|
|
12270
|
+
printf '{"statement":"%s","evidence":"file-based completion via COMPLETION_REQUESTED fallback","confidence":"medium","source":"completion_requested_file_fallback"}' "$_fb_esc" > "${fallback_file}.tmp2.$$" 2>/dev/null \
|
|
12271
|
+
&& mv -f "${fallback_file}.tmp2.$$" "$fallback_file" 2>/dev/null \
|
|
12272
|
+
|| { rm -f "${fallback_file}.tmp2.$$" 2>/dev/null; printf '{"statement":"completion requested","evidence":"fallback","confidence":"low","source":"completion_requested_file_fallback"}' > "$fallback_file" 2>/dev/null; }
|
|
12273
|
+
fi
|
|
12237
12274
|
fi
|
|
12238
12275
|
|
|
12239
12276
|
if [ ! -f "$signal_file" ]; then
|
package/dashboard/__init__.py
CHANGED
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.98.0
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var z8=Object.defineProperty;var X8=($)=>$;function K8($,Q){this[$]=X8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)z8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:K8.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var y1={};b(y1,{lokiDir:()=>P,homeLokiDir:()=>T$,findRepoRootForVersion:()=>e$,REPO_ROOT:()=>h});import{resolve as t,dirname as i$}from"path";import{fileURLToPath as q8}from"url";import{existsSync as E$}from"fs";import{homedir as J8}from"os";function V8(){let $=h1;for(let Q=0;Q<6;Q++){if(E$(t($,"VERSION"))&&E$(t($,"autonomy/run.sh")))return $;let Z=i$($);if(Z===$)break;$=Z}return t(h1,"..","..","..")}function e$($){let Q=$;for(let Z=0;Z<6;Z++){if(E$(t(Q,"VERSION"))&&E$(t(Q,"autonomy/run.sh")))return Q;let z=i$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function P(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(J8(),".loki")}var h1,h;var C=L(()=>{h1=i$(q8(import.meta.url));h=V8()});import{readFileSync as W8}from"fs";import{resolve as U8,dirname as H8}from"path";import{fileURLToPath as G8}from"url";function N$(){if(Q$!==null)return Q$;let $="7.
|
|
2
|
+
var z8=Object.defineProperty;var X8=($)=>$;function K8($,Q){this[$]=X8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)z8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:K8.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var y1={};b(y1,{lokiDir:()=>P,homeLokiDir:()=>T$,findRepoRootForVersion:()=>e$,REPO_ROOT:()=>h});import{resolve as t,dirname as i$}from"path";import{fileURLToPath as q8}from"url";import{existsSync as E$}from"fs";import{homedir as J8}from"os";function V8(){let $=h1;for(let Q=0;Q<6;Q++){if(E$(t($,"VERSION"))&&E$(t($,"autonomy/run.sh")))return $;let Z=i$($);if(Z===$)break;$=Z}return t(h1,"..","..","..")}function e$($){let Q=$;for(let Z=0;Z<6;Z++){if(E$(t(Q,"VERSION"))&&E$(t(Q,"autonomy/run.sh")))return Q;let z=i$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function P(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(J8(),".loki")}var h1,h;var C=L(()=>{h1=i$(q8(import.meta.url));h=V8()});import{readFileSync as W8}from"fs";import{resolve as U8,dirname as H8}from"path";import{fileURLToPath as G8}from"url";function N$(){if(Q$!==null)return Q$;let $="7.98.0";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=H8(G8(import.meta.url)),Z=e$(Q);Q$=W8(U8(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var $1=L(()=>{C()});var u1={};b(u1,{runOrThrow:()=>x8,run:()=>F,readStreamCapped:()=>f1,commandVersion:()=>N8,commandExists:()=>f,ShellError:()=>Q1,MAX_STDOUT_BYTES:()=>m1});async function f1($,Q=m1){let Z=$.getReader(),z=new TextDecoder,X="",q=0;try{while(q<Q){let{done:K,value:W}=await Z.read();if(K)break;if(!W)continue;if(q+=W.byteLength,q>Q){let V=W.byteLength-(q-Q);X+=z.decode(W.subarray(0,V),{stream:!0});break}X+=z.decode(W,{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,W]=await Promise.all([f1(Z.stdout),new Response(Z.stderr).text(),Z.exited]);return{stdout:q,stderr:K,exitCode:W}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function x8($,Q={}){let Z=await F($,Q);if(Z.exitCode!==0)throw new Q1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function f($){let Q=E8($),Z=await F(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function E8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function N8($,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 m1=16777216,Q1;var d=L(()=>{Q1=class Q1 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 r($){return S8?"":$}var S8,T,S,_,lZ,I,k,y,J;var c=L(()=>{S8=(process.env.NO_COLOR??"").length>0;T=r("\x1B[0;31m"),S=r("\x1B[0;32m"),_=r("\x1B[1;33m"),lZ=r("\x1B[0;34m"),I=r("\x1B[0;36m"),k=r("\x1B[1m"),y=r("\x1B[2m"),J=r("\x1B[0m")});import{existsSync as u8}from"fs";async function Z$(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(u8($))return A$=$,$;let Q=await f("python3.12");if(Q)return A$=Q,Q;let Z=await f("python3");return A$=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 A$;var V$=L(()=>{d()});var q0={};b(q0,{runStatus:()=>W3});import{existsSync as v,readFileSync as U$,readdirSync as i1,statSync as e1}from"fs";import{resolve as D,basename as $3}from"path";import{homedir as Q3}from"os";function $0($){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 Q0($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*D$/Q);if(X>D$)X=D$;let q=D$-X,K=S;if(z>=80)K=T;else if(z>=50)K=_;let W="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),V=$0($),U=$0(Q);return` ${k}${Z}${J} ${K}[${W}]${J} ${z}% (${V} / ${U})`}async function z3(){if(await f("jq"))return!0;return process.stdout.write(`${T}Error: jq is required but not installed.${J}
|
|
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)
|
|
@@ -802,4 +802,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
802
802
|
`),2}default:return process.stderr.write(`Unknown command: ${Q}
|
|
803
803
|
`),process.stderr.write(Z8),2}}r1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var FZ=await jZ(Bun.argv.slice(2));process.exit(FZ);
|
|
804
804
|
|
|
805
|
-
//# debugId=
|
|
805
|
+
//# debugId=5C332E0B9079B5FC64756E2164756E21
|
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.98.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.98.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",
|