loki-mode 11.10.1 → 11.15.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 +2 -2
- package/SKILL.md +3 -3
- package/VERSION +1 -1
- package/autonomy/lib/backlog.py +18 -3
- package/autonomy/lib/chat.sh +6 -0
- package/autonomy/lib/engine10-push.sh +26 -2
- package/autonomy/lib/proof-generator.py +16 -0
- package/autonomy/lib/trust_trajectory.py +130 -0
- package/autonomy/lib/workspace.py +2 -3
- package/autonomy/loki +263 -58
- package/autonomy/quickstart.sh +40 -0
- package/autonomy/run.sh +39 -15
- package/autonomy/trigger-server.py +452 -29
- package/bin/loki +4 -1
- package/completions/_loki +1 -1
- package/completions/loki.bash +16 -1
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +7 -4
- package/docs/DEPLOYMENT.md +12 -5
- package/docs/EVALUATING.md +13 -0
- package/docs/INSTALLATION.md +2 -2
- package/docs/SIGNED-RECEIPTS.md +7 -0
- package/docs/WORKSPACES.md +2 -2
- package/docs/cost-controls.md +26 -0
- package/docs/merge-queue.md +19 -0
- package/docs/sentry-intake.md +4 -0
- package/docs/slack.md +2 -1
- package/docs/trackers.md +12 -1
- package/docs/v10/BOARD.md +140 -85
- package/docs/v10/CLI-MODERN.md +5 -4
- package/docs/v10/DECISIONS.md +1 -0
- package/docs/v10/ENGINE.md +2 -0
- package/docs/v10/FAILURE-CLASSES.md +3 -3
- package/docs/v10/MODERNIZE.md +34 -2
- package/docs/v10/PROGRESS.md +15 -0
- package/loki-ts/dist/loki.js +1225 -1139
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +1889 -1577
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/schemas/loki-yaml.schema.json +5 -0
- package/web-app/dist/assets/{AdminPage-D3PgG7SH.js → AdminPage-bZlvH4TL.js} +1 -1
- package/web-app/dist/assets/{Avatar-Ct77hvlG.js → Avatar-BZrBstQe.js} +1 -1
- package/web-app/dist/assets/{Badge-Cg_gZaJF.js → Badge-Q8l8r4Vq.js} +1 -1
- package/web-app/dist/assets/{Button-i9r2G84n.js → Button-B8Bt0A3S.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-C3UyLXyp.js → CockpitPage-CIYExrXa.js} +1 -1
- package/web-app/dist/assets/{ComparePage-B1dXHga_.js → ComparePage-CBOmHdam.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-CQ_xREw0.js → ErrorBoundary-BKwDPSnK.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-DwUxd_Xi.js → EvidenceReceiptPanel-KqzjphWl.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-C0jAnuAd.js → GitHubIssuesPanel-lF3GkHRv.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-B4pNXJMz.js → GitHubPRsPanel-BCzipPWD.js} +1 -1
- package/web-app/dist/assets/{HomePage-BC9UTS1l.js → HomePage-CIdnkzaN.js} +2 -2
- package/web-app/dist/assets/{LoginPage-CnpdwK8F.js → LoginPage-D-178nTT.js} +1 -1
- package/web-app/dist/assets/{MagicPage-Bj0lZuNp.js → MagicPage-BmHuzMT8.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-yyw3VnfX.js → MetricsPage-CPCiyDFn.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-LMxkJP15.js → NotFoundPage-B2T6n1gx.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-2x0MRkNu.js → ProjectPage-DQmpFhb0.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-A8J8o1gj.js → ProjectsPage-BmugzFEd.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-fwvOVcRb.js → SettingsPage-ZB-RrmgM.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-DqI4sUwk.js → ShowcasePage-BAhwHt4_.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-CyytfNo_.js → SystemSettingsPage-Bt7sf2Vu.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-BTTe76W1.js → TeamsPage-B-v5j_8q.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-CIp3OTlL.js → TemplatesPage-bdqUL-LG.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-dX5L4ky-.js → TerminalOutput-CRHEXBwS.js} +1 -1
- package/web-app/dist/assets/{activity-uHXr2AaF.js → activity-C-ROkmXt.js} +1 -1
- package/web-app/dist/assets/{bell-D6RbxRMo.js → bell-DbiCBxQA.js} +1 -1
- package/web-app/dist/assets/{bot-D31w2Mu6.js → bot-DsIgE_qr.js} +1 -1
- package/web-app/dist/assets/{check-CoKJksbr.js → check-CkAdmHWP.js} +1 -1
- package/web-app/dist/assets/{chevron-left-Bjx7oX7s.js → chevron-left-CYTLivAo.js} +1 -1
- package/web-app/dist/assets/{circle-alert-DOAh8Jmi.js → circle-alert-BVIcAsFJ.js} +1 -1
- package/web-app/dist/assets/{clock-DgEXPNWH.js → clock-Dg3Rq0go.js} +1 -1
- package/web-app/dist/assets/{cloud-0dXJFzBv.js → cloud-CenrqHFl.js} +1 -1
- package/web-app/dist/assets/{code-xml-DytQ_bq7.js → code-xml-C2mvfoug.js} +1 -1
- package/web-app/dist/assets/{database-Qyjryb72.js → database-BKa0_eCb.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-BzhTVy1e.js → dollar-sign-DfelUK1S.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-DTdSOALw.js → file-code-corner-CZKWoHVg.js} +1 -1
- package/web-app/dist/assets/{file-plus-VdjOG1RK.js → file-plus-CZ-m1zMX.js} +1 -1
- package/web-app/dist/assets/{globe-BhxNOfyM.js → globe-S0kv_GwC.js} +1 -1
- package/web-app/dist/assets/{hammer-MQzrw8ee.js → hammer-BW1MDdu1.js} +1 -1
- package/web-app/dist/assets/{index-DaxrMbHf.js → index-ACEYsTc2.js} +3 -3
- package/web-app/dist/assets/{layers-C7nusTP-.js → layers-BrXHYZ-L.js} +1 -1
- package/web-app/dist/assets/{loader-circle-B1qBkgOY.js → loader-circle-DOdhKFx0.js} +1 -1
- package/web-app/dist/assets/{lock-BdkOxK2O.js → lock-BcFTyg8J.js} +1 -1
- package/web-app/dist/assets/{package-RVyK96Zn.js → package-D34cMVQG.js} +1 -1
- package/web-app/dist/assets/{plus-ntmwFRrp.js → plus-CEaMeBxL.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-BJ39b_PP.js → refresh-cw-D2Rzxr5U.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-uPx_-3vz.js → rotate-ccw-C_-EjRLh.js} +1 -1
- package/web-app/dist/assets/{scroll-text-D9qvXkj-.js → scroll-text-BSSCMI_c.js} +1 -1
- package/web-app/dist/assets/{server-gs4xmD8Y.js → server-BKvLonWt.js} +1 -1
- package/web-app/dist/assets/{shield-alert-O2_YffGI.js → shield-alert-DbbQbPdW.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-B3RVBhQx.js → thumbs-up-NoBD1fUR.js} +1 -1
- package/web-app/dist/assets/{trash-2-DEUt7qhq.js → trash-2-BXz8rAyd.js} +1 -1
- package/web-app/dist/assets/{trending-down-oyTns4UZ.js → trending-down-D8u535Re.js} +1 -1
- package/web-app/dist/assets/{trending-up-CdpZK0Oc.js → trending-up-q8k3kgiy.js} +1 -1
- package/web-app/dist/assets/{upload-D9sbjjC8.js → upload-Cp7_zeBI.js} +1 -1
- package/web-app/dist/assets/{usePolling-6ognrnyV.js → usePolling-CTHVdcuX.js} +1 -1
- package/web-app/dist/assets/{user-CBKc8QoI.js → user-DF7bfSf_.js} +1 -1
- package/web-app/dist/index.html +1 -1
- package/autonomy/lib/doctor-fix.py +0 -279
package/autonomy/quickstart.sh
CHANGED
|
@@ -181,6 +181,9 @@ _qs_score_templates() {
|
|
|
181
181
|
# can tell a genuine match from simple-todo-app winning by default.
|
|
182
182
|
local best_mode=false
|
|
183
183
|
[ "${2:-}" = "--best" ] && best_mode=true
|
|
184
|
+
# --scores: print "name<TAB>score" for the top 3 (used by --explain-match).
|
|
185
|
+
local scores_mode=false
|
|
186
|
+
[ "${2:-}" = "--scores" ] && scores_mode=true
|
|
184
187
|
local tdir; tdir="$(_qs_templates_dir)"
|
|
185
188
|
local brief_lc; brief_lc=$(printf '%s' "$brief" | tr '[:upper:]' '[:lower:]')
|
|
186
189
|
|
|
@@ -263,6 +266,8 @@ _qs_score_templates() {
|
|
|
263
266
|
' | sort -t"$(printf '\t')" -k1,1nr -k2,2n -k3,3 | {
|
|
264
267
|
if [ "$best_mode" = true ]; then
|
|
265
268
|
head -1 | cut -f1 | awk '{ print ($1 == "" ? 0 : $1) }'
|
|
269
|
+
elif [ "$scores_mode" = true ]; then
|
|
270
|
+
head -3 | awk -F'\t' '{ printf "%s\t%s\n", $3, $1 }'
|
|
266
271
|
else
|
|
267
272
|
head -3 | cut -f3
|
|
268
273
|
fi
|
|
@@ -276,6 +281,27 @@ _qs_match_strength() {
|
|
|
276
281
|
_qs_score_templates "$1" --best
|
|
277
282
|
}
|
|
278
283
|
|
|
284
|
+
# _qs_explain_match <brief>: print the top 3 template scores and a confidence
|
|
285
|
+
# label. Reuses the scorer; offline and read-only.
|
|
286
|
+
_qs_explain_match() {
|
|
287
|
+
local brief="$1" strength rank=1 name score
|
|
288
|
+
strength="$(_qs_match_strength "$brief")"
|
|
289
|
+
case "$strength" in ''|*[!0-9]*) strength=0;; esac
|
|
290
|
+
printf '\n Template match scores:\n'
|
|
291
|
+
while IFS=$'\t' read -r name score; do
|
|
292
|
+
[ -n "$name" ] || continue
|
|
293
|
+
printf ' %d. %s score %s\n' "$rank" "$name" "$score"
|
|
294
|
+
rank=$((rank + 1))
|
|
295
|
+
done < <(_qs_score_templates "$brief" --scores)
|
|
296
|
+
if [ "$strength" -ge 4 ]; then
|
|
297
|
+
printf ' Match confidence: high (strength %s)\n' "$strength"
|
|
298
|
+
elif [ "$strength" -ge 2 ]; then
|
|
299
|
+
printf ' Match confidence: medium (strength %s)\n' "$strength"
|
|
300
|
+
else
|
|
301
|
+
printf ' Match confidence: low (strength %s): no strong match, using a plain spec\n' "$strength"
|
|
302
|
+
fi
|
|
303
|
+
}
|
|
304
|
+
|
|
279
305
|
# _qs_template_summary <name>: a short one-line description for the picker.
|
|
280
306
|
# Read from the template's first prose line would be fragile; use a small
|
|
281
307
|
# curated table so the picker copy is stable and honest.
|
|
@@ -919,6 +945,7 @@ _qs_help() {
|
|
|
919
945
|
printf ' --yes, -y Auto-confirm the final build prompt (still shows the plan)\n'
|
|
920
946
|
printf ' --dry-run Preview the selected template and plan; write/start nothing\n'
|
|
921
947
|
printf ' --json Emit machine-readable output for a read-only command\n'
|
|
948
|
+
printf ' --explain-match With --dry-run, show the top 3 template scores and match confidence\n'
|
|
922
949
|
printf ' --from-preview F Continue saved JSON from file F (or - for piped stdin); requires --yes\n'
|
|
923
950
|
printf ' --verify-preview F Verify saved JSON from file F (or - for piped stdin); executes nothing\n'
|
|
924
951
|
printf ' --template N Use the exact shipped template N for an IDEA\n'
|
|
@@ -986,6 +1013,7 @@ cmd_quickstart() {
|
|
|
986
1013
|
local template_flag_seen=false
|
|
987
1014
|
local list_templates=false
|
|
988
1015
|
local list_templates_flag_seen=false
|
|
1016
|
+
local explain_match=false
|
|
989
1017
|
local from_preview=""
|
|
990
1018
|
local from_preview_flag_seen=false
|
|
991
1019
|
local verify_preview=""
|
|
@@ -1023,6 +1051,10 @@ cmd_quickstart() {
|
|
|
1023
1051
|
json_output=true
|
|
1024
1052
|
shift
|
|
1025
1053
|
;;
|
|
1054
|
+
--explain-match)
|
|
1055
|
+
explain_match=true
|
|
1056
|
+
shift
|
|
1057
|
+
;;
|
|
1026
1058
|
--template)
|
|
1027
1059
|
if [ "$template_flag_seen" = true ]; then
|
|
1028
1060
|
printf '%s--template may be specified only once.%s\n' "$_QS_RED" "$_QS_NC" >&2
|
|
@@ -1168,6 +1200,11 @@ cmd_quickstart() {
|
|
|
1168
1200
|
exit 2
|
|
1169
1201
|
fi
|
|
1170
1202
|
|
|
1203
|
+
if [ "$explain_match" = true ] && { [ "$dry_run" != true ] || [ "$json_output" = true ]; }; then
|
|
1204
|
+
printf '%s--explain-match requires --dry-run and cannot be combined with --json.%s\n' "$_QS_RED" "$_QS_NC" >&2
|
|
1205
|
+
exit 2
|
|
1206
|
+
fi
|
|
1207
|
+
|
|
1171
1208
|
if [ "$json_output" = true ] && [ "$dry_run" != true ]; then
|
|
1172
1209
|
printf '%s--json requires --dry-run.%s\n' "$_QS_RED" "$_QS_NC" >&2
|
|
1173
1210
|
exit 2
|
|
@@ -1257,6 +1294,9 @@ cmd_quickstart() {
|
|
|
1257
1294
|
printf '\n'
|
|
1258
1295
|
if [ "$dry_run" = true ]; then
|
|
1259
1296
|
printf '%sLoki Mode quickstart preview -- template and plan only.%s\n' "$_QS_BOLD" "$_QS_NC"
|
|
1297
|
+
if [ "$explain_match" = true ]; then
|
|
1298
|
+
_qs_explain_match "$positional"
|
|
1299
|
+
fi
|
|
1260
1300
|
else
|
|
1261
1301
|
printf '%sLoki Mode quickstart -- four quick questions, then your build starts.%s\n' "$_QS_BOLD" "$_QS_NC"
|
|
1262
1302
|
fi
|
package/autonomy/run.sh
CHANGED
|
@@ -28292,6 +28292,41 @@ check_human_intervention() {
|
|
|
28292
28292
|
}
|
|
28293
28293
|
|
|
28294
28294
|
# Handle pause state - wait for resume
|
|
28295
|
+
# Writes .loki/state/interventions.json. Mirrors loki-ts/src/runner/intervention.ts
|
|
28296
|
+
# (count, basis, by_type enum counts, waited_s). Modes: "count" bumps count and
|
|
28297
|
+
# the by_type bucket inferred from the signal files; "waited <secs>" adds
|
|
28298
|
+
# wall-clock blocked seconds (an upper bound on human attention, not active
|
|
28299
|
+
# minutes). Best-effort: never fails a run.
|
|
28300
|
+
_loki_iv_record() {
|
|
28301
|
+
local loki_dir="$1" mode="$2" secs="${3:-0}" iv_type="authorization"
|
|
28302
|
+
[ -n "$loki_dir" ] || return 0
|
|
28303
|
+
if [ -e "$loki_dir/HUMAN_INPUT.md" ]; then iv_type="input"
|
|
28304
|
+
elif [ -e "$loki_dir/signals/GATE_ESCALATION" ] || [ -e "$loki_dir/signals/COUNCIL_REVIEW_REQUESTED" ]; then iv_type="repair"
|
|
28305
|
+
elif [ -e "$loki_dir/signals/BUDGET_EXCEEDED" ]; then iv_type="steer"
|
|
28306
|
+
fi
|
|
28307
|
+
mkdir -p "$loki_dir/state" 2>/dev/null || true
|
|
28308
|
+
python3 -I -c 'import json,sys
|
|
28309
|
+
p,mode,secs,t=sys.argv[1:5]
|
|
28310
|
+
def n(v):
|
|
28311
|
+
return v if isinstance(v,int) and not isinstance(v,bool) and v>=0 else 0
|
|
28312
|
+
try:
|
|
28313
|
+
d=json.load(open(p))
|
|
28314
|
+
if not isinstance(d,dict): d={}
|
|
28315
|
+
except Exception:
|
|
28316
|
+
d={}
|
|
28317
|
+
if mode=="waited" and not d:
|
|
28318
|
+
sys.exit(0)
|
|
28319
|
+
bt=d.get("by_type") if isinstance(d.get("by_type"),dict) else {}
|
|
28320
|
+
out={k:n(bt.get(k)) for k in ("steer","input","authorization","repair")}
|
|
28321
|
+
if mode=="count":
|
|
28322
|
+
out[t]+=1
|
|
28323
|
+
d["count"]=n(d.get("count"))+1
|
|
28324
|
+
d["basis"]="blocking pauses that waited on a human"
|
|
28325
|
+
d["by_type"]=out
|
|
28326
|
+
d["waited_s"]=n(d.get("waited_s"))+(int(secs) if mode=="waited" else 0)
|
|
28327
|
+
open(p,"w").write(json.dumps(d)+"\n")' "$loki_dir/state/interventions.json" "$mode" "$secs" "$iv_type" 2>/dev/null || true
|
|
28328
|
+
}
|
|
28329
|
+
|
|
28295
28330
|
handle_pause() {
|
|
28296
28331
|
# BUG-ST-007: Guard against concurrent pause handler execution
|
|
28297
28332
|
if [ "${_PAUSE_IN_PROGRESS:-0}" -eq 1 ]; then
|
|
@@ -28312,21 +28347,8 @@ handle_pause() {
|
|
|
28312
28347
|
#
|
|
28313
28348
|
# proof-generator reads this; when the file is absent the receipt renders NO
|
|
28314
28349
|
# interventions row rather than claiming zero. Best-effort: never fail a run.
|
|
28315
|
-
|
|
28316
|
-
|
|
28317
|
-
local _iv_file="$loki_dir/state/interventions.json"
|
|
28318
|
-
local _iv_prev=0
|
|
28319
|
-
if [ -f "$_iv_file" ]; then
|
|
28320
|
-
_iv_prev=$(python3 -c "import json,sys
|
|
28321
|
-
try:
|
|
28322
|
-
v=json.load(open(sys.argv[1])).get('count')
|
|
28323
|
-
print(int(v) if isinstance(v,int) and v>=0 else 0)
|
|
28324
|
-
except Exception:
|
|
28325
|
-
print(0)" "$_iv_file" 2>/dev/null || echo 0)
|
|
28326
|
-
fi
|
|
28327
|
-
printf '{"count":%s,"basis":"blocking pauses that waited on a human"}\n' \
|
|
28328
|
-
"$(( _iv_prev + 1 ))" > "$_iv_file" 2>/dev/null || true
|
|
28329
|
-
fi
|
|
28350
|
+
local _iv_t0=$SECONDS
|
|
28351
|
+
_loki_iv_record "$loki_dir" count
|
|
28330
28352
|
|
|
28331
28353
|
# Save state before pausing so it persists across potential crashes
|
|
28332
28354
|
save_state ${RETRY_COUNT:-0} "paused" 0
|
|
@@ -28426,6 +28448,7 @@ except Exception:
|
|
|
28426
28448
|
# Check for stop signal
|
|
28427
28449
|
if [ -f "$loki_dir/STOP" ]; then
|
|
28428
28450
|
rm -f "$loki_dir/STOP" "$loki_dir/PAUSED.md"
|
|
28451
|
+
_loki_iv_record "$loki_dir" waited "$(( SECONDS - ${_iv_t0:-$SECONDS} ))" 2>/dev/null || true
|
|
28429
28452
|
PAUSED=false
|
|
28430
28453
|
_PAUSE_IN_PROGRESS=0
|
|
28431
28454
|
return 1
|
|
@@ -28471,6 +28494,7 @@ except Exception:
|
|
|
28471
28494
|
done
|
|
28472
28495
|
|
|
28473
28496
|
rm -f "$loki_dir/PAUSED.md"
|
|
28497
|
+
_loki_iv_record "$loki_dir" waited "$(( SECONDS - ${_iv_t0:-$SECONDS} ))" 2>/dev/null || true
|
|
28474
28498
|
log_info "Resuming execution..."
|
|
28475
28499
|
PAUSED=false
|
|
28476
28500
|
_PAUSE_IN_PROGRESS=0
|