loki-mode 11.2.2 → 11.3.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 (216) hide show
  1. package/README.md +68 -650
  2. package/SKILL.md +4 -4
  3. package/VERSION +1 -1
  4. package/autonomy/completion-council.sh +2 -2
  5. package/autonomy/context-tracker.py +4 -4
  6. package/autonomy/council-v2.sh +1 -1
  7. package/autonomy/grill.sh +1 -1
  8. package/autonomy/lib/done-recognition.sh +1 -1
  9. package/autonomy/lib/prd-enrich.sh +1 -1
  10. package/autonomy/lib/skill-link-heal.sh +78 -1
  11. package/autonomy/lib/voter-agents.sh +1 -1
  12. package/autonomy/loki +99 -75
  13. package/autonomy/run.sh +30 -18
  14. package/autonomy/sandbox.sh +1 -1
  15. package/autonomy/tui.sh +6 -5
  16. package/autonomy/verify.sh +1 -1
  17. package/bin/loki +166 -59
  18. package/completions/_loki +2 -0
  19. package/completions/loki.bash +2 -2
  20. package/dashboard/__init__.py +1 -1
  21. package/dashboard/server.py +25 -31
  22. package/docs/ARCHITECTURE.md +337 -0
  23. package/docs/BRANDING.md +124 -0
  24. package/docs/CLI-REFERENCE.md +7 -1
  25. package/docs/COMPONENTS.md +447 -0
  26. package/docs/DEPLOYMENT.md +9 -9
  27. package/docs/DOCKER.md +469 -0
  28. package/docs/INSTALLATION.md +67 -1045
  29. package/docs/KNOWN-ISSUES.md +11 -35
  30. package/docs/TESTING.md +161 -0
  31. package/docs/air-gapped.md +1 -2
  32. package/docs/alternative-installations.md +14 -24
  33. package/docs/architecture/DECISIONS.md +333 -0
  34. package/docs/audit-logging.md +7 -7
  35. package/docs/authentication.md +3 -3
  36. package/docs/authorization.md +1 -1
  37. package/docs/certification/04-production-deployment/lab.md +6 -6
  38. package/docs/certification/04-production-deployment/lesson.md +4 -4
  39. package/docs/certification/README.md +1 -1
  40. package/docs/control-plane-container.md +2 -2
  41. package/docs/dev/real-run.md +34 -0
  42. package/docs/dev/release-checklist.md +2 -2
  43. package/docs/exit-codes.md +3 -3
  44. package/docs/git-workflow.md +3 -3
  45. package/docs/metrics.md +37 -55
  46. package/docs/network-security.md +1 -1
  47. package/docs/siem-integration.md +5 -5
  48. package/docs/v10/CLI-MODERN.md +4 -3
  49. package/docs/v10/DECISIONS.md +44 -0
  50. package/docs/v10/DEPS.md +22 -22
  51. package/docs/v10/ENGINE.md +1 -1
  52. package/docs/v10/FAILURE-CLASSES.md +129 -1
  53. package/docs/v10/FOUNDER-QUEUE.md +1 -0
  54. package/docs/v10/GUARDS.md +13 -0
  55. package/docs/v10/LEGACY-REMOVAL.md +4 -6
  56. package/docs/v10/METRICS.md +2 -2
  57. package/docs/v10/MODERNIZE.md +1 -1
  58. package/docs/v10/OPERATING-MODEL.md +2 -1
  59. package/docs/v10/PROGRESS.md +29 -0
  60. package/docs/v11/COST-HALF.md +352 -0
  61. package/docs/v11/MARKET-SLICES.md +315 -0
  62. package/docs/v11/REGISTRIES.md +730 -0
  63. package/loki-ts/data/model-pricing.json +52 -24
  64. package/loki-ts/dist/loki.js +1036 -957
  65. package/mcp/__init__.py +1 -1
  66. package/package.json +1 -1
  67. package/packages/control-plane/dist/server.js +2467 -736
  68. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  69. package/src/protocols/mcp-client.js +6 -2
  70. package/src/protocols/mcp-server.js +13 -3
  71. package/tools/audit-docs.py +1 -1
  72. package/web-app/dist/assets/{AdminPage-C-iMLNxe.js → AdminPage-CMkHNJbF.js} +1 -1
  73. package/web-app/dist/assets/{Avatar-C7VUvwsO.js → Avatar-BJyjV7Zi.js} +1 -1
  74. package/web-app/dist/assets/{Badge-tGvQEhnw.js → Badge-D572l0uq.js} +1 -1
  75. package/web-app/dist/assets/{Button-_iHlH_yL.js → Button-T4BnOZgl.js} +1 -1
  76. package/web-app/dist/assets/{CockpitPage-J_nNjbcR.js → CockpitPage-Cj_GFsNn.js} +1 -1
  77. package/web-app/dist/assets/{ComparePage-B05ui6Xt.js → ComparePage-A8m4ZXak.js} +1 -1
  78. package/web-app/dist/assets/{ErrorBoundary-Bxex6DLn.js → ErrorBoundary-hugCg5yg.js} +1 -1
  79. package/web-app/dist/assets/{EvidenceReceiptPanel-BsgWfdD1.js → EvidenceReceiptPanel-CuJKDC2G.js} +1 -1
  80. package/web-app/dist/assets/{GitHubIssuesPanel-DZBhZ8_X.js → GitHubIssuesPanel-BYGKjarC.js} +1 -1
  81. package/web-app/dist/assets/{GitHubPRsPanel-BaxlAl6R.js → GitHubPRsPanel-c7sFIJlf.js} +1 -1
  82. package/web-app/dist/assets/{HomePage-mVJvzqbF.js → HomePage-A1MIkG2P.js} +2 -2
  83. package/web-app/dist/assets/{LoginPage-B0zd4A_G.js → LoginPage-8KQMRhtR.js} +1 -1
  84. package/web-app/dist/assets/{MagicPage-DXLQ-y_R.js → MagicPage-C05QW2Lx.js} +1 -1
  85. package/web-app/dist/assets/{MetricsPage-CLS34Xvr.js → MetricsPage-Oukv5hme.js} +1 -1
  86. package/web-app/dist/assets/{NotFoundPage-BXG8PbNV.js → NotFoundPage-DKIwsawz.js} +1 -1
  87. package/web-app/dist/assets/{ProjectPage-D3kFFC0F.js → ProjectPage-DwFRPLCG.js} +3 -3
  88. package/web-app/dist/assets/{ProjectsPage-2bFn-gnC.js → ProjectsPage-CgY4YYDX.js} +1 -1
  89. package/web-app/dist/assets/{SettingsPage-CBM0ziWE.js → SettingsPage-BpfcSjUA.js} +1 -1
  90. package/web-app/dist/assets/{ShowcasePage-BTaXhjI3.js → ShowcasePage-BqBakC4K.js} +1 -1
  91. package/web-app/dist/assets/{SystemSettingsPage-BrC2hyAr.js → SystemSettingsPage-CZLu5VB0.js} +1 -1
  92. package/web-app/dist/assets/{TeamsPage-oqxdbVbY.js → TeamsPage-D55S1jKz.js} +1 -1
  93. package/web-app/dist/assets/{TemplatesPage-CEbUIY21.js → TemplatesPage-D3SydvxN.js} +1 -1
  94. package/web-app/dist/assets/{TerminalOutput-aIoWLbJA.js → TerminalOutput-hNg8G1-e.js} +1 -1
  95. package/web-app/dist/assets/{activity-CPyi45gt.js → activity-D2C0VagO.js} +1 -1
  96. package/web-app/dist/assets/{bell-BhaNBaJp.js → bell-CMvYi36w.js} +1 -1
  97. package/web-app/dist/assets/{bot-Da8REaEP.js → bot-BvtQ6lmo.js} +1 -1
  98. package/web-app/dist/assets/{check-DPj99ArM.js → check-B13xkXed.js} +1 -1
  99. package/web-app/dist/assets/{chevron-left-CkxonN0X.js → chevron-left-emu6r49E.js} +1 -1
  100. package/web-app/dist/assets/{circle-alert-C0JkB1y5.js → circle-alert-CExlwjuy.js} +1 -1
  101. package/web-app/dist/assets/{clock-COzFIiWi.js → clock-D7Uas3oL.js} +1 -1
  102. package/web-app/dist/assets/{cloud-bjkac4kn.js → cloud-CkB4S86C.js} +1 -1
  103. package/web-app/dist/assets/{code-xml-hlKlvXUJ.js → code-xml-SL9IIWIn.js} +1 -1
  104. package/web-app/dist/assets/{database-D555S5Km.js → database-BQFkd7t1.js} +1 -1
  105. package/web-app/dist/assets/{dollar-sign-CVcApzcD.js → dollar-sign-qHmnNYsU.js} +1 -1
  106. package/web-app/dist/assets/{file-code-corner-UORaMIcO.js → file-code-corner-C2YUDP0K.js} +1 -1
  107. package/web-app/dist/assets/{file-plus-ALJtDoI2.js → file-plus-C_ooIkDe.js} +1 -1
  108. package/web-app/dist/assets/{globe-CPlrM_IC.js → globe-CQ-GL485.js} +1 -1
  109. package/web-app/dist/assets/{hammer-qaGZHpja.js → hammer-U05L_D7V.js} +1 -1
  110. package/web-app/dist/assets/{index-BcXljIAO.js → index-CooHd7I-.js} +3 -3
  111. package/web-app/dist/assets/{layers-BV8R9VUK.js → layers-Buo17rjW.js} +1 -1
  112. package/web-app/dist/assets/{loader-circle-6TlDS9Tu.js → loader-circle-15vK3oV1.js} +1 -1
  113. package/web-app/dist/assets/{lock-B9t6oWI0.js → lock-BeXLebuJ.js} +1 -1
  114. package/web-app/dist/assets/{package-2gEUAtZJ.js → package-MVh_6-6R.js} +1 -1
  115. package/web-app/dist/assets/{plus-DXocxPjU.js → plus-Dh_nd9vS.js} +1 -1
  116. package/web-app/dist/assets/{refresh-cw-D3dWHBd6.js → refresh-cw-C9cBJEAT.js} +1 -1
  117. package/web-app/dist/assets/{rotate-ccw-CvuWqaSB.js → rotate-ccw-D3PAtzST.js} +1 -1
  118. package/web-app/dist/assets/{scroll-text-ktmD_xJY.js → scroll-text-DZCoXQjo.js} +1 -1
  119. package/web-app/dist/assets/{server-E7pZtj5A.js → server-OCOLI5J_.js} +1 -1
  120. package/web-app/dist/assets/{shield-alert-968j9z0V.js → shield-alert-oVhmf1_h.js} +1 -1
  121. package/web-app/dist/assets/{thumbs-up-Tz_8rpU_.js → thumbs-up-B-kbX4vN.js} +1 -1
  122. package/web-app/dist/assets/{trash-2-Drh9IIj8.js → trash-2-EL6moveW.js} +1 -1
  123. package/web-app/dist/assets/{trending-down-DCQXtVSL.js → trending-down-Cl3kjpsx.js} +1 -1
  124. package/web-app/dist/assets/{trending-up-BIiwQbWV.js → trending-up-DST7I6M2.js} +1 -1
  125. package/web-app/dist/assets/{upload-sCbPkfmy.js → upload-CUOT780G.js} +1 -1
  126. package/web-app/dist/assets/{usePolling-BMIg6ZVT.js → usePolling-Djmt90eb.js} +1 -1
  127. package/web-app/dist/assets/{user-kGzXC3V2.js → user-BRBohA6J.js} +1 -1
  128. package/web-app/dist/index.html +1 -1
  129. package/docs/ARCHITECTURE-OVERVIEW.md +0 -209
  130. package/docs/AUTONOMI-ECOSYSTEM.md +0 -107
  131. package/docs/COCKPIT-SPEC.md +0 -72
  132. package/docs/COCKPIT-UX-MANDATE.md +0 -53
  133. package/docs/COMPETITIVE-ANALYSIS.md +0 -303
  134. package/docs/COMPETITIVE-NEXT-10.md +0 -316
  135. package/docs/COMPETITIVE-RALPH-ZEROSHOT-2026-07-08.md +0 -81
  136. package/docs/DASHBOARD-9.12-EVIDENCE.md +0 -97
  137. package/docs/DASHBOARD-ARCHITECTURE.md +0 -425
  138. package/docs/DASHBOARD_V2_CHECKLIST.md +0 -243
  139. package/docs/DEMOS.md +0 -63
  140. package/docs/ENTERPRISE-IDENTITY-ROADMAP.md +0 -206
  141. package/docs/EVIDENCE-RECEIPT-BUILD-APPLICABILITY.md +0 -79
  142. package/docs/FEAT-PRDREUSE-DOCKER-PLAN.md +0 -144
  143. package/docs/GATE-FAILURE-TRIAGE.md +0 -254
  144. package/docs/HANDOFF-2026-08-03.md +0 -439
  145. package/docs/LOOP-CANDIDATE-PROPOSAL-v1.md +0 -167
  146. package/docs/LOOP-HARNESS-AUDIT.md +0 -684
  147. package/docs/MERGE-DEDUP-MAP.md +0 -420
  148. package/docs/MERGE-ROUTE-MAP.md +0 -139
  149. package/docs/MODEL-REGISTRY-PLAN.md +0 -155
  150. package/docs/OUTCOME-FRONTIER.md +0 -536
  151. package/docs/P2-SPEC-ROBUSTNESS-PLAN.md +0 -192
  152. package/docs/PLANS-INDEX.md +0 -32
  153. package/docs/PRD-REUSE-DONE-RECOGNITION-PLAN.md +0 -536
  154. package/docs/PROMPT-ABLATION-RESULT.md +0 -97
  155. package/docs/R4-TRUST-TRAJECTORY-DESIGN.md +0 -127
  156. package/docs/R5-AUTO-WIKI-DESIGN.md +0 -137
  157. package/docs/R6-ROLLBACK-CHECKPOINT-PLAN.md +0 -107
  158. package/docs/R7-ZERO-CONFIG-FIRST-RUN-PLAN.md +0 -137
  159. package/docs/R8-SHAREABLE-TEAM-ASSETS-PLAN.md +0 -129
  160. package/docs/R9-OPEN-CORE-HOOKS-PLAN.md +0 -113
  161. package/docs/RARV-C-100X-PLAN.md +0 -286
  162. package/docs/RARV-C-LOOP-EFFICIENCY-PLAN.md +0 -470
  163. package/docs/SHAREABLE-PROOF-PLAN.md +0 -194
  164. package/docs/SONNET5-DEFAULT-PLAN.md +0 -157
  165. package/docs/SPEED-AND-FIRST-PASS-PLAN.md +0 -281
  166. package/docs/STALE-STATE-AUDIT.md +0 -174
  167. package/docs/SYNERGY-TASKS.md +0 -143
  168. package/docs/TASKLIST-ACCURACY-PLAN.md +0 -355
  169. package/docs/TOP-100-BACKLOG.md +0 -159
  170. package/docs/V8-ACCEPTANCE-TRIAGE-2026-07-24.md +0 -114
  171. package/docs/V8-COMPLEXITY-AUDIT-2026-07-24.md +0 -45
  172. package/docs/V8-MAJOR-RELEASE-PLAN.md +0 -137
  173. package/docs/V8-OVERNIGHT-PLAN-2026-07-25.md +0 -82
  174. package/docs/V8-SDK-RESEARCH-RAW.md +0 -129
  175. package/docs/WELCOME-OPENER-PLAN.md +0 -106
  176. package/docs/adoption-baseline-2026-07-31.md +0 -84
  177. package/docs/architecture/bmad-integration-epic.md +0 -271
  178. package/docs/architecture/bmad-integration-review.md +0 -86
  179. package/docs/architecture/bmad-integration-validation.md +0 -249
  180. package/docs/architecture/bmad-loki-voice-agent-council-analysis.md +0 -61
  181. package/docs/auto-claude-comparison.md +0 -250
  182. package/docs/bug-fixes/agent-01-cli-fixes.md +0 -101
  183. package/docs/bug-fixes/agent-02-purplelab-fixes.md +0 -88
  184. package/docs/bug-fixes/agent-03-dashboard-fixes.md +0 -119
  185. package/docs/bug-fixes/agent-04-memory-fixes.md +0 -105
  186. package/docs/bug-fixes/agent-05-provider-fixes.md +0 -86
  187. package/docs/bug-fixes/agent-06-integration-fixes.md +0 -101
  188. package/docs/bug-fixes/agent-07-dash-run-fixes.md +0 -101
  189. package/docs/bug-fixes/agent-08-docker-fixes.md +0 -164
  190. package/docs/bug-fixes/agent-09-e2e-build-fixes.md +0 -69
  191. package/docs/bug-fixes/agent-10-e2e-fullstack-fixes.md +0 -102
  192. package/docs/bug-fixes/agent-11-e2e-session-fixes.md +0 -70
  193. package/docs/bug-fixes/agent-12-scenario-fixes.md +0 -120
  194. package/docs/bug-fixes/agent-13-enterprise-fixes.md +0 -143
  195. package/docs/bug-fixes/agent-14-uat-newuser-fixes.md +0 -88
  196. package/docs/bug-fixes/agent-15-uat-poweruser-fixes.md +0 -132
  197. package/docs/bug-fixes/agent-19-code-review.md +0 -316
  198. package/docs/bug-fixes/agent-20-architecture-review.md +0 -331
  199. package/docs/competitive/bolt-new-analysis.md +0 -579
  200. package/docs/competitive/emergence-others-analysis.md +0 -605
  201. package/docs/competitive/replit-lovable-analysis.md +0 -622
  202. package/docs/dashboard-guide.md +0 -487
  203. package/docs/enterprise/migration.md +0 -265
  204. package/docs/history/one-run-audit.md +0 -304
  205. package/docs/plans/FORGE-AUTONOMOUS-QUEUE.md +0 -312
  206. package/docs/plans/ULTRAPLAN-FORGE-BAAS.md +0 -612
  207. package/docs/plans/UT2-6-LSP-DIAGNOSTIC-BROADCAST.md +0 -394
  208. package/docs/prd-purple-lab-ide.md +0 -152
  209. package/docs/prd-purple-lab-platform-v2.md +0 -223
  210. package/docs/prd-purple-lab-platform.md +0 -319
  211. package/docs/retrospectives/v7.5.15-fleet-postmortem.md +0 -325
  212. package/docs/retrospectives/v7.5.15-honesty-audit.md +0 -136
  213. package/docs/retrospectives/v7.5.15-llm-failure-modes.md +0 -49
  214. package/docs/show-hn-post.md +0 -46
  215. package/docs/test-scenarios/enterprise-scenarios.md +0 -732
  216. package/docs/thick2thin.md +0 -173
package/bin/loki CHANGED
@@ -32,6 +32,39 @@ SCRIPT_DIR=$(dirname "$SCRIPT_PATH")
32
32
  REPO_ROOT=$(cd "$SCRIPT_DIR/.." 2>/dev/null && pwd)
33
33
  BASH_CLI="$REPO_ROOT/autonomy/loki"
34
34
 
35
+ # FC-38 (scoped): `loki start --attempts` never reaches the legacy bash loop. Every other
36
+ # start, and every other command, keeps the plain bash fallback.
37
+ _LOKI_START_ATTEMPTS=0
38
+ if [ "${1:-}" = "start" ]; then
39
+ for _loki_a0 in "${@:2}"; do
40
+ case "$_loki_a0" in --attempts|--attempts=*) _LOKI_START_ATTEMPTS=1 ;; esac
41
+ done
42
+ unset _loki_a0
43
+ fi
44
+ _loki_bash_or_refuse() {
45
+ if [ "${1:-}" = "start" ] && [ "$_LOKI_START_ATTEMPTS" = "1" ]; then
46
+ echo "loki: 'loki start' runs only the Loki 10 engine, which needs the Bun entry (loki-ts). It cannot fall back to the removed legacy loop; reinstall loki-mode or fix LOKI_TS_ENTRY / BUN_FROM_SOURCE." >&2
47
+ exit 1
48
+ fi
49
+ exec "$BASH_CLI" "$@"
50
+ }
51
+
52
+ # T5-D2 (FC-38 sweep): quick, run, demo and tour have no attempts engine; --attempts there would
53
+ # reach the legacy loop, so it is refused before any route split.
54
+ case "${1:-}" in
55
+ quick|run|demo|tour)
56
+ for _loki_a1 in "${@:2}"; do
57
+ case "$_loki_a1" in
58
+ --attempts|--attempts=*)
59
+ echo "loki: --attempts is only supported by 'loki start --attempts N --no-pr' (the Loki 10 engine). 'loki $1' would run the removed legacy loop; drop --attempts or use 'loki start --attempts N --no-pr'." >&2
60
+ exit 2
61
+ ;;
62
+ esac
63
+ done
64
+ unset _loki_a1
65
+ ;;
66
+ esac
67
+
35
68
  # v8.1: resolve the one-switch SDK mode (LOKI_SDK_MODE=off|judges|full) into the
36
69
  # per-site LOKI_SDK_* flags HERE, in the outermost shim, BEFORE the `start`
37
70
  # routing fork below reads LOKI_SDK_LOOP. Without this, `LOKI_SDK_MODE=full loki
@@ -78,7 +111,7 @@ if [ -n "${LOKI_TS_ENTRY:-}" ]; then
78
111
  # invoke commands while they fix the path.
79
112
  if [ ! -f "$LOKI_TS_ENTRY" ]; then
80
113
  echo "ERROR: LOKI_TS_ENTRY=$LOKI_TS_ENTRY does not exist; falling through to bash CLI. Unset the variable or fix the path." >&2
81
- exec "$BASH_CLI" "$@"
114
+ _loki_bash_or_refuse "$@"
82
115
  fi
83
116
  BUN_CLI="$LOKI_TS_ENTRY"
84
117
  elif [ "${BUN_FROM_SOURCE:-0}" = "1" ] || [ "${BUN_FROM_SOURCE:-}" = "true" ]; then
@@ -89,7 +122,7 @@ elif [ "${BUN_FROM_SOURCE:-0}" = "1" ] || [ "${BUN_FROM_SOURCE:-}" = "true" ]; t
89
122
  BUN_CLI="$REPO_ROOT/loki-ts/dist/loki.js"
90
123
  else
91
124
  echo "ERROR: BUN_FROM_SOURCE set but neither src/cli.ts nor dist/loki.js found; falling through to bash" >&2
92
- exec "$BASH_CLI" "$@"
125
+ _loki_bash_or_refuse "$@"
93
126
  fi
94
127
  elif [ -f "$REPO_ROOT/loki-ts/dist/loki.js" ]; then
95
128
  BUN_CLI="$REPO_ROOT/loki-ts/dist/loki.js"
@@ -112,7 +145,7 @@ elif [ -f "$REPO_ROOT/loki-ts/src/cli.ts" ]; then
112
145
  BUN_CLI="$REPO_ROOT/loki-ts/src/cli.ts"
113
146
  else
114
147
  # Neither dist nor src available; fall through to bash silently.
115
- exec "$BASH_CLI" "$@"
148
+ _loki_bash_or_refuse "$@"
116
149
  fi
117
150
 
118
151
  # FC-30: an install artifact must not outlive the install that made it. If a provider
@@ -259,7 +292,7 @@ esac
259
292
 
260
293
  # Force-fall-through to bash when the rollback flag is set.
261
294
  if [ "${LOKI_LEGACY_BASH:-0}" = "1" ] || [ "${LOKI_LEGACY_BASH:-}" = "true" ]; then
262
- exec "$BASH_CLI" "$@"
295
+ _loki_bash_or_refuse "$@"
263
296
  fi
264
297
 
265
298
  # Loki 10 bun resolver: bun on PATH, then an npm-installed @oven/bun-* optional
@@ -335,6 +368,105 @@ case "${1:-}" in
335
368
  ;;
336
369
  esac
337
370
 
371
+ _loki_start_needs_bash() {
372
+ # $@ = the start args (already know $1 = start). Return 0 (divert to bash) if
373
+ # any bash-only orchestration flag or an issue-ref spec is present.
374
+ local a
375
+ local explicit_provider=""
376
+ local provider_value_next=0
377
+ for a in "$@"; do
378
+ if [ "$provider_value_next" = "1" ]; then
379
+ explicit_provider="$a"
380
+ provider_value_next=0
381
+ continue
382
+ fi
383
+ case "$a" in
384
+ --provider)
385
+ provider_value_next=1 ;;
386
+ --provider=*)
387
+ explicit_provider="${a#--provider=}" ;;
388
+ --parallel|--bg|--background|--github|--api|--sandbox \
389
+ |--fast|--repo-fast|--full|--repo-full \
390
+ |--bmad-project|--openspec \
391
+ |--mirofish|--mirofish-docker|--mirofish-rounds|--mirofish-timeout|--mirofish-bg \
392
+ |--issue|--dry-run|--no-start|--output|--worktree|-w|--pr|--ship|--detach|-d)
393
+ return 0 ;;
394
+ --isolation)
395
+ # value follows; only worktree/docker/sandbox divert (none stays Bun).
396
+ _loki_iso_next=1 ;;
397
+ worktree|wt|docker|sandbox)
398
+ [ "${_loki_iso_next:-0}" = "1" ] && { unset _loki_iso_next; return 0; }
399
+ _loki_iso_next=0 ;;
400
+ *)
401
+ # issue-ref positional: owner/repo#N, a tracker URL, or *#<digits>.
402
+ case "$a" in
403
+ */*\#[0-9]*|http*://*/issues/*|http*://*/browse/*) return 0 ;;
404
+ esac
405
+ _loki_iso_next=0 ;;
406
+ esac
407
+ done
408
+ unset _loki_iso_next
409
+
410
+ # The Bun RARV loop has not ported the opencode invoker yet. Keep the
411
+ # released, autonomous shell adapter reachable when SDK mode is enabled
412
+ # instead of accepting the selection and then failing after intake. CLI
413
+ # selection wins over env, which wins over the project-level saved choice.
414
+ local effective_provider="$explicit_provider"
415
+ if [ -z "$effective_provider" ] && [ -n "${LOKI_PROVIDER:-}" ]; then
416
+ effective_provider="$LOKI_PROVIDER"
417
+ fi
418
+ if [ -z "$effective_provider" ] && [ -f "${PWD}/.loki/state/provider" ]; then
419
+ effective_provider="$(sed -n '1p' "${PWD}/.loki/state/provider" 2>/dev/null || true)"
420
+ fi
421
+ [ "$effective_provider" = "opencode" ] && return 0
422
+ return 1
423
+ }
424
+ _loki_attempts_refuse() {
425
+ if _loki_start_needs_bash "$@"; then
426
+ echo "loki: 'loki start --attempts' runs only the Loki 10 engine; an option or provider in this command (for example --parallel, --github, --sandbox, --issue, --dry-run, --detach, or opencode) was only honored by the removed legacy loop. Remove it, or use a task string, an issue ref or a PRD path." >&2
427
+ exit 2
428
+ fi
429
+ case "${LOKI_PROVIDER:-claude}" in
430
+ claude|codex|cline|aider) ;;
431
+ *) echo "loki: the Loki 10 engine does not support LOKI_PROVIDER=${LOKI_PROVIDER:-}; use claude, codex, cline or aider." >&2; exit 2 ;;
432
+ esac
433
+ }
434
+
435
+ # FC-37: --attempts is handled HERE, once, before any route split (engine10 positional task, Bun
436
+ # loop, bash cmd_start). A flag accepted on one route must be honored or refused loudly on every
437
+ # other. N=1 is stripped so every route sees today's argv byte-for-byte; N=2..5 runs on the Bun
438
+ # start command (loki-ts/src/commands/start.ts), which spawns one engine10 run per worktree.
439
+ if [ "${1:-}" = "start" ]; then
440
+ _loki_att_args=()
441
+ _loki_att_n=""
442
+ _loki_att_skip=0
443
+ for _loki_att_a in "${@:2}"; do
444
+ if [ "$_loki_att_skip" = "1" ]; then _loki_att_n="$_loki_att_a"; _loki_att_skip=0; continue; fi
445
+ case "$_loki_att_a" in
446
+ --attempts) _loki_att_skip=1 ;;
447
+ --attempts=*) _loki_att_n="${_loki_att_a#--attempts=}" ;;
448
+ *) _loki_att_args+=("$_loki_att_a") ;;
449
+ esac
450
+ done
451
+ if [ "$_loki_att_skip" = "1" ]; then
452
+ echo "loki: --attempts requires a value from 1 to 5." >&2
453
+ exit 2
454
+ fi
455
+ if [ -n "$_loki_att_n" ]; then
456
+ case "$_loki_att_n" in
457
+ 1) set -- start ${_loki_att_args[@]+"${_loki_att_args[@]}"} ;;
458
+ [2-5])
459
+ _lb=$(_loki_bun)
460
+ [ -n "$_lb" ] || { echo "loki: --attempts $_loki_att_n needs bun (install from https://bun.sh); refusing to run a single attempt silently." >&2; exit 1; }
461
+ _loki_attempts_refuse "${@:2}"
462
+ exec "$_lb" "$BUN_CLI" "$@"
463
+ ;;
464
+ *) echo "loki: --attempts must be an integer from 1 to 5, got '$_loki_att_n'." >&2; exit 2 ;;
465
+ esac
466
+ fi
467
+ unset _loki_att_args _loki_att_n _loki_att_skip _loki_att_a
468
+ fi
469
+
338
470
  # Loki 10 engine (D29, the only engine from 11.0.0). Routes `loki "<task>"`,
339
471
  # `loki owner/repo#N`, `loki quick "<task>"`, `keys` and `verify --pubkey` to engine10.
340
472
  # shellcheck disable=SC2194
@@ -376,7 +508,23 @@ case "v10" in
376
508
  # `loki <ref>`; any other start call (PRD file, flags first, one word) stays legacy.
377
509
  start)
378
510
  case "${2:-}" in
379
- */*\#[0-9]*|http*://*/issues/*|http*://*/browse/*|jira:*|linear:*|https://linear.app/*/issue/*|*" "*) _e10=1; _e10_args=("${@:2}") ;;
511
+ */*\#[0-9]*|http*://*/issues/*|http*://*/browse/*|jira:*|linear:*|https://linear.app/*/issue/*|*" "*)
512
+ _e10=1; _e10_args=("${@:2}")
513
+ if [ "$_LOKI_START_ATTEMPTS" = "1" ]; then
514
+ _e10_hard=1 # FC-38: --attempts never falls back to the legacy engine
515
+ # FC-37: engine10 has no --budget; unmapped it would be glued onto the task text. Its per-run cap is --max-cost.
516
+ _e10_args=(); _e10_bnext=0
517
+ for _e10_a in "${@:2}"; do
518
+ if [ "$_e10_bnext" = "1" ]; then _e10_args+=("$_e10_a"); _e10_bnext=0; continue; fi
519
+ case "$_e10_a" in
520
+ --budget|--budget-limit) _e10_args+=(--max-cost); _e10_bnext=1 ;;
521
+ --budget=*|--budget-limit=*) _e10_args+=("--max-cost=${_e10_a#*=}") ;;
522
+ *) _e10_args+=("$_e10_a") ;;
523
+ esac
524
+ done
525
+ unset _e10_a _e10_bnext
526
+ fi
527
+ ;;
380
528
  *) _e10=0 ;;
381
529
  esac
382
530
  ;;
@@ -425,6 +573,10 @@ esac
425
573
  # Bun must be installed for the new path; if it isn't, fall through to bash
426
574
  # silently rather than fail. This keeps users on systems without Bun working.
427
575
  if ! command -v bun &>/dev/null; then
576
+ if [ "${1:-}" = "start" ] && [ "$_LOKI_START_ATTEMPTS" = "1" ]; then
577
+ echo "loki: 'loki start' runs the Loki 10 engine, which needs bun. Install bun from https://bun.sh. The legacy loop is not reachable from start." >&2
578
+ exit 1
579
+ fi
428
580
  exec "$BASH_CLI" "$@"
429
581
  fi
430
582
 
@@ -448,59 +600,14 @@ fi
448
600
  # guarantee that makes the eventual loop default-flip a no-regression. Runner
449
601
  # flags (--simple, --allow-haiku, --regen-prd, --skip-memory, provider knobs) are
450
602
  # handled by start.ts and do NOT divert. See artifacts/ITER1-FLAG-RECONCILE.md.
451
- _loki_start_needs_bash() {
452
- # $@ = the start args (already know $1 = start). Return 0 (divert to bash) if
453
- # any bash-only orchestration flag or an issue-ref spec is present.
454
- local a
455
- local explicit_provider=""
456
- local provider_value_next=0
457
- for a in "$@"; do
458
- if [ "$provider_value_next" = "1" ]; then
459
- explicit_provider="$a"
460
- provider_value_next=0
461
- continue
462
- fi
463
- case "$a" in
464
- --provider)
465
- provider_value_next=1 ;;
466
- --provider=*)
467
- explicit_provider="${a#--provider=}" ;;
468
- --parallel|--bg|--background|--github|--api|--sandbox \
469
- |--fast|--repo-fast|--full|--repo-full \
470
- |--bmad-project|--openspec \
471
- |--mirofish|--mirofish-docker|--mirofish-rounds|--mirofish-timeout|--mirofish-bg \
472
- |--issue|--dry-run|--no-start|--output|--worktree|-w|--pr|--ship|--detach|-d)
473
- return 0 ;;
474
- --isolation)
475
- # value follows; only worktree/docker/sandbox divert (none stays Bun).
476
- _loki_iso_next=1 ;;
477
- worktree|wt|docker|sandbox)
478
- [ "${_loki_iso_next:-0}" = "1" ] && { unset _loki_iso_next; return 0; }
479
- _loki_iso_next=0 ;;
480
- *)
481
- # issue-ref positional: owner/repo#N, a tracker URL, or *#<digits>.
482
- case "$a" in
483
- */*\#[0-9]*|http*://*/issues/*|http*://*/browse/*) return 0 ;;
484
- esac
485
- _loki_iso_next=0 ;;
486
- esac
487
- done
488
- unset _loki_iso_next
489
-
490
- # The Bun RARV loop has not ported the opencode invoker yet. Keep the
491
- # released, autonomous shell adapter reachable when SDK mode is enabled
492
- # instead of accepting the selection and then failing after intake. CLI
493
- # selection wins over env, which wins over the project-level saved choice.
494
- local effective_provider="$explicit_provider"
495
- if [ -z "$effective_provider" ] && [ -n "${LOKI_PROVIDER:-}" ]; then
496
- effective_provider="$LOKI_PROVIDER"
497
- fi
498
- if [ -z "$effective_provider" ] && [ -f "${PWD}/.loki/state/provider" ]; then
499
- effective_provider="$(sed -n '1p' "${PWD}/.loki/state/provider" 2>/dev/null || true)"
500
- fi
501
- [ "$effective_provider" = "opencode" ] && return 0
502
- return 1
503
- }
603
+ # FC-38 (scoped to --attempts; plain start keeps the 11.3.0 routing below): no `start --attempts` reaches the legacy loop (bash cmd_start, run.sh, runAutonomous).
604
+ # Issue refs and multi-word tasks were sent to engine10 above; every other start (PRD path, brief,
605
+ # flags) goes to the Bun start command, which runs engine10 and seals a receipt. A flag only the
606
+ # legacy route honored, or a provider engine10 cannot invoke, is refused loudly instead.
607
+ if [ "${1:-}" = "start" ] && [ "$_LOKI_START_ATTEMPTS" = "1" ]; then
608
+ _loki_attempts_refuse "${@:2}"
609
+ exec bun "$BUN_CLI" "$@"
610
+ fi
504
611
  if [ "${1:-}" = "start" ] && { [ "${LOKI_SDK_LOOP:-}" = "1" ] || [ "${LOKI_SDK_LOOP:-}" = "true" ]; }; then
505
612
  if _loki_start_needs_bash "${@:2}"; then
506
613
  exec "$BASH_CLI" "$@"
@@ -603,7 +710,7 @@ fi
603
710
  # Two-token routes (provider show/list, memory list/index) match on the first
604
711
  # token only; the Bun dispatcher handles subcommand routing internally.
605
712
  case "${1:-}" in
606
- version|--version|-v|status|stats|doctor|provider|memory|rollback|internal|kpis|trust|proof|receipt|wiki|crash|control|contract|slack|answer|completion|__complete)
713
+ version|--version|-v|status|stats|doctor|provider|memory|rollback|internal|kpis|trust|proof|receipt|wiki|crash|control|contract|slack|queue|answer|completion|__complete)
607
714
  # v7.5.2: rollback added (wires loki-ts/src/commands/rollback.ts).
608
715
  # v7.5.3: internal added for autonomy/run.sh phase1-hooks calls.
609
716
  # v7.5.28: kpis added (Phase K MVP: read-only KPI snapshot).
package/completions/_loki CHANGED
@@ -209,6 +209,7 @@ function _loki_commands {
209
209
  'otel:OpenTelemetry management'
210
210
  'wiki:Wiki commands'
211
211
  'answer:Resume a BLOCKED run with an answer'
212
+ 'queue:Overnight issue queue with a morning digest'
212
213
  'control:Control plane (preview, LOKI_CONTROL=1)'
213
214
  'workspace:Multi-project workspaces (preview, LOKI_WORKSPACES=1)'
214
215
  'backlog:Run every matching open issue, N in parallel'
@@ -264,6 +265,7 @@ function _loki_start {
264
265
  '-y[Skip confirmation prompts]' \
265
266
  '--budget[Cost budget limit in USD]:amount:' \
266
267
  '--max-iterations[Max iterations]:number:' \
268
+ '--attempts[Independent attempts in worktrees, 1-5]:number:(1 2 3 4 5)' \
267
269
  '*:spec file:_loki_spec_files'
268
270
  }
269
271
 
@@ -5,7 +5,7 @@ _loki_completion() {
5
5
  _init_completion || return
6
6
 
7
7
  # Main subcommands (must match autonomy/loki main case statement)
8
- local main_commands="start backlog quick monitor demo tour welcome init stop pause resume steer status next ship dashboard web serve api sandbox notify import github issue intent config provider reset memory compound checkpoint council dogfood projects enterprise secrets cockpit secure own handoff doctor watchdog audit metrics syslog onboard share proof receipt outcomes explain plan report cost estimate kpis stats test ci watch telemetry agent context ctx code run export review optimize heal modernize migrate cluster worktree wt trigger failover remote deploy docker mcp magic assets analyze compliance crash control workspace open otel preview quickstart rc rollback merge self-update sentrux setup-skill spec state template trust trust-metrics ultracode update verify voice why wiki bench cleanup logs grill docs cp version completions help keys answer acp"
8
+ local main_commands="start backlog quick monitor demo tour welcome init stop pause resume steer status next ship dashboard web serve api sandbox notify import github issue intent config provider reset memory compound checkpoint council dogfood projects enterprise secrets cockpit secure own handoff doctor watchdog audit metrics syslog onboard share proof receipt outcomes explain plan report cost estimate kpis stats test ci watch telemetry agent context ctx code run export review optimize heal modernize migrate cluster worktree wt trigger failover remote deploy docker mcp magic assets analyze compliance crash control workspace open otel preview quickstart rc rollback merge self-update sentrux setup-skill spec state template trust trust-metrics ultracode update verify voice why wiki bench cleanup logs grill docs cp version completions help keys answer queue acp"
9
9
 
10
10
  # 1. If we are on the first argument (subcommand)
11
11
  if [[ $cword -eq 1 ]]; then
@@ -27,7 +27,7 @@ _loki_completion() {
27
27
 
28
28
  # If the word starts with a dash, show flags
29
29
  if [[ "$cur" == -* ]]; then
30
- local flags="--provider --max-iterations --parallel --background --bg --simple --complex --github --no-dashboard --sandbox --skip-memory --yes --budget --help"
30
+ local flags="--provider --max-iterations --parallel --background --bg --simple --complex --github --no-dashboard --sandbox --skip-memory --yes --budget --attempts --help"
31
31
  COMPREPLY=( $(compgen -W "${flags}" -- "$cur") )
32
32
  return 0
33
33
  fi
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "11.2.2"
10
+ __version__ = "11.3.1"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -1520,9 +1520,9 @@ async def get_provider_models() -> dict:
1520
1520
  "schema_version": 1,
1521
1521
  "providers": {
1522
1522
  "claude": {
1523
- "latest_planning": "claude-opus-4-7",
1524
- "latest_development": "claude-opus-4-7",
1525
- "latest_fast": "claude-sonnet-4-6",
1523
+ "latest_planning": "opus",
1524
+ "latest_development": "opus",
1525
+ "latest_fast": "sonnet",
1526
1526
  "models": [],
1527
1527
  }
1528
1528
  },
@@ -3360,7 +3360,7 @@ def _provider_model_offers(provider: str) -> list[dict]:
3360
3360
  Every other provider is offered the generic tiers (small/medium/high), which
3361
3361
  are provider-independent, each annotated with the concrete model id the
3362
3362
  catalog says that provider dispatches. That is what makes the picker read
3363
- "medium -> gpt-5.6-terra" on codex and "medium -> claude-sonnet-5" on claude
3363
+ "medium -> gpt-5.6-terra" on codex and "medium -> <catalog sonnet id>" on claude
3364
3364
  without the frontend knowing a single model id.
3365
3365
  """
3366
3366
  if provider == "claude":
@@ -7738,23 +7738,24 @@ async def stop_session(request: Request):
7738
7738
  # At runtime, overridden by .loki/pricing.json if available
7739
7739
  _DEFAULT_PRICING = {
7740
7740
  # Claude (Anthropic)
7741
- # Fable 5 is the top-tier advisory model at exactly 2x Opus per token.
7742
- "fable": {"input": 10.00, "output": 50.00},
7743
- "claude-fable-5": {"input": 10.00, "output": 50.00},
7744
- "opus": {"input": 5.00, "output": 25.00},
7745
- "sonnet": {"input": 2.00, "output": 10.00},
7746
- "haiku": {"input": 1.00, "output": 5.00},
7741
+ # Fable 5 is the top-tier advisory model at 2.5x Opus 5.5 per token.
7742
+ "fable": {"input": 10.00, "output": 50.00, "cache_read": 0.25, "cache_write": 12.5, "cache_write_1h": 20},
7743
+ "claude-fable-5": {"input": 10.00, "output": 50.00, "cache_read": 0.25, "cache_write": 12.5, "cache_write_1h": 20},
7744
+ "opus": {"input": 4.00, "output": 20.00, "cache_read": 0.2, "cache_write": 5, "cache_write_1h": 8},
7745
+ "sonnet": {"input": 2.00, "output": 10.00, "cache_read": 0.1, "cache_write": 2.5, "cache_write_1h": 4},
7746
+ # haiku = Haiku 5.5 up to 100K prompt tokens (no over-100K tier here)
7747
+ "haiku": {"input": 0.10, "output": 0.50, "cache_read": 0.01, "cache_write": 0.125, "cache_write_1h": 0.2},
7748
+ # Exact ids (a lookup by recorded model string must not fall back to sonnet)
7749
+ "claude-haiku-4-5": {"input": 1.00, "output": 5.00, "cache_read": 0.1, "cache_write": 1.25, "cache_write_1h": 2},
7750
+ "claude-haiku-5-5": {"input": 0.10, "output": 0.50, "cache_read": 0.01, "cache_write": 0.125, "cache_write_1h": 0.2},
7747
7751
  # OpenAI Codex
7748
- "gpt-5.3-codex": {"input": 1.50, "output": 12.00},
7752
+ "gpt-5.3-codex": {"input": 1.75, "output": 14.00},
7749
7753
  # gpt-5.6 line: sol (high) / terra (medium, default) / luna (small).
7750
- # UNVERIFIED RATES. The model IDs are confirmed against
7751
- # developers.openai.com/api/docs/models, but OpenAI's published per-token
7752
- # prices for this line were not, so these are placeholders scaled from the
7753
- # gpt-5.3 rate. They drive a display estimate only, never a gate. Replace
7754
- # from the pricing page; tools/probe-model-catalog.py is the refresh path.
7755
- "gpt-5.6-sol": {"input": 2.50, "output": 20.00},
7756
- "gpt-5.6-terra": {"input": 1.50, "output": 12.00},
7757
- "gpt-5.6-luna": {"input": 0.50, "output": 4.00},
7754
+ # Rates from developers.openai.com/api/docs/pricing (read 2026-10-08),
7755
+ # Standard tier, short context (up to 272K). tests/test-pricing-parity.sh pins them.
7756
+ "gpt-5.6-sol": {"input": 4.00, "output": 20.00},
7757
+ "gpt-5.6-terra": {"input": 2.00, "output": 12.00},
7758
+ "gpt-5.6-luna": {"input": 0.20, "output": 1.20},
7758
7759
  }
7759
7760
 
7760
7761
  # Active pricing - starts with defaults, updated from .loki/pricing.json
@@ -8565,11 +8566,11 @@ async def get_gate_policy():
8565
8566
  # =============================================================================
8566
8567
 
8567
8568
  _PROVIDER_LABELS = {
8568
- # v7.104.0: current model IDs (model_catalog.json): opus=claude-opus-4-8,
8569
- # sonnet=claude-sonnet-5 (the default execution model), haiku=claude-haiku-4-5.
8570
- "opus": "Opus 4.8",
8571
- "sonnet": "Sonnet 5",
8572
- "haiku": "Haiku 4.5",
8569
+ # v7.104.0: current model IDs (model_catalog.json): opus, sonnet (the default execution model), haiku: ids live in
8570
+ # the catalog cli_aliases, not here.
8571
+ "opus": "Opus 5.5",
8572
+ "sonnet": "Sonnet 5.5",
8573
+ "haiku": "Haiku 5.5",
8573
8574
  "gpt-5.3-codex": "GPT-5.3 Codex",
8574
8575
  "gpt-5.6-sol": "GPT-5.6 Sol",
8575
8576
  "gpt-5.6-terra": "GPT-5.6 Terra",
@@ -8580,18 +8581,11 @@ _PROVIDER_LABELS = {
8580
8581
  # the UI WITHOUT changing any computed cost number. The Sonnet 5 intro price
8581
8582
  # ($2/$10 per MTok) became the standard price, so the 2026-09-01 increase to
8582
8583
  # $3/$15 will not occur (platform.claude.com pricing page, read 2026-10-03).
8583
- _UNVERIFIED_RATE_NOTE = (
8584
- "Unverified placeholder rate, scaled from gpt-5.3; not from OpenAI's pricing page."
8585
- )
8586
8584
  _MODEL_PRICING_NOTES = {
8587
8585
  "sonnet": (
8588
8586
  "Standard pricing: $2 / $10 per MTok. "
8589
8587
  "The intro price became the standard price; no increase to $3 / $15."
8590
8588
  ),
8591
- # See the UNVERIFIED RATES comment on the pricing table: shown, not hidden.
8592
- "gpt-5.6-sol": _UNVERIFIED_RATE_NOTE,
8593
- "gpt-5.6-terra": _UNVERIFIED_RATE_NOTE,
8594
- "gpt-5.6-luna": _UNVERIFIED_RATE_NOTE,
8595
8589
  }
8596
8590
 
8597
8591
  _MODEL_PROVIDERS = {