loki-mode 7.115.0 → 7.116.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/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.115.0
6
+ # Loki Mode v7.116.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.115.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
411
+ **v7.116.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 7.115.0
1
+ 7.116.0
package/autonomy/run.sh CHANGED
@@ -1668,7 +1668,7 @@ _loki_trust_run_id() {
1668
1668
  # Args: $1 = the new phase value (REASONING, BUILDING, VERIFYING, COMPLETED, etc.)
1669
1669
  _advance_current_phase() {
1670
1670
  local new_phase="${1:?phase required}"
1671
- local loki_dir="${LOKI_DIR:-${TARGET_DIR:-.}}/.loki"
1671
+ local loki_dir="${LOKI_DIR:-${TARGET_DIR:-.}/.loki}"
1672
1672
  local orch="$loki_dir/state/orchestrator.json"
1673
1673
  [ -f "$orch" ] || return 0
1674
1674
  # Values are passed via argv (not interpolated into the source) so a phase or
@@ -9159,6 +9159,51 @@ sys.stdout.write(t.strip())
9159
9159
  details="cargo test: $(echo "$output" | tail -3 | tr '\n' ' ')"
9160
9160
  fi
9161
9161
 
9162
+ # node --test (built-in Node test runner) -- config-less fallback (task #79).
9163
+ # Node's built-in runner (stable since Node 18) runs *.test.{js,mjs,cjs}
9164
+ # with ZERO config and NO package.json. A deliverable of slug.js +
9165
+ # slug.test.js (a real, passing suite) previously fell straight through to
9166
+ # runner="none" and recorded verification_gap="source_without_tests" -- a
9167
+ # FALSE-NEGATIVE trust defect (symmetric to fake-green): genuinely-correct,
9168
+ # fully-tested work read as NOT VERIFIED. This branch fires ONLY as a
9169
+ # fallback below every explicit-framework path (vitest/jest/mocha/scripts.test
9170
+ # via package.json, monorepo, pytest, go, cargo all gate on
9171
+ # test_runner=="none"), so package.json-with-jest still selects jest. It runs
9172
+ # only when node is on PATH AND *.test.{js,mjs,cjs} files exist at root or
9173
+ # under test/ or tests/. A failing suite records test_passed=false (never
9174
+ # swallowed); absence of node or test files falls through to the honest
9175
+ # "none"/inconclusive path below (never fabricates a pass).
9176
+ if [ "$test_runner" = "none" ] && command -v node &>/dev/null; then
9177
+ local _nt_files=()
9178
+ local _nt_f
9179
+ # Root-level test files (maxdepth 1) plus test/ and tests/ dirs, skipping
9180
+ # vendored trees so we never walk node_modules.
9181
+ while IFS= read -r _nt_f; do
9182
+ [ -n "$_nt_f" ] && _nt_files+=("$_nt_f")
9183
+ done < <(find "${TARGET_DIR:-.}" -maxdepth 1 -type f \
9184
+ \( -name '*.test.js' -o -name '*.test.mjs' -o -name '*.test.cjs' \) \
9185
+ 2>/dev/null)
9186
+ for _nt_dir in test tests; do
9187
+ [ -d "${TARGET_DIR:-.}/$_nt_dir" ] || continue
9188
+ while IFS= read -r _nt_f; do
9189
+ [ -n "$_nt_f" ] && _nt_files+=("$_nt_f")
9190
+ done < <(find "${TARGET_DIR:-.}/$_nt_dir" -maxdepth 3 -type f \
9191
+ \( -name '*.test.js' -o -name '*.test.mjs' -o -name '*.test.cjs' \) \
9192
+ -not -path '*/node_modules/*' 2>/dev/null)
9193
+ done
9194
+ if [ "${#_nt_files[@]}" -gt 0 ]; then
9195
+ test_runner="node-test"
9196
+ local output
9197
+ # Pass matched files explicitly (node --test globbing is
9198
+ # Node-version-sensitive); quote each so paths with spaces survive.
9199
+ output=$(cd "${TARGET_DIR:-.}" && timeout "${LOKI_GATE_TIMEOUT:-300}" \
9200
+ node --test "${_nt_files[@]}" 2>&1) || test_passed=false
9201
+ # tail -14 so node's TAP summary block (# tests / # pass N / # fail N,
9202
+ # ~10 lines) survives truncation for the best-effort count parse below.
9203
+ details="node --test: $(echo "$output" | tail -14 | tr '\n' ' ')"
9204
+ fi
9205
+ fi
9206
+
9162
9207
  if [ "$test_runner" = "none" ]; then
9163
9208
  log_info "Test coverage: no test runner detected, recording inconclusive (not pass)"
9164
9209
  # v7.41.x fail-open fix: previously this wrote pass:true, so a project
@@ -9258,6 +9303,10 @@ TREOF
9258
9303
  local _tr_passed_n _tr_failed_n
9259
9304
  _tr_passed_n=$(printf '%s' "$details" | grep -oE '[0-9]+ passed' | grep -oE '[0-9]+' | head -1)
9260
9305
  _tr_failed_n=$(printf '%s' "$details" | grep -oE '[0-9]+ failed' | grep -oE '[0-9]+' | head -1)
9306
+ # node --test emits TAP-ish "# pass N" / "# fail N" summary lines, which the
9307
+ # "N passed"/"N failed" pattern above does not match. Fall back to those.
9308
+ [ -n "$_tr_passed_n" ] || _tr_passed_n=$(printf '%s' "$details" | grep -oE '# pass [0-9]+' | grep -oE '[0-9]+' | head -1)
9309
+ [ -n "$_tr_failed_n" ] || _tr_failed_n=$(printf '%s' "$details" | grep -oE '# fail [0-9]+' | grep -oE '[0-9]+' | head -1)
9261
9310
  [ -n "$_tr_passed_n" ] || _tr_passed_n=null
9262
9311
  [ -n "$_tr_failed_n" ] || _tr_failed_n=null
9263
9312
 
@@ -19316,7 +19365,7 @@ main() {
19316
19365
  # engine's own is_completed() recognise this session as terminal. Write the
19317
19366
  # file-system COMPLETED marker (checked by is_completed() in the main loop).
19318
19367
  _advance_current_phase "COMPLETED"
19319
- local loki_dir="${LOKI_DIR:-${TARGET_DIR:-.}}/.loki"
19368
+ local loki_dir="${LOKI_DIR:-${TARGET_DIR:-.}/.loki}"
19320
19369
  echo "Session completed at $(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$loki_dir/COMPLETED" 2>/dev/null || true
19321
19370
 
19322
19371
  # Finish-and-own (v7.88.0): write a plain-English ownership handoff
@@ -383,6 +383,41 @@ verify_gate_tests() {
383
383
  fi
384
384
  fi
385
385
 
386
+ # node --test (built-in Node runner) -- config-less fallback (task #79).
387
+ # Node's built-in test runner (stable since Node 18) runs
388
+ # *.test.{js,mjs,cjs} with ZERO config and NO package.json, so a real
389
+ # passing suite (slug.js + slug.test.js, no package.json) previously fell
390
+ # through to runner="none" -> tests "skipped" -- a FALSE-NEGATIVE on the
391
+ # verdict surface (symmetric to fake-green). This branch fires ONLY below
392
+ # the explicit-framework paths (vitest/jest/mocha via package.json all set
393
+ # runner above), so package.json-with-jest still selects jest. Runs only
394
+ # when node is on PATH AND *.test.{js,mjs,cjs} exist at root or under
395
+ # test/ or tests/. A FAILING run records fail (never swallowed); absence of
396
+ # node or test files falls through to the honest "skipped" path below.
397
+ if [ "$runner" = "none" ] && command -v node >/dev/null 2>&1; then
398
+ local _nt_files=()
399
+ local _nt_f _nt_dir
400
+ while IFS= read -r _nt_f; do
401
+ [ -n "$_nt_f" ] && _nt_files+=("$_nt_f")
402
+ done < <(find "$tree" -maxdepth 1 -type f \
403
+ \( -name '*.test.js' -o -name '*.test.mjs' -o -name '*.test.cjs' \) \
404
+ 2>/dev/null)
405
+ for _nt_dir in test tests; do
406
+ [ -d "$tree/$_nt_dir" ] || continue
407
+ while IFS= read -r _nt_f; do
408
+ [ -n "$_nt_f" ] && _nt_files+=("$_nt_f")
409
+ done < <(find "$tree/$_nt_dir" -maxdepth 3 -type f \
410
+ \( -name '*.test.js' -o -name '*.test.mjs' -o -name '*.test.cjs' \) \
411
+ -not -path '*/node_modules/*' 2>/dev/null)
412
+ done
413
+ if [ "${#_nt_files[@]}" -gt 0 ]; then
414
+ runner="node-test"
415
+ # Pass matched files explicitly (node --test globbing is
416
+ # Node-version-sensitive); quote each so paths with spaces survive.
417
+ out="$(cd "$tree" && timeout "$timeout_s" node --test "${_nt_files[@]}" 2>&1)" || rc=$?
418
+ fi
419
+ fi
420
+
386
421
  if [ "$runner" = "none" ]; then
387
422
  _verify_add_gate "tests" "skipped" "" "no test framework detected" "true"
388
423
  return 0
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "7.115.0"
10
+ __version__ = "7.116.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -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.115.0
5
+ **Version:** v7.116.0
6
6
 
7
7
  ---
8
8
 
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var q8=Object.defineProperty;var J8=($)=>$;function V8($,Q){this[$]=J8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)q8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:V8.bind(Q,Z)})};var P=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var m1={};b(m1,{lokiDir:()=>j,homeLokiDir:()=>T$,findRepoRootForVersion:()=>$1,REPO_ROOT:()=>h});import{resolve as t,dirname as e$}from"path";import{fileURLToPath as W8}from"url";import{existsSync as N$}from"fs";import{homedir as H8}from"os";function G8(){let $=v1;for(let Q=0;Q<6;Q++){if(N$(t($,"VERSION"))&&N$(t($,"autonomy/run.sh")))return $;let Z=e$($);if(Z===$)break;$=Z}return t(v1,"..","..","..")}function $1($){let Q=$;for(let Z=0;Z<6;Z++){if(N$(t(Q,"VERSION"))&&N$(t(Q,"autonomy/run.sh")))return Q;let z=e$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function j(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(H8(),".loki")}var v1,h;var C=P(()=>{v1=e$(W8(import.meta.url));h=G8()});import{readFileSync as U8}from"fs";import{resolve as Y8,dirname as B8}from"path";import{fileURLToPath as M8}from"url";function S$(){if(Q$!==null)return Q$;let $="7.115.0";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=B8(M8(import.meta.url)),Z=$1(Q);Q$=U8(Y8(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var Q1=P(()=>{C()});var p1={};b(p1,{runOrThrow:()=>S8,run:()=>R,readStreamCapped:()=>c1,commandVersion:()=>C8,commandExists:()=>u,ShellError:()=>Z1,MAX_STDOUT_BYTES:()=>u1});async function c1($,Q=u1){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 R($,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([c1(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 S8($,Q={}){let Z=await R($,Q);if(Z.exitCode!==0)throw new Z1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function u($){let Q=D8($),Z=await R(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function D8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function C8($,Q="--version"){if(!await u($))return null;let z=await R([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var u1=16777216,Z1;var o=P(()=>{Z1=class Z1 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 b8?"":$}var b8,M,S,_,tZ,L,k,y,J;var p=P(()=>{b8=(process.env.NO_COLOR??"").length>0;M=r("\x1B[0;31m"),S=r("\x1B[0;32m"),_=r("\x1B[1;33m"),tZ=r("\x1B[0;34m"),L=r("\x1B[0;36m"),k=r("\x1B[1m"),y=r("\x1B[2m"),J=r("\x1B[0m")});import{existsSync as l8}from"fs";async function Z$(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(l8($))return A$=$,$;let Q=await u("python3.12");if(Q)return A$=Q,Q;let Z=await u("python3");return A$=Z,Z}async function z$($,Q={}){let Z=await Z$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return R([Z,"-c",$],Q)}var A$;var V$=P(()=>{o()});var V0={};b(V0,{runStatus:()=>U3});import{existsSync as v,readFileSync as H$,readdirSync as $0,statSync as Q0}from"fs";import{resolve as D,basename as z3}from"path";import{homedir as X3}from"os";function Z0($){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 z0($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*C$/Q);if(X>C$)X=C$;let q=C$-X,K=S;if(z>=80)K=M;else if(z>=50)K=_;let W="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),V=Z0($),H=Z0(Q);return` ${k}${Z}${J} ${K}[${W}]${J} ${z}% (${V} / ${H})`}async function q3(){if(await u("jq"))return!0;return process.stdout.write(`${M}Error: jq is required but not installed.${J}
2
+ var q8=Object.defineProperty;var J8=($)=>$;function V8($,Q){this[$]=J8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)q8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:V8.bind(Q,Z)})};var P=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var m1={};b(m1,{lokiDir:()=>j,homeLokiDir:()=>T$,findRepoRootForVersion:()=>$1,REPO_ROOT:()=>h});import{resolve as t,dirname as e$}from"path";import{fileURLToPath as W8}from"url";import{existsSync as N$}from"fs";import{homedir as H8}from"os";function G8(){let $=v1;for(let Q=0;Q<6;Q++){if(N$(t($,"VERSION"))&&N$(t($,"autonomy/run.sh")))return $;let Z=e$($);if(Z===$)break;$=Z}return t(v1,"..","..","..")}function $1($){let Q=$;for(let Z=0;Z<6;Z++){if(N$(t(Q,"VERSION"))&&N$(t(Q,"autonomy/run.sh")))return Q;let z=e$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function j(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(H8(),".loki")}var v1,h;var C=P(()=>{v1=e$(W8(import.meta.url));h=G8()});import{readFileSync as U8}from"fs";import{resolve as Y8,dirname as B8}from"path";import{fileURLToPath as M8}from"url";function S$(){if(Q$!==null)return Q$;let $="7.116.0";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=B8(M8(import.meta.url)),Z=$1(Q);Q$=U8(Y8(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var Q1=P(()=>{C()});var p1={};b(p1,{runOrThrow:()=>S8,run:()=>R,readStreamCapped:()=>c1,commandVersion:()=>C8,commandExists:()=>u,ShellError:()=>Z1,MAX_STDOUT_BYTES:()=>u1});async function c1($,Q=u1){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 R($,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([c1(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 S8($,Q={}){let Z=await R($,Q);if(Z.exitCode!==0)throw new Z1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function u($){let Q=D8($),Z=await R(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function D8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function C8($,Q="--version"){if(!await u($))return null;let z=await R([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var u1=16777216,Z1;var o=P(()=>{Z1=class Z1 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 b8?"":$}var b8,M,S,_,tZ,L,k,y,J;var p=P(()=>{b8=(process.env.NO_COLOR??"").length>0;M=r("\x1B[0;31m"),S=r("\x1B[0;32m"),_=r("\x1B[1;33m"),tZ=r("\x1B[0;34m"),L=r("\x1B[0;36m"),k=r("\x1B[1m"),y=r("\x1B[2m"),J=r("\x1B[0m")});import{existsSync as l8}from"fs";async function Z$(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(l8($))return A$=$,$;let Q=await u("python3.12");if(Q)return A$=Q,Q;let Z=await u("python3");return A$=Z,Z}async function z$($,Q={}){let Z=await Z$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return R([Z,"-c",$],Q)}var A$;var V$=P(()=>{o()});var V0={};b(V0,{runStatus:()=>U3});import{existsSync as v,readFileSync as H$,readdirSync as $0,statSync as Q0}from"fs";import{resolve as D,basename as z3}from"path";import{homedir as X3}from"os";function Z0($){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 z0($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*C$/Q);if(X>C$)X=C$;let q=C$-X,K=S;if(z>=80)K=M;else if(z>=50)K=_;let W="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),V=Z0($),H=Z0(Q);return` ${k}${Z}${J} ${K}[${W}]${J} ${z}% (${V} / ${H})`}async function q3(){if(await u("jq"))return!0;return process.stdout.write(`${M}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)
@@ -814,4 +814,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
814
814
  `),2}default:return process.stderr.write(`Unknown command: ${Q}
815
815
  `),process.stderr.write(K8),2}}e1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var SZ=await NZ(Bun.argv.slice(2));process.exit(SZ);
816
816
 
817
- //# debugId=7679240CF905E39B64756E2164756E21
817
+ //# debugId=30F27BA7342E3CAE64756E2164756E21
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '7.115.0'
60
+ __version__ = '7.116.0'
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.115.0",
4
+ "version": "7.116.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.115.0",
5
+ "version": "7.116.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",