loki-mode 7.19.4 → 7.21.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 CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # Loki Mode
4
4
 
5
- ### Build the future, faster.
5
+ ### The spec-driven autonomous builder with verified completion.
6
6
 
7
- **Describe what you want. Get production-ready code.**
7
+ **Hand it a spec. It does not accept "done" on an empty diff or failing tests.**
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/loki-mode?style=for-the-badge&logo=npm&logoColor=white&color=553DE9)](https://www.npmjs.com/package/loki-mode)
10
10
  [![npm downloads](https://img.shields.io/npm/dt/loki-mode?style=for-the-badge&logo=npm&logoColor=white&color=1FC5A8&label=downloads)](https://www.npmjs.com/package/loki-mode)
@@ -24,12 +24,12 @@
24
24
 
25
25
  ## Why Loki Mode?
26
26
 
27
- - **Spec to product, autonomously** -- Describe what you want, walk away, come back to working code with tests. Loki runs the full RARV-C closure loop (Reason - Act - Reflect - Verify - Close) until the work is actually done, not just attempted.
27
+ - **Spec-driven, autonomous, with a built-in trust layer** -- Hand Loki a spec, walk away, come back to working code with tests. The full RARV-C closure loop (Reason - Act - Reflect - Verify - Close) runs until the work is actually done, not just attempted. The verified-completion evidence gate (`skills/quality-gates.md`) refuses any "done" claim on an empty git diff against the run-start commit, and blocks completion when tests run red, so "complete" means proven, not promised.
28
28
  - **Production quality built in** -- 11 quality gates (`skills/quality-gates.md`), blind 3-reviewer code review (`run.sh:run_code_review()`), anti-sycophancy checks
29
29
  - **Cross-project memory** -- Episodic/semantic/procedural memory with vector search; knowledge learned on one project surfaces on the next (v5.15.0+, see `memory/engine.py`)
30
30
  - **Self-hosted and private** -- Your keys, your infrastructure, no data leaves your network
31
31
  - **Legacy system healing** -- `loki heal` archaeology/stabilize/isolate/modernize/validate phases (v6.67.0, see `skills/healing.md`)
32
- - **MCP server** -- 15 tools including ChromaDB code search (`mcp/server.py`)
32
+ - **MCP server** -- 34 tools (including ChromaDB code search) plus 3 resources and 2 prompts (`mcp/server.py`, with managed-memory and magic tools registered from `mcp/managed_tools.py` and `mcp/magic_tools.py`)
33
33
  - **Full-stack output** -- Source code, tests, Docker configs, CI/CD pipelines, audit logs
34
34
  - **Provider-agnostic** -- runs on Claude, Codex, Cline, or Aider with automatic failover (`loki-ts/src/runner/providers.ts`); no vendor lock-in. Gemini CLI deprecated v7.5.18; Antigravity CLI coming soon.
35
35
  - **Open source** -- Free for personal, internal, and academic use.
@@ -409,8 +409,8 @@ Self-reported results from the included test harness. Verification scripts inclu
409
409
 
410
410
  | Benchmark | Result | Notes |
411
411
  |-----------|--------|-------|
412
- | HumanEval | 162/164 (98.78%) | Max 3 retries, RARV self-verification |
413
- | SWE-bench | 299/300 patches | Patch generation -- evaluator not yet run |
412
+ | HumanEval | 162/164 (98.78%) | Self-reported; harness + results JSON in `benchmarks/results/humaneval-loki-results.json`. Max 3 retries, RARV self-verification. |
413
+ | SWE-bench | Not yet measured | Harness exists and generates patches, but the official SWE-bench evaluator has not been run, so there is no pass-rate to report. Run it yourself: `./benchmarks/run-benchmarks.sh swebench --execute` |
414
414
 
415
415
  See [benchmarks/](benchmarks/) for methodology.
416
416
 
package/SKILL.md CHANGED
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: loki-mode
3
- description: Autonomous spec-to-product system. Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product via the RARV-C closure loop, with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
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.19.4
6
+ # Loki Mode v7.21.0
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
10
- **Spec in, product out.** A "spec" is whatever describes the work: a Markdown PRD, a GitHub issue, an OpenAPI doc, a Jira ticket -- a PRD is one form of spec.
10
+ **Spec in, verified product out.** Spec-driven: a "spec" is whatever describes the work -- a Markdown PRD, a GitHub issue, an OpenAPI doc, a Jira ticket (a PRD is one form of spec). The differentiator is the trust layer: Loki does not call work done until it is verified. The RARV-C closure loop, 11 quality gates, the completion council, and the verified-completion evidence gate must all clear before completion is accepted.
11
11
 
12
12
  **Provider-agnostic (stable since v5.0.0):** runs on Claude/Codex/Cline/Aider with abstract model tiers and degraded mode for non-Claude providers; no vendor lock-in. Gemini deprecated v7.5.18. See `skills/providers.md`. **Current track (v7.7.x):** LSP grounding as first-class agent tool (v7.7.0-v7.7.9; lsp_get_diagnostics actually-returns-diagnostics regression fix v7.7.14), provider_source cli (v7.7.11-v7.7.12 bash/bun parity), Docker/bash-3.2 robustness (v7.7.13), audit chain cross-file verification fix (v7.7.15), Phase 1 RARV-C closure (real provider judges, gate-failure flock, synthetic PRD e2e, status `--json`).
13
13
 
@@ -383,4 +383,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
383
383
 
384
384
  ---
385
385
 
386
- **v7.19.4 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
386
+ **v7.21.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 7.19.4
1
+ 7.21.0
@@ -557,6 +557,32 @@ _lpg_find_git_root() {
557
557
  # Layer order: parent -> members -> subdir(root-to-leaf, deepest last)
558
558
  # -> scope. All paths are deduped via a tracked set of absolute paths.
559
559
  # Honors __LPG_TOTAL_CAP across all layers (stops at layer boundary).
560
+ # _lpg_memory_file <dir>
561
+ #
562
+ # Resolve the per-directory memory/conventions file for the layered doc walker.
563
+ # Prefers AGENTS.md (the agents.md standard: plain Markdown, nearest-file-wins,
564
+ # read natively by Claude Code/Codex/etc.) and falls back to CLAUDE.md only when
565
+ # AGENTS.md is absent in that directory. The two are never merged. The reader
566
+ # (_lpg_read_layer / _append_layer) is filename-agnostic, so this is the single
567
+ # point that decides which file each layer site reads.
568
+ _lpg_memory_file() {
569
+ local dir="$1"
570
+ if [ -f "$dir/AGENTS.md" ]; then
571
+ printf '%s/AGENTS.md' "$dir"
572
+ else
573
+ printf '%s/CLAUDE.md' "$dir"
574
+ fi
575
+ }
576
+
577
+ # load_app_graph_context -- emit the layered conventions/doc context (parent,
578
+ # member, subdir, and scope layers) as <!-- LOKI_LAYER --> blocks.
579
+ #
580
+ # NOTE (route asymmetry, conscious + pre-existing): the TS route has NO port of
581
+ # this function. loki-ts/src/project_graph.ts is a membership graph, not a
582
+ # doc-layer text emitter, so this layered AGENTS.md/CLAUDE.md walker is BASH-ONLY
583
+ # by design (the layered-CLAUDE.md doc walker was never ported to TS). The
584
+ # AGENTS.md precedence added here therefore lives only in bash; do not add a TS
585
+ # walker to "fix" the asymmetry.
560
586
  load_app_graph_context() {
561
587
  local root="${LOKI_PROJECT_GRAPH_ROOT:-}"
562
588
 
@@ -634,7 +660,7 @@ load_app_graph_context() {
634
660
 
635
661
  # Parent layer first.
636
662
  if [ -n "$root" ]; then
637
- _append_layer parent "$root/CLAUDE.md" || { printf '%s' "$out"; return 0; }
663
+ _append_layer parent "$(_lpg_memory_file "$root")" || { printf '%s' "$out"; return 0; }
638
664
  fi
639
665
 
640
666
  # Member layers (skip the scope member -- we add it as scope below).
@@ -644,7 +670,7 @@ load_app_graph_context() {
644
670
  if [ "$m" = "$target_dir" ]; then
645
671
  continue
646
672
  fi
647
- _append_layer member "$m/CLAUDE.md" || { printf '%s' "$out"; return 0; }
673
+ _append_layer member "$(_lpg_memory_file "$m")" || { printf '%s' "$out"; return 0; }
648
674
  done
649
675
 
650
676
  # Subdir layers: ancestors of target_dir up to (and including) git_root,
@@ -674,12 +700,12 @@ load_app_graph_context() {
674
700
  # subdir_chain is leaf-to-root order; reverse so we emit root-to-leaf.
675
701
  local i count=${#subdir_chain[@]}
676
702
  for (( i = count - 1; i >= 0; i-- )); do
677
- _append_layer subdir "${subdir_chain[$i]}/CLAUDE.md" || { printf '%s' "$out"; return 0; }
703
+ _append_layer subdir "$(_lpg_memory_file "${subdir_chain[$i]}")" || { printf '%s' "$out"; return 0; }
678
704
  done
679
705
  fi
680
706
 
681
707
  # Scope layer (target dir).
682
- _append_layer scope "$target_dir/CLAUDE.md" || { printf '%s' "$out"; return 0; }
708
+ _append_layer scope "$(_lpg_memory_file "$target_dir")" || { printf '%s' "$out"; return 0; }
683
709
 
684
710
  printf '%s' "$out"
685
711
  }
package/autonomy/run.sh CHANGED
@@ -10068,6 +10068,14 @@ build_prompt() {
10068
10068
  # is the single most leveraged grounding primitive per OpenCode research.
10069
10069
  local lsp_grounding_instruction="LSP_GROUNDING: When the loki-mode-lsp-proxy MCP server is available, prefer LSP tools for symbol verification BEFORE writing code that references those symbols. Workflow: (1) Need to call \`foo.bar()\` you have not already read? -> mcp__loki-mode-lsp-proxy__lsp_check_exists with symbol='bar' (sub-200ms when cached). If exists:false, do NOT write the call -- use mcp__loki-mode-lsp-proxy__lsp_workspace_symbols with the concept name to find the real symbol, or use Read to see the actual API. (2) Just edited a file? -> mcp__loki-mode-lsp-proxy__lsp_get_diagnostics on that file to see new errors before the next iteration. (3) Need to jump to a definition by name (no file:line known)? -> mcp__loki-mode-lsp-proxy__lsp_find_definition_by_name. Skip these tools silently when the server is not available -- check the tool list, do not retry on errors. Goal: eliminate hallucinated API calls before they ship."
10070
10070
 
10071
+ # AGENTS.md instruction (agents.md standard: plain Markdown at repo root,
10072
+ # nearest-file-wins, read natively by Claude Code/Codex/etc.). Loki prefers
10073
+ # AGENTS.md and falls back to CLAUDE.md only when AGENTS.md is absent; the
10074
+ # two are never merged. This string MUST stay byte-identical to
10075
+ # AGENTS_MD_INSTRUCTION in loki-ts/src/runner/build_prompt.ts (parity-locked,
10076
+ # same precedent as AUTONOMY_OVERRIDE_TEXT in providers/claude_flags.ts).
10077
+ local agents_md_instruction="Project conventions: read AGENTS.md in the repository root for build, test, and style conventions. If AGENTS.md is absent, read CLAUDE.md instead. The nearest such file to the code you are editing takes precedence."
10078
+
10071
10079
  # Load existing context if resuming
10072
10080
  local context_injection=""
10073
10081
  if [ $retry -gt 0 ]; then
@@ -10397,15 +10405,15 @@ except Exception:
10397
10405
  else
10398
10406
  if [ $retry -eq 0 ]; then
10399
10407
  if [ -n "$prd" ]; then
10400
- echo "Loki Mode with PRD at $prd. $update_instruction $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $rarv_instruction $memory_instruction $usage_doc_instruction $lsp_grounding_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
10408
+ echo "Loki Mode with PRD at $prd. $update_instruction $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $rarv_instruction $memory_instruction $usage_doc_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
10401
10409
  else
10402
- echo "Loki Mode. $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $analysis_instruction $rarv_instruction $memory_instruction $usage_doc_instruction $lsp_grounding_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
10410
+ echo "Loki Mode. $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $analysis_instruction $rarv_instruction $memory_instruction $usage_doc_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
10403
10411
  fi
10404
10412
  else
10405
10413
  if [ -n "$prd" ]; then
10406
- echo "Loki Mode - Resume iteration #$iteration (retry #$retry). PRD: $prd. $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $rarv_instruction $memory_instruction $usage_doc_instruction $lsp_grounding_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
10414
+ echo "Loki Mode - Resume iteration #$iteration (retry #$retry). PRD: $prd. $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $rarv_instruction $memory_instruction $usage_doc_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
10407
10415
  else
10408
- echo "Loki Mode - Resume iteration #$iteration (retry #$retry). $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section Use .loki/generated-prd.md if exists. $rarv_instruction $memory_instruction $usage_doc_instruction $lsp_grounding_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
10416
+ echo "Loki Mode - Resume iteration #$iteration (retry #$retry). $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section Use .loki/generated-prd.md if exists. $rarv_instruction $memory_instruction $usage_doc_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
10409
10417
  fi
10410
10418
  fi
10411
10419
  fi
@@ -10448,6 +10456,7 @@ except Exception:
10448
10456
  fi
10449
10457
  printf '%s\n' "$usage_doc_instruction"
10450
10458
  printf '%s\n' "$lsp_grounding_instruction"
10459
+ printf '%s\n' "$agents_md_instruction"
10451
10460
  printf '</loki_system>\n'
10452
10461
  printf '[CACHE_BREAKPOINT]\n'
10453
10462
 
@@ -10480,6 +10489,7 @@ except Exception:
10480
10489
  printf '%s\n' "$memory_instruction"
10481
10490
  printf '%s\n' "$usage_doc_instruction"
10482
10491
  printf '%s\n' "$lsp_grounding_instruction"
10492
+ printf '%s\n' "$agents_md_instruction"
10483
10493
  # For codebase-analysis mode (no PRD), analysis_instruction is part of the
10484
10494
  # static prefix so it remains cache-stable.
10485
10495
  if [ -z "$prd" ]; then
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "7.19.4"
10
+ __version__ = "7.21.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -1,8 +1,8 @@
1
1
  # Loki Mode Installation Guide
2
2
 
3
- The flagship product of [Autonomi](https://www.autonomi.dev/). Complete installation instructions for all platforms and use cases.
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.19.4
5
+ **Version:** v7.21.0
6
6
 
7
7
  ---
8
8
 
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var f8=Object.defineProperty;var u8=($)=>$;function c8($,Q){this[$]=u8.bind(null,Q)}var g=($,Q)=>{for(var Z in Q)f8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:c8.bind(Q,Z)})};var k=($,Q)=>()=>($&&(Q=$($=0)),Q);var X1=import.meta.require;var F$={};g(F$,{lokiDir:()=>P,homeLokiDir:()=>o1,findRepoRootForVersion:()=>d1,REPO_ROOT:()=>f});import{resolve as n,dirname as l1}from"path";import{fileURLToPath as p8}from"url";import{existsSync as L1}from"fs";import{homedir as l8}from"os";function d8(){let $=j$;for(let Q=0;Q<6;Q++){if(L1(n($,"VERSION"))&&L1(n($,"autonomy/run.sh")))return $;let Z=l1($);if(Z===$)break;$=Z}return n(j$,"..","..","..")}function d1($){let Q=$;for(let Z=0;Z<6;Z++){if(L1(n(Q,"VERSION"))&&L1(n(Q,"autonomy/run.sh")))return Q;let z=l1(Q);if(z===Q)break;Q=z}return n($,"..","..","..")}function P(){return process.env.LOKI_DIR??n(process.cwd(),".loki")}function o1(){return n(l8(),".loki")}var j$,f;var y=k(()=>{j$=l1(p8(import.meta.url));f=d8()});import{readFileSync as o8}from"fs";import{resolve as n8,dirname as a8}from"path";import{fileURLToPath as s8}from"url";function k1(){if($1!==null)return $1;let $="7.19.4";if(typeof $==="string"&&$.length>0)return $1=$,$1;try{let Q=a8(s8(import.meta.url)),Z=d1(Q);$1=o8(n8(Z,"VERSION"),"utf-8").trim()}catch{$1="unknown"}return $1}var $1=null;var n1=k(()=>{y()});var E$={};g(E$,{runOrThrow:()=>t8,run:()=>j,commandVersion:()=>i8,commandExists:()=>v,ShellError:()=>a1});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,K;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}K=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[H,X,q]=await Promise.all([new Response(Z.stdout).text(),new Response(Z.stderr).text(),Z.exited]);return{stdout:H,stderr:X,exitCode:q}}finally{if(z)clearTimeout(z);if(K)clearTimeout(K)}}async function t8($,Q={}){let Z=await j($,Q);if(Z.exitCode!==0)throw new a1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function v($){let Q=r8($),Z=await j(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function r8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function i8($,Q="--version"){if(!await v($))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 a1;var d=k(()=>{a1=class a1 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 e8?"":$}var e8,T,N,_,KZ,A,R,h,J;var c=k(()=>{e8=(process.env.NO_COLOR??"").length>0;T=a("\x1B[0;31m"),N=a("\x1B[0;32m"),_=a("\x1B[1;33m"),KZ=a("\x1B[0;34m"),A=a("\x1B[0;36m"),R=a("\x1B[1m"),h=a("\x1B[2m"),J=a("\x1B[0m")});import{existsSync as U7}from"fs";async function Q1(){if(B1!==void 0)return B1;let $="/opt/homebrew/bin/python3.12";if(U7($))return B1=$,$;let Q=await v("python3.12");if(Q)return B1=Q,Q;let Z=await v("python3");return B1=Z,Z}async function Z1($,Q={}){let Z=await Q1();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return j([Z,"-c",$],Q)}var B1;var H1=k(()=>{d()});var d$={};g(d$,{runStatus:()=>N7});import{existsSync as b,readFileSync as q1,readdirSync as v$,statSync as f$}from"fs";import{resolve as D,basename as P7}from"path";import{homedir as L7}from"os";async function j7(){if(await v("jq"))return!0;return process.stdout.write(`${T}Error: jq is required but not installed.${J}
2
+ var f8=Object.defineProperty;var u8=($)=>$;function c8($,Q){this[$]=u8.bind(null,Q)}var g=($,Q)=>{for(var Z in Q)f8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:c8.bind(Q,Z)})};var k=($,Q)=>()=>($&&(Q=$($=0)),Q);var X1=import.meta.require;var F$={};g(F$,{lokiDir:()=>P,homeLokiDir:()=>o1,findRepoRootForVersion:()=>d1,REPO_ROOT:()=>f});import{resolve as n,dirname as l1}from"path";import{fileURLToPath as p8}from"url";import{existsSync as L1}from"fs";import{homedir as l8}from"os";function d8(){let $=j$;for(let Q=0;Q<6;Q++){if(L1(n($,"VERSION"))&&L1(n($,"autonomy/run.sh")))return $;let Z=l1($);if(Z===$)break;$=Z}return n(j$,"..","..","..")}function d1($){let Q=$;for(let Z=0;Z<6;Z++){if(L1(n(Q,"VERSION"))&&L1(n(Q,"autonomy/run.sh")))return Q;let z=l1(Q);if(z===Q)break;Q=z}return n($,"..","..","..")}function P(){return process.env.LOKI_DIR??n(process.cwd(),".loki")}function o1(){return n(l8(),".loki")}var j$,f;var y=k(()=>{j$=l1(p8(import.meta.url));f=d8()});import{readFileSync as o8}from"fs";import{resolve as n8,dirname as a8}from"path";import{fileURLToPath as s8}from"url";function k1(){if($1!==null)return $1;let $="7.21.0";if(typeof $==="string"&&$.length>0)return $1=$,$1;try{let Q=a8(s8(import.meta.url)),Z=d1(Q);$1=o8(n8(Z,"VERSION"),"utf-8").trim()}catch{$1="unknown"}return $1}var $1=null;var n1=k(()=>{y()});var E$={};g(E$,{runOrThrow:()=>t8,run:()=>j,commandVersion:()=>i8,commandExists:()=>v,ShellError:()=>a1});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,K;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}K=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[H,X,q]=await Promise.all([new Response(Z.stdout).text(),new Response(Z.stderr).text(),Z.exited]);return{stdout:H,stderr:X,exitCode:q}}finally{if(z)clearTimeout(z);if(K)clearTimeout(K)}}async function t8($,Q={}){let Z=await j($,Q);if(Z.exitCode!==0)throw new a1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function v($){let Q=r8($),Z=await j(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function r8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function i8($,Q="--version"){if(!await v($))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 a1;var d=k(()=>{a1=class a1 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 e8?"":$}var e8,T,N,_,KZ,A,R,h,J;var c=k(()=>{e8=(process.env.NO_COLOR??"").length>0;T=a("\x1B[0;31m"),N=a("\x1B[0;32m"),_=a("\x1B[1;33m"),KZ=a("\x1B[0;34m"),A=a("\x1B[0;36m"),R=a("\x1B[1m"),h=a("\x1B[2m"),J=a("\x1B[0m")});import{existsSync as U7}from"fs";async function Q1(){if(B1!==void 0)return B1;let $="/opt/homebrew/bin/python3.12";if(U7($))return B1=$,$;let Q=await v("python3.12");if(Q)return B1=Q,Q;let Z=await v("python3");return B1=Z,Z}async function Z1($,Q={}){let Z=await Q1();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return j([Z,"-c",$],Q)}var B1;var H1=k(()=>{d()});var d$={};g(d$,{runStatus:()=>N7});import{existsSync as b,readFileSync as q1,readdirSync as v$,statSync as f$}from"fs";import{resolve as D,basename as P7}from"path";import{homedir as L7}from"os";async function j7(){if(await v("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)
@@ -787,4 +787,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
787
787
  `),2}default:return process.stderr.write(`Unknown command: ${Q}
788
788
  `),process.stderr.write(v8),2}}g$();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var l3=await p3(Bun.argv.slice(2));process.exit(l3);
789
789
 
790
- //# debugId=2A6844500BDB683A64756E2164756E21
790
+ //# debugId=C58800C688F6E31C64756E2164756E21
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '7.19.4'
60
+ __version__ = '7.21.0'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "7.19.4",
3
+ "version": "7.21.0",
4
4
  "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).",
5
5
  "keywords": [
6
6
  "agent",