loki-mode 8.0.2 → 8.0.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 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 v8.0.2
6
+ # Loki Mode v8.0.3
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -469,4 +469,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
469
469
 
470
470
  ---
471
471
 
472
- **v8.0.2 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
472
+ **v8.0.3 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 8.0.2
1
+ 8.0.3
@@ -624,12 +624,29 @@
624
624
  } else {
625
625
  gaps = '<p class="h-sub" style="margin-top:10px;">No gaps were flagged for this run.</p>';
626
626
  }
627
+ // Why the run stopped. The generator already collects facts.termination
628
+ // facts.execution (reason / outcome / run_status) but nothing rendered it,
629
+ // so a receipt for
630
+ // a run that stopped on a gate showed a headline with no cause -- the reader
631
+ // could see the verdict and not the reason for it. Display-only: the value
632
+ // is whatever the generator recorded, never recomputed here.
633
+ var term = "";
634
+ var tReason = String(g(p, "facts.execution.reason", "") || "").trim();
635
+ var tOutcome = String(g(p, "facts.execution.outcome", "") || "").trim();
636
+ if (tReason || (tOutcome && tOutcome !== "complete")) {
637
+ term = '<div class="h-sub">Stopped: ' +
638
+ esc(tReason || tOutcome) +
639
+ (tReason && tOutcome && tOutcome !== tReason
640
+ ? " (" + esc(tOutcome) + ")" : "") +
641
+ "</div>";
642
+ }
627
643
  el.className = "honesty " + v.cls;
628
644
  el.innerHTML =
629
645
  '<span class="h-mark" aria-hidden="true">' + v.mark + "</span>" +
630
646
  '<div class="h-body">' +
631
647
  '<div class="h-headline">' + esc(headline) + "</div>" +
632
648
  '<div class="h-sub">' + v.sub + "</div>" +
649
+ term +
633
650
  gaps +
634
651
  "</div>";
635
652
  }
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "8.0.2"
10
+ __version__ = "8.0.3"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -679,14 +679,37 @@ async def _push_loki_state_loop() -> None:
679
679
  pass
680
680
 
681
681
  status_str = raw.get("mode", "autonomous")
682
- if not _pid_alive:
683
- status_str = "stopped"
684
- elif status_str == "paused":
685
- status_str = "paused"
686
- elif status_str in ("stopped", ""):
687
- status_str = "stopped"
688
- else:
689
- status_str = "running"
682
+ # Control files are the AUTHORITY, and they are checked
683
+ # first. dashboard-state.json's "mode" is written by the
684
+ # engine and goes stale the moment a run pauses: on a
685
+ # real paused run it still read "autonomous", so this
686
+ # stream reported "running" while /api/status -- which
687
+ # reads .loki/PAUSE -- reported "paused" for the SAME
688
+ # run. Two live surfaces disagreeing about whether a
689
+ # build is running is worse than either being wrong
690
+ # alone, because the user cannot tell which to believe.
691
+ try:
692
+ _ctl = loki_dir
693
+ if (_ctl / "STOP").exists():
694
+ status_str = "stopped"
695
+ elif (_ctl / "PAUSE").exists():
696
+ status_str = "paused"
697
+ elif not _pid_alive:
698
+ status_str = "stopped"
699
+ elif status_str == "paused":
700
+ status_str = "paused"
701
+ elif status_str in ("stopped", ""):
702
+ status_str = "stopped"
703
+ else:
704
+ status_str = "running"
705
+ except (OSError, TypeError, NameError):
706
+ # Never let a control-file read break the stream.
707
+ if not _pid_alive:
708
+ status_str = "stopped"
709
+ elif status_str in ("stopped", ""):
710
+ status_str = "stopped"
711
+ elif status_str != "paused":
712
+ status_str = "running"
690
713
 
691
714
  payload = {
692
715
  "status": status_str,
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var k_=Object.create;var{getPrototypeOf:x_,defineProperty:oK,getOwnPropertyNames:S_}=Object;var y_=Object.prototype.hasOwnProperty;function b_(Z){return this[Z]}var __,f_,h_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?__??=new WeakMap:f_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?k_(x_(Z)):{};let K=X||!Z||!Z.__esModule?oK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of S_(Z))if(!y_.call(K,$))oK(K,$,{get:b_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var VQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var v_=(Z)=>Z;function g_(Z,X){this[Z]=v_.bind(null,X)}var c0=(Z,X)=>{for(var Q in X)oK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:g_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var t0=import.meta.require;var EO={};c0(EO,{lokiDir:()=>j0,homeLokiDir:()=>I4,findRepoRootForVersion:()=>tK,REPO_ROOT:()=>Q8});import{resolve as s7,dirname as rK}from"path";import{fileURLToPath as m_}from"url";import{existsSync as qQ}from"fs";import{homedir as u_}from"os";function p_(){let Z=DO;for(let X=0;X<6;X++){if(qQ(s7(Z,"VERSION"))&&qQ(s7(Z,"autonomy/run.sh")))return Z;let Q=rK(Z);if(Q===Z)break;Z=Q}return s7(DO,"..","..","..")}function tK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(qQ(s7(X,"VERSION"))&&qQ(s7(X,"autonomy/run.sh")))return X;let Y=rK(X);if(Y===X)break;X=Y}return s7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??s7(process.cwd(),".loki")}function I4(){return s7(u_(),".loki")}var DO,Q8;var G8=p(()=>{DO=rK(m_(import.meta.url));Q8=p_()});import{readFileSync as d_}from"fs";import{resolve as c_,dirname as l_}from"path";import{fileURLToPath as i_}from"url";function _3(){if(f5!==null)return f5;let Z="8.0.2";if(typeof Z==="string"&&Z.length>0)return f5=Z,f5;try{let X=l_(i_(import.meta.url)),Q=tK(X);f5=d_(c_(Q,"VERSION"),"utf-8").trim()}catch{f5="unknown"}return f5}var f5=null;var GQ=p(()=>{G8()});var kO={};c0(kO,{runOrThrow:()=>Wf,run:()=>D0,readStreamCapped:()=>HQ,commandVersion:()=>qf,commandExists:()=>H9,ShellError:()=>eK,MAX_STDOUT_BYTES:()=>RO});async function HQ(Z,X=RO){let Q=Z.getReader(),Y=new TextDecoder,J="",z=0;try{while(z<X){let{done:K,value:$}=await Q.read();if(K)break;if(!$)continue;if(z+=$.byteLength,z>X){let W=$.byteLength-(z-X);J+=Y.decode($.subarray(0,W),{stream:!0});break}J+=Y.decode($,{stream:!0})}J+=Y.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function D0(Z,X={}){let Q=Bun.spawn({cmd:[...Z],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),Y,J;if(X.timeoutMs&&X.timeoutMs>0)Y=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[z,K,$]=await Promise.all([HQ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:K,exitCode:$}}finally{if(Y)clearTimeout(Y);if(J)clearTimeout(J)}}async function Wf(Z,X={}){let Q=await D0(Z,X);if(Q.exitCode!==0)throw new eK(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function H9(Z){let X=Vf(Z),Q=await D0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Vf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function qf(Z,X="--version"){if(!await H9(Z))return null;let Y=await D0([Z,X],{timeoutMs:5000});if(Y.exitCode!==0)return null;return((Y.stdout||Y.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var RO=16777216,eK;var k9=p(()=>{eK=class eK extends Error{message;exitCode;stdout;stderr;constructor(Z,X,Q,Y){super(Z);this.message=Z;this.exitCode=X;this.stdout=Q;this.stderr=Y;this.name="ShellError"}}});function n7(Z){return Gf?"":Z}var Gf,M0,k8,l0,gW0,a0,H8,X9,g;var S6=p(()=>{Gf=(process.env.NO_COLOR??"").length>0;M0=n7("\x1B[0;31m"),k8=n7("\x1B[0;32m"),l0=n7("\x1B[1;33m"),gW0=n7("\x1B[0;34m"),a0=n7("\x1B[0;36m"),H8=n7("\x1B[1m"),X9=n7("\x1B[2m"),g=n7("\x1B[0m")});import{existsSync as wf}from"fs";async function F7(){if(R4!==void 0)return R4;let Z="/opt/homebrew/bin/python3.12";if(wf(Z))return R4=Z,Z;let X=await H9("python3.12");if(X)return R4=X,X;let Q=await H9("python3");return R4=Q,Q}async function D7(Z,X={}){let Q=await F7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return D0([Q,"-c",Z],X)}var R4;var o7=p(()=>{k9()});var oO={};c0(oO,{runStatus:()=>of});import{existsSync as Q9,readFileSync as h3,readdirSync as pO,statSync as dO}from"fs";import{resolve as h8,basename as mf}from"path";import{homedir as uf}from"os";function cO(Z){let X=Math.trunc(Z);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function lO(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*BQ/X);if(J>BQ)J=BQ;let z=BQ-J,K=k8;if(Y>=80)K=M0;else if(Y>=50)K=l0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),W=cO(Z),V=cO(X);return` ${H8}${Q}${g} ${K}[${$}]${g} ${Y}% (${W} / ${V})`}async function df(){if(await H9("jq"))return!0;return process.stdout.write(`${M0}Error: jq is required but not installed.${g}
2
+ var k_=Object.create;var{getPrototypeOf:x_,defineProperty:oK,getOwnPropertyNames:S_}=Object;var y_=Object.prototype.hasOwnProperty;function b_(Z){return this[Z]}var __,f_,h_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?__??=new WeakMap:f_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?k_(x_(Z)):{};let K=X||!Z||!Z.__esModule?oK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of S_(Z))if(!y_.call(K,$))oK(K,$,{get:b_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var VQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var v_=(Z)=>Z;function g_(Z,X){this[Z]=v_.bind(null,X)}var c0=(Z,X)=>{for(var Q in X)oK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:g_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var t0=import.meta.require;var EO={};c0(EO,{lokiDir:()=>j0,homeLokiDir:()=>I4,findRepoRootForVersion:()=>tK,REPO_ROOT:()=>Q8});import{resolve as s7,dirname as rK}from"path";import{fileURLToPath as m_}from"url";import{existsSync as qQ}from"fs";import{homedir as u_}from"os";function p_(){let Z=DO;for(let X=0;X<6;X++){if(qQ(s7(Z,"VERSION"))&&qQ(s7(Z,"autonomy/run.sh")))return Z;let Q=rK(Z);if(Q===Z)break;Z=Q}return s7(DO,"..","..","..")}function tK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(qQ(s7(X,"VERSION"))&&qQ(s7(X,"autonomy/run.sh")))return X;let Y=rK(X);if(Y===X)break;X=Y}return s7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??s7(process.cwd(),".loki")}function I4(){return s7(u_(),".loki")}var DO,Q8;var G8=p(()=>{DO=rK(m_(import.meta.url));Q8=p_()});import{readFileSync as d_}from"fs";import{resolve as c_,dirname as l_}from"path";import{fileURLToPath as i_}from"url";function _3(){if(f5!==null)return f5;let Z="8.0.3";if(typeof Z==="string"&&Z.length>0)return f5=Z,f5;try{let X=l_(i_(import.meta.url)),Q=tK(X);f5=d_(c_(Q,"VERSION"),"utf-8").trim()}catch{f5="unknown"}return f5}var f5=null;var GQ=p(()=>{G8()});var kO={};c0(kO,{runOrThrow:()=>Wf,run:()=>D0,readStreamCapped:()=>HQ,commandVersion:()=>qf,commandExists:()=>H9,ShellError:()=>eK,MAX_STDOUT_BYTES:()=>RO});async function HQ(Z,X=RO){let Q=Z.getReader(),Y=new TextDecoder,J="",z=0;try{while(z<X){let{done:K,value:$}=await Q.read();if(K)break;if(!$)continue;if(z+=$.byteLength,z>X){let W=$.byteLength-(z-X);J+=Y.decode($.subarray(0,W),{stream:!0});break}J+=Y.decode($,{stream:!0})}J+=Y.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function D0(Z,X={}){let Q=Bun.spawn({cmd:[...Z],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),Y,J;if(X.timeoutMs&&X.timeoutMs>0)Y=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[z,K,$]=await Promise.all([HQ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:K,exitCode:$}}finally{if(Y)clearTimeout(Y);if(J)clearTimeout(J)}}async function Wf(Z,X={}){let Q=await D0(Z,X);if(Q.exitCode!==0)throw new eK(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function H9(Z){let X=Vf(Z),Q=await D0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Vf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function qf(Z,X="--version"){if(!await H9(Z))return null;let Y=await D0([Z,X],{timeoutMs:5000});if(Y.exitCode!==0)return null;return((Y.stdout||Y.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var RO=16777216,eK;var k9=p(()=>{eK=class eK extends Error{message;exitCode;stdout;stderr;constructor(Z,X,Q,Y){super(Z);this.message=Z;this.exitCode=X;this.stdout=Q;this.stderr=Y;this.name="ShellError"}}});function n7(Z){return Gf?"":Z}var Gf,M0,k8,l0,gW0,a0,H8,X9,g;var S6=p(()=>{Gf=(process.env.NO_COLOR??"").length>0;M0=n7("\x1B[0;31m"),k8=n7("\x1B[0;32m"),l0=n7("\x1B[1;33m"),gW0=n7("\x1B[0;34m"),a0=n7("\x1B[0;36m"),H8=n7("\x1B[1m"),X9=n7("\x1B[2m"),g=n7("\x1B[0m")});import{existsSync as wf}from"fs";async function F7(){if(R4!==void 0)return R4;let Z="/opt/homebrew/bin/python3.12";if(wf(Z))return R4=Z,Z;let X=await H9("python3.12");if(X)return R4=X,X;let Q=await H9("python3");return R4=Q,Q}async function D7(Z,X={}){let Q=await F7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return D0([Q,"-c",Z],X)}var R4;var o7=p(()=>{k9()});var oO={};c0(oO,{runStatus:()=>of});import{existsSync as Q9,readFileSync as h3,readdirSync as pO,statSync as dO}from"fs";import{resolve as h8,basename as mf}from"path";import{homedir as uf}from"os";function cO(Z){let X=Math.trunc(Z);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function lO(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*BQ/X);if(J>BQ)J=BQ;let z=BQ-J,K=k8;if(Y>=80)K=M0;else if(Y>=50)K=l0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),W=cO(Z),V=cO(X);return` ${H8}${Q}${g} ${K}[${$}]${g} ${Y}% (${W} / ${V})`}async function df(){if(await H9("jq"))return!0;return process.stdout.write(`${M0}Error: jq is required but not installed.${g}
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)
@@ -1203,4 +1203,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
1203
1203
  `),2}case"start":{let{runStart:Y}=await Promise.resolve().then(() => (I_(),E_));return Y(Q)}default:return process.stderr.write(`Unknown command: ${X}
1204
1204
  `),process.stderr.write(P_),2}}mO();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var TW0=await MW0(Bun.argv.slice(2));process.exit(TW0);
1205
1205
 
1206
- //# debugId=0B4A1F7E210B77BE64756E2164756E21
1206
+ //# debugId=3C2284D252E647F964756E2164756E21
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '8.0.2'
60
+ __version__ = '8.0.3'
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": "8.0.2",
4
+ "version": "8.0.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 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": "8.0.2",
5
+ "version": "8.0.3",
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",