loki-mode 6.9.0 → 6.10.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: 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.9.0
6
+ # Loki Mode v6.10.0
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.9.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
270
+ **v6.10.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 6.9.0
1
+ 6.10.0
@@ -27,6 +27,7 @@
27
27
  # LOKI_COUNCIL_MIN_ITERATIONS - Minimum iterations before council runs (default: 3)
28
28
  # LOKI_COUNCIL_CONVERGENCE_WINDOW - Iterations to track for convergence (default: 3)
29
29
  # LOKI_COUNCIL_STAGNATION_LIMIT - Max iterations with no git changes (default: 5)
30
+ # LOKI_COUNCIL_DONE_SIGNAL_LIMIT - Max total done signals before force stop (default: 10)
30
31
  #
31
32
  # Usage:
32
33
  # source autonomy/completion-council.sh
@@ -48,6 +49,7 @@ fi
48
49
  COUNCIL_MIN_ITERATIONS=${LOKI_COUNCIL_MIN_ITERATIONS:-3}
49
50
  COUNCIL_CONVERGENCE_WINDOW=${LOKI_COUNCIL_CONVERGENCE_WINDOW:-3}
50
51
  COUNCIL_STAGNATION_LIMIT=${LOKI_COUNCIL_STAGNATION_LIMIT:-5}
52
+ COUNCIL_DONE_SIGNAL_LIMIT=${LOKI_COUNCIL_DONE_SIGNAL_LIMIT:-10}
51
53
 
52
54
  # Error budget: severity-aware completion (v5.49.0)
53
55
  # SEVERITY_THRESHOLD: minimum severity that blocks completion (critical, high, medium, low)
@@ -62,6 +64,7 @@ COUNCIL_STATE_DIR=""
62
64
  COUNCIL_PRD_PATH=""
63
65
  COUNCIL_CONSECUTIVE_NO_CHANGE=0
64
66
  COUNCIL_DONE_SIGNALS=0
67
+ COUNCIL_TOTAL_DONE_SIGNALS=0
65
68
  COUNCIL_LAST_DIFF_HASH=""
66
69
 
67
70
  #===============================================================================
@@ -149,6 +152,7 @@ council_track_iteration() {
149
152
 
150
153
  if [ "$done_indicators" -gt 0 ]; then
151
154
  ((COUNCIL_DONE_SIGNALS++))
155
+ ((COUNCIL_TOTAL_DONE_SIGNALS++))
152
156
  else
153
157
  # Reset if agent stopped claiming done
154
158
  COUNCIL_DONE_SIGNALS=0
@@ -172,6 +176,7 @@ council_track_iteration() {
172
176
  _COUNCIL_STATE_FILE="$COUNCIL_STATE_DIR/state.json" \
173
177
  _COUNCIL_NO_CHANGE="$COUNCIL_CONSECUTIVE_NO_CHANGE" \
174
178
  _COUNCIL_DONE_SIGNALS="$COUNCIL_DONE_SIGNALS" \
179
+ _COUNCIL_TOTAL_DONE_SIGNALS="$COUNCIL_TOTAL_DONE_SIGNALS" \
175
180
  _COUNCIL_ITERATION="${ITERATION_COUNT:-0}" \
176
181
  _COUNCIL_FILES_CHANGED="$files_changed" \
177
182
  python3 -c "
@@ -184,6 +189,7 @@ except (json.JSONDecodeError, FileNotFoundError, OSError):
184
189
  state = {}
185
190
  state['consecutive_no_change'] = int(os.environ['_COUNCIL_NO_CHANGE'])
186
191
  state['done_signals'] = int(os.environ['_COUNCIL_DONE_SIGNALS'])
192
+ state['total_done_signals'] = int(os.environ['_COUNCIL_TOTAL_DONE_SIGNALS'])
187
193
  state['last_track_iteration'] = int(os.environ['_COUNCIL_ITERATION'])
188
194
  state['files_changed'] = int(os.environ['_COUNCIL_FILES_CHANGED'])
189
195
  with open(state_file, 'w') as f:
@@ -459,7 +465,8 @@ EVIDENCE_SECTION
459
465
 
460
466
  ## Convergence Data
461
467
  - Consecutive iterations with no code changes: $COUNCIL_CONSECUTIVE_NO_CHANGE
462
- - Done signals from agent: $COUNCIL_DONE_SIGNALS
468
+ - Done signals from agent (consecutive): $COUNCIL_DONE_SIGNALS
469
+ - Total done signals from agent: $COUNCIL_TOTAL_DONE_SIGNALS
463
470
  - Current iteration: $ITERATION_COUNT
464
471
 
465
472
  ## Queue Status
@@ -990,6 +997,8 @@ council_evaluate_member() {
990
997
  if [ -f "$log_file" ]; then
991
998
  local errs
992
999
  errs=$(tail -50 "$log_file" 2>/dev/null | grep -ciE "(uncaught|unhandled|panic|fatal|segfault|traceback)" 2>/dev/null || echo "0")
1000
+ errs=$(echo "$errs" | tr -dc '0-9')
1001
+ errs="${errs:-0}"
993
1002
  error_count=$((error_count + errs))
994
1003
  fi
995
1004
  done
@@ -1365,6 +1374,13 @@ council_should_stop() {
1365
1374
  fi
1366
1375
  fi
1367
1376
 
1377
+ # Safety valve 2: Total done signals exceed limit (agent keeps saying done)
1378
+ if [ "$COUNCIL_TOTAL_DONE_SIGNALS" -ge "$COUNCIL_DONE_SIGNAL_LIMIT" ]; then
1379
+ log_error "Safety valve: Agent signaled 'done' $COUNCIL_TOTAL_DONE_SIGNALS times (limit: $COUNCIL_DONE_SIGNAL_LIMIT)"
1380
+ log_error "Forcing stop - agent believes work is complete"
1381
+ return 0 # FORCE STOP
1382
+ fi
1383
+
1368
1384
  return 1 # CONTINUE
1369
1385
  }
1370
1386
 
@@ -1385,7 +1401,8 @@ council_write_report() {
1385
1401
  ## Convergence Data
1386
1402
  - Total iterations: $ITERATION_COUNT
1387
1403
  - Final consecutive no-change count: $COUNCIL_CONSECUTIVE_NO_CHANGE
1388
- - Done signals from agent: $COUNCIL_DONE_SIGNALS
1404
+ - Done signals from agent (consecutive): $COUNCIL_DONE_SIGNALS
1405
+ - Total done signals from agent: $COUNCIL_TOTAL_DONE_SIGNALS
1389
1406
 
1390
1407
  ## Council Configuration
1391
1408
  - Council size: $COUNCIL_SIZE
@@ -252,7 +252,7 @@ class PrdAnalyzer:
252
252
  count = 0
253
253
  in_feature_section = False
254
254
  for line in self.lines:
255
- if re.search(r"(?i)#+\s.*(?:feature|requirement|scope|functional)", line):
255
+ if re.search(r"(?i)#+\s.*(?:feature|requirement|scope|functional|module|component|service|endpoint|api|milestone|deliverable|workstream|epic|story|task|phase|capability|objective)", line):
256
256
  in_feature_section = True
257
257
  continue
258
258
  if in_feature_section and re.match(r"^\s*#+\s", line):
@@ -262,12 +262,25 @@ class PrdAnalyzer:
262
262
  if re.match(r"^\s*[-*]\s+\S", line) or re.match(r"^\s*\d+\.\s+\S", line):
263
263
  count += 1
264
264
 
265
+ # Fallback: count ## headings as feature indicators when bullet items are few
266
+ if count == 0:
267
+ for line in self.lines:
268
+ if re.match(r"^##\s+\S", line):
269
+ count += 1
270
+
265
271
  self.feature_count = count
266
272
  for threshold, label in SCOPE_THRESHOLDS:
267
273
  if count <= threshold:
268
274
  self.scope = label
269
275
  break
270
276
 
277
+ # Word-count fallback: large PRDs should never be classified as small
278
+ word_count = len(self.content.split())
279
+ if word_count > 2000 and self.scope in ("small", "medium"):
280
+ self.scope = "large"
281
+ elif word_count > 500 and self.scope == "small":
282
+ self.scope = "medium"
283
+
271
284
  def generate_observations(self):
272
285
  """Generate the observations markdown content."""
273
286
  now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
package/autonomy/run.sh CHANGED
@@ -622,6 +622,11 @@ MAX_WORKTREES=${LOKI_MAX_WORKTREES:-5}
622
622
  MAX_PARALLEL_SESSIONS=${LOKI_MAX_PARALLEL_SESSIONS:-3}
623
623
  PARALLEL_TESTING=${LOKI_PARALLEL_TESTING:-true}
624
624
  PARALLEL_DOCS=${LOKI_PARALLEL_DOCS:-true}
625
+
626
+ # Gate Escalation Ladder (v6.10.0)
627
+ GATE_CLEAR_LIMIT=${LOKI_GATE_CLEAR_LIMIT:-3}
628
+ GATE_ESCALATE_LIMIT=${LOKI_GATE_ESCALATE_LIMIT:-5}
629
+ GATE_PAUSE_LIMIT=${LOKI_GATE_PAUSE_LIMIT:-10}
625
630
  TARGET_DIR="${LOKI_TARGET_DIR:-$(pwd)}"
626
631
  PARALLEL_BLOG=${LOKI_PARALLEL_BLOG:-false}
627
632
  AUTO_MERGE=${LOKI_AUTO_MERGE:-true}
@@ -5250,6 +5255,69 @@ SAFEOF
5250
5255
  fi
5251
5256
  }
5252
5257
 
5258
+ #===============================================================================
5259
+ # Gate Failure Tracking (v6.10.0)
5260
+ #===============================================================================
5261
+
5262
+ track_gate_failure() {
5263
+ local gate_name="$1"
5264
+ local gate_file="${TARGET_DIR:-.}/.loki/quality/gate-failure-count.json"
5265
+ mkdir -p "$(dirname "$gate_file")"
5266
+
5267
+ _GATE_FILE="$gate_file" _GATE_NAME="$gate_name" python3 -c "
5268
+ import json, os
5269
+ gate_file = os.environ['_GATE_FILE']
5270
+ gate_name = os.environ['_GATE_NAME']
5271
+ try:
5272
+ with open(gate_file) as f:
5273
+ counts = json.load(f)
5274
+ except (json.JSONDecodeError, FileNotFoundError, OSError):
5275
+ counts = {}
5276
+ counts[gate_name] = counts.get(gate_name, 0) + 1
5277
+ with open(gate_file, 'w') as f:
5278
+ json.dump(counts, f, indent=2)
5279
+ print(counts[gate_name])
5280
+ " 2>/dev/null || echo "1"
5281
+ }
5282
+
5283
+ clear_gate_failure() {
5284
+ local gate_name="$1"
5285
+ local gate_file="${TARGET_DIR:-.}/.loki/quality/gate-failure-count.json"
5286
+ [ -f "$gate_file" ] || return 0
5287
+
5288
+ _GATE_FILE="$gate_file" _GATE_NAME="$gate_name" python3 -c "
5289
+ import json, os
5290
+ gate_file = os.environ['_GATE_FILE']
5291
+ gate_name = os.environ['_GATE_NAME']
5292
+ try:
5293
+ with open(gate_file) as f:
5294
+ counts = json.load(f)
5295
+ except (json.JSONDecodeError, FileNotFoundError, OSError):
5296
+ counts = {}
5297
+ counts[gate_name] = 0
5298
+ with open(gate_file, 'w') as f:
5299
+ json.dump(counts, f, indent=2)
5300
+ " 2>/dev/null || true
5301
+ }
5302
+
5303
+ get_gate_failure_count() {
5304
+ local gate_name="$1"
5305
+ local gate_file="${TARGET_DIR:-.}/.loki/quality/gate-failure-count.json"
5306
+ [ -f "$gate_file" ] || { echo "0"; return; }
5307
+
5308
+ _GATE_FILE="$gate_file" _GATE_NAME="$gate_name" python3 -c "
5309
+ import json, os
5310
+ gate_file = os.environ['_GATE_FILE']
5311
+ gate_name = os.environ['_GATE_NAME']
5312
+ try:
5313
+ with open(gate_file) as f:
5314
+ counts = json.load(f)
5315
+ print(counts.get(gate_name, 0))
5316
+ except (json.JSONDecodeError, FileNotFoundError, OSError):
5317
+ print(0)
5318
+ " 2>/dev/null || echo "0"
5319
+ }
5320
+
5253
5321
  # ============================================================================
5254
5322
  # Hard Quality Gate: Test Coverage (v6.7.0)
5255
5323
  # Detects test runner and runs tests with coverage reporting
@@ -5287,6 +5355,58 @@ enforce_test_coverage() {
5287
5355
  fi
5288
5356
  fi
5289
5357
 
5358
+ # Monorepo: scan workspace packages for test runners (v6.10.0)
5359
+ if [ "$test_runner" = "none" ] && [ -f "${TARGET_DIR:-.}/package.json" ]; then
5360
+ local is_monorepo=false
5361
+ # Detect monorepo indicators
5362
+ if [ -f "${TARGET_DIR:-.}/pnpm-workspace.yaml" ] || \
5363
+ [ -f "${TARGET_DIR:-.}/turbo.json" ] || \
5364
+ [ -f "${TARGET_DIR:-.}/lerna.json" ] || \
5365
+ grep -q '"workspaces"' "${TARGET_DIR:-.}/package.json" 2>/dev/null; then
5366
+ is_monorepo=true
5367
+ fi
5368
+
5369
+ if [ "$is_monorepo" = "true" ]; then
5370
+ # Allow env override
5371
+ if [ -n "${LOKI_MONOREPO_TEST_CMD:-}" ]; then
5372
+ test_runner="monorepo-custom"
5373
+ local output
5374
+ output=$(cd "${TARGET_DIR:-.}" && eval "$LOKI_MONOREPO_TEST_CMD" 2>&1) || test_passed=false
5375
+ details="monorepo-custom: $(echo "$output" | tail -3 | tr '\n' ' ')"
5376
+ else
5377
+ # Scan workspace packages for test runners
5378
+ local workspace_runner=""
5379
+ for pkg_json in "${TARGET_DIR:-.}"/packages/*/package.json \
5380
+ "${TARGET_DIR:-.}"/apps/*/package.json \
5381
+ "${TARGET_DIR:-.}"/services/*/package.json; do
5382
+ [ -f "$pkg_json" ] || continue
5383
+ if grep -q '"vitest"' "$pkg_json" 2>/dev/null; then
5384
+ workspace_runner="vitest"
5385
+ break
5386
+ elif grep -q '"jest"' "$pkg_json" 2>/dev/null; then
5387
+ workspace_runner="jest"
5388
+ break
5389
+ fi
5390
+ done
5391
+
5392
+ if [ -n "$workspace_runner" ]; then
5393
+ test_runner="monorepo-$workspace_runner"
5394
+ local output
5395
+ if [ -f "${TARGET_DIR:-.}/turbo.json" ] && command -v turbo &>/dev/null; then
5396
+ output=$(cd "${TARGET_DIR:-.}" && npx turbo test 2>&1) || test_passed=false
5397
+ details="turbo test ($workspace_runner): $(echo "$output" | tail -3 | tr '\n' ' ')"
5398
+ elif [ -f "${TARGET_DIR:-.}/pnpm-workspace.yaml" ] && command -v pnpm &>/dev/null; then
5399
+ output=$(cd "${TARGET_DIR:-.}" && pnpm test --recursive 2>&1) || test_passed=false
5400
+ details="pnpm test --recursive ($workspace_runner): $(echo "$output" | tail -3 | tr '\n' ' ')"
5401
+ else
5402
+ output=$(cd "${TARGET_DIR:-.}" && npm test 2>&1) || test_passed=false
5403
+ details="npm test ($workspace_runner): $(echo "$output" | tail -3 | tr '\n' ' ')"
5404
+ fi
5405
+ fi
5406
+ fi
5407
+ fi
5408
+ fi
5409
+
5290
5410
  # Python
5291
5411
  if [ "$test_runner" = "none" ]; then
5292
5412
  if [ -f "${TARGET_DIR:-.}/setup.py" ] || [ -f "${TARGET_DIR:-.}/pyproject.toml" ] || \
@@ -7398,11 +7518,16 @@ build_prompt() {
7398
7518
  if [ -n "$COMPLETION_PROMISE" ]; then
7399
7519
  completion_instruction="COMPLETION_PROMISE: [$COMPLETION_PROMISE]. ONLY output 'COMPLETION PROMISE FULFILLED: $COMPLETION_PROMISE' when this EXACT condition is met."
7400
7520
  else
7401
- completion_instruction="NO COMPLETION PROMISE SET. Run forever finding improvements. Iteration $iteration of max $MAX_ITERATIONS."
7521
+ completion_instruction="NO COMPLETION PROMISE SET. Continue finding improvements. The Completion Council will evaluate your progress periodically. Iteration $iteration of max $MAX_ITERATIONS."
7402
7522
  fi
7403
7523
 
7404
7524
  # Core autonomous instructions - NO questions, NO waiting, NEVER say done
7405
- local autonomous_suffix="CRITICAL AUTONOMY RULES: 1) NEVER ask questions - just decide. 2) NEVER wait for confirmation - just act. 3) NEVER say 'done' or 'complete' - there's always more to improve. 4) NEVER stop voluntarily - if out of tasks, create new ones (add tests, optimize, refactor, add features). 5) Work continues PERPETUALLY. Even if PRD is implemented, find bugs, add tests, improve UX, optimize performance."
7525
+ local autonomous_suffix=""
7526
+ if [ "$AUTONOMY_MODE" = "perpetual" ] || [ "$PERPETUAL_MODE" = "true" ]; then
7527
+ autonomous_suffix="CRITICAL AUTONOMY RULES: 1) NEVER ask questions - just decide. 2) NEVER wait for confirmation - just act. 3) NEVER say 'done' or 'complete' - there's always more to improve. 4) NEVER stop voluntarily - if out of tasks, create new ones (add tests, optimize, refactor, add features). 5) Work continues PERPETUALLY. Even if PRD is implemented, find bugs, add tests, improve UX, optimize performance."
7528
+ else
7529
+ autonomous_suffix="CRITICAL AUTONOMY RULES: 1) NEVER ask questions - just decide. 2) NEVER wait for confirmation - just act. 3) When all PRD requirements are implemented and tests pass, output the completion promise text EXACTLY: '$COMPLETION_PROMISE'. 4) If out of tasks but PRD is not fully implemented, continue working on remaining requirements. 5) Focus on completing PRD scope, not endless improvements."
7530
+ fi
7406
7531
 
7407
7532
  # Skill files are always copied to .loki/skills/ for all providers
7408
7533
  local sdlc_instruction="SDLC_PHASES_ENABLED: [$phases]. Execute ALL enabled phases. Log results to .loki/logs/. See .loki/SKILL.md for phase details. Skill modules at .loki/skills/."
@@ -7823,6 +7948,21 @@ run_autonomous() {
7823
7948
  fi
7824
7949
  fi
7825
7950
 
7951
+ # Auto-derive completion promise from PRD (v6.10.0)
7952
+ # When PRD exists but no explicit promise, auto-derive one and switch to checkpoint mode
7953
+ if [ -n "$prd_path" ] && [ -f "$prd_path" ] && [ -z "$COMPLETION_PROMISE" ]; then
7954
+ if [ "${LOKI_AUTO_COMPLETION_PROMISE:-true}" = "true" ]; then
7955
+ COMPLETION_PROMISE="All PRD requirements implemented and tests passing"
7956
+ log_info "Auto-derived completion promise: $COMPLETION_PROMISE"
7957
+ # PRD-driven work is finite; switch from perpetual to checkpoint
7958
+ if [ "${LOKI_FORCE_PERPETUAL:-false}" != "true" ] && [ "$AUTONOMY_MODE" = "perpetual" ]; then
7959
+ AUTONOMY_MODE="checkpoint"
7960
+ PERPETUAL_MODE="false"
7961
+ log_info "Switched autonomy mode: perpetual -> checkpoint (PRD-driven work is finite)"
7962
+ fi
7963
+ fi
7964
+ fi
7965
+
7826
7966
  # Populate task queue from BMAD artifacts (if present, runs once)
7827
7967
  populate_bmad_queue
7828
7968
 
@@ -8302,29 +8442,55 @@ if __name__ == "__main__":
8302
8442
  # Checkpoint after each iteration (v5.57.0)
8303
8443
  create_checkpoint "iteration-${ITERATION_COUNT} complete" "iteration-${ITERATION_COUNT}"
8304
8444
 
8305
- # Quality gates (v6.7.0 - hard enforcement)
8445
+ # Quality gates (v6.10.0 - escalation ladder)
8306
8446
  local gate_failures=""
8307
8447
  if [ "${LOKI_HARD_GATES:-true}" = "true" ]; then
8308
8448
  # Static analysis gate
8309
8449
  if [ "${PHASE_STATIC_ANALYSIS:-true}" = "true" ]; then
8310
- enforce_static_analysis || {
8450
+ if enforce_static_analysis; then
8451
+ clear_gate_failure "static_analysis"
8452
+ else
8453
+ local sa_count
8454
+ sa_count=$(track_gate_failure "static_analysis")
8311
8455
  gate_failures="${gate_failures}static_analysis,"
8312
- log_warn "Static analysis FAILED - findings injected into next iteration"
8313
- }
8456
+ log_warn "Static analysis FAILED ($sa_count consecutive) - findings injected into next iteration"
8457
+ fi
8314
8458
  fi
8315
8459
  # Test coverage gate
8316
8460
  if [ "${PHASE_UNIT_TESTS:-true}" = "true" ]; then
8317
- enforce_test_coverage || {
8461
+ if enforce_test_coverage; then
8462
+ clear_gate_failure "test_coverage"
8463
+ else
8464
+ local tc_count
8465
+ tc_count=$(track_gate_failure "test_coverage")
8318
8466
  gate_failures="${gate_failures}test_coverage,"
8319
- log_warn "Test coverage gate FAILED - must pass next iteration"
8320
- }
8467
+ log_warn "Test coverage gate FAILED ($tc_count consecutive) - must pass next iteration"
8468
+ fi
8321
8469
  fi
8322
- # Code review gate (upgraded from advisory)
8470
+ # Code review gate (upgraded from advisory, with escalation)
8323
8471
  if [ "$PHASE_CODE_REVIEW" = "true" ] && [ "$ITERATION_COUNT" -gt 0 ]; then
8324
- run_code_review || {
8325
- gate_failures="${gate_failures}code_review,"
8326
- log_warn "Code review BLOCKED - Critical/High findings"
8327
- }
8472
+ if run_code_review; then
8473
+ clear_gate_failure "code_review"
8474
+ else
8475
+ local cr_count
8476
+ cr_count=$(track_gate_failure "code_review")
8477
+ if [ "$cr_count" -ge "$GATE_PAUSE_LIMIT" ]; then
8478
+ log_error "Gate escalation: code_review failed $cr_count times (>= $GATE_PAUSE_LIMIT) - forcing PAUSE for human intervention"
8479
+ echo "PAUSE" > "${TARGET_DIR:-.}/.loki/signals/GATE_ESCALATION"
8480
+ echo "code_review gate failed $cr_count consecutive times" >> "${TARGET_DIR:-.}/.loki/signals/GATE_ESCALATION"
8481
+ touch "${TARGET_DIR:-.}/.loki/signals/PAUSE"
8482
+ elif [ "$cr_count" -ge "$GATE_ESCALATE_LIMIT" ]; then
8483
+ log_warn "Gate escalation: code_review failed $cr_count times (>= $GATE_ESCALATE_LIMIT) - escalating"
8484
+ echo "ESCALATE" > "${TARGET_DIR:-.}/.loki/signals/GATE_ESCALATION"
8485
+ gate_failures="${gate_failures}code_review_ESCALATED,"
8486
+ elif [ "$cr_count" -ge "$GATE_CLEAR_LIMIT" ]; then
8487
+ log_warn "Gate cleared: code_review failed $cr_count times (>= $GATE_CLEAR_LIMIT) - clearing gate, agent tried"
8488
+ clear_gate_failure "code_review"
8489
+ else
8490
+ gate_failures="${gate_failures}code_review,"
8491
+ log_warn "Code review BLOCKED ($cr_count consecutive) - Critical/High findings"
8492
+ fi
8493
+ fi
8328
8494
  fi
8329
8495
  # Store gate failures for prompt injection
8330
8496
  if [ -n "$gate_failures" ]; then
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "6.9.0"
10
+ __version__ = "6.10.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/). Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v6.9.0
5
+ **Version:** v6.10.0
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.9.0'
60
+ __version__ = '6.10.0'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "6.9.0",
3
+ "version": "6.10.0",
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",