loki-mode 6.9.0 → 6.11.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.11.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.11.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 6.9.0
1
+ 6.11.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
package/autonomy/loki CHANGED
@@ -448,6 +448,7 @@ show_help() {
448
448
  echo " --compliance PRESET Enable compliance mode (default|healthcare|fintech|government)"
449
449
  echo " --budget USD Set cost budget limit (display in dashboard/status)"
450
450
  echo " --bmad-project PATH Use BMAD Method project artifacts as input"
451
+ echo " --openspec PATH Use OpenSpec change directory as input"
451
452
  echo ""
452
453
  echo "Options for 'run' (v6.0.0):"
453
454
  echo " --dry-run Preview generated PRD without starting"
@@ -490,6 +491,7 @@ cmd_start() {
490
491
  local prd_file=""
491
492
  local provider=""
492
493
  local bmad_project_path=""
494
+ local openspec_change_path=""
493
495
 
494
496
  while [[ $# -gt 0 ]]; do
495
497
  case "$1" in
@@ -514,6 +516,7 @@ cmd_start() {
514
516
  echo " --compliance PRESET Enable compliance mode (default|healthcare|fintech|government)"
515
517
  echo " --budget USD Cost budget limit (auto-pause when exceeded)"
516
518
  echo " --bmad-project PATH Use BMAD Method project artifacts as input"
519
+ echo " --openspec PATH Use OpenSpec change directory as input"
517
520
  echo " --yes, -y Skip confirmation prompts (auto-confirm)"
518
521
  echo ""
519
522
  echo "Environment Variables:"
@@ -529,6 +532,7 @@ cmd_start() {
529
532
  echo " loki start ./prd.md --parallel # Parallel mode with worktrees"
530
533
  echo " loki start --provider codex # Use OpenAI Codex CLI"
531
534
  echo " loki start --bmad-project ./my-project # Start from BMAD artifacts"
535
+ echo " loki start --openspec ./openspec/changes/my-feature # Start from OpenSpec change"
532
536
  echo " loki start --yes # Skip confirmation prompt"
533
537
  echo " LOKI_PRD_FILE=./prd.md loki start # PRD via env var"
534
538
  exit 0
@@ -652,6 +656,19 @@ cmd_start() {
652
656
  bmad_project_path="${1#*=}"
653
657
  shift
654
658
  ;;
659
+ --openspec)
660
+ if [[ -n "${2:-}" ]]; then
661
+ openspec_change_path="$2"
662
+ shift 2
663
+ else
664
+ echo -e "${RED}--openspec requires a path to an OpenSpec change directory${NC}"
665
+ exit 1
666
+ fi
667
+ ;;
668
+ --openspec=*)
669
+ openspec_change_path="${1#*=}"
670
+ shift
671
+ ;;
655
672
  --budget)
656
673
  if [[ -n "${2:-}" ]]; then
657
674
  if ! echo "$2" | grep -qE '^[0-9]+(\.[0-9]+)?$'; then
@@ -690,6 +707,12 @@ cmd_start() {
690
707
  prd_file="$LOKI_PRD_FILE"
691
708
  fi
692
709
 
710
+ # Mutual exclusivity: --openspec and --bmad-project cannot be used together
711
+ if [[ -n "${openspec_change_path:-}" ]] && [[ -n "${bmad_project_path:-}" ]]; then
712
+ echo -e "${RED}Error: --openspec and --bmad-project are mutually exclusive. Use one or the other.${NC}"
713
+ exit 1
714
+ fi
715
+
693
716
  # BMAD project validation and adapter execution
694
717
  if [[ -n "$bmad_project_path" ]]; then
695
718
  # Resolve to absolute path
@@ -752,6 +775,65 @@ cmd_start() {
752
775
  fi
753
776
  fi
754
777
 
778
+ # OpenSpec change directory validation and adapter execution
779
+ if [[ -n "$openspec_change_path" ]]; then
780
+ # Resolve to absolute path
781
+ if [[ ! "$openspec_change_path" = /* ]]; then
782
+ local original_openspec_path="$openspec_change_path"
783
+ openspec_change_path="$(cd "$openspec_change_path" 2>/dev/null && pwd)" || {
784
+ echo -e "${RED}Error: OpenSpec change path does not exist: $original_openspec_path${NC}"
785
+ exit 1
786
+ }
787
+ fi
788
+
789
+ # Validate path is a directory
790
+ if [[ ! -d "$openspec_change_path" ]]; then
791
+ echo -e "${RED}Error: OpenSpec change path is not a directory: $openspec_change_path${NC}"
792
+ exit 1
793
+ fi
794
+
795
+ # Check for required OpenSpec artifacts
796
+ if [[ ! -f "$openspec_change_path/proposal.md" ]]; then
797
+ echo -e "${RED}Error: No proposal.md found in $openspec_change_path${NC}"
798
+ echo "Expected an OpenSpec change directory with proposal.md and specs/."
799
+ exit 1
800
+ fi
801
+
802
+ # Export for run.sh to access
803
+ export OPENSPEC_CHANGE_PATH="$openspec_change_path"
804
+
805
+ # Ensure .loki directory exists for adapter output
806
+ mkdir -p "$LOKI_DIR"
807
+
808
+ # Run the OpenSpec adapter to normalize artifacts
809
+ echo -e "${CYAN}Running OpenSpec adapter...${NC}"
810
+ local adapter_script="${SCRIPT_DIR:-$(dirname "$0")}/openspec-adapter.py"
811
+ if [[ ! -f "$adapter_script" ]]; then
812
+ echo -e "${RED}Error: OpenSpec adapter not found at $adapter_script${NC}"
813
+ echo "Please ensure autonomy/openspec-adapter.py exists."
814
+ exit 1
815
+ fi
816
+
817
+ # Validate first
818
+ if ! python3 "$adapter_script" "$openspec_change_path" --validate; then
819
+ echo -e "${RED}Error: OpenSpec adapter validation failed. Check the change artifacts.${NC}"
820
+ exit 1
821
+ fi
822
+
823
+ # Generate output files
824
+ if ! python3 "$adapter_script" "$openspec_change_path" --output-dir "$LOKI_DIR"; then
825
+ echo -e "${RED}Error: OpenSpec adapter failed to generate output files.${NC}"
826
+ exit 1
827
+ fi
828
+ echo -e "${GREEN}OpenSpec artifacts normalized successfully.${NC}"
829
+
830
+ # If no explicit PRD was provided, use the normalized OpenSpec PRD
831
+ if [[ -z "$prd_file" ]] && [[ -f "$LOKI_DIR/openspec-prd-normalized.md" ]]; then
832
+ prd_file="$LOKI_DIR/openspec-prd-normalized.md"
833
+ echo -e "${CYAN}Using normalized OpenSpec PRD: $prd_file${NC}"
834
+ fi
835
+ fi
836
+
755
837
  if [ -n "$prd_file" ]; then
756
838
  args+=("$prd_file")
757
839
  else