loki-mode 7.122.1 → 7.123.1

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.122.1
6
+ # Loki Mode v7.123.1
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.122.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
411
+ **v7.123.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 7.122.1
1
+ 7.123.1
@@ -1184,9 +1184,34 @@ EVIDENCE_SECTION
1184
1184
  echo "## PRD Checklist Verification Results" >> "$evidence_file"
1185
1185
  cat ".loki/checklist/verification-results.json" >> "$evidence_file" 2>/dev/null || true
1186
1186
  else
1187
+ # Scope honesty (rec #5): a missing checklist is not neutral -- it means
1188
+ # "done" cannot be verified against derived acceptance criteria on this
1189
+ # run. Say so explicitly so a council member weights their vote on the
1190
+ # OTHER evidence (tests, diff, build) rather than reading silence as a
1191
+ # pass. Distinguish "a spec exists but yielded no checklist" (a real
1192
+ # scope-honesty concern -- the criteria were underivable) from "no spec
1193
+ # was provided" (a one-line brief; checklist absence is expected, not a
1194
+ # gap). Never fabricate coverage that does not exist.
1187
1195
  echo "" >> "$evidence_file"
1188
1196
  echo "## PRD Checklist Verification Results" >> "$evidence_file"
1189
- echo "No PRD checklist has been created yet." >> "$evidence_file"
1197
+ local _has_spec="no"
1198
+ if [ -n "$prd_path" ] && [ -f "$prd_path" ]; then
1199
+ _has_spec="yes"
1200
+ elif [ -f ".loki/prd.md" ] || [ -f ".loki/spec/spec.md" ]; then
1201
+ _has_spec="yes"
1202
+ fi
1203
+ if [ "$_has_spec" = "yes" ]; then
1204
+ echo "SCOPE-HONESTY: A spec/PRD is present but NO checklist of" \
1205
+ "acceptance criteria was derived from it. \"Done\" cannot be" \
1206
+ "verified against explicit criteria on this run -- treat" \
1207
+ "completion as UNVERIFIED-BY-CHECKLIST and rely on the other" \
1208
+ "evidence below (tests, diff, build). Do not read the absence" \
1209
+ "of a checklist as a pass." >> "$evidence_file"
1210
+ else
1211
+ echo "No PRD checklist has been created yet (no spec/PRD provided;" \
1212
+ "checklist-based completion criteria are not applicable to this" \
1213
+ "run). Completion rests on the other evidence below." >> "$evidence_file"
1214
+ fi
1190
1215
  fi
1191
1216
 
1192
1217
  # Playwright smoke test results (v5.46.0 - advisory only)
@@ -112,6 +112,9 @@ _verify_render_explain() {
112
112
  "${VERIFY_BASE_REF:-?}"
113
113
  printf 'Evidence freshness: run %s -> %s (this run; gates re-executed now)\n' \
114
114
  "$started_at" "$completed_at"
115
+ printf 'Graded tree: HEAD %s, worktree %s. Re-check later with: loki verify --check-fresh\n' \
116
+ "${VERIFY_HEAD_SHA:0:12}" \
117
+ "$([ "${VERIFY_WORKTREE_CLEAN:-}" = "true" ] && echo "clean" || echo "had uncommitted changes")"
115
118
  printf '\n'
116
119
  printf ' %-18s %-12s %-14s %-6s %s\n' "GATE" "STATUS" "RUNNER" "REPRO" "EVIDENCE"
117
120
  printf ' %-18s %-12s %-14s %-6s %s\n' "----" "------" "------" "-----" "--------"
@@ -1669,6 +1672,7 @@ verify_emit_evidence() {
1669
1672
  _V_TOOLVER="$tool_version" \
1670
1673
  _V_REPO="$repo_name" \
1671
1674
  _V_HEAD="${VERIFY_HEAD_SHA:-}" \
1675
+ _V_WT_CLEAN="${VERIFY_WORKTREE_CLEAN:-}" \
1672
1676
  _V_BASE="${VERIFY_BASE_REF:-}" \
1673
1677
  _V_MB="${VERIFY_MERGE_BASE:-}" \
1674
1678
  _V_FILES="${VERIFY_DIFF_FILES:-0}" \
@@ -1741,6 +1745,7 @@ doc = {
1741
1745
  "repo": os.environ["_V_REPO"],
1742
1746
  "pr_number": None,
1743
1747
  "head_sha": os.environ["_V_HEAD"],
1748
+ "worktree_clean_at_grade": (os.environ.get("_V_WT_CLEAN") == "true"),
1744
1749
  "base_branch": os.environ["_V_BASE"],
1745
1750
  "merge_base_sha": os.environ["_V_MB"],
1746
1751
  "diff_stats": {
@@ -1908,6 +1913,14 @@ OPTIONS:
1908
1913
  produced the evidence, whether it is reproducible, plus
1909
1914
  freshness and the diff graded. Additive render before the
1910
1915
  VERDICT banner; never changes the verdict or exit code.
1916
+ --check-fresh Do NOT re-run gates. Read a prior <out>/evidence.json and
1917
+ decide whether its verdict still applies to the CURRENT
1918
+ repo. FRESH (0) when the graded head_sha matches HEAD and
1919
+ the worktree is clean (ignoring .loki/); STALE (2) when
1920
+ HEAD drifted or the tree changed; ERROR (3) when evidence
1921
+ is missing/unparseable. Fail-closed: stale or unreadable
1922
+ evidence never reports FRESH. For CI / proof consumers that
1923
+ must not trust a cached green after the code moved on.
1911
1924
  --hosted Opt-in. When the embedded Autonomi Verify engine is
1912
1925
  usable (bun present + bundle present), fold its verdict
1913
1926
  fields into evidence.json under a "hosted" key. Additive
@@ -2353,6 +2366,102 @@ PYEOF
2353
2366
  return 0
2354
2367
  }
2355
2368
 
2369
+ # Worktree dirtiness for freshness purposes, EXCLUDING verify's own output
2370
+ # directory (.loki/). `git status --porcelain` lists every change one per line;
2371
+ # we drop any path under .loki/ so evidence.json/report.md written by this very
2372
+ # run never register as code drift. Emits the filtered porcelain (empty = clean).
2373
+ _verify_dirty_porcelain() {
2374
+ git status --porcelain 2>/dev/null | grep -v -E '(^|[[:space:]])"?\.loki/' || true
2375
+ }
2376
+
2377
+ # ---------------------------------------------------------------------------
2378
+ # Freshness gate (--check-fresh)
2379
+ # ---------------------------------------------------------------------------
2380
+ # Reads a prior <out>/evidence.json and decides whether the verdict it records
2381
+ # still applies to the CURRENT repo state. This is the consumer-side half of the
2382
+ # trust contract: --explain shows WHAT the evidence is; --check-fresh proves it
2383
+ # is CURRENT before anyone trusts a stored green.
2384
+ #
2385
+ # Fail-closed, always:
2386
+ # fresh (graded head_sha == current HEAD, worktree clean) -> VERIFIED (0)
2387
+ # drifted (HEAD moved) or worktree dirty -> BLOCKED (2)
2388
+ # evidence missing / unparseable / no head_sha / not in a repo-> ERROR (3)
2389
+ # A stale or unreadable evidence document NEVER yields VERIFIED. The whole point
2390
+ # is that "it passed once" is not "it passes now".
2391
+ _verify_check_fresh() {
2392
+ local out_dir="$1"
2393
+ local ev_path="$out_dir/evidence.json"
2394
+
2395
+ if [ ! -f "$ev_path" ]; then
2396
+ _verify_err "no evidence at $ev_path; run 'loki verify' first (fail-closed)"
2397
+ VERIFY_VERDICT="ERROR"; VERIFY_EXIT=$VERIFY_EXIT_ERROR
2398
+ printf 'VERDICT: NOT FRESH (no evidence)\n'
2399
+ return $VERIFY_EXIT_ERROR
2400
+ fi
2401
+
2402
+ local cur_head cur_dirty
2403
+ cur_head="$(git rev-parse HEAD 2>/dev/null || echo "")"
2404
+ if [ -z "$cur_head" ]; then
2405
+ _verify_err "not inside a git repository; cannot check freshness (fail-closed)"
2406
+ VERIFY_VERDICT="ERROR"; VERIFY_EXIT=$VERIFY_EXIT_ERROR
2407
+ printf 'VERDICT: NOT FRESH (no git HEAD)\n'
2408
+ return $VERIFY_EXIT_ERROR
2409
+ fi
2410
+ # Any tracked-or-untracked change means the graded tree is not the live tree.
2411
+ # Exclude .loki/ -- verify writes its own evidence.json/report.md there, so
2412
+ # counting it would make every run report its own output as drift.
2413
+ if [ -n "$(_verify_dirty_porcelain)" ]; then
2414
+ cur_dirty="true"
2415
+ else
2416
+ cur_dirty="false"
2417
+ fi
2418
+
2419
+ # Parse the graded head_sha out of the evidence document. python3 is the same
2420
+ # dependency the emitter uses; a parse failure is fail-closed (ERROR).
2421
+ local graded_head parse_rc
2422
+ graded_head="$(_VF_EV="$ev_path" python3 - <<'PYEOF' 2>/dev/null
2423
+ import json, os, sys
2424
+ try:
2425
+ doc = json.load(open(os.environ["_VF_EV"]))
2426
+ print((doc.get("subject") or {}).get("head_sha") or "")
2427
+ except Exception:
2428
+ sys.exit(1)
2429
+ PYEOF
2430
+ )"
2431
+ parse_rc=$?
2432
+ if [ "$parse_rc" -ne 0 ]; then
2433
+ _verify_err "evidence.json unparseable at $ev_path (fail-closed)"
2434
+ VERIFY_VERDICT="ERROR"; VERIFY_EXIT=$VERIFY_EXIT_ERROR
2435
+ printf 'VERDICT: NOT FRESH (unparseable evidence)\n'
2436
+ return $VERIFY_EXIT_ERROR
2437
+ fi
2438
+ if [ -z "$graded_head" ]; then
2439
+ _verify_err "evidence.json has no subject.head_sha (fail-closed)"
2440
+ VERIFY_VERDICT="ERROR"; VERIFY_EXIT=$VERIFY_EXIT_ERROR
2441
+ printf 'VERDICT: NOT FRESH (evidence records no graded head_sha)\n'
2442
+ return $VERIFY_EXIT_ERROR
2443
+ fi
2444
+
2445
+ if [ "$graded_head" != "$cur_head" ]; then
2446
+ _verify_log "freshness: HEAD drifted ${graded_head:0:12} -> ${cur_head:0:12}"
2447
+ VERIFY_VERDICT="BLOCKED"; VERIFY_EXIT=$VERIFY_EXIT_BLOCKED
2448
+ printf 'VERDICT: STALE (graded %s, now %s) -- re-run loki verify\n' \
2449
+ "${graded_head:0:12}" "${cur_head:0:12}"
2450
+ return $VERIFY_EXIT_BLOCKED
2451
+ fi
2452
+ if [ "$cur_dirty" = "true" ]; then
2453
+ _verify_log "freshness: worktree dirty since grade"
2454
+ VERIFY_VERDICT="BLOCKED"; VERIFY_EXIT=$VERIFY_EXIT_BLOCKED
2455
+ printf 'VERDICT: STALE (worktree modified since %s) -- re-run loki verify\n' \
2456
+ "${graded_head:0:12}"
2457
+ return $VERIFY_EXIT_BLOCKED
2458
+ fi
2459
+
2460
+ VERIFY_VERDICT="VERIFIED"; VERIFY_EXIT=$VERIFY_EXIT_VERIFIED
2461
+ printf 'VERDICT: FRESH (evidence matches HEAD %s, clean worktree)\n' "${cur_head:0:12}"
2462
+ return $VERIFY_EXIT_VERIFIED
2463
+ }
2464
+
2356
2465
  # ---------------------------------------------------------------------------
2357
2466
  # Entry point
2358
2467
  # ---------------------------------------------------------------------------
@@ -2365,6 +2474,10 @@ verify_main() {
2365
2474
  VERIFY_HOSTED_SUMMARY=""
2366
2475
  # Opt-in one-screen trust-proof render (--explain). Default 0 = exactly today.
2367
2476
  VERIFY_EXPLAIN=0
2477
+ # Opt-in freshness gate (--check-fresh). Default 0 = exactly today. When set,
2478
+ # verify does NOT re-run gates: it reads a prior evidence.json and fails
2479
+ # closed if the repo has drifted since that evidence was graded.
2480
+ VERIFY_CHECK_FRESH=0
2368
2481
 
2369
2482
  # Fail-closed defaults. These globals are read at the end of this function
2370
2483
  # (the VERDICT banner and the function return code). verify_compute_verdict()
@@ -2398,6 +2511,18 @@ verify_main() {
2398
2511
  # unchanged. This is the "why you can trust this" surface -- Loki
2399
2512
  # runs more verification than competitors but proved it worse.
2400
2513
  VERIFY_EXPLAIN=1; shift ;;
2514
+ --check-fresh)
2515
+ # Freshness gate for CONSUMERS of a prior verify run (CI, proof
2516
+ # share, a council reading a cached green). Does NOT re-run gates:
2517
+ # reads <out>/evidence.json and fails CLOSED if the current repo
2518
+ # HEAD differs from the graded head_sha, or the worktree is dirty,
2519
+ # or the evidence is missing/unparseable. A stored VERIFIED that
2520
+ # no longer matches the code it was graded against is not trust --
2521
+ # it is a stale cache, and trusting it is exactly the fake-green
2522
+ # the moat forbids. Fresh -> exit 0; drifted -> exit 2 (BLOCKED);
2523
+ # missing/unreadable -> exit 3 (ERROR). Never prints VERIFIED for
2524
+ # stale evidence.
2525
+ VERIFY_CHECK_FRESH=1; shift ;;
2401
2526
  --hosted)
2402
2527
  # Opt-in: when the embedded Autonomi Verify engine is usable
2403
2528
  # (bun present + bundle present), enrich evidence.json with the
@@ -2442,6 +2567,24 @@ verify_main() {
2442
2567
  # Still emit an evidence doc with inconclusive verdict (never silent pass).
2443
2568
  fi
2444
2569
 
2570
+ # --check-fresh short-circuits BEFORE any gate runs: it is a pure freshness
2571
+ # gate over a prior evidence.json, not a verification. Dispatch here so it
2572
+ # never spawns runners/scanners and never rewrites the evidence document.
2573
+ if [ "${VERIFY_CHECK_FRESH:-0}" = "1" ]; then
2574
+ _verify_check_fresh "$out_dir"
2575
+ return $?
2576
+ fi
2577
+
2578
+ # Record the worktree state at grade time so a later --check-fresh (and any
2579
+ # external consumer) knows whether this evidence was graded against a clean
2580
+ # tree. Empty porcelain output = clean. Best-effort; defaults to unknown-safe
2581
+ # "false" (treated as not-clean) if git cannot answer.
2582
+ if [ -z "$(_verify_dirty_porcelain)" ] && git rev-parse HEAD >/dev/null 2>&1; then
2583
+ VERIFY_WORKTREE_CLEAN="true"
2584
+ else
2585
+ VERIFY_WORKTREE_CLEAN="false"
2586
+ fi
2587
+
2445
2588
  _VERIFY_FINDINGS_FILE="$(mktemp -t loki-verify-findings.XXXXXX)" || { _verify_err "mktemp failed"; return $VERIFY_EXIT_ERROR; }
2446
2589
  _VERIFY_GATES_FILE="$(mktemp -t loki-verify-gates.XXXXXX)" || { _verify_err "mktemp failed"; return $VERIFY_EXIT_ERROR; }
2447
2590
  # shellcheck disable=SC2064
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "7.122.1"
10
+ __version__ = "7.123.1"
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.122.1
5
+ **Version:** v7.123.1
6
6
 
7
7
  ---
8
8
 
@@ -396,7 +396,7 @@ provider works inside the container. Provide auth with your Anthropic API key:
396
396
  # Run Loki Mode in Docker (Claude provider, API-key auth)
397
397
  docker run --rm -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
398
398
  -v $(pwd):/workspace -w /workspace \
399
- asklokesh/loki-mode:7.122.1 start ./my-spec.md
399
+ asklokesh/loki-mode:7.123.1 start ./my-spec.md
400
400
  ```
401
401
 
402
402
  ##### docker compose + .env (no host install)
@@ -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.122.1";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.123.1";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=EB9A5D1CD7D5B98164756E2164756E21
817
+ //# debugId=55CB80637F3CD12064756E2164756E21
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '7.122.1'
60
+ __version__ = '7.123.1'
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.122.1",
4
+ "version": "7.123.1",
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.122.1",
5
+ "version": "7.123.1",
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",