loki-mode 9.51.1 → 9.53.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 +3 -2
- package/SKILL.md +3 -3
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +93 -53
- package/autonomy/lib/workspace_diff.py +18 -1
- package/autonomy/loki +212 -35
- package/autonomy/receipt_jwt.py +7 -0
- package/autonomy/run.sh +79 -30
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +2 -2
- package/docs/LOKI-10-BUILD-PROMPT.md +350 -0
- package/docs/SIGNED-RECEIPTS.md +9 -6
- package/docs/V10-RESEARCH.md +81 -0
- package/docs/V10-VISION.md +161 -0
- package/docs/exit-codes.md +41 -0
- package/docs/v10/BACKLOG.md +95 -0
- package/docs/v10/DECISIONS.md +52 -0
- package/docs/v10/FOUNDER-QUEUE.md +13 -0
- package/docs/v10/METRICS.md +47 -0
- package/docs/v10/PROGRESS.md +49 -0
- package/loki-ts/dist/loki.js +411 -404
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/tools/verify-chain.py +4 -1
package/autonomy/run.sh
CHANGED
|
@@ -2678,7 +2678,7 @@ _advance_current_phase() {
|
|
|
2678
2678
|
[ -f "$orch" ] || return 0
|
|
2679
2679
|
# Values are passed via argv (not interpolated into the source) so a phase or
|
|
2680
2680
|
# path containing quotes can never break or inject into the python.
|
|
2681
|
-
python3 -c "
|
|
2681
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
2682
2682
|
import json, sys
|
|
2683
2683
|
f, phase = sys.argv[1], sys.argv[2]
|
|
2684
2684
|
try:
|
|
@@ -4377,7 +4377,7 @@ _loki_receipt_facts() {
|
|
|
4377
4377
|
local pj="$loki_dir/proofs/$rid/proof.json"
|
|
4378
4378
|
[ -f "$pj" ] || return 0
|
|
4379
4379
|
local headline=""
|
|
4380
|
-
headline="$(python3 -c "
|
|
4380
|
+
headline="$(python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
4381
4381
|
import json, sys
|
|
4382
4382
|
try:
|
|
4383
4383
|
d = json.load(open(sys.argv[1]))
|
|
@@ -4999,7 +4999,7 @@ except Exception:
|
|
|
4999
4999
|
_LOKI_CS_ASSUMPTIONS_HIGH="$assumptions_high" \
|
|
5000
5000
|
_LOKI_CS_OUT_FILE="$loki_dir/state/completion.json" \
|
|
5001
5001
|
_LOKI_CS_LAST_ERROR="$loki_dir/state/LAST_ERROR.json" \
|
|
5002
|
-
python3 -c "
|
|
5002
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
5003
5003
|
import json, os, tempfile
|
|
5004
5004
|
out = os.environ['_LOKI_CS_OUT_FILE']
|
|
5005
5005
|
def i(v):
|
|
@@ -5219,7 +5219,7 @@ print_completion_card() {
|
|
|
5219
5219
|
# split would collapse adjacent empties). Any failure leaves the card
|
|
5220
5220
|
# unrendered. Trailing-newline guard: NUL-free, fields are single-line.
|
|
5221
5221
|
local _fields
|
|
5222
|
-
_fields="$(python3 -c "
|
|
5222
|
+
_fields="$(python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
5223
5223
|
import json,sys
|
|
5224
5224
|
try:
|
|
5225
5225
|
d=json.load(open(sys.argv[1]))
|
|
@@ -5541,7 +5541,8 @@ validate_exec_manifest_result() {
|
|
|
5541
5541
|
result_file=$(mktemp "${TARGET_DIR}/.loki/.exec-manifest-result.XXXXXX") || return 1
|
|
5542
5542
|
LOKI_RESULT_FILE="$result_file" LOKI_RESULT_STREAM="$stream_name" \
|
|
5543
5543
|
LOKI_RESULT_BASE="$base_sha" LOKI_RESULT_BRANCH="$branch" \
|
|
5544
|
-
LOKI_RESULT_REPO="$TARGET_DIR" python3 <<'PY'
|
|
5544
|
+
LOKI_RESULT_REPO="$TARGET_DIR" python3 -E - <<'PY'
|
|
5545
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
5545
5546
|
import json, os, subprocess
|
|
5546
5547
|
paths = subprocess.check_output(
|
|
5547
5548
|
["git", "-C", os.environ["LOKI_RESULT_REPO"], "diff", "--name-only",
|
|
@@ -8098,7 +8099,7 @@ generate_proof_of_run() {
|
|
|
8098
8099
|
ITERATION_COUNT="${ITERATION_COUNT:-0}" \
|
|
8099
8100
|
PROVIDER_NAME="$provider" \
|
|
8100
8101
|
PRD_PATH="${prd_path:-}" \
|
|
8101
|
-
python3 "$gen" \
|
|
8102
|
+
python3 -E "$gen" \
|
|
8102
8103
|
--loki-dir "$loki_dir" \
|
|
8103
8104
|
--loki-version "$ver" \
|
|
8104
8105
|
--provider "$provider" \
|
|
@@ -8125,7 +8126,7 @@ generate_proof_of_run() {
|
|
|
8125
8126
|
ITERATION_COUNT="${ITERATION_COUNT:-0}" \
|
|
8126
8127
|
PROVIDER_NAME="$provider" \
|
|
8127
8128
|
PRD_PATH="${prd_path:-}" \
|
|
8128
|
-
python3 "$gen" \
|
|
8129
|
+
python3 -E "$gen" \
|
|
8129
8130
|
--loki-dir "$loki_dir" \
|
|
8130
8131
|
--loki-version "$ver" \
|
|
8131
8132
|
--provider "$provider" \
|
|
@@ -9132,6 +9133,21 @@ setup_agent_branch() {
|
|
|
9132
9133
|
|
|
9133
9134
|
log_info "Branch protection enabled - creating agent branch: $branch_name (base: $cur)"
|
|
9134
9135
|
|
|
9136
|
+
# Record the user's own untracked (not ignored) files, repo-wide,
|
|
9137
|
+
# NUL-delimited and relative to the repo top, so commit_session_changes
|
|
9138
|
+
# and the receipt (autonomy/lib/workspace_diff.py) leave them alone. Taken
|
|
9139
|
+
# only when a branch is minted: on resume, untracked files can be the
|
|
9140
|
+
# agent's own uncommitted work. .loki/ is self-ignored above.
|
|
9141
|
+
local top="" snap=".loki/state/preexisting-untracked.z"
|
|
9142
|
+
if top="$(git rev-parse --show-toplevel 2>/dev/null)" \
|
|
9143
|
+
&& git -C "$top" ls-files -z --others --exclude-standard > "$snap.tmp" 2>/dev/null \
|
|
9144
|
+
&& mv -f "$snap.tmp" "$snap" 2>/dev/null; then
|
|
9145
|
+
:
|
|
9146
|
+
else
|
|
9147
|
+
rm -f "$snap.tmp" "$snap" 2>/dev/null
|
|
9148
|
+
log_warn "Could not record pre-existing untracked files; the session commit may include them"
|
|
9149
|
+
fi
|
|
9150
|
+
|
|
9135
9151
|
# Create and checkout the feature branch
|
|
9136
9152
|
if ! git checkout -b "$branch_name" 2>/dev/null; then
|
|
9137
9153
|
log_error "Failed to create agent branch: $branch_name"
|
|
@@ -9210,6 +9226,24 @@ commit_session_changes() {
|
|
|
9210
9226
|
':!*.key' ':!*.pem' ':!*.p12' ':!*.keystore' \
|
|
9211
9227
|
':!id_rsa*' ':!*.token' ':!credentials*' 2>/dev/null || true
|
|
9212
9228
|
|
|
9229
|
+
# Unstage exactly the files that were untracked when the branch was minted
|
|
9230
|
+
# (setup_agent_branch): they are the user's, not this session's work, and
|
|
9231
|
+
# committing them here would delete them from disk on a later checkout of
|
|
9232
|
+
# the base. Agent-created files stay staged. Skip an empty snapshot: an
|
|
9233
|
+
# empty --pathspec-from-file resets the WHOLE index. No snapshot (older
|
|
9234
|
+
# session): behave as before. If the unstage fails (git < 2.25), commit
|
|
9235
|
+
# nothing rather than sweep the user's files in.
|
|
9236
|
+
local preexisting="$PWD/.loki/state/preexisting-untracked.z" top=""
|
|
9237
|
+
if [ -s "$preexisting" ]; then
|
|
9238
|
+
if ! { top="$(git rev-parse --show-toplevel 2>/dev/null)" \
|
|
9239
|
+
&& git -C "$top" --literal-pathspecs reset -q \
|
|
9240
|
+
--pathspec-from-file="$preexisting" --pathspec-file-nul >/dev/null 2>&1; }; then
|
|
9241
|
+
git reset -q >/dev/null 2>&1 || true
|
|
9242
|
+
log_warn "Left uncommitted: could not exclude your pre-existing untracked files from the session commit (needs git 2.25+). Review and commit manually."
|
|
9243
|
+
return 0
|
|
9244
|
+
fi
|
|
9245
|
+
fi
|
|
9246
|
+
|
|
9213
9247
|
# Nothing staged = clean no-op, never an error.
|
|
9214
9248
|
if git diff --cached --quiet 2>/dev/null; then
|
|
9215
9249
|
return 0
|
|
@@ -10227,7 +10261,8 @@ _loki_supervised_build_result_passes() {
|
|
|
10227
10261
|
local result_file="$1"
|
|
10228
10262
|
! loki_is_supervised_simple_web && return 0
|
|
10229
10263
|
[ -s "$result_file" ] || return 1
|
|
10230
|
-
python3 - "$result_file" <<'PYEOF' 2>/dev/null
|
|
10264
|
+
python3 -E - "$result_file" <<'PYEOF' 2>/dev/null
|
|
10265
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
10231
10266
|
import json
|
|
10232
10267
|
import sys
|
|
10233
10268
|
|
|
@@ -10712,7 +10747,8 @@ SAEMPTYEOF
|
|
|
10712
10747
|
# not product-specific copy or design opinions.
|
|
10713
10748
|
local _ui_contract_out="" _ui_contract_rc=0
|
|
10714
10749
|
_ui_contract_out=$(
|
|
10715
|
-
_LOKI_CHANGED_FILES="$changed_files" python3 - "${TARGET_DIR:-.}" <<'PYEOF' 2>/dev/null
|
|
10750
|
+
_LOKI_CHANGED_FILES="$changed_files" python3 -E - "${TARGET_DIR:-.}" <<'PYEOF' 2>/dev/null
|
|
10751
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
10716
10752
|
import os
|
|
10717
10753
|
import re
|
|
10718
10754
|
import sys
|
|
@@ -10778,8 +10814,14 @@ PYEOF
|
|
|
10778
10814
|
[ -f "${TARGET_DIR:-.}/$f" ] || continue
|
|
10779
10815
|
total_checked=$((total_checked + 1))
|
|
10780
10816
|
local _py_compile_rc=0
|
|
10817
|
+
# Same check as `python3 -m py_compile` (importlib's source_to_code
|
|
10818
|
+
# is compile(bytes, path, "exec", dont_inherit=True)), but it
|
|
10819
|
+
# writes no __pycache__/*.pyc into the user's repo, where the
|
|
10820
|
+
# session commit would pick it up. -E and the sys.path filter
|
|
10821
|
+
# (D7): the repo under check must not supply modules to the gate.
|
|
10781
10822
|
LOKI_DEADLINE_IDLE_TIMEOUT=0 _loki_with_deadline "$gate_timeout" \
|
|
10782
|
-
python3 -
|
|
10823
|
+
python3 -E -c 'import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]; compile(open(sys.argv[1], "rb").read(), sys.argv[1], "exec", dont_inherit=True)' \
|
|
10824
|
+
"${TARGET_DIR:-.}/$f" 2>&1 || _py_compile_rc=$?
|
|
10783
10825
|
if [ "$_py_compile_rc" -ne 0 ]; then
|
|
10784
10826
|
findings=$((findings + 1))
|
|
10785
10827
|
if [ "$_py_compile_rc" -eq 124 ]; then
|
|
@@ -11096,7 +11138,7 @@ SECEMPTY
|
|
|
11096
11138
|
|
|
11097
11139
|
# Run the scanner. exit 0 = no findings, 1 = findings, 2 = bad input.
|
|
11098
11140
|
local raw rc=0
|
|
11099
|
-
raw=$(python3 "$scanner" "${TARGET_DIR:-.}" --json 2>/dev/null) || rc=$?
|
|
11141
|
+
raw=$(python3 -E "$scanner" "${TARGET_DIR:-.}" --json 2>/dev/null) || rc=$?
|
|
11100
11142
|
if [ "$rc" -eq 2 ] || [ -z "$raw" ]; then
|
|
11101
11143
|
cat > "$out_file" << 'SECEMPTY'
|
|
11102
11144
|
{"rules_version":null,"findings":[],"summary":{"total":0,"by_severity":{}},"skipped":"scanner-error"}
|
|
@@ -11110,7 +11152,7 @@ SECEMPTY
|
|
|
11110
11152
|
# It prints a final line: ACTIVE_HIGH=<n>\tACTIVE_TOTAL=<n>\tWAIVED=<n>
|
|
11111
11153
|
# and writes the enriched receipt (findings carry a "waived" bool).
|
|
11112
11154
|
local verdict
|
|
11113
|
-
verdict=$(_SEC_RAW="$raw" _SEC_WAIVERS="$waivers_file" _SEC_OUT="$out_file" python3 -c '
|
|
11155
|
+
verdict=$(_SEC_RAW="$raw" _SEC_WAIVERS="$waivers_file" _SEC_OUT="$out_file" python3 -E -c 'import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
11114
11156
|
import json, os, sys
|
|
11115
11157
|
raw = os.environ.get("_SEC_RAW", "")
|
|
11116
11158
|
waivers_file = os.environ.get("_SEC_WAIVERS", "")
|
|
@@ -11610,7 +11652,7 @@ measure_test_coverage() {
|
|
|
11610
11652
|
--coverage.reportsDirectory=.loki/quality/vitest-cov >/dev/null 2>&1) || true
|
|
11611
11653
|
local f="$target_dir/.loki/quality/vitest-cov/coverage-summary.json"
|
|
11612
11654
|
if [ -f "$f" ]; then
|
|
11613
|
-
COVERAGE_PCT=$(_LOKI_COV_F="$f" python3 -c "
|
|
11655
|
+
COVERAGE_PCT=$(_LOKI_COV_F="$f" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
11614
11656
|
import json, os, sys
|
|
11615
11657
|
try:
|
|
11616
11658
|
d=json.load(open(os.environ['_LOKI_COV_F']))
|
|
@@ -11629,7 +11671,7 @@ except Exception:
|
|
|
11629
11671
|
--coverageDirectory=.loki/quality/jest-cov --passWithNoTests >/dev/null 2>&1) || true
|
|
11630
11672
|
local f="$target_dir/.loki/quality/jest-cov/coverage-summary.json"
|
|
11631
11673
|
if [ -f "$f" ]; then
|
|
11632
|
-
COVERAGE_PCT=$(_LOKI_COV_F="$f" python3 -c "
|
|
11674
|
+
COVERAGE_PCT=$(_LOKI_COV_F="$f" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
11633
11675
|
import json, os, sys
|
|
11634
11676
|
try:
|
|
11635
11677
|
d=json.load(open(os.environ['_LOKI_COV_F']))
|
|
@@ -11649,7 +11691,7 @@ except Exception:
|
|
|
11649
11691
|
_loki_run_pytest_with_timeout "$target_dir" \
|
|
11650
11692
|
--cov --cov-report="json:$pyc_json" -q >/dev/null 2>&1 || true
|
|
11651
11693
|
if [ -f "$pyc_json" ]; then
|
|
11652
|
-
COVERAGE_PCT=$(_LOKI_COV_F="$pyc_json" python3 -c "
|
|
11694
|
+
COVERAGE_PCT=$(_LOKI_COV_F="$pyc_json" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
11653
11695
|
import json, os, sys
|
|
11654
11696
|
try:
|
|
11655
11697
|
d=json.load(open(os.environ['_LOKI_COV_F']))
|
|
@@ -11689,7 +11731,7 @@ except Exception:
|
|
|
11689
11731
|
local out
|
|
11690
11732
|
out=$(cd "$target_dir" && timeout "$gate_timeout" cargo llvm-cov --json 2>/dev/null) || true
|
|
11691
11733
|
if [ -n "$out" ]; then
|
|
11692
|
-
COVERAGE_PCT=$(_LOKI_COV_JSON="$out" python3 -c "
|
|
11734
|
+
COVERAGE_PCT=$(_LOKI_COV_JSON="$out" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
11693
11735
|
import json, os, sys
|
|
11694
11736
|
try:
|
|
11695
11737
|
d=json.loads(os.environ['_LOKI_COV_JSON'])
|
|
@@ -12412,7 +12454,7 @@ TREOF
|
|
|
12412
12454
|
local cov_below=false
|
|
12413
12455
|
if [ "$COVERAGE_MEASURED" = "true" ] && [ -n "$COVERAGE_PCT" ]; then
|
|
12414
12456
|
# Float-safe compare via python3 (pct may be e.g. 87.5).
|
|
12415
|
-
if _LOKI_COV_PCT="$COVERAGE_PCT" _LOKI_COV_MIN="$min_coverage" python3 -c "
|
|
12457
|
+
if _LOKI_COV_PCT="$COVERAGE_PCT" _LOKI_COV_MIN="$min_coverage" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
12416
12458
|
import os, sys
|
|
12417
12459
|
try:
|
|
12418
12460
|
pct=float(os.environ['_LOKI_COV_PCT']); mn=float(os.environ['_LOKI_COV_MIN'])
|
|
@@ -12437,7 +12479,7 @@ sys.exit(0 if pct < mn else 1)
|
|
|
12437
12479
|
_LOKI_COV_BLOCKED="$coverage_block" \
|
|
12438
12480
|
_LOKI_COV_RUNNER="$test_runner" \
|
|
12439
12481
|
_LOKI_COV_OUT="$quality_dir/coverage.json" \
|
|
12440
|
-
python3 -c "
|
|
12482
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
12441
12483
|
import json, os, tempfile
|
|
12442
12484
|
out=os.environ['_LOKI_COV_OUT']
|
|
12443
12485
|
measured = os.environ.get('_LOKI_COV_MEASURED','false') == 'true'
|
|
@@ -12498,7 +12540,7 @@ os.replace(tmp, out)
|
|
|
12498
12540
|
_LOKI_COV_BLOCKED="false" \
|
|
12499
12541
|
_LOKI_COV_RUNNER="$test_runner" \
|
|
12500
12542
|
_LOKI_COV_OUT="$quality_dir/coverage.json" \
|
|
12501
|
-
python3 -c "
|
|
12543
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
12502
12544
|
import json, os, tempfile
|
|
12503
12545
|
out=os.environ['_LOKI_COV_OUT']
|
|
12504
12546
|
measured = os.environ.get('_LOKI_COV_MEASURED','false') == 'true'
|
|
@@ -12767,7 +12809,7 @@ run_doc_quality_gate() {
|
|
|
12767
12809
|
local manifest="$project_dir/.loki/docs/docs-manifest.json"
|
|
12768
12810
|
if [ -f "$manifest" ]; then
|
|
12769
12811
|
local doc_sha
|
|
12770
|
-
doc_sha=$(python3 -c "import json; print(json.load(open('$manifest')).get('git_sha', ''))" 2>/dev/null)
|
|
12812
|
+
doc_sha=$(python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json; print(json.load(open('$manifest')).get('git_sha', ''))" 2>/dev/null)
|
|
12771
12813
|
if [ -n "$doc_sha" ]; then
|
|
12772
12814
|
local behind
|
|
12773
12815
|
behind=$(git -C "$project_dir" rev-list --count "$doc_sha..HEAD" 2>/dev/null || echo "0")
|
|
@@ -13198,7 +13240,7 @@ enforce_lsp_diagnostics() {
|
|
|
13198
13240
|
fi
|
|
13199
13241
|
|
|
13200
13242
|
if [ -f "$lsp_file" ]; then
|
|
13201
|
-
verdict=$(_LOKI_LSP_FILE="$lsp_file" python3 -c '
|
|
13243
|
+
verdict=$(_LOKI_LSP_FILE="$lsp_file" python3 -E -c 'import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
13202
13244
|
import json, os, sys
|
|
13203
13245
|
try:
|
|
13204
13246
|
with open(os.environ["_LOKI_LSP_FILE"], encoding="utf-8") as handle:
|
|
@@ -13537,7 +13579,8 @@ council_verdicts_to_txt_files() {
|
|
|
13537
13579
|
local out_dir_env="$review_dir"
|
|
13538
13580
|
export LOKI_COUNCIL_OUT_DIR="$out_dir_env"
|
|
13539
13581
|
export LOKI_COUNCIL_VERDICTS_JSON="$verdicts_json"
|
|
13540
|
-
python3 << 'COUNCIL_WRITE'
|
|
13582
|
+
python3 -E - << 'COUNCIL_WRITE'
|
|
13583
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
13541
13584
|
import json
|
|
13542
13585
|
import os
|
|
13543
13586
|
import re
|
|
@@ -13626,6 +13669,9 @@ _run_managed_review_council() {
|
|
|
13626
13669
|
|
|
13627
13670
|
local result_json
|
|
13628
13671
|
result_json=$(python3 << 'MANAGED_REVIEW' 2>&1
|
|
13672
|
+
# Drops the cwd (the agent's repo) from sys.path. No -E here: the
|
|
13673
|
+
# LOKI_MANAGED_REVIEW_FAKE_MODULE test hook below is found through PYTHONPATH.
|
|
13674
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
13629
13675
|
import json
|
|
13630
13676
|
import os
|
|
13631
13677
|
import sys
|
|
@@ -13724,7 +13770,7 @@ MANAGED_REVIEW
|
|
|
13724
13770
|
fi
|
|
13725
13771
|
|
|
13726
13772
|
local status
|
|
13727
|
-
status=$(printf '%s' "$result_json" | python3 -c "import json,sys; d=json.loads(sys.stdin.read() or '{}'); print(d.get('status',''))" 2>/dev/null || echo "")
|
|
13773
|
+
status=$(printf '%s' "$result_json" | python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json,sys; d=json.loads(sys.stdin.read() or '{}'); print(d.get('status',''))" 2>/dev/null || echo "")
|
|
13728
13774
|
|
|
13729
13775
|
if [ "$status" != "ok" ]; then
|
|
13730
13776
|
local reason
|
|
@@ -16384,7 +16430,8 @@ REVIEW_WAVE_TIMING
|
|
|
16384
16430
|
export LOKI_REVIEW_AGG_QSCORE="$quality_score"
|
|
16385
16431
|
export LOKI_REVIEW_AGG_QMED="$nonblocking_medium"
|
|
16386
16432
|
export LOKI_REVIEW_AGG_QLOW="$nonblocking_low"
|
|
16387
|
-
python3 << 'AGG_SCRIPT'
|
|
16433
|
+
python3 -E - << 'AGG_SCRIPT'
|
|
16434
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
16388
16435
|
import json, os
|
|
16389
16436
|
result = {
|
|
16390
16437
|
"review_id": os.environ["LOKI_REVIEW_AGG_ID"],
|
|
@@ -16527,7 +16574,8 @@ AGG_SCRIPT
|
|
|
16527
16574
|
|
|
16528
16575
|
_LOKI_DA_AGG_FILE="$review_dir/$review_id/aggregate.json" \
|
|
16529
16576
|
_LOKI_DA_STATUS="$da_status" _LOKI_DA_RC="$da_dispatch_rc" \
|
|
16530
|
-
_LOKI_DA_SPECULATIVE="$da_speculative" python3 <<'DA_AGG_PATCH' 2>/dev/null || true
|
|
16577
|
+
_LOKI_DA_SPECULATIVE="$da_speculative" python3 -E - <<'DA_AGG_PATCH' 2>/dev/null || true
|
|
16578
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
16531
16579
|
import json
|
|
16532
16580
|
import os
|
|
16533
16581
|
|
|
@@ -17895,7 +17943,7 @@ is_completed() {
|
|
|
17895
17943
|
# Check orchestrator state
|
|
17896
17944
|
if [ -f ".loki/state/orchestrator.json" ]; then
|
|
17897
17945
|
if command -v python3 &> /dev/null; then
|
|
17898
|
-
local phase=$(python3 -c "import json; print(json.load(open('.loki/state/orchestrator.json')).get('currentPhase', ''))" 2>/dev/null || echo "")
|
|
17946
|
+
local phase=$(python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json; print(json.load(open('.loki/state/orchestrator.json')).get('currentPhase', ''))" 2>/dev/null || echo "")
|
|
17899
17947
|
# Accept various completion states
|
|
17900
17948
|
if [ "$phase" = "COMPLETED" ] || [ "$phase" = "complete" ] || [ "$phase" = "finalized" ] || [ "$phase" = "growth-loop" ]; then
|
|
17901
17949
|
return 0
|
|
@@ -21909,7 +21957,8 @@ _loki_supervised_completion_gates_pass() {
|
|
|
21909
21957
|
local test_iteration="$quality_dir/.test-results.iter"
|
|
21910
21958
|
if [ ! -s "$test_results" ] || [ ! -s "$test_iteration" ] \
|
|
21911
21959
|
|| [ "$(tr -d '[:space:]' < "$test_iteration" 2>/dev/null)" != "${ITERATION_COUNT:-0}" ] \
|
|
21912
|
-
|| ! python3 - "$test_results" <<'PYEOF' 2>/dev/null
|
|
21960
|
+
|| ! python3 -E - "$test_results" <<'PYEOF' 2>/dev/null
|
|
21961
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
21913
21962
|
import json
|
|
21914
21963
|
import sys
|
|
21915
21964
|
|
|
@@ -27102,7 +27151,7 @@ main() {
|
|
|
27102
27151
|
local _terminal_status=""
|
|
27103
27152
|
local _terminal_state_file
|
|
27104
27153
|
_terminal_state_file="$(_loki_state_file)"
|
|
27105
|
-
_terminal_status=$(LOKI_STATE_FILE="$_terminal_state_file" python3 -c "import json, os; print(json.load(open(os.environ['LOKI_STATE_FILE'])).get('status',''))" 2>/dev/null || true)
|
|
27154
|
+
_terminal_status=$(LOKI_STATE_FILE="$_terminal_state_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json, os; print(json.load(open(os.environ['LOKI_STATE_FILE'])).get('status',''))" 2>/dev/null || true)
|
|
27106
27155
|
case "$_terminal_status" in
|
|
27107
27156
|
deterministic_gates_passed|council_approved|council_force_approved|completion_promise_fulfilled|reuse_already_satisfied)
|
|
27108
27157
|
if [ "$result" = "0" ]; then
|
|
@@ -27163,7 +27212,7 @@ main() {
|
|
|
27163
27212
|
# Refresh its durable files against the final HEAD without notifying twice.
|
|
27164
27213
|
local _completion_file="${TARGET_DIR:-.}/.loki/state/completion.json"
|
|
27165
27214
|
local _completion_outcome=""
|
|
27166
|
-
_completion_outcome=$(LOKI_COMPLETION_FILE="$_completion_file" python3 -c '
|
|
27215
|
+
_completion_outcome=$(LOKI_COMPLETION_FILE="$_completion_file" python3 -E -c 'import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
27167
27216
|
import json, os
|
|
27168
27217
|
try:
|
|
27169
27218
|
value = json.load(open(os.environ["LOKI_COMPLETION_FILE"], encoding="utf-8")).get("outcome", "")
|
|
@@ -27288,7 +27337,7 @@ except Exception:
|
|
|
27288
27337
|
if [ "${LOKI_DURABLE_STATE:-0}" = "1" ]; then
|
|
27289
27338
|
local _final_status _final_state_file
|
|
27290
27339
|
_final_state_file="$(_loki_state_file)"
|
|
27291
|
-
_final_status=$(LOKI_STATE_FILE="$_final_state_file" python3 -c "import json, os; print(json.load(open(os.environ['LOKI_STATE_FILE'])).get('status','unknown'))" 2>/dev/null || echo "unknown")
|
|
27340
|
+
_final_status=$(LOKI_STATE_FILE="$_final_state_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json, os; print(json.load(open(os.environ['LOKI_STATE_FILE'])).get('status','unknown'))" 2>/dev/null || echo "unknown")
|
|
27292
27341
|
case "$_final_status" in
|
|
27293
27342
|
council_approved|council_force_approved|deterministic_gates_passed|completion_promise_fulfilled|paused|interrupted|stopped)
|
|
27294
27343
|
result=0 ;;
|
package/dashboard/__init__.py
CHANGED
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
|
|
4
4
|
|
|
5
|
-
**Version:** v9.
|
|
5
|
+
**Version:** v9.53.0
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -443,7 +443,7 @@ provider works inside the container. Provide auth with your Anthropic API key:
|
|
|
443
443
|
# Run Loki Mode in Docker (Claude provider, API-key auth)
|
|
444
444
|
docker run --rm -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
|
|
445
445
|
-v $(pwd):/workspace -w /workspace \
|
|
446
|
-
asklokesh/loki-mode:
|
|
446
|
+
asklokesh/loki-mode:latest start ./my-spec.md
|
|
447
447
|
```
|
|
448
448
|
|
|
449
449
|
##### docker compose + .env (no host install)
|