loki-mode 9.74.0 → 9.76.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 +24 -6
- package/autonomy/council-v2.sh +60 -13
- package/autonomy/lib/done-recognition.sh +73 -21
- package/autonomy/lib/proof-check.sh +43 -8
- package/autonomy/lib/voter-agents.sh +42 -5
- package/autonomy/loki +3 -0
- package/autonomy/prd-checklist.sh +77 -16
- package/autonomy/run.sh +38 -3
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/R3-COST-OBSERVABILITY-DESIGN.md +7 -1
- package/docs/exit-codes.md +21 -0
- package/docs/v10/ARCHITECT-CUTS.md +397 -234
- package/docs/v10/BOARD.md +84 -44
- package/docs/v10/GUARDS.md +45 -28
- package/loki-ts/dist/loki.js +341 -338
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-DaeYgQSE.js → AdminPage-Bw8oPnII.js} +1 -1
- package/web-app/dist/assets/{Avatar-CgwQi58_.js → Avatar-BwEtc3RH.js} +1 -1
- package/web-app/dist/assets/{Badge-Bwq-lpRh.js → Badge-C_-lfbUl.js} +1 -1
- package/web-app/dist/assets/{Button-BEf4Nher.js → Button-BdDGKKeF.js} +1 -1
- package/web-app/dist/assets/CockpitPage-Dx9d4fEm.js +47 -0
- package/web-app/dist/assets/{ComparePage-tFbdo90G.js → ComparePage-BKtAhhIJ.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-Brewvgm9.js → ErrorBoundary-BuG16GpG.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-h_82QBVa.js → EvidenceReceiptPanel-NATnqxKs.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-Dcg5xDMm.js → GitHubIssuesPanel-BgOwdOpj.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-DFKzVyA1.js → GitHubPRsPanel-CBJyHI1c.js} +1 -1
- package/web-app/dist/assets/{HomePage-D21cM1Je.js → HomePage-BHj17Epq.js} +2 -2
- package/web-app/dist/assets/{LoginPage-DJ9yqMn4.js → LoginPage-Dig4H-HO.js} +1 -1
- package/web-app/dist/assets/{MagicPage-mwkjJhBy.js → MagicPage-w6WJ35PH.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-D2q-PD-s.js → MetricsPage-CvjSUOWn.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-BtusJvgS.js → NotFoundPage-PAcYmGkU.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-CRPALtO8.js → ProjectPage-CBkT5JyW.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-DuzABpfc.js → ProjectsPage-Cs6yuWEU.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-DhJPX-Rf.js → SettingsPage-BU9F40Yn.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-CvgS47nu.js → ShowcasePage-jCNABTeT.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-l3Cv9YjY.js → SystemSettingsPage-Crmc-ryL.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-DridGcnR.js → TeamsPage-DN8W-9m5.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-CTNsfp03.js → TemplatesPage-WvaXwZIl.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-BuyksqLh.js → TerminalOutput-Bf_do2tO.js} +1 -1
- package/web-app/dist/assets/{activity-DM2TKaBi.js → activity-CMl9JvHl.js} +1 -1
- package/web-app/dist/assets/{bell-D2PMLbbX.js → bell-CnjqTAUX.js} +1 -1
- package/web-app/dist/assets/{bot-BnN32Jxp.js → bot-BBprDFVS.js} +1 -1
- package/web-app/dist/assets/{check-CU128nw_.js → check-DW9Hq4y4.js} +1 -1
- package/web-app/dist/assets/{chevron-left-ehNW1Do7.js → chevron-left-DC9pMI2E.js} +1 -1
- package/web-app/dist/assets/{circle-alert-Cpw2gtOC.js → circle-alert-BJoll9YV.js} +1 -1
- package/web-app/dist/assets/{clock-BOZHdPVS.js → clock-BdHhRTHO.js} +1 -1
- package/web-app/dist/assets/{cloud-BZ2L9Fzi.js → cloud-C54B7EO9.js} +1 -1
- package/web-app/dist/assets/{code-xml-sSo522gu.js → code-xml-DwQK2vpV.js} +1 -1
- package/web-app/dist/assets/{database-DrR1xHzS.js → database-DsWVFir7.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-CHE3T_rh.js → dollar-sign-DuRPNc2M.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-CgcssyRQ.js → file-code-corner-C4j2P44-.js} +1 -1
- package/web-app/dist/assets/{file-plus-DtwfrxYH.js → file-plus-rnI2RZjF.js} +1 -1
- package/web-app/dist/assets/{globe-Dzla77iL.js → globe-BbBhsaS5.js} +1 -1
- package/web-app/dist/assets/{hammer-BAMdG66t.js → hammer-BxcycH3E.js} +1 -1
- package/web-app/dist/assets/{index-mQOnSYoW.js → index-xGj3noKA.js} +2 -2
- package/web-app/dist/assets/{layers-DhuyLqmc.js → layers-CcAOhZeY.js} +1 -1
- package/web-app/dist/assets/{loader-circle-DclFyQ3B.js → loader-circle-DN_Xjd5e.js} +1 -1
- package/web-app/dist/assets/{lock-C8v_bXNl.js → lock-Dn8AMO-D.js} +1 -1
- package/web-app/dist/assets/{package-B4AnjM5D.js → package-uroTpCjn.js} +1 -1
- package/web-app/dist/assets/{plus-DM95CmZI.js → plus-CYJAEX02.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-CWaauzqX.js → refresh-cw-BUGsMChj.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-DxcvylpJ.js → rotate-ccw-C_4D-XGl.js} +1 -1
- package/web-app/dist/assets/{scroll-text-Dx-V_BpP.js → scroll-text-DrAJG0H3.js} +1 -1
- package/web-app/dist/assets/{server-Cj2EfoGN.js → server-Di6lHsM9.js} +1 -1
- package/web-app/dist/assets/{shield-alert-OlmWv7sU.js → shield-alert-DH1bNjkD.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-CIpJhyTd.js → thumbs-up-Enk3ppj_.js} +1 -1
- package/web-app/dist/assets/{trash-2-BIkoZkY6.js → trash-2-CezqQT3x.js} +1 -1
- package/web-app/dist/assets/{trending-down-CI-OcCGt.js → trending-down-B_ChI0U7.js} +1 -1
- package/web-app/dist/assets/{trending-up-B0dpgKi-.js → trending-up-BtsvHd_-.js} +1 -1
- package/web-app/dist/assets/{upload-NhOBAjKA.js → upload-XiWa_WBM.js} +1 -1
- package/web-app/dist/assets/{usePolling-_QRF6f7x.js → usePolling-B6Hxwbk1.js} +1 -1
- package/web-app/dist/assets/{user-kRNvOpun.js → user-oL_Oya-S.js} +1 -1
- package/web-app/dist/index.html +1 -1
- package/web-app/dist/assets/CockpitPage-Bj41Xtg9.js +0 -47
package/autonomy/loki
CHANGED
|
@@ -1271,6 +1271,8 @@ loki_remote_verify_receipt() {
|
|
|
1271
1271
|
echo " the JWKS URL is not https -- only loopback is allowed over plain http)."
|
|
1272
1272
|
echo " Its integrity hash matches. Provenance is unproven here, not disproven."
|
|
1273
1273
|
echo " Install python3 cryptography, or re-run where the build server is reachable."
|
|
1274
|
+
echo " The verifier runs python3 -E, so cryptography supplied through PYTHONPATH is"
|
|
1275
|
+
echo " not seen; install it where the base interpreter finds it (site or user site)."
|
|
1274
1276
|
return 0
|
|
1275
1277
|
fi
|
|
1276
1278
|
|
|
@@ -37143,6 +37145,7 @@ print(json.dumps(json.load(open(os.environ['LOKI_PROOF_JSON'])), indent=2))
|
|
|
37143
37145
|
# verifier is a finding and is never softened to 2.
|
|
37144
37146
|
echo -e "${YELLOW}attestation: NOT CHECKED -- could not check against ${_pv_jwks} (key set unreadable,${NC}" >&2
|
|
37145
37147
|
echo -e "${YELLOW} verifier dependency missing, or the JWKS URL is not https -- only loopback is allowed over plain http).${NC}" >&2
|
|
37148
|
+
echo " The verifier runs python3 -E, so cryptography supplied through PYTHONPATH is not seen (a site or user-site install is)." >&2
|
|
37146
37149
|
echo " This is not a failure of the receipt. Nothing was proven either way (exit 2)." >&2
|
|
37147
37150
|
if [ "$_pv_rc" -eq 0 ]; then _pv_rc=2; fi
|
|
37148
37151
|
_pv_attestation_field="NOT CHECKED"
|
|
@@ -19,12 +19,23 @@
|
|
|
19
19
|
# LOKI_CHECKLIST_ENABLED - Enable/disable checklist (default: true)
|
|
20
20
|
#
|
|
21
21
|
# Inline Python (D7): verification runs with the cwd inside the agent's repo,
|
|
22
|
-
# so every python3 here
|
|
23
|
-
# committed sitecustomize.py) and every -c / - body drops '' and
|
|
24
|
-
# sys.path before any other import (a committed json.py would print
|
|
25
|
-
# verdict). Pinned by tests/moat/p2-honest-verdict.sh
|
|
22
|
+
# so every python3 here ignores PYTHON* env vars (an empty PYTHONPATH component
|
|
23
|
+
# would load a committed sitecustomize.py) and every -c / - body drops '' and
|
|
24
|
+
# '.' from sys.path before any other import (a committed json.py would print
|
|
25
|
+
# the verdict). Pinned by tests/moat/p2-honest-verdict.sh
|
|
26
26
|
# P2.checklist-verify-not-shadowed.
|
|
27
27
|
#
|
|
28
|
+
# S-204 (BACKLOG 53): -E alone still loads the user site-packages, whose .pth
|
|
29
|
+
# "import" lines run at startup and can patch json.dump, so checklist-verify.py
|
|
30
|
+
# wrote failing checks as verified into the results file the council hard gate
|
|
31
|
+
# trusts. Every call site resolves its interpreter through
|
|
32
|
+
# _loki_snapshot_py_tool and runs it -I -S; when none resolves, nothing is
|
|
33
|
+
# verified or summarized (the hard gate then blocks fail-closed). See that
|
|
34
|
+
# function's comment in run.sh for the rationale and accepted gaps. The copy
|
|
35
|
+
# below only serves callers that source this file before or without run.sh
|
|
36
|
+
# (tests); run.sh is the source of truth, keep it byte-identical. Pinned by
|
|
37
|
+
# tests/test-prd-checklist-no-user-site-pth.sh.
|
|
38
|
+
#
|
|
28
39
|
# Data:
|
|
29
40
|
# .loki/checklist/checklist.json - Full checklist with verification
|
|
30
41
|
# .loki/checklist/verification-results.json - Summary of last verification
|
|
@@ -37,6 +48,28 @@
|
|
|
37
48
|
#
|
|
38
49
|
#===============================================================================
|
|
39
50
|
|
|
51
|
+
declare -F _loki_snapshot_py_tool >/dev/null 2>&1 || \
|
|
52
|
+
_loki_snapshot_py_tool() {
|
|
53
|
+
local c
|
|
54
|
+
for c in /usr/bin/python3 /bin/python3; do
|
|
55
|
+
[ -x "$c" ] && [ ! -d "$c" ] && "$c" -I -S -c '' >/dev/null 2>&1 && { printf '%s\n' "$c"; return 0; }
|
|
56
|
+
done
|
|
57
|
+
local dir
|
|
58
|
+
local IFS=:
|
|
59
|
+
for dir in $PATH; do
|
|
60
|
+
case "$dir" in
|
|
61
|
+
/*) ;;
|
|
62
|
+
*) continue ;;
|
|
63
|
+
esac
|
|
64
|
+
if [ -x "$dir/python3" ] && [ ! -d "$dir/python3" ] \
|
|
65
|
+
&& "$dir/python3" -I -S -c '' >/dev/null 2>&1; then
|
|
66
|
+
printf '%s\n' "$dir/python3"
|
|
67
|
+
return 0
|
|
68
|
+
fi
|
|
69
|
+
done
|
|
70
|
+
return 1
|
|
71
|
+
}
|
|
72
|
+
|
|
40
73
|
# Configuration
|
|
41
74
|
CHECKLIST_ENABLED=${LOKI_CHECKLIST_ENABLED:-true}
|
|
42
75
|
CHECKLIST_INTERVAL=${LOKI_CHECKLIST_INTERVAL:-5}
|
|
@@ -200,12 +233,14 @@ checklist_oracle_triangulate() {
|
|
|
200
233
|
local status_token="NOOP"
|
|
201
234
|
local status_file=""
|
|
202
235
|
local status_tmp_root="${TMPDIR:-/tmp}"
|
|
236
|
+
local _cl_py
|
|
237
|
+
_cl_py="$(_loki_snapshot_py_tool)" || return 0
|
|
203
238
|
if status_file="$(mktemp "${status_tmp_root%/}/loki-oracle-status.XXXXXX" 2>/dev/null)"; then
|
|
204
239
|
if _ORACLE_SPEC="$CHECKLIST_PRD_PATH" \
|
|
205
240
|
_ORACLE_OUT="$findings_file" \
|
|
206
241
|
_ORACLE_PROJECT="$project_dir" \
|
|
207
242
|
_ORACLE_INSTALL_DIR="$oracle_install_dir" \
|
|
208
|
-
|
|
243
|
+
"$_cl_py" -I -S - > "$status_file" 2>/dev/null <<'ORACLE_PY'
|
|
209
244
|
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
210
245
|
import json, os, re, sys, tempfile, glob
|
|
211
246
|
|
|
@@ -701,7 +736,9 @@ checklist_oracle_evidence() {
|
|
|
701
736
|
if [ ! -f "$findings_file" ]; then
|
|
702
737
|
return 0
|
|
703
738
|
fi
|
|
704
|
-
|
|
739
|
+
local _cl_py
|
|
740
|
+
_cl_py="$(_loki_snapshot_py_tool)" || return 0
|
|
741
|
+
_ORACLE_OUT="$findings_file" "$_cl_py" -I -S -c 'import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
705
742
|
import json, os
|
|
706
743
|
try:
|
|
707
744
|
with open(os.environ["_ORACLE_OUT"]) as f:
|
|
@@ -804,8 +841,9 @@ checklist_select_heldout() {
|
|
|
804
841
|
# Honest caveat: re-selection or partial-survival after a regen can reserve
|
|
805
842
|
# items the build loop already saw in earlier prompts (the hidden-from-loop
|
|
806
843
|
# guarantee is best-effort once the checklist ids change mid-run).
|
|
807
|
-
local status_token
|
|
808
|
-
|
|
844
|
+
local status_token _cl_py
|
|
845
|
+
_cl_py="$(_loki_snapshot_py_tool)" || return 0
|
|
846
|
+
status_token=$(_CHECKLIST_FILE="$CHECKLIST_FILE" _HELDOUT_FILE="$heldout_file" "$_cl_py" -I -S -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
809
847
|
import json, os, sys, hashlib, tempfile
|
|
810
848
|
|
|
811
849
|
cl_path = os.environ['_CHECKLIST_FILE']
|
|
@@ -953,7 +991,9 @@ checklist_heldout_ids() {
|
|
|
953
991
|
if [ ! -f "$heldout_file" ]; then
|
|
954
992
|
return 0
|
|
955
993
|
fi
|
|
956
|
-
|
|
994
|
+
local _cl_py
|
|
995
|
+
_cl_py="$(_loki_snapshot_py_tool)" || return 0
|
|
996
|
+
_HELDOUT_FILE="$heldout_file" "$_cl_py" -I -S -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
957
997
|
import json, os
|
|
958
998
|
try:
|
|
959
999
|
with open(os.environ['_HELDOUT_FILE']) as f:
|
|
@@ -997,9 +1037,17 @@ checklist_verify() {
|
|
|
997
1037
|
return 0
|
|
998
1038
|
fi
|
|
999
1039
|
|
|
1040
|
+
# Non-zero so council_reverify_checklist replaces any stale green results
|
|
1041
|
+
# with its fail-closed sentinel (run.sh's interval call ignores the status).
|
|
1042
|
+
local _cl_py
|
|
1043
|
+
if ! _cl_py="$(_loki_snapshot_py_tool)"; then
|
|
1044
|
+
log_warn "checklist verification skipped: no isolated python3 interpreter resolved"
|
|
1045
|
+
return 1
|
|
1046
|
+
fi
|
|
1047
|
+
|
|
1000
1048
|
log_step "Running PRD checklist verification..."
|
|
1001
1049
|
|
|
1002
|
-
|
|
1050
|
+
"$_cl_py" -I -S "$verify_script" \
|
|
1003
1051
|
--checklist "$CHECKLIST_FILE" \
|
|
1004
1052
|
--timeout "$CHECKLIST_TIMEOUT" 2>/dev/null || true
|
|
1005
1053
|
|
|
@@ -1027,11 +1075,13 @@ checklist_summary() {
|
|
|
1027
1075
|
echo ""
|
|
1028
1076
|
return 0
|
|
1029
1077
|
fi
|
|
1078
|
+
local _cl_py
|
|
1079
|
+
_cl_py="$(_loki_snapshot_py_tool)" || { echo ""; return 0; }
|
|
1030
1080
|
|
|
1031
1081
|
_CHECKLIST_RESULTS="$CHECKLIST_RESULTS_FILE" \
|
|
1032
1082
|
_CHECKLIST_WAIVERS="${CHECKLIST_DIR:-".loki/checklist"}/waivers.json" \
|
|
1033
1083
|
_CHECKLIST_HELDOUT="${CHECKLIST_DIR:-".loki/checklist"}/held-out.json" \
|
|
1034
|
-
|
|
1084
|
+
"$_cl_py" -I -S -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1035
1085
|
import json, sys, os
|
|
1036
1086
|
try:
|
|
1037
1087
|
fpath = os.environ.get('_CHECKLIST_RESULTS', '')
|
|
@@ -1128,13 +1178,16 @@ checklist_as_evidence() {
|
|
|
1128
1178
|
if [ ! -f "$CHECKLIST_RESULTS_FILE" ]; then
|
|
1129
1179
|
return 0
|
|
1130
1180
|
fi
|
|
1181
|
+
local _cl_py
|
|
1182
|
+
# No interpreter: the failed exec falls to "Checklist data unavailable" below.
|
|
1183
|
+
_cl_py="$(_loki_snapshot_py_tool)" || _cl_py="/nonexistent/python3"
|
|
1131
1184
|
|
|
1132
1185
|
{
|
|
1133
1186
|
echo ""
|
|
1134
1187
|
echo "## PRD Checklist Verification"
|
|
1135
1188
|
echo ""
|
|
1136
1189
|
|
|
1137
|
-
_CHECKLIST_RESULTS="$CHECKLIST_RESULTS_FILE"
|
|
1190
|
+
_CHECKLIST_RESULTS="$CHECKLIST_RESULTS_FILE" "$_cl_py" -I -S -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1138
1191
|
import json, os
|
|
1139
1192
|
try:
|
|
1140
1193
|
data = json.load(open(os.environ['_CHECKLIST_RESULTS']))
|
|
@@ -1170,7 +1223,9 @@ checklist_waiver_load() {
|
|
|
1170
1223
|
if [ ! -f "$waivers_file" ]; then
|
|
1171
1224
|
return 0
|
|
1172
1225
|
fi
|
|
1173
|
-
|
|
1226
|
+
local _cl_py
|
|
1227
|
+
_cl_py="$(_loki_snapshot_py_tool)" || return 0
|
|
1228
|
+
_WAIVERS_FILE="$waivers_file" "$_cl_py" -I -S -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1174
1229
|
import json, sys, os
|
|
1175
1230
|
try:
|
|
1176
1231
|
waivers_file = os.environ['_WAIVERS_FILE']
|
|
@@ -1193,8 +1248,10 @@ checklist_waiver_add() {
|
|
|
1193
1248
|
local waivers_file="${CHECKLIST_DIR:-".loki/checklist"}/waivers.json"
|
|
1194
1249
|
local timestamp
|
|
1195
1250
|
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
1251
|
+
local _cl_py
|
|
1252
|
+
_cl_py="$(_loki_snapshot_py_tool)" || return 1
|
|
1196
1253
|
|
|
1197
|
-
_WAIVERS_FILE="$waivers_file"
|
|
1254
|
+
_WAIVERS_FILE="$waivers_file" "$_cl_py" -I -S -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1198
1255
|
import json, os, sys
|
|
1199
1256
|
|
|
1200
1257
|
waivers_file = os.environ['_WAIVERS_FILE']
|
|
@@ -1246,8 +1303,10 @@ checklist_waiver_remove() {
|
|
|
1246
1303
|
echo "No waivers file found"
|
|
1247
1304
|
return 1
|
|
1248
1305
|
fi
|
|
1306
|
+
local _cl_py
|
|
1307
|
+
_cl_py="$(_loki_snapshot_py_tool)" || return 1
|
|
1249
1308
|
|
|
1250
|
-
_WAIVERS_FILE="$waivers_file"
|
|
1309
|
+
_WAIVERS_FILE="$waivers_file" "$_cl_py" -I -S -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1251
1310
|
import json, os, sys
|
|
1252
1311
|
|
|
1253
1312
|
waivers_file = os.environ['_WAIVERS_FILE']
|
|
@@ -1282,8 +1341,10 @@ checklist_waiver_list() {
|
|
|
1282
1341
|
echo "No waivers configured"
|
|
1283
1342
|
return 0
|
|
1284
1343
|
fi
|
|
1344
|
+
local _cl_py
|
|
1345
|
+
_cl_py="$(_loki_snapshot_py_tool)" || return 1
|
|
1285
1346
|
|
|
1286
|
-
_WAIVERS_FILE="$waivers_file"
|
|
1347
|
+
_WAIVERS_FILE="$waivers_file" "$_cl_py" -I -S -c "import sys; sys.path[:] = [p for p in sys.path if p not in ('', '.')]
|
|
1287
1348
|
import json, os
|
|
1288
1349
|
waivers_file = os.environ['_WAIVERS_FILE']
|
|
1289
1350
|
with open(waivers_file) as f:
|
package/autonomy/run.sh
CHANGED
|
@@ -10949,9 +10949,26 @@ _loki_untrack_agent_committed_user_files() {
|
|
|
10949
10949
|
fi
|
|
10950
10950
|
rm -f "$rec.added"
|
|
10951
10951
|
if [ ! -s "$rec.new" ]; then
|
|
10952
|
-
|
|
10953
|
-
#
|
|
10954
|
-
|
|
10952
|
+
rm -f "$rec.new"
|
|
10953
|
+
# S-194: the tree diff above cannot see a file an earlier (resumed)
|
|
10954
|
+
# session added and then untracked, but the branch history still
|
|
10955
|
+
# holds it and create_session_pr gates the push on this record. Keep
|
|
10956
|
+
# the record while that history holds any recorded path; on a failed
|
|
10957
|
+
# check, keep it too (fail closed).
|
|
10958
|
+
if [ -s "$rec" ]; then
|
|
10959
|
+
local range="${fork}..HEAD" held_paths=() p="" hist=""
|
|
10960
|
+
[ "$(git cat-file -t "$fork" 2>/dev/null)" = tree ] && range="HEAD"
|
|
10961
|
+
while IFS= read -r -d '' p; do held_paths+=("$p"); done < "$rec"
|
|
10962
|
+
if [ "${#held_paths[@]}" -eq 0 ] \
|
|
10963
|
+
|| ! hist="$(git -C "$top" --literal-pathspecs log -1 --format=%H --no-renames --diff-filter=A "$range" -- "${held_paths[@]}" 2>/dev/null)" \
|
|
10964
|
+
|| [ -n "$hist" ]; then
|
|
10965
|
+
return 0
|
|
10966
|
+
fi
|
|
10967
|
+
fi
|
|
10968
|
+
# BACKLOG 102: zero hits this session and no recorded path left in the
|
|
10969
|
+
# branch history -- clear a stale record left by an earlier session,
|
|
10970
|
+
# or it persists forever with nothing to read it.
|
|
10971
|
+
rm -f "$rec"
|
|
10955
10972
|
return 0
|
|
10956
10973
|
fi
|
|
10957
10974
|
mv -f "$rec.new" "$rec"
|
|
@@ -11198,6 +11215,24 @@ create_session_pr() {
|
|
|
11198
11215
|
return 0
|
|
11199
11216
|
fi
|
|
11200
11217
|
|
|
11218
|
+
# BACKLOG 108: _loki_untrack_agent_committed_user_files removed the user's
|
|
11219
|
+
# pre-existing files from the branch tip, but the commit that added them is
|
|
11220
|
+
# still in the branch history, so a push publishes them. Print the cleanup
|
|
11221
|
+
# before any push advice, and refuse the LOKI_AUTO_PR push. The fork is the
|
|
11222
|
+
# merge base with the recorded base, as that helper computes it; its
|
|
11223
|
+
# session-start-sha fallback cannot apply here, because without a merge
|
|
11224
|
+
# base commit_count is 0 and this function already returned.
|
|
11225
|
+
if [ -s .loki/state/agent-committed-user-files.z ]; then
|
|
11226
|
+
local _uc_fork="" _uc_names=""
|
|
11227
|
+
_uc_fork="$(git merge-base HEAD "$base" 2>/dev/null)" || _uc_fork=""
|
|
11228
|
+
_uc_names="$(_loki_nul_names .loki/state/agent-committed-user-files.z)"
|
|
11229
|
+
log_warn "The history of ${branch_name} still holds your pre-existing files the agent committed: ${_uc_names:-see .loki/state/agent-committed-user-files.z}. Before pushing, drop them from its history: git reset --soft ${_uc_fork:-<fork commit>} && git commit"
|
|
11230
|
+
if [ "${LOKI_AUTO_PR:-0}" = "1" ]; then
|
|
11231
|
+
log_warn "LOKI_AUTO_PR: not pushing ${branch_name}; its history holds your pre-existing files."
|
|
11232
|
+
return 1
|
|
11233
|
+
fi
|
|
11234
|
+
fi
|
|
11235
|
+
|
|
11201
11236
|
# DEFAULT: advisory only. Print the exact commands; never push, never PR.
|
|
11202
11237
|
if [ "${LOKI_AUTO_PR:-0}" != "1" ]; then
|
|
11203
11238
|
if declare -f print_pr_advice >/dev/null 2>&1; then
|
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.76.0
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -60,6 +60,7 @@ Read-only. Returns two honest series plus a budget block:
|
|
|
60
60
|
"cost_usd": 1.84, "files_changed": 3, "final_verdict": "APPROVE"}
|
|
61
61
|
],
|
|
62
62
|
"project_total_usd": 1.89,
|
|
63
|
+
"project_total_partial": false,
|
|
63
64
|
"runs_count": 1,
|
|
64
65
|
"budget": {
|
|
65
66
|
"limit": 50.0, "used": 1.89, "remaining": 48.11,
|
|
@@ -74,7 +75,12 @@ Read-only. Returns two honest series plus a budget block:
|
|
|
74
75
|
prefer `cost_usd`; if null, price from tokens via the EXISTING
|
|
75
76
|
`_calculate_model_cost` helper (do not add a new pricer).
|
|
76
77
|
- `runs` from `.loki/proofs/*/proof.json` (reuse `_proofs_dir` + `_safe_json_read`).
|
|
77
|
-
- `project_total_usd`
|
|
78
|
+
- `project_total_usd` totals only the runs whose proof recorded a cost
|
|
79
|
+
(the persistent history). It is null when no run recorded a cost, since
|
|
80
|
+
runs that each read "not recorded" do not add up to a $0.00 project; a
|
|
81
|
+
measured $0.00 run still makes it 0.0.
|
|
82
|
+
- `project_total_partial` is true when only some runs recorded a cost. The
|
|
83
|
+
total is then a lower bound, not the project's full spend.
|
|
78
84
|
- `budget.status`: "ok" (<80%), "warn" (>=80% and <100%), "exceeded" (>=100%).
|
|
79
85
|
Computed at read time. No budget.json schema change (avoids the
|
|
80
86
|
byte-identical-JSON parity trap with run.sh heredoc / budget.ts).
|
package/docs/exit-codes.md
CHANGED
|
@@ -67,6 +67,27 @@ An early draft spec listed `1=BLOCKED, 2=CONCERNS`. That ordering was rejected:
|
|
|
67
67
|
it is not used anywhere, it has no consumers, and it inverts the
|
|
68
68
|
severity-rises-with-the-code rule that every other command follows.
|
|
69
69
|
|
|
70
|
+
### Known gaps until v10.0.0
|
|
71
|
+
|
|
72
|
+
The table above is the target. On the current release, four inputs do not
|
|
73
|
+
return what it implies. Measured on this checkout:
|
|
74
|
+
|
|
75
|
+
| Input | Command | Exit today | Target |
|
|
76
|
+
|---|---|---|---|
|
|
77
|
+
| Empty diff (a git repo with no changes vs base) | `loki verify` | 1 (CONCERNS) | 3 |
|
|
78
|
+
| Not a git directory | `loki verify` | 1 (CONCERNS) | 2 |
|
|
79
|
+
| Unknown flag | `loki verify --no-such-flag` | 3 | 64 |
|
|
80
|
+
| `--fast` with nothing scanned (0 files) | `loki verify --fast <empty-dir> --no-cache` | 0 | nonzero |
|
|
81
|
+
|
|
82
|
+
`loki verify --fast` (`autonomy/lib/fast_verify.py`) also exits 0 for a
|
|
83
|
+
nonexistent root and silently ignores unknown flags. Until v10.0.0, do not
|
|
84
|
+
trust exit 0 from `--fast` alone: check stdout for `INCONCLUSIVE`, which it
|
|
85
|
+
prints when nothing was scanned.
|
|
86
|
+
|
|
87
|
+
Both gaps are tracked as pending moat cases, milestone v10.0.0, in
|
|
88
|
+
`tests/moat/pending.txt`: P2.verify-exit-contract (the first three rows)
|
|
89
|
+
and P2.fast-verify-inconclusive-not-zero (the `--fast` row).
|
|
90
|
+
|
|
70
91
|
## `loki proof verify <id>`
|
|
71
92
|
|
|
72
93
|
Re-checks one Evidence Receipt against the repo (tamper and drift). The same
|