loki-mode 6.37.4 → 6.37.6

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: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v6.37.4
6
+ # Loki Mode v6.37.6
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -267,4 +267,4 @@ The following features are documented in skill modules but not yet fully automat
267
267
  | Quality gates 3-reviewer system | Implemented (v5.35.0) | 5 specialist reviewers in `skills/quality-gates.md`; execution in run.sh |
268
268
  | Benchmarks (HumanEval, SWE-bench) | Infrastructure only | Runner scripts and datasets exist in `benchmarks/`; no published results |
269
269
 
270
- **v6.37.4 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
270
+ **v6.37.6 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 6.37.4
1
+ 6.37.6
@@ -42,8 +42,9 @@ COUNCIL_ENABLED=${LOKI_COUNCIL_ENABLED:-true}
42
42
  COUNCIL_SIZE=${LOKI_COUNCIL_SIZE:-3}
43
43
  COUNCIL_THRESHOLD=${LOKI_COUNCIL_THRESHOLD:-2}
44
44
  COUNCIL_CHECK_INTERVAL=${LOKI_COUNCIL_CHECK_INTERVAL:-5}
45
- # Guard against zero/negative interval (division by zero in modulo)
46
- if [ "$COUNCIL_CHECK_INTERVAL" -le 0 ] 2>/dev/null; then
45
+ # Guard against invalid interval (must be positive integer)
46
+ if ! [[ "$COUNCIL_CHECK_INTERVAL" =~ ^[1-9][0-9]*$ ]]; then
47
+ echo "Warning: invalid COUNCIL_CHECK_INTERVAL '$COUNCIL_CHECK_INTERVAL', using default 5" >&2
47
48
  COUNCIL_CHECK_INTERVAL=5
48
49
  fi
49
50
  COUNCIL_MIN_ITERATIONS=${LOKI_COUNCIL_MIN_ITERATIONS:-3}
package/autonomy/loki CHANGED
@@ -1144,8 +1144,9 @@ cmd_stop() {
1144
1144
  if [ -n "$target_session" ]; then
1145
1145
  if is_session_running "$target_session"; then
1146
1146
  _stop_session_by_id "$target_session"
1147
+ echo "Stopped session: $target_session"
1147
1148
  else
1148
- echo -e "${YELLOW}Session '$target_session' is not running.${NC}"
1149
+ echo "No active session found"
1149
1150
  fi
1150
1151
  return 0
1151
1152
  fi
@@ -1365,6 +1366,15 @@ cmd_pause() {
1365
1366
  fi
1366
1367
 
1367
1368
  if is_session_running; then
1369
+ # Warn if running in perpetual mode where PAUSE is auto-cleared (#84)
1370
+ local current_mode="${LOKI_AUTONOMY_MODE:-perpetual}"
1371
+ local perpetual_flag="${LOKI_PERPETUAL_MODE:-false}"
1372
+ if [ "$current_mode" = "perpetual" ] || [ "$perpetual_flag" = "true" ]; then
1373
+ echo -e "${YELLOW}Warning: Session is running in perpetual mode.${NC}"
1374
+ echo -e "${YELLOW}PAUSE signals are auto-cleared in perpetual mode and will be ignored.${NC}"
1375
+ echo -e "Use ${CYAN}loki stop${NC} to halt a perpetual session, or switch autonomy mode first:"
1376
+ echo -e " ${DIM}loki config set autonomy_mode checkpoint${NC}"
1377
+ fi
1368
1378
  touch "$LOKI_DIR/PAUSE"
1369
1379
  # Emit session pause event
1370
1380
  emit_event session cli pause "reason=user_requested"
@@ -3026,6 +3036,10 @@ cmd_web_start() {
3026
3036
  echo -e "${RED}Error: Port must be between 1 and 65535, got $port${NC}"
3027
3037
  exit 1
3028
3038
  fi
3039
+ if lsof -Pi :"$port" -sTCP:LISTEN -t >/dev/null 2>&1; then
3040
+ echo -e "${RED}Error: Port $port is already in use${NC}"
3041
+ exit 1
3042
+ fi
3029
3043
 
3030
3044
  # Validate --prd file if provided
3031
3045
  if [ -n "$prd_file" ]; then
@@ -4440,12 +4454,12 @@ cmd_watch() {
4440
4454
  esac
4441
4455
  done
4442
4456
 
4443
- # Validate numeric arguments
4444
- if ! [[ "$poll_interval" =~ ^[0-9]+$ ]] || [ "$poll_interval" -lt 1 ]; then
4457
+ # Validate numeric arguments (no leading zeros, no decimals, positive integers only)
4458
+ if ! [[ "$poll_interval" =~ ^[1-9][0-9]*$ ]]; then
4445
4459
  echo -e "${RED}Invalid --interval: $poll_interval (expected positive integer)${NC}"
4446
4460
  return 1
4447
4461
  fi
4448
- if ! [[ "$debounce" =~ ^[0-9]+$ ]] || [ "$debounce" -lt 0 ]; then
4462
+ if ! [[ "$debounce" =~ ^[1-9][0-9]*$ ]] && [ "$debounce" != "0" ]; then
4449
4463
  echo -e "${RED}Invalid --debounce: $debounce (expected non-negative integer)${NC}"
4450
4464
  return 1
4451
4465
  fi
@@ -4476,6 +4490,13 @@ cmd_watch() {
4476
4490
  return 1
4477
4491
  fi
4478
4492
 
4493
+ # Verify the PRD file is readable (#67)
4494
+ if [ ! -r "$prd_path" ]; then
4495
+ echo -e "${RED}PRD file is not readable: $prd_path${NC}"
4496
+ echo "Check file permissions: ls -la $prd_path"
4497
+ return 1
4498
+ fi
4499
+
4479
4500
  # Resolve to absolute path
4480
4501
  prd_path="$(cd "$(dirname "$prd_path")" && pwd)/$(basename "$prd_path")"
4481
4502
  local prd_basename
@@ -5001,7 +5022,11 @@ cmd_config_set() {
5001
5022
  ;;
5002
5023
  budget)
5003
5024
  if ! echo "$value" | grep -qE '^[0-9]+(\.[0-9]+)?$'; then
5004
- echo -e "${RED}Invalid budget: $value (expected: numeric USD amount)${NC}"; return 1
5025
+ echo -e "${RED}Invalid budget: $value (expected: positive numeric USD amount)${NC}"; return 1
5026
+ fi
5027
+ # Reject zero and negative values (#68)
5028
+ if echo "$value" | grep -qE '^0+(\.0+)?$'; then
5029
+ echo -e "${RED}Invalid budget: $value (must be greater than 0)${NC}"; return 1
5005
5030
  fi
5006
5031
  ;;
5007
5032
  model.planning|model.development|model.fast)
@@ -13960,6 +13985,13 @@ cmd_remote() {
13960
13985
  # Emit event
13961
13986
  emit_event session cli remote_start "prd=${prd_abs:-none}"
13962
13987
 
13988
+ # Check SSH directory exists (needed for remote connections)
13989
+ if [ ! -d "$HOME/.ssh" ]; then
13990
+ echo -e "${RED}Error: ~/.ssh directory not found${NC}"
13991
+ echo "Create it with: mkdir -p ~/.ssh && chmod 700 ~/.ssh"
13992
+ return 1
13993
+ fi
13994
+
13963
13995
  # Always use bypassPermissions so Loki Mode can operate autonomously
13964
13996
  rc_flags+=("--permission-mode" "bypassPermissions")
13965
13997
 
@@ -14717,33 +14749,40 @@ for a in agents:
14717
14749
  echo -e "${DIM}Persona: ${persona:0:80}...${NC}"
14718
14750
  echo ""
14719
14751
 
14720
- # Invoke current provider
14752
+ # Invoke current provider and capture exit code (#72)
14721
14753
  local provider="${LOKI_PROVIDER:-claude}"
14722
14754
  if [ -f ".loki/state/provider" ]; then
14723
14755
  provider=$(cat ".loki/state/provider" 2>/dev/null)
14724
14756
  fi
14725
14757
 
14758
+ local agent_exit=0
14726
14759
  case "$provider" in
14727
14760
  claude)
14728
- claude -p "$full_prompt" 2>&1
14761
+ claude -p "$full_prompt" 2>&1 || agent_exit=$?
14729
14762
  ;;
14730
14763
  codex)
14731
- codex exec --full-auto "$full_prompt" 2>&1
14764
+ codex exec --full-auto "$full_prompt" 2>&1 || agent_exit=$?
14732
14765
  ;;
14733
14766
  gemini)
14734
- gemini --approval-mode=yolo "$full_prompt" 2>&1
14767
+ gemini --approval-mode=yolo "$full_prompt" 2>&1 || agent_exit=$?
14735
14768
  ;;
14736
14769
  cline)
14737
- cline -y "$full_prompt" 2>&1
14770
+ cline -y "$full_prompt" 2>&1 || agent_exit=$?
14738
14771
  ;;
14739
14772
  aider)
14740
- aider --message "$full_prompt" --yes-always --no-auto-commits < /dev/null 2>&1
14773
+ aider --message "$full_prompt" --yes-always --no-auto-commits < /dev/null 2>&1 || agent_exit=$?
14741
14774
  ;;
14742
14775
  *)
14743
14776
  echo -e "${RED}Unknown provider: $provider${NC}"
14744
14777
  return 1
14745
14778
  ;;
14746
14779
  esac
14780
+
14781
+ if [ "$agent_exit" -ne 0 ]; then
14782
+ echo ""
14783
+ echo -e "${RED}Agent exited with code $agent_exit${NC}"
14784
+ return "$agent_exit"
14785
+ fi
14747
14786
  ;;
14748
14787
 
14749
14788
  start)
@@ -15730,7 +15769,7 @@ cmd_explain() {
15730
15769
 
15731
15770
  while [[ $# -gt 0 ]]; do
15732
15771
  case "$1" in
15733
- --json) output_json=true; shift ;;
15772
+ --json) output_json=true; require_jq || return 1; shift ;;
15734
15773
  --brief) output_brief=true; shift ;;
15735
15774
  --save) output_save=true; shift ;;
15736
15775
  --help|-h)
package/autonomy/run.sh CHANGED
@@ -1243,6 +1243,7 @@ detect_complexity() {
1243
1243
  if [ -n "$prd_path" ] && [ -f "$prd_path" ]; then
1244
1244
  local prd_words=$(wc -w < "$prd_path" | tr -d ' ')
1245
1245
  local feature_count=0
1246
+ local prd_lines=$(wc -l < "$prd_path" | tr -d ' ')
1246
1247
 
1247
1248
  # Detect PRD format and count features accordingly
1248
1249
  if [[ "$prd_path" == *.json ]]; then
@@ -1262,14 +1263,23 @@ detect_complexity() {
1262
1263
  feature_count=$(grep -c "^##\|^- \[" "$prd_path" 2>/dev/null || echo "0")
1263
1264
  fi
1264
1265
 
1265
- if [ "$prd_words" -lt 200 ] && [ "$feature_count" -lt 5 ]; then
1266
+ # Count distinct sections (h2/h3 headers) for structural complexity (#74)
1267
+ local section_count=0
1268
+ if [[ "$prd_path" != *.json ]]; then
1269
+ section_count=$(grep -c "^##\|^###" "$prd_path" 2>/dev/null || echo "0")
1270
+ fi
1271
+
1272
+ # PRD complexity uses content length, feature count, AND structural depth (#74)
1273
+ # A PRD with multiple sections or substantial content is not "simple" even with few project files
1274
+ if [ "$prd_words" -lt 200 ] && [ "$feature_count" -lt 5 ] && [ "$section_count" -lt 3 ]; then
1266
1275
  prd_complexity="simple"
1267
- elif [ "$prd_words" -gt 1000 ] || [ "$feature_count" -gt 15 ]; then
1276
+ elif [ "$prd_words" -gt 1000 ] || [ "$feature_count" -gt 15 ] || [ "$section_count" -gt 10 ]; then
1268
1277
  prd_complexity="complex"
1269
1278
  fi
1270
1279
  fi
1271
1280
 
1272
1281
  # Determine final complexity
1282
+ # A non-simple PRD always prevents "simple" classification regardless of file count (#74)
1273
1283
  if [ "$file_count" -le 5 ] && [ "$prd_complexity" = "simple" ] && \
1274
1284
  [ "$has_external" = "false" ] && [ "$has_microservices" = "false" ]; then
1275
1285
  DETECTED_COMPLEXITY="simple"
@@ -1280,7 +1290,7 @@ detect_complexity() {
1280
1290
  DETECTED_COMPLEXITY="standard"
1281
1291
  fi
1282
1292
 
1283
- log_info "Detected complexity: $DETECTED_COMPLEXITY (files: $file_count, external: $has_external, microservices: $has_microservices)"
1293
+ log_info "Detected complexity: $DETECTED_COMPLEXITY (files: $file_count, prd: $prd_complexity, external: $has_external, microservices: $has_microservices)"
1284
1294
  }
1285
1295
 
1286
1296
  # Get phases based on complexity tier
@@ -2824,6 +2834,9 @@ init_loki_dir() {
2824
2834
  mkdir -p .loki/artifacts/{releases,reports,backups}
2825
2835
  mkdir -p .loki/memory/{ledgers,handoffs,learnings,episodic,semantic,skills}
2826
2836
  mkdir -p .loki/metrics/{efficiency,rewards}
2837
+ # Clear stale metrics from previous sessions so loki metrics shows current run data (#75)
2838
+ rm -f .loki/metrics/efficiency/iteration-*.json 2>/dev/null || true
2839
+ rm -f .loki/metrics/rewards/*.json 2>/dev/null || true
2827
2840
  mkdir -p .loki/rules
2828
2841
  mkdir -p .loki/signals
2829
2842
 
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "6.37.4"
10
+ __version__ = "6.37.6"
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/). Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v6.37.4
5
+ **Version:** v6.37.6
6
6
 
7
7
  ---
8
8
 
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '6.37.4'
60
+ __version__ = '6.37.6'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "6.37.4",
3
+ "version": "6.37.6",
4
4
  "description": "Loki Mode by Autonomi - Multi-agent autonomous startup system for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "keywords": [
6
6
  "agent",