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.
Files changed (99) hide show
  1. package/README.md +2 -2
  2. package/SKILL.md +3 -3
  3. package/VERSION +1 -1
  4. package/autonomy/lib/backlog.py +18 -3
  5. package/autonomy/lib/chat.sh +6 -0
  6. package/autonomy/lib/engine10-push.sh +26 -2
  7. package/autonomy/lib/proof-generator.py +16 -0
  8. package/autonomy/lib/trust_trajectory.py +130 -0
  9. package/autonomy/lib/workspace.py +2 -3
  10. package/autonomy/loki +263 -58
  11. package/autonomy/quickstart.sh +40 -0
  12. package/autonomy/run.sh +39 -15
  13. package/autonomy/trigger-server.py +452 -29
  14. package/bin/loki +4 -1
  15. package/completions/_loki +1 -1
  16. package/completions/loki.bash +16 -1
  17. package/dashboard/__init__.py +1 -1
  18. package/docs/CLI-REFERENCE.md +7 -4
  19. package/docs/DEPLOYMENT.md +12 -5
  20. package/docs/EVALUATING.md +13 -0
  21. package/docs/INSTALLATION.md +2 -2
  22. package/docs/SIGNED-RECEIPTS.md +7 -0
  23. package/docs/WORKSPACES.md +2 -2
  24. package/docs/cost-controls.md +26 -0
  25. package/docs/merge-queue.md +19 -0
  26. package/docs/sentry-intake.md +4 -0
  27. package/docs/slack.md +2 -1
  28. package/docs/trackers.md +12 -1
  29. package/docs/v10/BOARD.md +140 -85
  30. package/docs/v10/CLI-MODERN.md +5 -4
  31. package/docs/v10/DECISIONS.md +1 -0
  32. package/docs/v10/ENGINE.md +2 -0
  33. package/docs/v10/FAILURE-CLASSES.md +3 -3
  34. package/docs/v10/MODERNIZE.md +34 -2
  35. package/docs/v10/PROGRESS.md +15 -0
  36. package/loki-ts/dist/loki.js +1225 -1139
  37. package/mcp/__init__.py +1 -1
  38. package/package.json +2 -2
  39. package/packages/control-plane/dist/server.js +1889 -1577
  40. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  41. package/schemas/loki-yaml.schema.json +5 -0
  42. package/web-app/dist/assets/{AdminPage-D3PgG7SH.js → AdminPage-bZlvH4TL.js} +1 -1
  43. package/web-app/dist/assets/{Avatar-Ct77hvlG.js → Avatar-BZrBstQe.js} +1 -1
  44. package/web-app/dist/assets/{Badge-Cg_gZaJF.js → Badge-Q8l8r4Vq.js} +1 -1
  45. package/web-app/dist/assets/{Button-i9r2G84n.js → Button-B8Bt0A3S.js} +1 -1
  46. package/web-app/dist/assets/{CockpitPage-C3UyLXyp.js → CockpitPage-CIYExrXa.js} +1 -1
  47. package/web-app/dist/assets/{ComparePage-B1dXHga_.js → ComparePage-CBOmHdam.js} +1 -1
  48. package/web-app/dist/assets/{ErrorBoundary-CQ_xREw0.js → ErrorBoundary-BKwDPSnK.js} +1 -1
  49. package/web-app/dist/assets/{EvidenceReceiptPanel-DwUxd_Xi.js → EvidenceReceiptPanel-KqzjphWl.js} +1 -1
  50. package/web-app/dist/assets/{GitHubIssuesPanel-C0jAnuAd.js → GitHubIssuesPanel-lF3GkHRv.js} +1 -1
  51. package/web-app/dist/assets/{GitHubPRsPanel-B4pNXJMz.js → GitHubPRsPanel-BCzipPWD.js} +1 -1
  52. package/web-app/dist/assets/{HomePage-BC9UTS1l.js → HomePage-CIdnkzaN.js} +2 -2
  53. package/web-app/dist/assets/{LoginPage-CnpdwK8F.js → LoginPage-D-178nTT.js} +1 -1
  54. package/web-app/dist/assets/{MagicPage-Bj0lZuNp.js → MagicPage-BmHuzMT8.js} +1 -1
  55. package/web-app/dist/assets/{MetricsPage-yyw3VnfX.js → MetricsPage-CPCiyDFn.js} +1 -1
  56. package/web-app/dist/assets/{NotFoundPage-LMxkJP15.js → NotFoundPage-B2T6n1gx.js} +1 -1
  57. package/web-app/dist/assets/{ProjectPage-2x0MRkNu.js → ProjectPage-DQmpFhb0.js} +3 -3
  58. package/web-app/dist/assets/{ProjectsPage-A8J8o1gj.js → ProjectsPage-BmugzFEd.js} +1 -1
  59. package/web-app/dist/assets/{SettingsPage-fwvOVcRb.js → SettingsPage-ZB-RrmgM.js} +1 -1
  60. package/web-app/dist/assets/{ShowcasePage-DqI4sUwk.js → ShowcasePage-BAhwHt4_.js} +1 -1
  61. package/web-app/dist/assets/{SystemSettingsPage-CyytfNo_.js → SystemSettingsPage-Bt7sf2Vu.js} +1 -1
  62. package/web-app/dist/assets/{TeamsPage-BTTe76W1.js → TeamsPage-B-v5j_8q.js} +1 -1
  63. package/web-app/dist/assets/{TemplatesPage-CIp3OTlL.js → TemplatesPage-bdqUL-LG.js} +1 -1
  64. package/web-app/dist/assets/{TerminalOutput-dX5L4ky-.js → TerminalOutput-CRHEXBwS.js} +1 -1
  65. package/web-app/dist/assets/{activity-uHXr2AaF.js → activity-C-ROkmXt.js} +1 -1
  66. package/web-app/dist/assets/{bell-D6RbxRMo.js → bell-DbiCBxQA.js} +1 -1
  67. package/web-app/dist/assets/{bot-D31w2Mu6.js → bot-DsIgE_qr.js} +1 -1
  68. package/web-app/dist/assets/{check-CoKJksbr.js → check-CkAdmHWP.js} +1 -1
  69. package/web-app/dist/assets/{chevron-left-Bjx7oX7s.js → chevron-left-CYTLivAo.js} +1 -1
  70. package/web-app/dist/assets/{circle-alert-DOAh8Jmi.js → circle-alert-BVIcAsFJ.js} +1 -1
  71. package/web-app/dist/assets/{clock-DgEXPNWH.js → clock-Dg3Rq0go.js} +1 -1
  72. package/web-app/dist/assets/{cloud-0dXJFzBv.js → cloud-CenrqHFl.js} +1 -1
  73. package/web-app/dist/assets/{code-xml-DytQ_bq7.js → code-xml-C2mvfoug.js} +1 -1
  74. package/web-app/dist/assets/{database-Qyjryb72.js → database-BKa0_eCb.js} +1 -1
  75. package/web-app/dist/assets/{dollar-sign-BzhTVy1e.js → dollar-sign-DfelUK1S.js} +1 -1
  76. package/web-app/dist/assets/{file-code-corner-DTdSOALw.js → file-code-corner-CZKWoHVg.js} +1 -1
  77. package/web-app/dist/assets/{file-plus-VdjOG1RK.js → file-plus-CZ-m1zMX.js} +1 -1
  78. package/web-app/dist/assets/{globe-BhxNOfyM.js → globe-S0kv_GwC.js} +1 -1
  79. package/web-app/dist/assets/{hammer-MQzrw8ee.js → hammer-BW1MDdu1.js} +1 -1
  80. package/web-app/dist/assets/{index-DaxrMbHf.js → index-ACEYsTc2.js} +3 -3
  81. package/web-app/dist/assets/{layers-C7nusTP-.js → layers-BrXHYZ-L.js} +1 -1
  82. package/web-app/dist/assets/{loader-circle-B1qBkgOY.js → loader-circle-DOdhKFx0.js} +1 -1
  83. package/web-app/dist/assets/{lock-BdkOxK2O.js → lock-BcFTyg8J.js} +1 -1
  84. package/web-app/dist/assets/{package-RVyK96Zn.js → package-D34cMVQG.js} +1 -1
  85. package/web-app/dist/assets/{plus-ntmwFRrp.js → plus-CEaMeBxL.js} +1 -1
  86. package/web-app/dist/assets/{refresh-cw-BJ39b_PP.js → refresh-cw-D2Rzxr5U.js} +1 -1
  87. package/web-app/dist/assets/{rotate-ccw-uPx_-3vz.js → rotate-ccw-C_-EjRLh.js} +1 -1
  88. package/web-app/dist/assets/{scroll-text-D9qvXkj-.js → scroll-text-BSSCMI_c.js} +1 -1
  89. package/web-app/dist/assets/{server-gs4xmD8Y.js → server-BKvLonWt.js} +1 -1
  90. package/web-app/dist/assets/{shield-alert-O2_YffGI.js → shield-alert-DbbQbPdW.js} +1 -1
  91. package/web-app/dist/assets/{thumbs-up-B3RVBhQx.js → thumbs-up-NoBD1fUR.js} +1 -1
  92. package/web-app/dist/assets/{trash-2-DEUt7qhq.js → trash-2-BXz8rAyd.js} +1 -1
  93. package/web-app/dist/assets/{trending-down-oyTns4UZ.js → trending-down-D8u535Re.js} +1 -1
  94. package/web-app/dist/assets/{trending-up-CdpZK0Oc.js → trending-up-q8k3kgiy.js} +1 -1
  95. package/web-app/dist/assets/{upload-D9sbjjC8.js → upload-Cp7_zeBI.js} +1 -1
  96. package/web-app/dist/assets/{usePolling-6ognrnyV.js → usePolling-CTHVdcuX.js} +1 -1
  97. package/web-app/dist/assets/{user-CBKc8QoI.js → user-DF7bfSf_.js} +1 -1
  98. package/web-app/dist/index.html +1 -1
  99. package/autonomy/lib/doctor-fix.py +0 -279
@@ -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
- if [ -n "${loki_dir}" ]; then
28316
- mkdir -p "$loki_dir/state" 2>/dev/null || true
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