loki-mode 6.13.1 → 6.14.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/README.md +1 -1
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/loki +221 -0
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
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.14.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.14.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
6.
|
|
1
|
+
6.14.0
|
package/autonomy/loki
CHANGED
|
@@ -419,6 +419,7 @@ show_help() {
|
|
|
419
419
|
echo " checkpoint|cp Save/restore session checkpoints"
|
|
420
420
|
echo " projects Multi-project registry management"
|
|
421
421
|
echo " audit [cmd] Agent audit log and quality scanning (log|scan)"
|
|
422
|
+
echo " review [dir] Run quality gates on any project (standalone, no AI needed)"
|
|
422
423
|
echo " optimize Optimize prompts based on session history"
|
|
423
424
|
echo " enterprise Enterprise feature management (tokens, OIDC)"
|
|
424
425
|
echo " metrics Prometheus/OpenMetrics metrics from dashboard"
|
|
@@ -7848,6 +7849,9 @@ main() {
|
|
|
7848
7849
|
audit)
|
|
7849
7850
|
cmd_audit "$@"
|
|
7850
7851
|
;;
|
|
7852
|
+
review)
|
|
7853
|
+
cmd_review "$@"
|
|
7854
|
+
;;
|
|
7851
7855
|
optimize)
|
|
7852
7856
|
cmd_optimize "$@"
|
|
7853
7857
|
;;
|
|
@@ -7895,6 +7899,223 @@ main() {
|
|
|
7895
7899
|
esac
|
|
7896
7900
|
}
|
|
7897
7901
|
|
|
7902
|
+
# Standalone project review - run quality gates on any codebase (v6.14.0)
|
|
7903
|
+
cmd_review() {
|
|
7904
|
+
local target_dir="."
|
|
7905
|
+
local json_output=""
|
|
7906
|
+
local verbose=""
|
|
7907
|
+
|
|
7908
|
+
while [[ $# -gt 0 ]]; do
|
|
7909
|
+
case "$1" in
|
|
7910
|
+
--json) json_output="true"; shift ;;
|
|
7911
|
+
--verbose|-v) verbose="true"; shift ;;
|
|
7912
|
+
--help|-h)
|
|
7913
|
+
echo -e "${BOLD}loki review${NC} - Run quality gates on any project (standalone)"
|
|
7914
|
+
echo ""
|
|
7915
|
+
echo "Usage: loki review [directory] [options]"
|
|
7916
|
+
echo ""
|
|
7917
|
+
echo "Arguments:"
|
|
7918
|
+
echo " directory Path to project (default: current directory)"
|
|
7919
|
+
echo ""
|
|
7920
|
+
echo "Options:"
|
|
7921
|
+
echo " --json Machine-readable JSON output"
|
|
7922
|
+
echo " --verbose, -v Show detailed output per gate"
|
|
7923
|
+
echo " --help, -h Show this help"
|
|
7924
|
+
echo ""
|
|
7925
|
+
echo "Gates: project-type, lint, tests, security, dependencies, structure"
|
|
7926
|
+
echo "Exit code: 0 if all pass, 1 if any fail"
|
|
7927
|
+
return 0
|
|
7928
|
+
;;
|
|
7929
|
+
-*) echo -e "${RED}Unknown option: $1${NC}"; return 1 ;;
|
|
7930
|
+
*) target_dir="$1"; shift ;;
|
|
7931
|
+
esac
|
|
7932
|
+
done
|
|
7933
|
+
|
|
7934
|
+
# Resolve and validate directory
|
|
7935
|
+
target_dir="$(cd "$target_dir" 2>/dev/null && pwd)" || {
|
|
7936
|
+
echo -e "${RED}Error: Directory not found: $target_dir${NC}"; return 1
|
|
7937
|
+
}
|
|
7938
|
+
|
|
7939
|
+
local project_type="unknown"
|
|
7940
|
+
local results=() # gate:status pairs
|
|
7941
|
+
local total_pass=0 total_warn=0 total_fail=0
|
|
7942
|
+
local gate_details=()
|
|
7943
|
+
|
|
7944
|
+
# Helper: record gate result
|
|
7945
|
+
_review_gate() {
|
|
7946
|
+
local gate="$1" status="$2" detail="${3:-}"
|
|
7947
|
+
results+=("$gate:$status")
|
|
7948
|
+
gate_details+=("$gate:$detail")
|
|
7949
|
+
case "$status" in
|
|
7950
|
+
PASS) total_pass=$((total_pass + 1)) ;;
|
|
7951
|
+
WARN) total_warn=$((total_warn + 1)) ;;
|
|
7952
|
+
FAIL) total_fail=$((total_fail + 1)) ;;
|
|
7953
|
+
esac
|
|
7954
|
+
}
|
|
7955
|
+
|
|
7956
|
+
# Gate 1: Detect project type
|
|
7957
|
+
if [ -f "$target_dir/package.json" ]; then
|
|
7958
|
+
project_type="node"
|
|
7959
|
+
elif [ -f "$target_dir/pyproject.toml" ] || [ -f "$target_dir/setup.py" ] || [ -f "$target_dir/requirements.txt" ]; then
|
|
7960
|
+
project_type="python"
|
|
7961
|
+
elif [ -f "$target_dir/go.mod" ]; then
|
|
7962
|
+
project_type="go"
|
|
7963
|
+
elif [ -f "$target_dir/Cargo.toml" ]; then
|
|
7964
|
+
project_type="rust"
|
|
7965
|
+
fi
|
|
7966
|
+
if [ "$project_type" != "unknown" ]; then
|
|
7967
|
+
_review_gate "project-type" "PASS" "Detected: $project_type"
|
|
7968
|
+
else
|
|
7969
|
+
_review_gate "project-type" "WARN" "Could not detect project type"
|
|
7970
|
+
fi
|
|
7971
|
+
|
|
7972
|
+
# Gate 2: Lint check
|
|
7973
|
+
local lint_output="" lint_status="PASS"
|
|
7974
|
+
case "$project_type" in
|
|
7975
|
+
node)
|
|
7976
|
+
if [ -f "$target_dir/.eslintrc.js" ] || [ -f "$target_dir/.eslintrc.json" ] || [ -f "$target_dir/.eslintrc.yml" ] || [ -f "$target_dir/eslint.config.js" ] || [ -f "$target_dir/eslint.config.mjs" ]; then
|
|
7977
|
+
lint_output=$(cd "$target_dir" && npx eslint . --max-warnings=0 2>&1) || lint_status="FAIL"
|
|
7978
|
+
else
|
|
7979
|
+
lint_output="No ESLint config found"; lint_status="WARN"
|
|
7980
|
+
fi ;;
|
|
7981
|
+
python)
|
|
7982
|
+
if command -v ruff &>/dev/null; then
|
|
7983
|
+
lint_output=$(cd "$target_dir" && ruff check . 2>&1) || lint_status="FAIL"
|
|
7984
|
+
elif command -v pylint &>/dev/null; then
|
|
7985
|
+
lint_output=$(cd "$target_dir" && pylint --recursive=y . 2>&1) || lint_status="FAIL"
|
|
7986
|
+
else
|
|
7987
|
+
lint_output="No linter available (install ruff or pylint)"; lint_status="WARN"
|
|
7988
|
+
fi ;;
|
|
7989
|
+
go)
|
|
7990
|
+
if command -v golangci-lint &>/dev/null; then
|
|
7991
|
+
lint_output=$(cd "$target_dir" && golangci-lint run 2>&1) || lint_status="FAIL"
|
|
7992
|
+
else
|
|
7993
|
+
lint_output=$(cd "$target_dir" && go vet ./... 2>&1) || lint_status="FAIL"
|
|
7994
|
+
fi ;;
|
|
7995
|
+
rust)
|
|
7996
|
+
lint_output=$(cd "$target_dir" && cargo clippy -- -D warnings 2>&1) || lint_status="FAIL"
|
|
7997
|
+
;;
|
|
7998
|
+
*) lint_output="Skipped (unknown project type)"; lint_status="WARN" ;;
|
|
7999
|
+
esac
|
|
8000
|
+
_review_gate "lint" "$lint_status" "$lint_output"
|
|
8001
|
+
|
|
8002
|
+
# Gate 3: Tests
|
|
8003
|
+
local test_output="" test_status="PASS"
|
|
8004
|
+
case "$project_type" in
|
|
8005
|
+
node)
|
|
8006
|
+
if grep -q '"test"' "$target_dir/package.json" 2>/dev/null; then
|
|
8007
|
+
test_output=$(cd "$target_dir" && npm test 2>&1) || test_status="FAIL"
|
|
8008
|
+
else
|
|
8009
|
+
test_output="No test script in package.json"; test_status="WARN"
|
|
8010
|
+
fi ;;
|
|
8011
|
+
python)
|
|
8012
|
+
if command -v pytest &>/dev/null; then
|
|
8013
|
+
test_output=$(cd "$target_dir" && pytest --tb=short 2>&1) || test_status="FAIL"
|
|
8014
|
+
else
|
|
8015
|
+
test_output="pytest not available"; test_status="WARN"
|
|
8016
|
+
fi ;;
|
|
8017
|
+
go) test_output=$(cd "$target_dir" && go test ./... 2>&1) || test_status="FAIL" ;;
|
|
8018
|
+
rust) test_output=$(cd "$target_dir" && cargo test 2>&1) || test_status="FAIL" ;;
|
|
8019
|
+
*) test_output="Skipped (unknown project type)"; test_status="WARN" ;;
|
|
8020
|
+
esac
|
|
8021
|
+
_review_gate "tests" "$test_status" "$test_output"
|
|
8022
|
+
|
|
8023
|
+
# Gate 4: Security - grep for hardcoded secrets
|
|
8024
|
+
local secret_output="" secret_status="PASS"
|
|
8025
|
+
local secret_patterns='(API_KEY|SECRET_KEY|PASSWORD|TOKEN|PRIVATE_KEY)\s*[=:]\s*["\x27][A-Za-z0-9+/=_-]{8,}'
|
|
8026
|
+
secret_output=$(grep -rEn "$secret_patterns" "$target_dir" \
|
|
8027
|
+
--include="*.js" --include="*.ts" --include="*.py" --include="*.go" --include="*.rs" \
|
|
8028
|
+
--include="*.jsx" --include="*.tsx" --include="*.java" --include="*.rb" \
|
|
8029
|
+
--exclude-dir=node_modules --exclude-dir=.git --exclude-dir=vendor \
|
|
8030
|
+
--exclude-dir=__pycache__ --exclude-dir=.venv --exclude-dir=target 2>/dev/null) || true
|
|
8031
|
+
if [ -n "$secret_output" ]; then
|
|
8032
|
+
secret_status="FAIL"
|
|
8033
|
+
secret_output="Potential hardcoded secrets found:
|
|
8034
|
+
$secret_output"
|
|
8035
|
+
else
|
|
8036
|
+
secret_output="No hardcoded secrets detected"
|
|
8037
|
+
fi
|
|
8038
|
+
_review_gate "security" "$secret_status" "$secret_output"
|
|
8039
|
+
|
|
8040
|
+
# Gate 5: Dependency audit
|
|
8041
|
+
local dep_output="" dep_status="PASS"
|
|
8042
|
+
case "$project_type" in
|
|
8043
|
+
node)
|
|
8044
|
+
if [ -f "$target_dir/package-lock.json" ] || [ -f "$target_dir/yarn.lock" ]; then
|
|
8045
|
+
dep_output=$(cd "$target_dir" && npm audit --production 2>&1) || dep_status="WARN"
|
|
8046
|
+
else
|
|
8047
|
+
dep_output="No lockfile found"; dep_status="WARN"
|
|
8048
|
+
fi ;;
|
|
8049
|
+
python)
|
|
8050
|
+
if command -v pip-audit &>/dev/null; then
|
|
8051
|
+
dep_output=$(cd "$target_dir" && pip-audit 2>&1) || dep_status="WARN"
|
|
8052
|
+
else
|
|
8053
|
+
dep_output="pip-audit not available"; dep_status="WARN"
|
|
8054
|
+
fi ;;
|
|
8055
|
+
*) dep_output="No dependency audit available for $project_type"; dep_status="WARN" ;;
|
|
8056
|
+
esac
|
|
8057
|
+
_review_gate "dependencies" "$dep_status" "$dep_output"
|
|
8058
|
+
|
|
8059
|
+
# Gate 6: Structure check
|
|
8060
|
+
local struct_output="" struct_status="PASS" struct_issues=()
|
|
8061
|
+
[ ! -f "$target_dir/README.md" ] && [ ! -f "$target_dir/README.rst" ] && [ ! -f "$target_dir/README" ] && struct_issues+=("Missing README")
|
|
8062
|
+
local file_count
|
|
8063
|
+
file_count=$(find "$target_dir" -type f -not -path '*/.git/*' -not -path '*/node_modules/*' -not -path '*/vendor/*' -not -path '*/__pycache__/*' -not -path '*/.venv/*' -not -path '*/target/*' 2>/dev/null | wc -l | tr -d ' ')
|
|
8064
|
+
[ "$file_count" -gt 5000 ] && struct_issues+=("Large project: $file_count files")
|
|
8065
|
+
local huge_files
|
|
8066
|
+
huge_files=$(find "$target_dir" -type f -size +1M -not -path '*/.git/*' -not -path '*/node_modules/*' -not -path '*/vendor/*' -not -path '*/target/*' 2>/dev/null | head -5)
|
|
8067
|
+
[ -n "$huge_files" ] && struct_issues+=("Files >1MB found: $(echo "$huge_files" | wc -l | tr -d ' ')")
|
|
8068
|
+
if [ ${#struct_issues[@]} -gt 0 ]; then
|
|
8069
|
+
struct_status="WARN"
|
|
8070
|
+
struct_output=$(printf '%s\n' "${struct_issues[@]}")
|
|
8071
|
+
else
|
|
8072
|
+
struct_output="README present, $file_count files, no oversized files"
|
|
8073
|
+
fi
|
|
8074
|
+
_review_gate "structure" "$struct_status" "$struct_output"
|
|
8075
|
+
|
|
8076
|
+
# Output results
|
|
8077
|
+
if [ -n "$json_output" ]; then
|
|
8078
|
+
local gates_json="["
|
|
8079
|
+
local first="true"
|
|
8080
|
+
for r in "${results[@]}"; do
|
|
8081
|
+
local gate="${r%%:*}" status="${r#*:}"
|
|
8082
|
+
[ "$first" = "true" ] && first="" || gates_json+=","
|
|
8083
|
+
gates_json+="{\"gate\":\"$gate\",\"status\":\"$status\"}"
|
|
8084
|
+
done
|
|
8085
|
+
gates_json+="]"
|
|
8086
|
+
printf '{"directory":"%s","project_type":"%s","pass":%d,"warn":%d,"fail":%d,"gates":%s}\n' \
|
|
8087
|
+
"$target_dir" "$project_type" "$total_pass" "$total_warn" "$total_fail" "$gates_json"
|
|
8088
|
+
else
|
|
8089
|
+
echo -e "${BOLD}Loki Review: $target_dir${NC}"
|
|
8090
|
+
echo -e "Project type: ${CYAN}$project_type${NC}"
|
|
8091
|
+
echo "---"
|
|
8092
|
+
for r in "${results[@]}"; do
|
|
8093
|
+
local gate="${r%%:*}" status="${r#*:}"
|
|
8094
|
+
case "$status" in
|
|
8095
|
+
PASS) echo -e " ${GREEN}[PASS]${NC} $gate" ;;
|
|
8096
|
+
WARN) echo -e " ${YELLOW}[WARN]${NC} $gate" ;;
|
|
8097
|
+
FAIL) echo -e " ${RED}[FAIL]${NC} $gate" ;;
|
|
8098
|
+
esac
|
|
8099
|
+
done
|
|
8100
|
+
echo "---"
|
|
8101
|
+
echo -e "Results: ${GREEN}$total_pass passed${NC}, ${YELLOW}$total_warn warnings${NC}, ${RED}$total_fail failed${NC}"
|
|
8102
|
+
|
|
8103
|
+
if [ -n "$verbose" ]; then
|
|
8104
|
+
echo ""
|
|
8105
|
+
echo -e "${BOLD}Details:${NC}"
|
|
8106
|
+
for d in "${gate_details[@]}"; do
|
|
8107
|
+
local gate="${d%%:*}" detail="${d#*:}"
|
|
8108
|
+
echo -e "\n${CYAN}[$gate]${NC}"
|
|
8109
|
+
echo "$detail" | head -30
|
|
8110
|
+
done
|
|
8111
|
+
fi
|
|
8112
|
+
fi
|
|
8113
|
+
|
|
8114
|
+
# Exit code: 1 if any failures
|
|
8115
|
+
[ "$total_fail" -gt 0 ] && return 1
|
|
8116
|
+
return 0
|
|
8117
|
+
}
|
|
8118
|
+
|
|
7898
8119
|
# Worktree management (v6.7.0)
|
|
7899
8120
|
cmd_worktree() {
|
|
7900
8121
|
local subcommand="${1:-list}"
|
package/dashboard/__init__.py
CHANGED
package/docs/INSTALLATION.md
CHANGED
package/mcp/__init__.py
CHANGED