loki-mode 7.32.2 → 7.32.3
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/run.sh +58 -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/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, 11 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.32.
|
|
6
|
+
# Loki Mode v7.32.3
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -398,4 +398,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
398
398
|
|
|
399
399
|
---
|
|
400
400
|
|
|
401
|
-
**v7.32.
|
|
401
|
+
**v7.32.3 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.32.
|
|
1
|
+
7.32.3
|
package/autonomy/run.sh
CHANGED
|
@@ -4543,7 +4543,14 @@ _loki_hash_stdin() {
|
|
|
4543
4543
|
# Compute a cheap, clone-stable signature of the codebase so we can tell whether
|
|
4544
4544
|
# it changed since the generated PRD was last written. Git repos: HEAD sha +
|
|
4545
4545
|
# dirty flag (.loki/.git churn filtered out). Non-git: a hash of sorted
|
|
4546
|
-
# path+size pairs
|
|
4546
|
+
# path+size pairs PLUS file content (v7.32.3, #569: path+size alone was blind to
|
|
4547
|
+
# a same-size content edit, so a stale PRD could be silently reused with a
|
|
4548
|
+
# false "codebase unchanged" disclosure). Content hashing is clone-stable
|
|
4549
|
+
# (mtime is not, which is why mtime was never used). Trees larger than
|
|
4550
|
+
# LOKI_PRD_SIG_CONTENT_BUDGET bytes (default 50MB) skip the content pass and
|
|
4551
|
+
# emit a "files-shallow:" signature so startup stays fast; the safe failure
|
|
4552
|
+
# mode there is unchanged-from-before (size-blind), never a false "changed".
|
|
4553
|
+
# Echoes the signature.
|
|
4547
4554
|
compute_codebase_signature() {
|
|
4548
4555
|
local dir="${1:-.}"
|
|
4549
4556
|
( cd "$dir" 2>/dev/null || exit 0
|
|
@@ -4558,7 +4565,7 @@ compute_codebase_signature() {
|
|
|
4558
4565
|
fi
|
|
4559
4566
|
echo "git:${head}:${dirty}"
|
|
4560
4567
|
else
|
|
4561
|
-
local listing count
|
|
4568
|
+
local listing count total_sz budget
|
|
4562
4569
|
listing=$(find . \
|
|
4563
4570
|
-type d \( -name .loki -o -name .git -o -name node_modules -o -name dist \
|
|
4564
4571
|
-o -name build -o -name .next -o -name target -o -name vendor \
|
|
@@ -4569,8 +4576,26 @@ compute_codebase_signature() {
|
|
|
4569
4576
|
sz=$(stat -f%z "$f" 2>/dev/null || stat -c%s "$f" 2>/dev/null || echo 0)
|
|
4570
4577
|
printf '%s\t%s\n' "$f" "$sz"
|
|
4571
4578
|
done | LC_ALL=C sort)
|
|
4572
|
-
|
|
4573
|
-
|
|
4579
|
+
# grep -c prints 0 itself on no match (exit 1); '|| true' avoids the
|
|
4580
|
+
# old '|| echo 0' double-zero that embedded a newline on empty trees
|
|
4581
|
+
count=$(printf '%s\n' "$listing" | grep -c . || true)
|
|
4582
|
+
total_sz=$(printf '%s\n' "$listing" | awk -F'\t' '{s+=$2} END {printf "%d", s}')
|
|
4583
|
+
budget="${LOKI_PRD_SIG_CONTENT_BUDGET:-52428800}"
|
|
4584
|
+
if [ "${total_sz:-0}" -le "$budget" ] 2>/dev/null; then
|
|
4585
|
+
# Content pass: stream all file contents through one hash in the
|
|
4586
|
+
# same sorted order as the listing. Detects same-size edits.
|
|
4587
|
+
# xargs -0 batches the reads into a handful of cat invocations,
|
|
4588
|
+
# so cost scales with BYTES (which the budget above bounds), not
|
|
4589
|
+
# file count: a fork-per-file loop here measured ~38s of added
|
|
4590
|
+
# startup on a 30k-small-file tree. Renames and content swaps
|
|
4591
|
+
# are still caught by the listing hash (paths+sizes) below.
|
|
4592
|
+
local content_hash
|
|
4593
|
+
content_hash=$(printf '%s\n' "$listing" | cut -f1 | tr '\n' '\0' \
|
|
4594
|
+
| xargs -0 cat 2>/dev/null | _loki_hash_stdin)
|
|
4595
|
+
echo "files:$(printf '%s' "$listing" | _loki_hash_stdin):${count}:${content_hash}"
|
|
4596
|
+
else
|
|
4597
|
+
echo "files-shallow:$(printf '%s' "$listing" | _loki_hash_stdin):${count}"
|
|
4598
|
+
fi
|
|
4574
4599
|
fi
|
|
4575
4600
|
)
|
|
4576
4601
|
}
|
|
@@ -4644,6 +4669,25 @@ except Exception:
|
|
|
4644
4669
|
if [ "$stored" = "$current" ]; then
|
|
4645
4670
|
echo "reuse"
|
|
4646
4671
|
else
|
|
4672
|
+
# v7.32.3 format transition (#569): a stored pre-content-hash signature
|
|
4673
|
+
# ("files:<listing>:<count>", 3 fields) compared against the new 4-field
|
|
4674
|
+
# format would falsely claim "codebase changed" on the first post-upgrade
|
|
4675
|
+
# run. When the new signature extends the stored one (same listing
|
|
4676
|
+
# fields), the tree is unchanged at the old format's trust level: reuse,
|
|
4677
|
+
# honestly. The next persist upgrades the stored format. A same-size edit
|
|
4678
|
+
# made BEFORE the upgrade stays invisible for this one run, exactly as it
|
|
4679
|
+
# was on the old version (no regression, no false disclosure).
|
|
4680
|
+
case "$stored" in
|
|
4681
|
+
files:*:*)
|
|
4682
|
+
# Require the legitimate old 3-field format (files:HASH:COUNT,
|
|
4683
|
+
# exactly 2 colons), not a truncated/corrupted 2-field value
|
|
4684
|
+
# (council hardening: corruption must fall to update, as before).
|
|
4685
|
+
if [ "$(printf '%s' "$stored" | tr -dc ':' | wc -c | tr -d ' ')" = "2" ] \
|
|
4686
|
+
&& [ "${current#"${stored}":}" != "$current" ]; then
|
|
4687
|
+
echo "reuse"; return 0
|
|
4688
|
+
fi
|
|
4689
|
+
;;
|
|
4690
|
+
esac
|
|
4647
4691
|
echo "update"
|
|
4648
4692
|
fi
|
|
4649
4693
|
}
|
|
@@ -4692,7 +4736,16 @@ try:
|
|
|
4692
4736
|
except Exception:
|
|
4693
4737
|
prev = {}
|
|
4694
4738
|
prev_at = prev.get('generated_at') if isinstance(prev, dict) else None
|
|
4695
|
-
|
|
4739
|
+
prev_sig = prev.get('signature') if isinstance(prev, dict) else None
|
|
4740
|
+
# Unchanged, OR the v7.32.3 files-signature format upgrade (#569): the new
|
|
4741
|
+
# 4-field signature extends an old 3-field one whose listing fields match.
|
|
4742
|
+
# Preserve the date in both cases; the PRD content did not change.
|
|
4743
|
+
_legacy_upgrade = (
|
|
4744
|
+
isinstance(prev_sig, str) and prev_sig.startswith('files:')
|
|
4745
|
+
and prev_sig.count(':') == 2
|
|
4746
|
+
and sig.startswith(prev_sig + ':')
|
|
4747
|
+
)
|
|
4748
|
+
if prev_at and (prev_sig == sig or _legacy_upgrade):
|
|
4696
4749
|
generated_at = prev_at
|
|
4697
4750
|
else:
|
|
4698
4751
|
generated_at = datetime.datetime.now(datetime.timezone.utc).isoformat().replace('+00:00','Z')
|
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.32.
|
|
5
|
+
**Version:** v7.32.3
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var n6=Object.defineProperty;var a6=($)=>$;function s6($,Q){this[$]=a6.bind(null,Q)}var h=($,Q)=>{for(var Z in Q)n6($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:s6.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var K$=import.meta.require;var S1={};h(S1,{lokiDir:()=>P,homeLokiDir:()=>o$,findRepoRootForVersion:()=>d$,REPO_ROOT:()=>m});import{resolve as n,dirname as l$}from"path";import{fileURLToPath as t6}from"url";import{existsSync as P$}from"fs";import{homedir as r6}from"os";function i6(){let $=N1;for(let Q=0;Q<6;Q++){if(P$(n($,"VERSION"))&&P$(n($,"autonomy/run.sh")))return $;let Z=l$($);if(Z===$)break;$=Z}return n(N1,"..","..","..")}function d$($){let Q=$;for(let Z=0;Z<6;Z++){if(P$(n(Q,"VERSION"))&&P$(n(Q,"autonomy/run.sh")))return Q;let z=l$(Q);if(z===Q)break;Q=z}return n($,"..","..","..")}function P(){return process.env.LOKI_DIR??n(process.cwd(),".loki")}function o$(){return n(r6(),".loki")}var N1,m;var C=L(()=>{N1=l$(t6(import.meta.url));m=i6()});import{readFileSync as e6}from"fs";import{resolve as $Q,dirname as QQ}from"path";import{fileURLToPath as ZQ}from"url";function F$(){if($$!==null)return $$;let $="7.32.
|
|
2
|
+
var n6=Object.defineProperty;var a6=($)=>$;function s6($,Q){this[$]=a6.bind(null,Q)}var h=($,Q)=>{for(var Z in Q)n6($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:s6.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var K$=import.meta.require;var S1={};h(S1,{lokiDir:()=>P,homeLokiDir:()=>o$,findRepoRootForVersion:()=>d$,REPO_ROOT:()=>m});import{resolve as n,dirname as l$}from"path";import{fileURLToPath as t6}from"url";import{existsSync as P$}from"fs";import{homedir as r6}from"os";function i6(){let $=N1;for(let Q=0;Q<6;Q++){if(P$(n($,"VERSION"))&&P$(n($,"autonomy/run.sh")))return $;let Z=l$($);if(Z===$)break;$=Z}return n(N1,"..","..","..")}function d$($){let Q=$;for(let Z=0;Z<6;Z++){if(P$(n(Q,"VERSION"))&&P$(n(Q,"autonomy/run.sh")))return Q;let z=l$(Q);if(z===Q)break;Q=z}return n($,"..","..","..")}function P(){return process.env.LOKI_DIR??n(process.cwd(),".loki")}function o$(){return n(r6(),".loki")}var N1,m;var C=L(()=>{N1=l$(t6(import.meta.url));m=i6()});import{readFileSync as e6}from"fs";import{resolve as $Q,dirname as QQ}from"path";import{fileURLToPath as ZQ}from"url";function F$(){if($$!==null)return $$;let $="7.32.3";if(typeof $==="string"&&$.length>0)return $$=$,$$;try{let Q=QQ(ZQ(import.meta.url)),Z=d$(Q);$$=e6($Q(Z,"VERSION"),"utf-8").trim()}catch{$$="unknown"}return $$}var $$=null;var n$=L(()=>{C()});var C1={};h(C1,{runOrThrow:()=>zQ,run:()=>j,commandVersion:()=>KQ,commandExists:()=>f,ShellError:()=>a$});async function j($,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[W,K,U]=await Promise.all([new Response(Z.stdout).text(),new Response(Z.stderr).text(),Z.exited]);return{stdout:W,stderr:K,exitCode:U}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function zQ($,Q={}){let Z=await j($,Q);if(Z.exitCode!==0)throw new a$(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function f($){let Q=XQ($),Z=await j(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function XQ($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function KQ($,Q="--version"){if(!await f($))return null;let z=await j([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var a$;var d=L(()=>{a$=class a$ 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 a($){return WQ?"":$}var WQ,T,S,I,TZ,w,R,y,q;var c=L(()=>{WQ=(process.env.NO_COLOR??"").length>0;T=a("\x1B[0;31m"),S=a("\x1B[0;32m"),I=a("\x1B[1;33m"),TZ=a("\x1B[0;34m"),w=a("\x1B[0;36m"),R=a("\x1B[1m"),y=a("\x1B[2m"),q=a("\x1B[0m")});import{existsSync as TQ}from"fs";async function Q$(){if(B$!==void 0)return B$;let $="/opt/homebrew/bin/python3.12";if(TQ($))return B$=$,$;let Q=await f("python3.12");if(Q)return B$=Q,Q;let Z=await f("python3");return B$=Z,Z}async function Z$($,Q={}){let Z=await Q$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return j([Z,"-c",$],Q)}var B$;var W$=L(()=>{d()});var t1={};h(t1,{runStatus:()=>gQ});import{existsSync as v,readFileSync as U$,readdirSync as l1,statSync as d1}from"fs";import{resolve as D,basename as xQ}from"path";import{homedir as NQ}from"os";async function DQ(){if(await f("jq"))return!0;return process.stdout.write(`${T}Error: jq is required but not installed.${q}
|
|
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)
|
|
@@ -789,4 +789,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
789
789
|
`),2}default:return process.stderr.write(`Unknown command: ${Q}
|
|
790
790
|
`),process.stderr.write(o6),2}}p1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var ZZ=await QZ(Bun.argv.slice(2));process.exit(ZZ);
|
|
791
791
|
|
|
792
|
-
//# debugId=
|
|
792
|
+
//# debugId=E69BF9B144A89A3864756E2164756E21
|
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.32.
|
|
4
|
+
"version": "7.32.3",
|
|
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 11 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider).",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agent",
|