loki-mode 9.52.0 → 9.54.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 +84 -48
- package/autonomy/council-v2.sh +13 -7
- package/autonomy/lib/done-recognition.sh +24 -16
- package/autonomy/lib/proof-check.sh +11 -3
- package/autonomy/lib/voter-agents.sh +8 -3
- package/autonomy/lib/workspace_diff.py +112 -1
- package/autonomy/prd-checklist.sh +19 -11
- package/autonomy/run.sh +336 -39
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/v10/BACKLOG.md +51 -0
- package/docs/v10/METRICS.md +3 -1
- package/docs/v10/PROGRESS.md +35 -4
- package/loki-ts/dist/loki.js +323 -322
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v9.
|
|
6
|
+
# Loki Mode v9.54.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -470,4 +470,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
470
470
|
|
|
471
471
|
---
|
|
472
472
|
|
|
473
|
-
**v9.
|
|
473
|
+
**v9.54.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
9.
|
|
1
|
+
9.54.0
|
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
# - Multi-agent debate: Voting beats unanimous (+13.2%), KS adaptive stopping
|
|
20
20
|
# - NVIDIA ToolOrchestra: Efficiency metrics for agent tool use
|
|
21
21
|
#
|
|
22
|
+
# Inline Python (D7): the council runs with the cwd inside the agent's repo, so
|
|
23
|
+
# every "python3 -c" / "python3 -" here runs -E (a PYTHONPATH empty component
|
|
24
|
+
# would load a committed sitecustomize.py) and drops '' and '.' from sys.path
|
|
25
|
+
# before any other import (a committed json.py would print the verdict).
|
|
26
|
+
# Pinned by tests/moat/p2-honest-verdict.sh P2.council-readers-not-shadowed.
|
|
27
|
+
#
|
|
22
28
|
# Environment Variables:
|
|
23
29
|
# LOKI_COUNCIL_ENABLED - Enable completion council (default: true)
|
|
24
30
|
# LOKI_COUNCIL_SIZE - Number of council members (default: 3)
|
|
@@ -371,7 +377,7 @@ council_track_iteration() {
|
|
|
371
377
|
_COUNCIL_ITERATION="${ITERATION_COUNT:-0}" \
|
|
372
378
|
_COUNCIL_FILES_CHANGED="$files_changed" \
|
|
373
379
|
_COUNCIL_DIFF_HASH="$combined_hash" \
|
|
374
|
-
python3 -c "
|
|
380
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
375
381
|
import json, os
|
|
376
382
|
state_file = os.environ['_COUNCIL_STATE_FILE']
|
|
377
383
|
try:
|
|
@@ -453,7 +459,7 @@ _uncertainty_state_path() {
|
|
|
453
459
|
# Read uncertainty.json (or emit a default object if missing/corrupt) to stdout.
|
|
454
460
|
_uncertainty_read_state() {
|
|
455
461
|
local file="$1"
|
|
456
|
-
_UNC_FILE="$file" python3 -c "
|
|
462
|
+
_UNC_FILE="$file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
457
463
|
import json, os
|
|
458
464
|
f = os.environ['_UNC_FILE']
|
|
459
465
|
default = {
|
|
@@ -487,7 +493,7 @@ _uncertainty_write_state() {
|
|
|
487
493
|
dir="$(dirname "$file")"
|
|
488
494
|
mkdir -p "$dir" 2>/dev/null || true
|
|
489
495
|
tmp="${file}.tmp.$$"
|
|
490
|
-
if _UNC_PAYLOAD="$payload" _UNC_TMP="$tmp" python3 -c "
|
|
496
|
+
if _UNC_PAYLOAD="$payload" _UNC_TMP="$tmp" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
491
497
|
import json, os
|
|
492
498
|
payload = os.environ['_UNC_PAYLOAD']
|
|
493
499
|
tmp = os.environ['_UNC_TMP']
|
|
@@ -539,7 +545,7 @@ uncertainty_should_escalate() {
|
|
|
539
545
|
_UNC_SPLIT_ROUNDS="$split_rounds" \
|
|
540
546
|
_UNC_NOCHANGE_MIN="$nochange_min" \
|
|
541
547
|
_UNC_RING_SIZE="$ring_size" \
|
|
542
|
-
python3 -c "
|
|
548
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
543
549
|
import json, os
|
|
544
550
|
|
|
545
551
|
prior = json.loads(os.environ['_UNC_PRIOR'])
|
|
@@ -826,7 +832,7 @@ council_vote() {
|
|
|
826
832
|
local budget_exceeded=false
|
|
827
833
|
if [ "$total_issue_count" -gt 0 ] && [ "$COUNCIL_ERROR_BUDGET" != "0.0" ] && [ "$COUNCIL_ERROR_BUDGET" != "0" ]; then
|
|
828
834
|
# Check if non-blocking issue ratio exceeds the error budget
|
|
829
|
-
budget_exceeded=$(_NB="$non_blocking_count" _TOTAL="$total_issue_count" _BUDGET="$COUNCIL_ERROR_BUDGET" python3 -c "
|
|
835
|
+
budget_exceeded=$(_NB="$non_blocking_count" _TOTAL="$total_issue_count" _BUDGET="$COUNCIL_ERROR_BUDGET" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
830
836
|
import os
|
|
831
837
|
nb = int(os.environ['_NB'])
|
|
832
838
|
total = int(os.environ['_TOTAL'])
|
|
@@ -918,7 +924,7 @@ print('true' if ratio > budget else 'false')
|
|
|
918
924
|
_COUNCIL_REJECT="$reject_count" \
|
|
919
925
|
_COUNCIL_ITERATION="${ITERATION_COUNT:-0}" \
|
|
920
926
|
_COUNCIL_THRESHOLD="$effective_threshold" \
|
|
921
|
-
python3 -c "
|
|
927
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
922
928
|
import json, os
|
|
923
929
|
from datetime import datetime, timezone
|
|
924
930
|
state_file = os.environ['_COUNCIL_STATE_FILE']
|
|
@@ -1036,7 +1042,7 @@ council_write_transcript() {
|
|
|
1036
1042
|
_MEMBERS_DIR="$COUNCIL_STATE_DIR/votes/iteration-${iteration}" \
|
|
1037
1043
|
_THRESHOLD="$effective_threshold" \
|
|
1038
1044
|
_OUT="$transcript_file" \
|
|
1039
|
-
python3 -c "
|
|
1045
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1040
1046
|
import json, os, pathlib, re
|
|
1041
1047
|
|
|
1042
1048
|
iteration_id = os.environ['_IID']
|
|
@@ -1214,7 +1220,7 @@ EVIDENCE_SECTION
|
|
|
1214
1220
|
local queue_file=".loki/queue/${queue}.json"
|
|
1215
1221
|
if [ -f "$queue_file" ]; then
|
|
1216
1222
|
local count
|
|
1217
|
-
count=$(_QUEUE_FILE="$queue_file" python3 -c "import json, os; print(len(json.load(open(os.environ['_QUEUE_FILE']))))" 2>/dev/null || echo "?")
|
|
1223
|
+
count=$(_QUEUE_FILE="$queue_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json, os; print(len(json.load(open(os.environ['_QUEUE_FILE']))))" 2>/dev/null || echo "?")
|
|
1218
1224
|
echo "- ${queue}: $count tasks" >> "$evidence_file"
|
|
1219
1225
|
fi
|
|
1220
1226
|
done
|
|
@@ -1287,7 +1293,7 @@ EVIDENCE_SECTION
|
|
|
1287
1293
|
elif [ -f ".loki/verification/playwright-results.json" ]; then
|
|
1288
1294
|
echo "" >> "$evidence_file"
|
|
1289
1295
|
echo "## Playwright Smoke Test Results" >> "$evidence_file"
|
|
1290
|
-
_PW_RESULTS=".loki/verification/playwright-results.json" python3 -c "
|
|
1296
|
+
_PW_RESULTS=".loki/verification/playwright-results.json" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1291
1297
|
import json, os
|
|
1292
1298
|
try:
|
|
1293
1299
|
d = json.load(open(os.environ['_PW_RESULTS']))
|
|
@@ -1375,7 +1381,7 @@ council_checklist_gate() {
|
|
|
1375
1381
|
# council_heldout_gate at the ship gate, and surfacing them in this gate's
|
|
1376
1382
|
# block report would leak their identity back into the build loop.
|
|
1377
1383
|
local gate_result
|
|
1378
|
-
gate_result=$(_RESULTS_FILE="$results_file" _WAIVERS_FILE="$waivers_file" _HELDOUT_FILE="$heldout_file" python3 -c "
|
|
1384
|
+
gate_result=$(_RESULTS_FILE="$results_file" _WAIVERS_FILE="$waivers_file" _HELDOUT_FILE="$heldout_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1379
1385
|
import json, sys, os
|
|
1380
1386
|
|
|
1381
1387
|
results_file = os.environ['_RESULTS_FILE']
|
|
@@ -1438,13 +1444,13 @@ else:
|
|
|
1438
1444
|
local timestamp
|
|
1439
1445
|
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
1440
1446
|
local failures_json
|
|
1441
|
-
failures_json=$(_FAILURES="$failures" python3 -c "
|
|
1447
|
+
failures_json=$(_FAILURES="$failures" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1442
1448
|
import json, os
|
|
1443
1449
|
items = os.environ['_FAILURES'].split('|')
|
|
1444
1450
|
print(json.dumps(items))
|
|
1445
1451
|
" 2>/dev/null || echo '[]')
|
|
1446
1452
|
local critical_count
|
|
1447
|
-
critical_count=$(_FAILURES="$failures" python3 -c "
|
|
1453
|
+
critical_count=$(_FAILURES="$failures" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1448
1454
|
import os
|
|
1449
1455
|
print(len(os.environ['_FAILURES'].split('|')))
|
|
1450
1456
|
" 2>/dev/null || echo '0')
|
|
@@ -1514,7 +1520,7 @@ council_heldout_gate() {
|
|
|
1514
1520
|
# contain ':' or '|'); they are read separately from the held-out JSON block
|
|
1515
1521
|
# below in the BLOCK branch.
|
|
1516
1522
|
local gate_result
|
|
1517
|
-
gate_result=$(_RESULTS_FILE="$results_file" _HELDOUT_FILE="$heldout_file" _WAIVERS_FILE="$waivers_file" python3 -c "
|
|
1523
|
+
gate_result=$(_RESULTS_FILE="$results_file" _HELDOUT_FILE="$heldout_file" _WAIVERS_FILE="$waivers_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1518
1524
|
import json, sys, os
|
|
1519
1525
|
|
|
1520
1526
|
results_file = os.environ['_RESULTS_FILE']
|
|
@@ -1634,7 +1640,7 @@ print('%s %d %d' % (verdict, passed, failed))
|
|
|
1634
1640
|
if [ "$verdict" = "BLOCK" ]; then
|
|
1635
1641
|
# Read failing held-out titles directly from the data (colon/pipe-safe).
|
|
1636
1642
|
local titles_json titles_display
|
|
1637
|
-
titles_json=$(_RESULTS_FILE="$results_file" _HELDOUT_FILE="$heldout_file" _WAIVERS_FILE="$waivers_file" python3 -c "
|
|
1643
|
+
titles_json=$(_RESULTS_FILE="$results_file" _HELDOUT_FILE="$heldout_file" _WAIVERS_FILE="$waivers_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1638
1644
|
import json, os
|
|
1639
1645
|
results = json.load(open(os.environ['_RESULTS_FILE']))
|
|
1640
1646
|
heldout_ids = set(json.load(open(os.environ['_HELDOUT_FILE'])).get('held_out', []))
|
|
@@ -1653,7 +1659,7 @@ for cat in results.get('categories', []):
|
|
|
1653
1659
|
titles.append(item.get('title', iid))
|
|
1654
1660
|
print(json.dumps(titles[:5]))
|
|
1655
1661
|
" 2>/dev/null || echo '[]')
|
|
1656
|
-
titles_display=$(_T="$titles_json" python3 -c "
|
|
1662
|
+
titles_display=$(_T="$titles_json" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1657
1663
|
import json, os
|
|
1658
1664
|
try:
|
|
1659
1665
|
print(', '.join(json.loads(os.environ['_T'])))
|
|
@@ -1927,7 +1933,8 @@ council_evidence_gate() {
|
|
|
1927
1933
|
local test_inconclusive_reason=""
|
|
1928
1934
|
if [ -f "$tr_file" ]; then
|
|
1929
1935
|
local test_status
|
|
1930
|
-
test_status=$(_TR_FILE="$tr_file" python3 <<'PYEOF' 2>/dev/null || echo "INCONCLUSIVE:none:true"
|
|
1936
|
+
test_status=$(_TR_FILE="$tr_file" python3 -E -s - <<'PYEOF' 2>/dev/null || echo "INCONCLUSIVE:none:true"
|
|
1937
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
1931
1938
|
import json, os, sys
|
|
1932
1939
|
tr_file = os.environ['_TR_FILE']
|
|
1933
1940
|
try:
|
|
@@ -1954,7 +1961,10 @@ if runner == 'none':
|
|
|
1954
1961
|
elif passed is False:
|
|
1955
1962
|
print('FAIL:%s:false' % runner)
|
|
1956
1963
|
elif status == 'no_tests_run' or passed is not True:
|
|
1957
|
-
|
|
1964
|
+
# Both are INCONCLUSIVE; NO_PASS names the second: no boolean pass was
|
|
1965
|
+
# recorded at all (missing, null, or a non-boolean value), which is not a
|
|
1966
|
+
# zero-test run.
|
|
1967
|
+
print('%s:%s:true' % ('INCONCLUSIVE' if status == 'no_tests_run' else 'NO_PASS', runner))
|
|
1958
1968
|
else:
|
|
1959
1969
|
print('PASS:%s:true' % runner)
|
|
1960
1970
|
PYEOF
|
|
@@ -1985,6 +1995,13 @@ PYEOF
|
|
|
1985
1995
|
test_inconclusive="true"
|
|
1986
1996
|
test_inconclusive_reason="no_tests_executed"
|
|
1987
1997
|
fi
|
|
1998
|
+
# A real runner label but no boolean pass recorded: the same
|
|
1999
|
+
# pass-through INCONCLUSIVE, named for what it is. Not gated by the
|
|
2000
|
+
# opt-out either: an unrecorded outcome is never affirmative.
|
|
2001
|
+
if [ "$_verdict" = "NO_PASS" ]; then
|
|
2002
|
+
test_inconclusive="true"
|
|
2003
|
+
test_inconclusive_reason="no_pass_recorded"
|
|
2004
|
+
fi
|
|
1988
2005
|
else
|
|
1989
2006
|
# Missing test-results.json: no suite was recorded at all. Like the
|
|
1990
2007
|
# runner=="none" case this is not affirmative evidence, so classify it
|
|
@@ -2099,6 +2116,16 @@ INCONCLUSIVE_EOF
|
|
|
2099
2116
|
local _diff_ok _tests_ok
|
|
2100
2117
|
if [ "$diff_fails" = "true" ]; then _diff_ok="false"; else _diff_ok="true"; fi
|
|
2101
2118
|
if [ "$test_fails" = "true" ]; then _tests_ok="false"; else _tests_ok="true"; fi
|
|
2119
|
+
# BACKLOG 55: tests.pass is true only for affirmative evidence (a real
|
|
2120
|
+
# runner recorded a boolean pass and nothing downgraded it). $test_pass
|
|
2121
|
+
# itself is "true" for every inconclusive outcome (no runner, no results,
|
|
2122
|
+
# zero tests, no pass recorded, tautological), so it is not written raw.
|
|
2123
|
+
local _tests_pass_json='"inconclusive"'
|
|
2124
|
+
if [ "$test_fails" = "true" ]; then
|
|
2125
|
+
_tests_pass_json="false"
|
|
2126
|
+
elif [ "$test_inconclusive" != "true" ] && [ "$test_runner" != "none" ] && [ "$test_pass" = "true" ]; then
|
|
2127
|
+
_tests_pass_json="true"
|
|
2128
|
+
fi
|
|
2102
2129
|
# Proof-of-Function axes (nomock/persistence/auth) are declared later in
|
|
2103
2130
|
# the gate; default to "true"/"" when this helper runs before they are
|
|
2104
2131
|
# set (it never does in practice, but keep the write robust).
|
|
@@ -2122,7 +2149,7 @@ INCONCLUSIVE_EOF
|
|
|
2122
2149
|
"tests": {
|
|
2123
2150
|
"ok": $_tests_ok,
|
|
2124
2151
|
"runner": "$test_runner",
|
|
2125
|
-
"pass": $
|
|
2152
|
+
"pass": $_tests_pass_json,
|
|
2126
2153
|
"inconclusive": $test_inconclusive,
|
|
2127
2154
|
"inconclusive_reason": "$test_inconclusive_reason"
|
|
2128
2155
|
},
|
|
@@ -2175,7 +2202,8 @@ DETAILS_EOF
|
|
|
2175
2202
|
boot_inconclusive_reason="no_app_runner"
|
|
2176
2203
|
elif command -v python3 >/dev/null 2>&1; then
|
|
2177
2204
|
local _boot_status
|
|
2178
|
-
_boot_status=$(_HEALTH="$_health_file" _STATE="$_state_file" python3 <<'PYEOF' 2>/dev/null || echo "INCONCLUSIVE:parse_error"
|
|
2205
|
+
_boot_status=$(_HEALTH="$_health_file" _STATE="$_state_file" python3 -E -s - <<'PYEOF' 2>/dev/null || echo "INCONCLUSIVE:parse_error"
|
|
2206
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
2179
2207
|
import json, os
|
|
2180
2208
|
health_file = os.environ.get('_HEALTH', '')
|
|
2181
2209
|
state_file = os.environ.get('_STATE', '')
|
|
@@ -2338,7 +2366,8 @@ PYEOF
|
|
|
2338
2366
|
persist_inconclusive="true"; persist_inconclusive_reason="not_serveable"
|
|
2339
2367
|
elif command -v python3 >/dev/null 2>&1; then
|
|
2340
2368
|
local _p_status
|
|
2341
|
-
_p_status=$(_PF="$_proof_file" _ITER="${ITERATION_COUNT:-0}" python3 <<'PYEOF' 2>/dev/null || echo "MISSING"
|
|
2369
|
+
_p_status=$(_PF="$_proof_file" _ITER="${ITERATION_COUNT:-0}" python3 -E -s - <<'PYEOF' 2>/dev/null || echo "MISSING"
|
|
2370
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
2342
2371
|
import json, os
|
|
2343
2372
|
p = os.environ['_PF']
|
|
2344
2373
|
if not os.path.isfile(p):
|
|
@@ -2401,7 +2430,8 @@ PYEOF
|
|
|
2401
2430
|
auth_inconclusive="true"; auth_inconclusive_reason="not_serveable"
|
|
2402
2431
|
elif command -v python3 >/dev/null 2>&1; then
|
|
2403
2432
|
local _a_status
|
|
2404
|
-
_a_status=$(_PF="$_proof_file" _STRICT="${LOKI_PROOF_AUTH_STRICT:-1}" _ITER="${ITERATION_COUNT:-0}" python3 <<'PYEOF' 2>/dev/null || echo "MISSING"
|
|
2433
|
+
_a_status=$(_PF="$_proof_file" _STRICT="${LOKI_PROOF_AUTH_STRICT:-1}" _ITER="${ITERATION_COUNT:-0}" python3 -E -s - <<'PYEOF' 2>/dev/null || echo "MISSING"
|
|
2434
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
2405
2435
|
import json, os
|
|
2406
2436
|
p = os.environ['_PF']
|
|
2407
2437
|
strict = os.environ.get('_STRICT', '1') != '0'
|
|
@@ -2479,7 +2509,8 @@ PYEOF
|
|
|
2479
2509
|
authz_inconclusive="true"; authz_inconclusive_reason="not_serveable"
|
|
2480
2510
|
elif command -v python3 >/dev/null 2>&1; then
|
|
2481
2511
|
local _authz_status
|
|
2482
|
-
_authz_status=$(_PF="$_proof_file" _ITER="${ITERATION_COUNT:-0}" python3 <<'PYEOF' 2>/dev/null || echo "MISSING"
|
|
2512
|
+
_authz_status=$(_PF="$_proof_file" _ITER="${ITERATION_COUNT:-0}" python3 -E -s - <<'PYEOF' 2>/dev/null || echo "MISSING"
|
|
2513
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
2483
2514
|
import json, os
|
|
2484
2515
|
p = os.environ['_PF']
|
|
2485
2516
|
if not os.path.isfile(p):
|
|
@@ -2736,7 +2767,7 @@ PYEOF
|
|
|
2736
2767
|
local timestamp
|
|
2737
2768
|
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
2738
2769
|
local failures_json diff_ok tests_ok base_for_json
|
|
2739
|
-
failures_json=$(_FAILURES="$failures" python3 -c "
|
|
2770
|
+
failures_json=$(_FAILURES="$failures" python3 -E -s -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
2740
2771
|
import json, os
|
|
2741
2772
|
items = [s for s in os.environ['_FAILURES'].split('|') if s]
|
|
2742
2773
|
print(json.dumps(items[:5]))
|
|
@@ -2753,11 +2784,11 @@ print(json.dumps(items[:5]))
|
|
|
2753
2784
|
if [ "$authz_fails" = "true" ]; then authz_ok="false"; else authz_ok="true"; fi
|
|
2754
2785
|
# Record WHY boot was inconclusive (no_app_runner / not_serveable / etc.) so a
|
|
2755
2786
|
# consumer of the block report can tell a genuine boot pass from a pass-through.
|
|
2756
|
-
boot_reason_json=$(_R="${boot_inconclusive_reason:-}" python3 -c "import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2757
|
-
nomock_reason_json=$(_R="${nomock_inconclusive_reason:-}" python3 -c "import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2758
|
-
persist_reason_json=$(_R="${persist_inconclusive_reason:-}" python3 -c "import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2759
|
-
auth_reason_json=$(_R="${auth_inconclusive_reason:-}" python3 -c "import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2760
|
-
authz_reason_json=$(_R="${authz_inconclusive_reason:-}" python3 -c "import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2787
|
+
boot_reason_json=$(_R="${boot_inconclusive_reason:-}" python3 -E -s -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2788
|
+
nomock_reason_json=$(_R="${nomock_inconclusive_reason:-}" python3 -E -s -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2789
|
+
persist_reason_json=$(_R="${persist_inconclusive_reason:-}" python3 -E -s -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2790
|
+
auth_reason_json=$(_R="${auth_inconclusive_reason:-}" python3 -E -s -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2791
|
+
authz_reason_json=$(_R="${authz_inconclusive_reason:-}" python3 -E -s -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json,os; print(json.dumps(os.environ['_R']))" 2>/dev/null || echo '""')
|
|
2761
2792
|
base_for_json="${base_sha:-}"
|
|
2762
2793
|
cat > "$ev_tmp" << EVIDENCE_EOF
|
|
2763
2794
|
{
|
|
@@ -3395,7 +3426,7 @@ council_heuristic_review() {
|
|
|
3395
3426
|
local _tr_file=".loki/quality/test-results.json"
|
|
3396
3427
|
local _tests_ok=0
|
|
3397
3428
|
if [ -f "$_tr_file" ] && command -v python3 >/dev/null 2>&1; then
|
|
3398
|
-
_tests_ok=$(_TR="$_tr_file" python3 -c "
|
|
3429
|
+
_tests_ok=$(_TR="$_tr_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
3399
3430
|
import json, os
|
|
3400
3431
|
try:
|
|
3401
3432
|
with open(os.environ['_TR']) as f:
|
|
@@ -3568,7 +3599,7 @@ council_evaluate_member() {
|
|
|
3568
3599
|
local test_runner_seen="none"
|
|
3569
3600
|
if [ -f "$tr_file" ]; then
|
|
3570
3601
|
local _tr_status
|
|
3571
|
-
_tr_status=$(_TR_FILE="$tr_file" python3 -c "
|
|
3602
|
+
_tr_status=$(_TR_FILE="$tr_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
3572
3603
|
import json, os, sys
|
|
3573
3604
|
try:
|
|
3574
3605
|
with open(os.environ['_TR_FILE']) as f:
|
|
@@ -3625,7 +3656,7 @@ else:
|
|
|
3625
3656
|
local _q _qcount
|
|
3626
3657
|
for _q in pending in-progress blocked; do
|
|
3627
3658
|
[ -f "$loki_dir/queue/${_q}.json" ] || continue
|
|
3628
|
-
_qcount=$(_QUEUE_FILE="$loki_dir/queue/${_q}.json" python3 -c "import json, os
|
|
3659
|
+
_qcount=$(_QUEUE_FILE="$loki_dir/queue/${_q}.json" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json, os
|
|
3629
3660
|
d = json.load(open(os.environ['_QUEUE_FILE']))
|
|
3630
3661
|
print(len(d.get('tasks', d) if isinstance(d, dict) else d))" 2>/dev/null || echo "0")
|
|
3631
3662
|
# Guard against a non-numeric read (malformed file, python absent).
|
|
@@ -3762,7 +3793,7 @@ council_aggregate_votes() {
|
|
|
3762
3793
|
# Serialize the votes array with json.dumps so backslashes/control chars are
|
|
3763
3794
|
# escaped correctly (BUG fix: sed-only escaping produced invalid JSON).
|
|
3764
3795
|
local votes_json
|
|
3765
|
-
votes_json=$(_MEMBERS="$_members" _ROLES="$_roles" _VOTEVALS="$_vote_values" _REASONS="$_reasons" python3 -c "
|
|
3796
|
+
votes_json=$(_MEMBERS="$_members" _ROLES="$_roles" _VOTEVALS="$_vote_values" _REASONS="$_reasons" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
3766
3797
|
import json, os
|
|
3767
3798
|
def lines(name):
|
|
3768
3799
|
v = os.environ.get(name, '')
|
|
@@ -3805,7 +3836,7 @@ print(json.dumps(out))
|
|
|
3805
3836
|
_VERDICT="$verdict" \
|
|
3806
3837
|
_VOTES="$votes_json" \
|
|
3807
3838
|
_ROUND_FILE="$round_file" \
|
|
3808
|
-
python3 -c "
|
|
3839
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
3809
3840
|
import json, os
|
|
3810
3841
|
from datetime import datetime, timezone
|
|
3811
3842
|
round_data = {
|
|
@@ -3866,7 +3897,7 @@ council_devils_advocate_review() {
|
|
|
3866
3897
|
local tr_file="$loki_dir/quality/test-results.json"
|
|
3867
3898
|
if [ -f "$tr_file" ]; then
|
|
3868
3899
|
local _tr_status
|
|
3869
|
-
_tr_status=$(_TR_FILE="$tr_file" python3 -c "
|
|
3900
|
+
_tr_status=$(_TR_FILE="$tr_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
3870
3901
|
import json, os, sys
|
|
3871
3902
|
try:
|
|
3872
3903
|
with open(os.environ['_TR_FILE']) as f:
|
|
@@ -3904,7 +3935,7 @@ else:
|
|
|
3904
3935
|
# Skeptical check 2: Are there still failing tasks in the queue?
|
|
3905
3936
|
if [ -f "$loki_dir/queue/failed.json" ]; then
|
|
3906
3937
|
local failed_count
|
|
3907
|
-
failed_count=$(_QUEUE_FILE="$loki_dir/queue/failed.json" python3 -c "import json, os; print(len(json.load(open(os.environ['_QUEUE_FILE']))))" 2>/dev/null || echo "0")
|
|
3938
|
+
failed_count=$(_QUEUE_FILE="$loki_dir/queue/failed.json" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json, os; print(len(json.load(open(os.environ['_QUEUE_FILE']))))" 2>/dev/null || echo "0")
|
|
3908
3939
|
if [ "$failed_count" -gt 0 ]; then
|
|
3909
3940
|
((issues_found++))
|
|
3910
3941
|
issue_details="${issue_details}$failed_count tasks in failed queue; "
|
|
@@ -3950,7 +3981,7 @@ else:
|
|
|
3950
3981
|
_ISSUES="$issues_found" \
|
|
3951
3982
|
_DETAILS="${issue_details:-none}" \
|
|
3952
3983
|
_DA_FILE="$da_file" \
|
|
3953
|
-
python3 -c "
|
|
3984
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
3954
3985
|
import json, os
|
|
3955
3986
|
from datetime import datetime, timezone
|
|
3956
3987
|
da_result = {
|
|
@@ -4046,7 +4077,7 @@ council_evaluate() {
|
|
|
4046
4077
|
if loki_council_dispatch_agents "$ITERATION_COUNT" "${COUNCIL_PRD_PATH:-}"; then
|
|
4047
4078
|
local _va_round_file="$COUNCIL_STATE_DIR/votes/round-${ITERATION_COUNT}.json"
|
|
4048
4079
|
if [ -f "$_va_round_file" ]; then
|
|
4049
|
-
aggregate_result=$(_RF="$_va_round_file" python3 -c "import json, os; print(json.load(open(os.environ['_RF'])).get('verdict', 'CONTINUE'))" 2>/dev/null || echo "")
|
|
4080
|
+
aggregate_result=$(_RF="$_va_round_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['_RF'])).get('verdict', 'CONTINUE'))" 2>/dev/null || echo "")
|
|
4050
4081
|
fi
|
|
4051
4082
|
fi
|
|
4052
4083
|
fi
|
|
@@ -4068,7 +4099,7 @@ council_evaluate() {
|
|
|
4068
4099
|
local complete_count=0
|
|
4069
4100
|
local members_present=0
|
|
4070
4101
|
if [ -f "$round_file" ]; then
|
|
4071
|
-
complete_count=$(_RF="$round_file" python3 -c "import json, os; print(json.load(open(os.environ['_RF'])).get('complete_votes', 0))" 2>/dev/null || echo "0")
|
|
4102
|
+
complete_count=$(_RF="$round_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['_RF'])).get('complete_votes', 0))" 2>/dev/null || echo "0")
|
|
4072
4103
|
# WAVE13 CRITICAL quorum gate: how many voters actually responded
|
|
4073
4104
|
# (total_members records the ACTUAL returned count -- see
|
|
4074
4105
|
# voter-agents.sh). A degraded/partial dispatch response must never
|
|
@@ -4076,7 +4107,7 @@ council_evaluate() {
|
|
|
4076
4107
|
# somehow read COMPLETE. This is defense-in-depth: the parser
|
|
4077
4108
|
# already forces CONTINUE on undercount, but the completion-detection
|
|
4078
4109
|
# trust core must independently assert full quorum before stopping.
|
|
4079
|
-
members_present=$(_RF="$round_file" python3 -c "import json, os; print(json.load(open(os.environ['_RF'])).get('total_members', 0))" 2>/dev/null || echo "0")
|
|
4110
|
+
members_present=$(_RF="$round_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['_RF'])).get('total_members', 0))" 2>/dev/null || echo "0")
|
|
4080
4111
|
fi
|
|
4081
4112
|
# Normalize to integers (guard against empty/non-numeric on read failure)
|
|
4082
4113
|
case "$complete_count" in (''|*[!0-9]*) complete_count=0 ;; esac
|
|
@@ -4172,7 +4203,7 @@ council_managed_should_stop() {
|
|
|
4172
4203
|
diff_summary=$(cd "$project_dir" 2>/dev/null && git diff --stat 2>/dev/null | tail -20 | tr '\n' ' ' || echo "")
|
|
4173
4204
|
local test_summary=""
|
|
4174
4205
|
if [ -f "$loki_dir/quality/test-results.json" ]; then
|
|
4175
|
-
test_summary=$(_TRF="$loki_dir/quality/test-results.json" python3 -c "
|
|
4206
|
+
test_summary=$(_TRF="$loki_dir/quality/test-results.json" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
4176
4207
|
import json, os
|
|
4177
4208
|
try:
|
|
4178
4209
|
d = json.load(open(os.environ['_TRF']))
|
|
@@ -4183,7 +4214,7 @@ except Exception:
|
|
|
4183
4214
|
fi
|
|
4184
4215
|
local pending_tasks="[]"
|
|
4185
4216
|
if [ -f "$loki_dir/queue/pending.json" ]; then
|
|
4186
|
-
pending_tasks=$(_QF="$loki_dir/queue/pending.json" python3 -c "
|
|
4217
|
+
pending_tasks=$(_QF="$loki_dir/queue/pending.json" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
4187
4218
|
import json, os
|
|
4188
4219
|
try:
|
|
4189
4220
|
d = json.load(open(os.environ['_QF']))
|
|
@@ -4206,12 +4237,17 @@ except Exception:
|
|
|
4206
4237
|
_CC_VERDICTS_DIR="$verdicts_dir" \
|
|
4207
4238
|
_CC_LOKI_DIR="$loki_dir" \
|
|
4208
4239
|
LOKI_TARGET_DIR="${TARGET_DIR:-$(pwd)}" \
|
|
4209
|
-
|
|
4240
|
+
PROJECT_DIR="${PROJECT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." 2>/dev/null && pwd)}" \
|
|
4241
|
+
python3 -E - <<'PYEOF' 2>/dev/null || exit_code=$?
|
|
4242
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
4210
4243
|
import json, os, sys, pathlib
|
|
4211
4244
|
|
|
4212
|
-
# Path setup:
|
|
4213
|
-
|
|
4214
|
-
|
|
4245
|
+
# Path setup: import providers.managed only from an explicit PROJECT_DIR. Never
|
|
4246
|
+
# fall back to the cwd (D7): it is the agent's repo, which could ship its own
|
|
4247
|
+
# providers/managed.py. Unset -> ImportError -> the Bash voting path.
|
|
4248
|
+
project_dir = os.environ.get("PROJECT_DIR", "")
|
|
4249
|
+
if project_dir:
|
|
4250
|
+
sys.path.insert(0, project_dir)
|
|
4215
4251
|
|
|
4216
4252
|
try:
|
|
4217
4253
|
from providers.managed import (
|
|
@@ -4383,7 +4419,7 @@ _council_convergence_evidence_green() {
|
|
|
4383
4419
|
# file or runner=="none" (no suite) is NOT affirmative evidence -> not green.
|
|
4384
4420
|
[ -f "$tr_file" ] || return 1
|
|
4385
4421
|
local tr_state
|
|
4386
|
-
tr_state=$(_TR_FILE="$tr_file" python3 -c "
|
|
4422
|
+
tr_state=$(_TR_FILE="$tr_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
4387
4423
|
import json, os, sys
|
|
4388
4424
|
try:
|
|
4389
4425
|
with open(os.environ['_TR_FILE']) as f:
|
|
@@ -4406,7 +4442,7 @@ print('yes' if (runner != 'none' and passed is True
|
|
|
4406
4442
|
local results_file="${TARGET_DIR:-.}/.loki/checklist/verification-results.json"
|
|
4407
4443
|
if [ -f "$results_file" ]; then
|
|
4408
4444
|
local cl_state
|
|
4409
|
-
cl_state=$(_RESULTS_FILE="$results_file" python3 -c "
|
|
4445
|
+
cl_state=$(_RESULTS_FILE="$results_file" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
4410
4446
|
import json, os, sys
|
|
4411
4447
|
try:
|
|
4412
4448
|
with open(os.environ['_RESULTS_FILE']) as f:
|
|
@@ -4655,7 +4691,7 @@ council_write_report() {
|
|
|
4655
4691
|
REPORT_HEADER
|
|
4656
4692
|
|
|
4657
4693
|
# Append vote history from state
|
|
4658
|
-
_COUNCIL_STATE_FILE="$COUNCIL_STATE_DIR/state.json" python3 -c "
|
|
4694
|
+
_COUNCIL_STATE_FILE="$COUNCIL_STATE_DIR/state.json" python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
4659
4695
|
import json, os
|
|
4660
4696
|
try:
|
|
4661
4697
|
with open(os.environ['_COUNCIL_STATE_FILE']) as f:
|
package/autonomy/council-v2.sh
CHANGED
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
# - swarm/sycophancy.py (sycophancy detection)
|
|
20
20
|
# - swarm/calibration.py (reviewer calibration)
|
|
21
21
|
#
|
|
22
|
+
# Inline Python (D7): the council runs with the cwd inside the agent's repo, so
|
|
23
|
+
# every python3 here runs -E and drops '' and '.' from sys.path before any other
|
|
24
|
+
# import (the swarm dir is inserted after that); a committed json.py or
|
|
25
|
+
# sitecustomize.py cannot read the votes. Pinned by
|
|
26
|
+
# tests/test-council-no-fabricated-verdict.sh (D7 section).
|
|
27
|
+
#
|
|
22
28
|
#===============================================================================
|
|
23
29
|
|
|
24
30
|
COUNCIL_V2_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -97,7 +103,7 @@ council_v2_vote() {
|
|
|
97
103
|
votes_json="$votes_json$vote_content"
|
|
98
104
|
|
|
99
105
|
local verdict
|
|
100
|
-
verdict=$(echo "$vote_content" | python3 -c "import sys,json; print(json.load(sys.stdin).get('verdict','').upper())" 2>/dev/null || echo "UNKNOWN")
|
|
106
|
+
verdict=$(echo "$vote_content" | python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json; print(json.load(sys.stdin).get('verdict','').upper())" 2>/dev/null || echo "UNKNOWN")
|
|
101
107
|
# TRUST: a reviewer that could not be REACHED did not vote REJECT.
|
|
102
108
|
#
|
|
103
109
|
# Every provider arm below used to substitute a literal
|
|
@@ -135,7 +141,7 @@ council_v2_vote() {
|
|
|
135
141
|
|
|
136
142
|
# Step 4: Sycophancy detection
|
|
137
143
|
local sycophancy_score
|
|
138
|
-
sycophancy_score=$(python3 -c "
|
|
144
|
+
sycophancy_score=$(python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
139
145
|
import sys
|
|
140
146
|
sys.path.insert(0, '${COUNCIL_V2_DIR}/../swarm')
|
|
141
147
|
from sycophancy import detect_sycophancy
|
|
@@ -150,7 +156,7 @@ print('{:.3f}'.format(detect_sycophancy(votes)))
|
|
|
150
156
|
if [ "$approve_count" -eq "$council_size" ]; then
|
|
151
157
|
local threshold="${LOKI_COUNCIL_SYCOPHANCY_THRESHOLD:-0.6}"
|
|
152
158
|
local should_challenge
|
|
153
|
-
should_challenge=$(python3 -c "print('yes' if float('$sycophancy_score') >= float('$threshold') else 'no')" 2>/dev/null || echo "no")
|
|
159
|
+
should_challenge=$(python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; print('yes' if float('$sycophancy_score') >= float('$threshold') else 'no')" 2>/dev/null || echo "no")
|
|
154
160
|
|
|
155
161
|
if [ "$should_challenge" = "yes" ]; then
|
|
156
162
|
log_warn "Sycophancy score $sycophancy_score >= $threshold -- adding devil's advocate"
|
|
@@ -167,7 +173,7 @@ print('{:.3f}'.format(detect_sycophancy(votes)))
|
|
|
167
173
|
# Same trust rule as the main tally: an unparseable devil's
|
|
168
174
|
# advocate did not vote REJECT. Defaulting to REJECT here would
|
|
169
175
|
# silently overturn a unanimous APPROVE on a transient failure.
|
|
170
|
-
da_verdict=$(cat "$da_vote" | python3 -c "import sys,json; print(json.load(sys.stdin).get('verdict','').upper())" 2>/dev/null || echo "INCONCLUSIVE")
|
|
176
|
+
da_verdict=$(cat "$da_vote" | python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]; import json; print(json.load(sys.stdin).get('verdict','').upper())" 2>/dev/null || echo "INCONCLUSIVE")
|
|
171
177
|
if [ "$da_verdict" = "INCONCLUSIVE" ]; then
|
|
172
178
|
log_warn "Devil's advocate produced no verdict -- unanimous approval left UNCHANGED (not overturned)"
|
|
173
179
|
elif [ "$da_verdict" = "REJECT" ]; then
|
|
@@ -201,7 +207,7 @@ print('{:.3f}'.format(detect_sycophancy(votes)))
|
|
|
201
207
|
final_decision="reject"
|
|
202
208
|
fi
|
|
203
209
|
|
|
204
|
-
python3 -c "
|
|
210
|
+
python3 -E -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
205
211
|
import sys
|
|
206
212
|
sys.path.insert(0, '${COUNCIL_V2_DIR}/../swarm')
|
|
207
213
|
from calibration import CalibrationTracker
|
|
@@ -388,7 +394,7 @@ Respond ONLY with a valid JSON object. No markdown fencing."
|
|
|
388
394
|
--json-schema "$_c2_schema_content" --output-format json 2>/dev/null)" || _c2_json=""
|
|
389
395
|
if [ -n "$_c2_json" ]; then
|
|
390
396
|
# Pull the schema-validated object out of the envelope.
|
|
391
|
-
result="$(printf '%s' "$_c2_json" | python3 -c 'import sys,json
|
|
397
|
+
result="$(printf '%s' "$_c2_json" | python3 -E -c 'import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]; import json
|
|
392
398
|
try:
|
|
393
399
|
e=json.load(sys.stdin)
|
|
394
400
|
p=e.get("structured_output")
|
|
@@ -490,7 +496,7 @@ except Exception:
|
|
|
490
496
|
# or neither, stays INCONCLUSIVE -- never guessed.
|
|
491
497
|
if [ -z "$extracted" ] && [ -n "${result:-}" ]; then
|
|
492
498
|
local _recovered
|
|
493
|
-
_recovered="$(printf '%s' "$result" | _LOKI_RAW="$result" python3 -c '
|
|
499
|
+
_recovered="$(printf '%s' "$result" | _LOKI_RAW="$result" python3 -E -c 'import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
494
500
|
import os, re, sys, json
|
|
495
501
|
raw = os.environ.get("_LOKI_RAW", "")
|
|
496
502
|
# Standalone words only: "APPROVE" not "approved-by", and not inside a URL.
|