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 +2 -2
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +19 -2
- package/autonomy/loki +82 -0
- package/autonomy/openspec-adapter.py +827 -0
- package/autonomy/prd-analyzer.py +14 -1
- package/autonomy/run.sh +294 -18
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/skills/00-index.md +9 -0
- package/skills/openspec-integration.md +147 -0
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.
|
|
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.
|
|
270
|
+
**v6.11.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
6.
|
|
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
|