loki-mode 9.53.0 → 9.54.2

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 (119) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/completion-council.sh +28 -5
  4. package/autonomy/council-v2.sh +13 -7
  5. package/autonomy/lib/done-recognition.sh +24 -16
  6. package/autonomy/lib/proof-check.sh +11 -3
  7. package/autonomy/lib/proof-generator.py +36 -5
  8. package/autonomy/lib/voter-agents.sh +8 -3
  9. package/autonomy/lib/workspace_diff.py +106 -12
  10. package/autonomy/prd-checklist.sh +19 -11
  11. package/autonomy/run.sh +503 -52
  12. package/dashboard/__init__.py +1 -1
  13. package/dashboard/api_v2.py +4 -0
  14. package/dashboard/audit.py +9 -1
  15. package/dashboard/auth.py +16 -4
  16. package/dashboard/registry.py +34 -12
  17. package/dashboard/rigour_integration.py +25 -17
  18. package/dashboard/server.py +252 -104
  19. package/dashboard/static/cost.html +55 -26
  20. package/dashboard/static/index.html +475 -1544
  21. package/dashboard/static/proofs.html +1 -1
  22. package/docs/INSTALLATION.md +1 -1
  23. package/docs/air-gapped.md +7 -2
  24. package/docs/image-provenance.md +4 -2
  25. package/docs/v10/BACKLOG.md +82 -2
  26. package/docs/v10/BOARD.md +105 -0
  27. package/docs/v10/DECISIONS.md +71 -0
  28. package/docs/v10/METRICS.md +2 -1
  29. package/docs/v10/PROGRESS.md +60 -0
  30. package/docs/v10/SWARM-PROMPT.md +98 -0
  31. package/docs/v10/SWARM.md +237 -0
  32. package/loki-ts/dist/loki.js +323 -322
  33. package/mcp/__init__.py +1 -1
  34. package/package.json +1 -1
  35. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  36. package/providers/aider.sh +8 -0
  37. package/providers/cline.sh +8 -0
  38. package/providers/codex.sh +9 -0
  39. package/providers/opencode.sh +9 -0
  40. package/web-app/dist/assets/AdminPage-CZrBkzRF.js +32 -0
  41. package/web-app/dist/assets/Avatar-gQIp6FBI.js +11 -0
  42. package/web-app/dist/assets/{Badge-BF3mhT57.js → Badge-D2_fBTFY.js} +1 -1
  43. package/web-app/dist/assets/{Button-BDp9aJ9q.js → Button-D5qDd2ef.js} +1 -1
  44. package/web-app/dist/assets/CockpitPage-DVMk2RUK.js +47 -0
  45. package/web-app/dist/assets/ComparePage-NMLyE1xL.js +1 -0
  46. package/web-app/dist/assets/{ErrorBoundary-ut3wrUmu.js → ErrorBoundary-BRABI-BT.js} +1 -1
  47. package/web-app/dist/assets/EvidenceReceiptPanel-D2LNKqUx.js +1 -0
  48. package/web-app/dist/assets/GitHubIssuesPanel-BC5GzKUN.js +7 -0
  49. package/web-app/dist/assets/{GitHubPRsPanel-DurZgSaj.js → GitHubPRsPanel-BSlmoVTS.js} +3 -3
  50. package/web-app/dist/assets/HomePage-D_CDMoen.js +12 -0
  51. package/web-app/dist/assets/{LoginPage-HeRGJeZy.js → LoginPage-BBNA_N9t.js} +1 -1
  52. package/web-app/dist/assets/{MagicPage-CUKrqsZs.js → MagicPage-CnFRZCMx.js} +1 -1
  53. package/web-app/dist/assets/MetricsPage-CPfLMRlh.js +6 -0
  54. package/web-app/dist/assets/{NotFoundPage-BZDZ-B77.js → NotFoundPage-lA0XSGTz.js} +1 -1
  55. package/web-app/dist/assets/ProjectPage-CNAPbr9z.js +256 -0
  56. package/web-app/dist/assets/ProjectsPage-CMtm8goN.js +6 -0
  57. package/web-app/dist/assets/SettingsPage-BhIjVMYE.js +10 -0
  58. package/web-app/dist/assets/{ShowcasePage-BGS2jTGH.js → ShowcasePage-BndtGeYo.js} +1 -1
  59. package/web-app/dist/assets/SystemSettingsPage-euXI-KXE.js +1 -0
  60. package/web-app/dist/assets/TeamsPage-ClUKecun.js +11 -0
  61. package/web-app/dist/assets/TemplatesPage-BWHWVk0L.js +29 -0
  62. package/web-app/dist/assets/{TerminalOutput-togzv9Zl.js → TerminalOutput-Cv3N3Szf.js} +1 -1
  63. package/web-app/dist/assets/{activity-Dreyb_Kr.js → activity-dEhz-bXR.js} +1 -1
  64. package/web-app/dist/assets/{bell-DWH0drES.js → bell-B3XUMq1t.js} +1 -1
  65. package/web-app/dist/assets/{bot-78MoCuDl.js → bot-X-ssNlwR.js} +1 -1
  66. package/web-app/dist/assets/{check-ikfylPst.js → check-C_9Nx7kb.js} +1 -1
  67. package/web-app/dist/assets/{chevron-left-DXUqkd8J.js → chevron-left-tvNswo3A.js} +1 -1
  68. package/web-app/dist/assets/{circle-alert-Da74VO8P.js → circle-alert-CSB88nEs.js} +1 -1
  69. package/web-app/dist/assets/{clock-mlGCFq8l.js → clock-C8p2e4NI.js} +1 -1
  70. package/web-app/dist/assets/{cloud-B_Y5ZrIO.js → cloud-CKp2ZvhG.js} +1 -1
  71. package/web-app/dist/assets/{code-xml-Bbom7YWV.js → code-xml-dY70LCHD.js} +1 -1
  72. package/web-app/dist/assets/{database-CLcofiVp.js → database-DObn5fmn.js} +1 -1
  73. package/web-app/dist/assets/{dollar-sign-C5mkjXIM.js → dollar-sign-DSu6n3K3.js} +1 -1
  74. package/web-app/dist/assets/{file-code-corner-CVrkaOQP.js → file-code-corner-DpCnS73z.js} +1 -1
  75. package/web-app/dist/assets/{file-plus-BV9240gX.js → file-plus-D3IPKCf1.js} +1 -1
  76. package/web-app/dist/assets/{globe-aZ0Zso4I.js → globe-C9QXkgH_.js} +1 -1
  77. package/web-app/dist/assets/{hammer-EgOQNukG.js → hammer-D_FtWe1y.js} +1 -1
  78. package/web-app/dist/assets/index-CI54rara.css +1 -0
  79. package/web-app/dist/assets/{index-DvZ0Kk2x.js → index-Cz7q1bvC.js} +2 -2
  80. package/web-app/dist/assets/{layers-BOVKmepE.js → layers-DsW7jnJX.js} +1 -1
  81. package/web-app/dist/assets/{loader-circle-0K8yLgHl.js → loader-circle-B3HspjKR.js} +1 -1
  82. package/web-app/dist/assets/{lock-XzlDMy8M.js → lock-DSI29pct.js} +1 -1
  83. package/web-app/dist/assets/{package-BtXTKusI.js → package-CLNxtA2x.js} +1 -1
  84. package/web-app/dist/assets/{plus-PxeiD8ju.js → plus-DyI4WC4_.js} +1 -1
  85. package/web-app/dist/assets/{refresh-cw-CjqzYczt.js → refresh-cw-D2dv0xA0.js} +1 -1
  86. package/web-app/dist/assets/{rotate-ccw-CY0os4DH.js → rotate-ccw-CBvihA-a.js} +1 -1
  87. package/web-app/dist/assets/scroll-text-DvoOvAl_.js +6 -0
  88. package/web-app/dist/assets/{server-pIIs9vNp.js → server-DenWvSUt.js} +1 -1
  89. package/web-app/dist/assets/{shield-alert-CsDqKXwA.js → shield-alert-40cX_FvG.js} +1 -1
  90. package/web-app/dist/assets/{thumbs-up-CAh3HVzH.js → thumbs-up-BrjZ6QuV.js} +12 -7
  91. package/web-app/dist/assets/trash-2-C6evwkEH.js +16 -0
  92. package/web-app/dist/assets/{trending-down-DrtBd_C9.js → trending-down-CfbZis3O.js} +1 -1
  93. package/web-app/dist/assets/{trending-up-D-DbCHXm.js → trending-up-DWuEK3WC.js} +1 -1
  94. package/web-app/dist/assets/{upload-D4l6DCOt.js → upload-B9DFBcPG.js} +1 -1
  95. package/web-app/dist/assets/{usePolling-D0aoTX80.js → usePolling-BryVC-T1.js} +1 -1
  96. package/web-app/dist/assets/{user-BQf_XJO_.js → user-DMRXwZiw.js} +1 -1
  97. package/web-app/dist/index.html +2 -2
  98. package/web-app/server.py +122 -47
  99. package/web-app/dist/assets/AdminPage-y6_b2Xo4.js +0 -32
  100. package/web-app/dist/assets/Avatar-BFPkXhIJ.js +0 -6
  101. package/web-app/dist/assets/CockpitPage-5TKICCoA.js +0 -47
  102. package/web-app/dist/assets/ComparePage-BSuNsUHy.js +0 -1
  103. package/web-app/dist/assets/EvidenceReceiptPanel-CcaBwEI-.js +0 -1
  104. package/web-app/dist/assets/GitHubIssuesPanel-DJeYgzAa.js +0 -12
  105. package/web-app/dist/assets/HomePage-Bs451LAy.js +0 -28
  106. package/web-app/dist/assets/MetricsPage-DvY1csgz.js +0 -6
  107. package/web-app/dist/assets/ProjectPage-CqHkEZkl.js +0 -257
  108. package/web-app/dist/assets/ProjectsPage-CLvCK1Y8.js +0 -6
  109. package/web-app/dist/assets/SettingsPage-DP7OmdwP.js +0 -10
  110. package/web-app/dist/assets/SystemSettingsPage-P_rlLh0x.js +0 -1
  111. package/web-app/dist/assets/TeamsPage-DxtBDcBC.js +0 -11
  112. package/web-app/dist/assets/TemplatesPage-5e-faH3W.js +0 -29
  113. package/web-app/dist/assets/folder-open-D_6yV78G.js +0 -11
  114. package/web-app/dist/assets/index-BSgmPwC0.css +0 -1
  115. package/web-app/dist/assets/lightbulb-DdASgqOG.js +0 -6
  116. package/web-app/dist/assets/mail-COu670_W.js +0 -6
  117. package/web-app/dist/assets/minus-bQpUt9ff.js +0 -6
  118. package/web-app/dist/assets/save-v8qep5cY.js +0 -6
  119. package/web-app/dist/assets/trash-2-Dt6urTyY.js +0 -6
@@ -136,6 +136,17 @@
136
136
  else if (s.split(".")[1].length === 1) s += "0";
137
137
  return "$" + s;
138
138
  }
139
+ // A total over runs where only some recorded a cost is a lower bound.
140
+ function projectTotal(d) {
141
+ return fmtUsd(d.project_total_usd) + (d.project_total_partial && d.project_total_usd != null ? " (partial)" : "");
142
+ }
143
+ // Same rule for a sum over iterations where only some recorded a cost.
144
+ function partialUsd(n, partial) {
145
+ return fmtUsd(n) + (partial && n !== null && n !== undefined ? " (partial)" : "");
146
+ }
147
+ function orNotRecorded(v) {
148
+ return (v === null || v === undefined) ? "not recorded" : esc(v);
149
+ }
139
150
  function badgeClass(v) {
140
151
  v = String(v || "").toUpperCase();
141
152
  if (v.indexOf("APPROVE") === 0 || v === "PASS" || v === "PASSED") return "b-approve";
@@ -143,10 +154,13 @@
143
154
  if (v.indexOf("CONCERN") === 0) return "b-concern";
144
155
  return "";
145
156
  }
146
- function statusText(st) {
157
+ function statusText(st, partial) {
158
+ if (st === "ok" && partial) return "Within budget so far, but some iterations recorded no cost, so true spend may be higher.";
147
159
  if (st === "exceeded") return "Budget cap reached. The run is paused to prevent a surprise bill.";
148
160
  if (st === "warn") return "Approaching budget cap (80% or more used). Warning only, the run continues.";
149
161
  if (st === "ok") return "Within budget.";
162
+ // A cap is set but no spend was measured: unknown, never "within budget".
163
+ if (st === "unknown") return "Spend not recorded yet, so budget use is unknown.";
150
164
  return "No budget cap set. Set LOKI_BUDGET_LIMIT to cap spend.";
151
165
  }
152
166
 
@@ -158,16 +172,19 @@
158
172
  '<div class="cap-note">When a cap is set, Loki warns at 80% and hard-stops at 100%.</div></div>';
159
173
  return html;
160
174
  }
161
- var pct = (b.percent_used === null || b.percent_used === undefined) ? 0 : Number(b.percent_used);
162
- var fillPct = Math.max(0, Math.min(100, pct));
163
- var st = esc(b.status || "ok");
175
+ // Unknown use is not 0% used: no fill and no percentage are drawn for it.
176
+ var pct = (b.percent_used === null || b.percent_used === undefined) ? NaN : Number(b.percent_used);
177
+ var known = isFinite(pct);
178
+ var fillPct = known ? Math.max(0, Math.min(100, pct)) : 0;
179
+ var st = esc(b.status || "unknown");
180
+ var part = b.partial === true;
164
181
  html += '<div class="gauge">' +
165
- '<div class="top"><span class="muted">' + fmtUsd(b.used) + ' of ' + fmtUsd(b.limit) + ' used</span>' +
166
- '<span class="pct">' + pct.toFixed(1) + '%</span></div>' +
182
+ '<div class="top"><span class="muted">' + partialUsd(b.used, part) + ' of ' + fmtUsd(b.limit) + ' used</span>' +
183
+ '<span class="pct">' + (known ? pct.toFixed(1) + '%' + (part ? ' (partial)' : '') : 'not recorded') + '</span></div>' +
167
184
  '<div class="bar"><div class="fill ' + st + '" style="width:' + fillPct + '%"></div>' +
168
185
  '<div class="warnline" title="80% warn threshold"></div></div>' +
169
- '<div class="status ' + st + '">' + statusText(b.status) + '</div>' +
170
- '<div class="cap-note">Remaining: ' + fmtUsd(b.remaining) +
186
+ '<div class="status ' + st + '">' + statusText(b.status, part) + '</div>' +
187
+ '<div class="cap-note">Remaining: ' + (part && b.remaining != null ? 'at most ' : '') + fmtUsd(b.remaining) +
171
188
  '. Warns at ' + esc(b.warn_threshold_percent) + '%, hard-stops at 100%.</div>' +
172
189
  '</div>';
173
190
  return html;
@@ -210,37 +227,49 @@
210
227
  return html;
211
228
  }
212
229
  var its = cr.iterations;
213
- // Inline SVG cumulative line.
230
+ // Inline SVG cumulative line. An iteration with no recorded cost is SKIPPED,
231
+ // never plotted at the floor as a measured zero; x keeps its index so the
232
+ // gap stays visible.
214
233
  var W = 900, H = 140, pad = 8;
234
+ var measured = [];
215
235
  var maxCum = 0;
216
236
  for (var i = 0; i < its.length; i++) {
217
- var cv = Number(its[i].cumulative_usd) || 0;
237
+ var raw = its[i].cumulative_usd;
238
+ var cv = (raw === null || raw === undefined) ? NaN : Number(raw);
239
+ if (!isFinite(cv)) continue;
240
+ measured.push([i, cv]);
218
241
  if (cv > maxCum) maxCum = cv;
219
242
  }
220
243
  if (maxCum <= 0) maxCum = 1;
221
244
  var pts = [];
222
- for (var j = 0; j < its.length; j++) {
223
- var x = its.length === 1 ? W / 2 : pad + (j / (its.length - 1)) * (W - 2 * pad);
224
- var y = H - pad - ((Number(its[j].cumulative_usd) || 0) / maxCum) * (H - 2 * pad);
245
+ for (var j = 0; j < measured.length; j++) {
246
+ var idx = measured[j][0];
247
+ var x = its.length === 1 ? W / 2 : pad + (idx / (its.length - 1)) * (W - 2 * pad);
248
+ var y = H - pad - (measured[j][1] / maxCum) * (H - 2 * pad);
225
249
  pts.push(x.toFixed(1) + "," + y.toFixed(1));
226
250
  }
227
- var poly = '<svg viewBox="0 0 ' + W + ' ' + H + '" preserveAspectRatio="none">' +
228
- '<polyline fill="none" stroke="#6f7bf7" stroke-width="2" points="' + pts.join(" ") + '"/>' +
229
- '</svg>';
251
+ var poly = pts.length === 0
252
+ ? '<div class="empty">No iteration in this run recorded a cost, so there is nothing to plot.</div>'
253
+ : '<svg viewBox="0 0 ' + W + ' ' + H + '" preserveAspectRatio="none">' +
254
+ '<polyline fill="none" stroke="#6f7bf7" stroke-width="2" points="' + pts.join(" ") + '"/>' +
255
+ '</svg>';
230
256
  html += '<div class="panel"><div class="muted" style="font-size:13px;margin-bottom:6px;">' +
231
- 'Cumulative spend this run: <span class="mono">' + fmtUsd(cr.total_usd) + '</span></div>' +
257
+ 'Cumulative spend this run: <span class="mono">' + partialUsd(cr.total_usd, cr.partial) + '</span></div>' +
232
258
  poly + '</div>';
233
259
  // Per-iteration table.
234
260
  var rows = "";
261
+ // Once an iteration went unmeasured, every later running total skips it.
262
+ var gap = false;
235
263
  for (var r = 0; r < its.length; r++) {
236
264
  var it = its[r];
265
+ if (it.cost_usd === null || it.cost_usd === undefined) gap = true;
237
266
  rows += '<tr><td class="num mono">' + esc(it.iteration) + '</td>' +
238
- '<td class="mono">' + esc(it.model) + '</td>' +
267
+ '<td class="mono">' + orNotRecorded(it.model) + '</td>' +
239
268
  '<td>' + esc(it.phase) + '</td>' +
240
- '<td class="num">' + esc(it.input_tokens) + '</td>' +
241
- '<td class="num">' + esc(it.output_tokens) + '</td>' +
269
+ '<td class="num">' + orNotRecorded(it.input_tokens) + '</td>' +
270
+ '<td class="num">' + orNotRecorded(it.output_tokens) + '</td>' +
242
271
  '<td class="num mono">' + fmtUsd(it.cost_usd) + '</td>' +
243
- '<td class="num mono">' + fmtUsd(it.cumulative_usd) + '</td></tr>';
272
+ '<td class="num mono">' + partialUsd(it.cumulative_usd, gap) + '</td></tr>';
244
273
  }
245
274
  html += '<table style="margin-top:14px;"><thead><tr>' +
246
275
  '<th class="num">Iter</th><th>Model</th><th>Phase</th>' +
@@ -271,7 +300,7 @@
271
300
  }
272
301
  html += '<table><thead><tr>' +
273
302
  '<th>Run</th><th>When</th><th>Model</th><th class="num">Files</th>' +
274
- '<th>Verdict</th><th class="num">Cost</th>' +
303
+ '<th>Council vote</th><th class="num">Cost</th>' +
275
304
  '</tr></thead><tbody>' + rows + '</tbody></table>';
276
305
  return html;
277
306
  }
@@ -281,14 +310,14 @@
281
310
  var b = d.budget || {};
282
311
  var cards = '<div class="cards">' +
283
312
  '<div class="card"><div class="label">Project total</div>' +
284
- '<div class="val">' + fmtUsd(d.project_total_usd) + '</div>' +
313
+ '<div class="val">' + projectTotal(d) + '</div>' +
285
314
  '<div class="note">' + esc(d.runs_count) + ' run(s) recorded</div></div>' +
286
315
  '<div class="card"><div class="label">Current run</div>' +
287
- '<div class="val">' + fmtUsd(d.current_run ? d.current_run.total_usd : null) + '</div>' +
316
+ '<div class="val">' + (d.current_run ? partialUsd(d.current_run.total_usd, d.current_run.partial) : fmtUsd(null)) + '</div>' +
288
317
  '<div class="note">' + (d.current_run && d.current_run.iterations ? d.current_run.iterations.length : 0) + ' iteration(s)</div></div>' +
289
318
  '<div class="card"><div class="label">Budget status</div>' +
290
- '<div class="val ' + esc(b.status || "none") + '" style="font-size:20px;text-transform:capitalize;">' + esc(b.status || "none") + '</div>' +
291
- '<div class="note">' + (b.limit ? fmtUsd(b.used) + ' / ' + fmtUsd(b.limit) : "no cap set") + '</div></div>' +
319
+ '<div class="val ' + esc(b.status || "none") + '" style="font-size:20px;text-transform:capitalize;">' + esc(b.status || "none") + (b.partial ? ' (partial)' : '') + '</div>' +
320
+ '<div class="note">' + (b.limit ? partialUsd(b.used, b.partial) + ' / ' + fmtUsd(b.limit) : "no cap set") + '</div></div>' +
292
321
  '</div>';
293
322
  c.innerHTML = cards +
294
323
  renderBudget(d.budget) +