loki-mode 11.12.1 → 11.17.1

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 (114) hide show
  1. package/README.md +2 -2
  2. package/SKILL.md +3 -3
  3. package/VERSION +1 -1
  4. package/autonomy/grill.sh +3 -1
  5. package/autonomy/hooks/validate-bash.sh +51 -13
  6. package/autonomy/lib/backlog.py +18 -3
  7. package/autonomy/lib/chat.sh +117 -7
  8. package/autonomy/lib/claude-flags.sh +20 -0
  9. package/autonomy/lib/claude_permissions.py +40 -0
  10. package/autonomy/lib/done-recognition.sh +8 -4
  11. package/autonomy/lib/engine10-push.sh +56 -7
  12. package/autonomy/lib/prd-enrich.sh +4 -2
  13. package/autonomy/lib/proof-generator.py +21 -0
  14. package/autonomy/lib/proof-verify.py +109 -1
  15. package/autonomy/lib/trust_trajectory.py +139 -0
  16. package/autonomy/lib/voter-agents.sh +3 -1
  17. package/autonomy/lib/workspace.py +2 -3
  18. package/autonomy/loki +427 -74
  19. package/autonomy/quickstart.sh +21 -2
  20. package/autonomy/run.sh +55 -21
  21. package/autonomy/trigger-server.py +461 -32
  22. package/bin/loki +4 -1
  23. package/completions/_loki +1 -1
  24. package/completions/loki.bash +10 -2
  25. package/dashboard/__init__.py +1 -1
  26. package/dashboard/api_start.py +2 -2
  27. package/dashboard/build_supervisor.py +2 -0
  28. package/docs/CLI-REFERENCE.md +6 -4
  29. package/docs/DEPLOYMENT.md +12 -5
  30. package/docs/EVALUATING.md +13 -0
  31. package/docs/INSTALLATION.md +2 -2
  32. package/docs/SIGNED-RECEIPTS.md +7 -0
  33. package/docs/WORKSPACES.md +2 -2
  34. package/docs/cost-controls.md +26 -0
  35. package/docs/merge-queue.md +19 -0
  36. package/docs/sentry-intake.md +4 -0
  37. package/docs/slack.md +2 -1
  38. package/docs/trackers.md +12 -1
  39. package/docs/v10/BOARD.md +148 -123
  40. package/docs/v10/CLI-MODERN.md +5 -5
  41. package/docs/v10/DECISIONS.md +2 -0
  42. package/docs/v10/ENGINE.md +2 -0
  43. package/docs/v10/FAILURE-CLASSES.md +18 -0
  44. package/docs/v10/MODERNIZE.md +32 -1
  45. package/docs/v10/PROGRESS.md +7 -0
  46. package/loki-ts/data/finding-schema.json +2 -1
  47. package/loki-ts/dist/loki.js +1222 -1128
  48. package/magic/core/debate.py +27 -1
  49. package/mcp/__init__.py +1 -1
  50. package/package.json +2 -2
  51. package/packages/control-plane/dist/server.js +5895 -5292
  52. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  53. package/providers/claude.sh +6 -3
  54. package/providers/model_catalog.json +6 -0
  55. package/schemas/loki-yaml.schema.json +5 -0
  56. package/src/policies/claude_permissions.js +114 -0
  57. package/web-app/dist/assets/{AdminPage-DuT74pf5.js → AdminPage-OVzN6eLm.js} +1 -1
  58. package/web-app/dist/assets/{Avatar-BtgidR5a.js → Avatar-hCCrxrCZ.js} +1 -1
  59. package/web-app/dist/assets/{Badge-D2nt8G_I.js → Badge-CDcpkhbJ.js} +1 -1
  60. package/web-app/dist/assets/{Button-BKl2jOyb.js → Button-8mwWlhEu.js} +1 -1
  61. package/web-app/dist/assets/{CockpitPage-DaWr0EUX.js → CockpitPage-D8cf3u22.js} +1 -1
  62. package/web-app/dist/assets/{ComparePage-aIiNhxLr.js → ComparePage-CIgkbDRY.js} +1 -1
  63. package/web-app/dist/assets/{ErrorBoundary-C1Q7rV23.js → ErrorBoundary-99kJH9g2.js} +1 -1
  64. package/web-app/dist/assets/{EvidenceReceiptPanel-C-C0-tOx.js → EvidenceReceiptPanel-C9fj32eS.js} +1 -1
  65. package/web-app/dist/assets/{GitHubIssuesPanel-l3IaXDag.js → GitHubIssuesPanel-De43YQ_C.js} +1 -1
  66. package/web-app/dist/assets/{GitHubPRsPanel-DweLBgr5.js → GitHubPRsPanel-7g7ZTnkx.js} +1 -1
  67. package/web-app/dist/assets/{HomePage-B_KK7AvY.js → HomePage-CcNA24ny.js} +2 -2
  68. package/web-app/dist/assets/{LoginPage-CKS-KLdH.js → LoginPage-BYjlb-IK.js} +1 -1
  69. package/web-app/dist/assets/{MagicPage-Cl6CEp8J.js → MagicPage-C0Dwt9Na.js} +1 -1
  70. package/web-app/dist/assets/{MetricsPage-n9CPUaX0.js → MetricsPage-jDGmdcgg.js} +1 -1
  71. package/web-app/dist/assets/{NotFoundPage-D85eWn70.js → NotFoundPage-C_ZO8tLE.js} +1 -1
  72. package/web-app/dist/assets/{ProjectPage-CDN7LpSo.js → ProjectPage-B5wnurfQ.js} +3 -3
  73. package/web-app/dist/assets/{ProjectsPage-D4SDmU4-.js → ProjectsPage--EyKt5-D.js} +1 -1
  74. package/web-app/dist/assets/{SettingsPage-Dby6GnKm.js → SettingsPage-cB0lnfti.js} +1 -1
  75. package/web-app/dist/assets/{ShowcasePage-CgHxeqoU.js → ShowcasePage-Dl16FDkK.js} +1 -1
  76. package/web-app/dist/assets/{SystemSettingsPage-BaewGHlc.js → SystemSettingsPage-BmAXd4V2.js} +1 -1
  77. package/web-app/dist/assets/{TeamsPage-905MJyke.js → TeamsPage-BFkWVOZe.js} +1 -1
  78. package/web-app/dist/assets/{TemplatesPage-DMrUHcvF.js → TemplatesPage-Bf2kmEUM.js} +1 -1
  79. package/web-app/dist/assets/{TerminalOutput-BsbEbBYX.js → TerminalOutput-BItv9Wa6.js} +1 -1
  80. package/web-app/dist/assets/{activity-BuaXhBsC.js → activity-Df2Awg6I.js} +1 -1
  81. package/web-app/dist/assets/{bell-BfEQ71OG.js → bell-D-1ztTsJ.js} +1 -1
  82. package/web-app/dist/assets/{bot-DOGeYewg.js → bot-A4qgZsKi.js} +1 -1
  83. package/web-app/dist/assets/{check-zbjPpb3E.js → check-BPfFpF0c.js} +1 -1
  84. package/web-app/dist/assets/{chevron-left-DWTOgfFt.js → chevron-left-CfSJvmDi.js} +1 -1
  85. package/web-app/dist/assets/{circle-alert-BEPKfRzR.js → circle-alert-wx2d1dzb.js} +1 -1
  86. package/web-app/dist/assets/{clock-C_fX3OHo.js → clock-pQMai6l-.js} +1 -1
  87. package/web-app/dist/assets/{cloud-DUXHygXQ.js → cloud-DWL470r6.js} +1 -1
  88. package/web-app/dist/assets/{code-xml-BEVl_9Hw.js → code-xml-BaEQpQLZ.js} +1 -1
  89. package/web-app/dist/assets/{database-_a22uh7l.js → database-h-N7WkQN.js} +1 -1
  90. package/web-app/dist/assets/{dollar-sign-l2en7xfg.js → dollar-sign-B5oYiD27.js} +1 -1
  91. package/web-app/dist/assets/{file-code-corner-DItKl6H4.js → file-code-corner-fbTtTy0o.js} +1 -1
  92. package/web-app/dist/assets/{file-plus-BSk7qFMA.js → file-plus-PaF6HMo8.js} +1 -1
  93. package/web-app/dist/assets/{globe-2TveFE5l.js → globe-Ct-GlWID.js} +1 -1
  94. package/web-app/dist/assets/{hammer-BU6OJlQj.js → hammer-C1oZFX51.js} +1 -1
  95. package/web-app/dist/assets/{index-DGnZXUYk.js → index-C2egrRhz.js} +3 -3
  96. package/web-app/dist/assets/{layers-DKw7MNuq.js → layers-Dt5ZK4v2.js} +1 -1
  97. package/web-app/dist/assets/{loader-circle-CoYfykzD.js → loader-circle-DrpMziic.js} +1 -1
  98. package/web-app/dist/assets/{lock-D9JzrXDL.js → lock-DOez8MmK.js} +1 -1
  99. package/web-app/dist/assets/{package-BZtqTIqH.js → package-ClGIkerr.js} +1 -1
  100. package/web-app/dist/assets/{plus-BGJfo8bV.js → plus-C004i9ua.js} +1 -1
  101. package/web-app/dist/assets/{refresh-cw-F6lowBgR.js → refresh-cw-Ddfk-7Sy.js} +1 -1
  102. package/web-app/dist/assets/{rotate-ccw-DHOK8dM4.js → rotate-ccw-Bu1KgDjS.js} +1 -1
  103. package/web-app/dist/assets/{scroll-text-CKcROoMV.js → scroll-text-3q1lW5pm.js} +1 -1
  104. package/web-app/dist/assets/{server-DbG8MDv6.js → server-pd6x4HW1.js} +1 -1
  105. package/web-app/dist/assets/{shield-alert-RNKNXdJT.js → shield-alert-B9jGJepT.js} +1 -1
  106. package/web-app/dist/assets/{thumbs-up-Yxp-UBxS.js → thumbs-up-Cdcc9nQf.js} +1 -1
  107. package/web-app/dist/assets/{trash-2-DY-eba1n.js → trash-2-foSojXHK.js} +1 -1
  108. package/web-app/dist/assets/{trending-down-CARiDB3t.js → trending-down-CTTiqlJ1.js} +1 -1
  109. package/web-app/dist/assets/{trending-up-brQqWbA3.js → trending-up-B_MgmRAx.js} +1 -1
  110. package/web-app/dist/assets/{upload-D6wRjKhz.js → upload-g6BfALzG.js} +1 -1
  111. package/web-app/dist/assets/{usePolling-BMrqNbAI.js → usePolling-DrHwvzuh.js} +1 -1
  112. package/web-app/dist/assets/{user-CK5-EXIj.js → user-COp75m7l.js} +1 -1
  113. package/web-app/dist/index.html +1 -1
  114. package/autonomy/lib/doctor-fix.py +0 -279
@@ -824,12 +824,31 @@ _qs_classify_invoke() {
824
824
  local to=""
825
825
  if command -v timeout >/dev/null 2>&1; then to="timeout"
826
826
  elif command -v gtimeout >/dev/null 2>&1; then to="gtimeout"; fi
827
+ _LOKI_PERM_ARGV=(--dangerously-skip-permissions)
828
+ if [ "${LOKI_PERMISSION_POLICY:-}" = "compiled" ]; then
829
+ # P12-26b: nothing on this path sources claude-flags.sh. Compute in a subshell so its
830
+ # top-level exports (caveman vars) never leak; fail closed to plan when unavailable.
831
+ local _qs_flags _qs_out _qs_a
832
+ _qs_flags="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)/lib/claude-flags.sh"
833
+ _LOKI_PERM_ARGV=(--permission-mode plan)
834
+ _qs_out="$(
835
+ # shellcheck source=/dev/null
836
+ . "$_qs_flags" >/dev/null 2>&1 || exit 1
837
+ type _loki_claude_permission_argv >/dev/null 2>&1 || exit 1
838
+ _loki_claude_permission_argv
839
+ printf '%s\n' "${_LOKI_PERM_ARGV[@]}"
840
+ )" || _qs_out=""
841
+ if [ -n "$_qs_out" ]; then
842
+ _LOKI_PERM_ARGV=()
843
+ while IFS= read -r _qs_a; do _LOKI_PERM_ARGV+=("$_qs_a"); done <<< "$_qs_out"
844
+ fi
845
+ fi
827
846
  if [ -n "$to" ]; then
828
847
  out=$(CAVEMAN_DEFAULT_MODE=off "$to" "${LOKI_QUICKSTART_CLASSIFY_TIMEOUT}" \
829
- claude --dangerously-skip-permissions -p "$prompt" 2>/dev/null) || rc=$?
848
+ claude "${_LOKI_PERM_ARGV[@]}" -p "$prompt" 2>/dev/null) || rc=$?
830
849
  else
831
850
  out=$(CAVEMAN_DEFAULT_MODE=off \
832
- claude --dangerously-skip-permissions -p "$prompt" 2>/dev/null) || rc=$?
851
+ claude "${_LOKI_PERM_ARGV[@]}" -p "$prompt" 2>/dev/null) || rc=$?
833
852
  fi
834
853
  [ "$rc" -ne 0 ] && return 1
835
854
  [ -z "$out" ] && return 1
package/autonomy/run.sh CHANGED
@@ -6709,13 +6709,15 @@ spawn_worktree_session() {
6709
6709
  # Expand the auto-flag array with the bash-3.2 empty-array guard
6710
6710
  # (${arr[@]+...}) so a bare "${arr[@]}" under set -u does not
6711
6711
  # abort with "unbound variable" when no flags were collected.
6712
+ _LOKI_PERM_ARGV=(--dangerously-skip-permissions)
6713
+ ! type _loki_claude_permission_argv >/dev/null 2>&1 || _loki_claude_permission_argv
6712
6714
  if [ -n "$_loki_wt_cm" ]; then
6713
- CAVEMAN_DEFAULT_MODE="$_loki_wt_cm" claude --dangerously-skip-permissions \
6715
+ CAVEMAN_DEFAULT_MODE="$_loki_wt_cm" claude "${_LOKI_PERM_ARGV[@]}" \
6714
6716
  "${_LOKI_WT_AUTO_FLAGS[@]+"${_LOKI_WT_AUTO_FLAGS[@]}"}" \
6715
6717
  -p "Loki Mode: $task_prompt. Read .loki/CONTINUITY.md for context." \
6716
6718
  >> "$log_file" 2>&1 || _wt_exit=$?
6717
6719
  else
6718
- claude --dangerously-skip-permissions \
6720
+ claude "${_LOKI_PERM_ARGV[@]}" \
6719
6721
  "${_LOKI_WT_AUTO_FLAGS[@]+"${_LOKI_WT_AUTO_FLAGS[@]}"}" \
6720
6722
  -p "Loki Mode: $task_prompt. Read .loki/CONTINUITY.md for context." \
6721
6723
  >> "$log_file" 2>&1 || _wt_exit=$?
@@ -6950,7 +6952,9 @@ Output ONLY the resolved file content with no conflict markers. No explanations.
6950
6952
  # variable (the shell, not the agent, writes the resolved file).
6951
6953
  # It needs no hooks, LSP, CLAUDE.md auto-discovery, or MCP, so
6952
6954
  # --bare is safe and cheaper. Gated + opt-out LOKI_BARE_SUBCALLS=0.
6953
- local _cr_argv=("--dangerously-skip-permissions")
6955
+ _LOKI_PERM_ARGV=(--dangerously-skip-permissions)
6956
+ ! type _loki_claude_permission_argv >/dev/null 2>&1 || _loki_claude_permission_argv
6957
+ local _cr_argv=("${_LOKI_PERM_ARGV[@]}")
6954
6958
  if type loki_subcall_bare_enabled >/dev/null 2>&1 && loki_subcall_bare_enabled; then
6955
6959
  _cr_argv+=("--bare")
6956
6960
  fi
@@ -16282,7 +16286,9 @@ _dispatch_reviewer() {
16282
16286
  # Guardrail, not a sandbox -- echo>/sed -i/etc. remain; the
16283
16287
  # real net is commit-before-agent-wave. Opt out
16284
16288
  # LOKI_REVIEW_TOOL_GUARD=0. See loki_review_guard_denylist.
16285
- local _rv_argv=("--dangerously-skip-permissions")
16289
+ _LOKI_PERM_ARGV=(--dangerously-skip-permissions)
16290
+ ! type _loki_claude_permission_argv >/dev/null 2>&1 || _loki_claude_permission_argv
16291
+ local _rv_argv=("${_LOKI_PERM_ARGV[@]}")
16286
16292
  # OPT-IN advisor pin (v7.104.0, LOKI_ADVISOR_MODEL): reviewers still
16287
16293
  # pass NO --model by default (unchanged behavior: they run on the
16288
16294
  # account default). When the operator/user sets LOKI_ADVISOR_MODEL to
@@ -21352,7 +21358,9 @@ ${_commits}"
21352
21358
  # needed, so --bare is safe and cheaper. Opt out LOKI_BARE_SUBCALLS=0.
21353
21359
  # Always at least --dangerously-skip-permissions, so the array is never
21354
21360
  # empty (empty "${arr[@]}" under set -u errors on bash 3.2, stock macOS).
21355
- local _ic_argv=("--dangerously-skip-permissions")
21361
+ _LOKI_PERM_ARGV=(--dangerously-skip-permissions)
21362
+ ! type _loki_claude_permission_argv >/dev/null 2>&1 || _loki_claude_permission_argv
21363
+ local _ic_argv=("${_LOKI_PERM_ARGV[@]}")
21356
21364
  if type loki_subcall_bare_enabled >/dev/null 2>&1 && loki_subcall_bare_enabled; then
21357
21365
  _ic_argv+=("--bare")
21358
21366
  fi
@@ -25529,7 +25537,9 @@ except Exception as exc:
25529
25537
  # present so the array is never empty (empty "${arr[@]}" under `set -u`
25530
25538
  # is an error on bash 3.2, the stock macOS shell). The autonomy override
25531
25539
  # is appended conditionally.
25532
- local _loki_claude_argv=("--dangerously-skip-permissions" "--model" "$tier_param")
25540
+ _LOKI_PERM_ARGV=(--dangerously-skip-permissions)
25541
+ ! type _loki_claude_permission_argv >/dev/null 2>&1 || _loki_claude_permission_argv
25542
+ local _loki_claude_argv=("${_LOKI_PERM_ARGV[@]}" "--model" "$tier_param")
25533
25543
  if [ "${LOKI_AUTONOMY_OVERRIDE:-on}" != "off" ] \
25534
25544
  && type _loki_autonomy_override_text >/dev/null 2>&1 \
25535
25545
  && type loki_claude_flag_supported >/dev/null 2>&1 \
@@ -28292,6 +28302,41 @@ check_human_intervention() {
28292
28302
  }
28293
28303
 
28294
28304
  # Handle pause state - wait for resume
28305
+ # Writes .loki/state/interventions.json. Mirrors loki-ts/src/runner/intervention.ts
28306
+ # (count, basis, by_type enum counts, waited_s). Modes: "count" bumps count and
28307
+ # the by_type bucket inferred from the signal files; "waited <secs>" adds
28308
+ # wall-clock blocked seconds (an upper bound on human attention, not active
28309
+ # minutes). Best-effort: never fails a run.
28310
+ _loki_iv_record() {
28311
+ local loki_dir="$1" mode="$2" secs="${3:-0}" iv_type="authorization"
28312
+ [ -n "$loki_dir" ] || return 0
28313
+ if [ -e "$loki_dir/HUMAN_INPUT.md" ]; then iv_type="input"
28314
+ elif [ -e "$loki_dir/signals/GATE_ESCALATION" ] || [ -e "$loki_dir/signals/COUNCIL_REVIEW_REQUESTED" ]; then iv_type="repair"
28315
+ elif [ -e "$loki_dir/signals/BUDGET_EXCEEDED" ]; then iv_type="steer"
28316
+ fi
28317
+ mkdir -p "$loki_dir/state" 2>/dev/null || true
28318
+ python3 -I -c 'import json,sys
28319
+ p,mode,secs,t=sys.argv[1:5]
28320
+ def n(v):
28321
+ return v if isinstance(v,int) and not isinstance(v,bool) and v>=0 else 0
28322
+ try:
28323
+ d=json.load(open(p))
28324
+ if not isinstance(d,dict): d={}
28325
+ except Exception:
28326
+ d={}
28327
+ if mode=="waited" and not d:
28328
+ sys.exit(0)
28329
+ bt=d.get("by_type") if isinstance(d.get("by_type"),dict) else {}
28330
+ out={k:n(bt.get(k)) for k in ("steer","input","authorization","repair")}
28331
+ if mode=="count":
28332
+ out[t]+=1
28333
+ d["count"]=n(d.get("count"))+1
28334
+ d["basis"]="blocking pauses that waited on a human"
28335
+ d["by_type"]=out
28336
+ d["waited_s"]=n(d.get("waited_s"))+(int(secs) if mode=="waited" else 0)
28337
+ open(p,"w").write(json.dumps(d)+"\n")' "$loki_dir/state/interventions.json" "$mode" "$secs" "$iv_type" 2>/dev/null || true
28338
+ }
28339
+
28295
28340
  handle_pause() {
28296
28341
  # BUG-ST-007: Guard against concurrent pause handler execution
28297
28342
  if [ "${_PAUSE_IN_PROGRESS:-0}" -eq 1 ]; then
@@ -28312,21 +28357,8 @@ handle_pause() {
28312
28357
  #
28313
28358
  # proof-generator reads this; when the file is absent the receipt renders NO
28314
28359
  # 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
28360
+ local _iv_t0=$SECONDS
28361
+ _loki_iv_record "$loki_dir" count
28330
28362
 
28331
28363
  # Save state before pausing so it persists across potential crashes
28332
28364
  save_state ${RETRY_COUNT:-0} "paused" 0
@@ -28426,6 +28458,7 @@ except Exception:
28426
28458
  # Check for stop signal
28427
28459
  if [ -f "$loki_dir/STOP" ]; then
28428
28460
  rm -f "$loki_dir/STOP" "$loki_dir/PAUSED.md"
28461
+ _loki_iv_record "$loki_dir" waited "$(( SECONDS - ${_iv_t0:-$SECONDS} ))" 2>/dev/null || true
28429
28462
  PAUSED=false
28430
28463
  _PAUSE_IN_PROGRESS=0
28431
28464
  return 1
@@ -28471,6 +28504,7 @@ except Exception:
28471
28504
  done
28472
28505
 
28473
28506
  rm -f "$loki_dir/PAUSED.md"
28507
+ _loki_iv_record "$loki_dir" waited "$(( SECONDS - ${_iv_t0:-$SECONDS} ))" 2>/dev/null || true
28474
28508
  log_info "Resuming execution..."
28475
28509
  PAUSED=false
28476
28510
  _PAUSE_IN_PROGRESS=0