loki-mode 9.55.0 → 9.57.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 (97) hide show
  1. package/.github/actions/issue-to-pr/action.yml +165 -29
  2. package/.github/workflows/loki-issue-to-pr.yml +137 -24
  3. package/SKILL.md +2 -2
  4. package/VERSION +1 -1
  5. package/autonomy/lib/proof-check.sh +9 -0
  6. package/autonomy/lib/proof-generator.py +12 -3
  7. package/autonomy/lib/workspace_diff.py +18 -7
  8. package/autonomy/loki +133 -3
  9. package/autonomy/run.sh +385 -22
  10. package/dashboard/__init__.py +1 -1
  11. package/dashboard/api_keys.py +12 -5
  12. package/dashboard/build_supervisor.py +25 -1
  13. package/dashboard/server.py +46 -24
  14. package/dashboard/static/index.html +57 -57
  15. package/docs/VERIFIED-COMPLETION-PLAN.md +7 -5
  16. package/docs/dev/architecture-reference.md +99 -0
  17. package/docs/dev/project-structure.md +134 -0
  18. package/docs/dev/release-checklist.md +157 -0
  19. package/docs/dev/research-foundation.md +29 -0
  20. package/docs/dev/tmp-cleanup.md +157 -0
  21. package/docs/environment-variables.md +1 -0
  22. package/docs/v10/BACKLOG.md +33 -0
  23. package/docs/v10/BOARD.md +97 -27
  24. package/docs/v10/DECISIONS.md +43 -0
  25. package/docs/v10/OPERATING-MODEL.md +47 -0
  26. package/docs/v10/PROGRESS.md +893 -0
  27. package/loki-ts/dist/loki.js +326 -325
  28. package/mcp/__init__.py +1 -1
  29. package/package.json +1 -1
  30. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  31. package/providers/claude.sh +1 -1
  32. package/providers/model_catalog.json +12 -5
  33. package/providers/models.sh +1 -1
  34. package/references/core-workflow.md +1 -1
  35. package/web-app/dist/assets/{AdminPage-CZrBkzRF.js → AdminPage-Oyx-w2Ch.js} +1 -1
  36. package/web-app/dist/assets/{Avatar-gQIp6FBI.js → Avatar-D60m65JB.js} +1 -1
  37. package/web-app/dist/assets/{Badge-D2_fBTFY.js → Badge-CqfZNaem.js} +1 -1
  38. package/web-app/dist/assets/{Button-D5qDd2ef.js → Button-BqjzE4fz.js} +1 -1
  39. package/web-app/dist/assets/CockpitPage-Czk7o_ou.js +47 -0
  40. package/web-app/dist/assets/ComparePage-BEfTrTb1.js +1 -0
  41. package/web-app/dist/assets/{ErrorBoundary-BRABI-BT.js → ErrorBoundary-BrLk5nkO.js} +1 -1
  42. package/web-app/dist/assets/EvidenceReceiptPanel-9vEpi5ir.js +1 -0
  43. package/web-app/dist/assets/{GitHubIssuesPanel-BC5GzKUN.js → GitHubIssuesPanel-D6izZx0w.js} +1 -1
  44. package/web-app/dist/assets/GitHubPRsPanel-BTkG2FgA.js +17 -0
  45. package/web-app/dist/assets/{HomePage-D_CDMoen.js → HomePage-nsr4kpN1.js} +2 -2
  46. package/web-app/dist/assets/{LoginPage-BBNA_N9t.js → LoginPage-BVblQrr9.js} +1 -1
  47. package/web-app/dist/assets/{MagicPage-CnFRZCMx.js → MagicPage-CmnSyLq7.js} +1 -1
  48. package/web-app/dist/assets/{MetricsPage-CPfLMRlh.js → MetricsPage-BVfwU81j.js} +1 -1
  49. package/web-app/dist/assets/{NotFoundPage-lA0XSGTz.js → NotFoundPage-AYQ6uqqI.js} +1 -1
  50. package/web-app/dist/assets/{ProjectPage-CNAPbr9z.js → ProjectPage-DMnbw9X9.js} +3 -3
  51. package/web-app/dist/assets/{ProjectsPage-CMtm8goN.js → ProjectsPage-CNVTAF2N.js} +1 -1
  52. package/web-app/dist/assets/{SettingsPage-BhIjVMYE.js → SettingsPage-D1_qasFD.js} +3 -3
  53. package/web-app/dist/assets/{ShowcasePage-BndtGeYo.js → ShowcasePage-2dBCjLXn.js} +1 -1
  54. package/web-app/dist/assets/{SystemSettingsPage-euXI-KXE.js → SystemSettingsPage-Djo6IE4u.js} +1 -1
  55. package/web-app/dist/assets/{TeamsPage-ClUKecun.js → TeamsPage-CY8p-yxD.js} +1 -1
  56. package/web-app/dist/assets/{TemplatesPage-BWHWVk0L.js → TemplatesPage-B6iFgH6t.js} +1 -1
  57. package/web-app/dist/assets/{TerminalOutput-Cv3N3Szf.js → TerminalOutput-B3yzZe-h.js} +1 -1
  58. package/web-app/dist/assets/{activity-dEhz-bXR.js → activity-CNfAjtRv.js} +1 -1
  59. package/web-app/dist/assets/{bell-B3XUMq1t.js → bell-CMETsHPH.js} +1 -1
  60. package/web-app/dist/assets/{bot-X-ssNlwR.js → bot-C9kXvk1i.js} +1 -1
  61. package/web-app/dist/assets/{check-C_9Nx7kb.js → check-BRK-zLB5.js} +1 -1
  62. package/web-app/dist/assets/{chevron-left-tvNswo3A.js → chevron-left-CxI5uD4g.js} +1 -1
  63. package/web-app/dist/assets/{circle-alert-CSB88nEs.js → circle-alert-CVFRPWpv.js} +1 -1
  64. package/web-app/dist/assets/{clock-C8p2e4NI.js → clock-CLYV8a_x.js} +1 -1
  65. package/web-app/dist/assets/{cloud-CKp2ZvhG.js → cloud-CiISiIOa.js} +1 -1
  66. package/web-app/dist/assets/{code-xml-dY70LCHD.js → code-xml-DHsgqwV-.js} +1 -1
  67. package/web-app/dist/assets/{database-DObn5fmn.js → database-DbvUqtz3.js} +1 -1
  68. package/web-app/dist/assets/{dollar-sign-DSu6n3K3.js → dollar-sign-Ct0lRPHw.js} +1 -1
  69. package/web-app/dist/assets/{file-code-corner-DpCnS73z.js → file-code-corner-D1sjFEh7.js} +1 -1
  70. package/web-app/dist/assets/{file-plus-D3IPKCf1.js → file-plus-DnmX18Fi.js} +1 -1
  71. package/web-app/dist/assets/{globe-C9QXkgH_.js → globe-bSpDNgoA.js} +1 -1
  72. package/web-app/dist/assets/{hammer-D_FtWe1y.js → hammer-Bj41Kvlq.js} +1 -1
  73. package/web-app/dist/assets/{index-CI54rara.css → index-BfQ0f3-S.css} +1 -1
  74. package/web-app/dist/assets/{index-Cz7q1bvC.js → index-CxajNJVu.js} +3 -3
  75. package/web-app/dist/assets/{layers-DsW7jnJX.js → layers-BNtBwYER.js} +1 -1
  76. package/web-app/dist/assets/{loader-circle-B3HspjKR.js → loader-circle-YY_VZofG.js} +1 -1
  77. package/web-app/dist/assets/{lock-DSI29pct.js → lock-rpjEPVoC.js} +1 -1
  78. package/web-app/dist/assets/{package-CLNxtA2x.js → package-desXU6XA.js} +1 -1
  79. package/web-app/dist/assets/{plus-DyI4WC4_.js → plus-7AoOU-I9.js} +1 -1
  80. package/web-app/dist/assets/{refresh-cw-D2dv0xA0.js → refresh-cw-oNj-Xn4B.js} +1 -1
  81. package/web-app/dist/assets/{rotate-ccw-CBvihA-a.js → rotate-ccw-DeiFjfVO.js} +1 -1
  82. package/web-app/dist/assets/{scroll-text-DvoOvAl_.js → scroll-text-Q9AzWiNV.js} +1 -1
  83. package/web-app/dist/assets/{server-DenWvSUt.js → server-DKgVwfek.js} +1 -1
  84. package/web-app/dist/assets/{shield-alert-40cX_FvG.js → shield-alert-G6x-bS-I.js} +1 -1
  85. package/web-app/dist/assets/{thumbs-up-BrjZ6QuV.js → thumbs-up-Qhk0yvw0.js} +1 -1
  86. package/web-app/dist/assets/{trash-2-C6evwkEH.js → trash-2-D23gvznl.js} +1 -1
  87. package/web-app/dist/assets/{trending-down-CfbZis3O.js → trending-down-CSQClPrr.js} +1 -1
  88. package/web-app/dist/assets/{trending-up-DWuEK3WC.js → trending-up-sjMSd1wc.js} +1 -1
  89. package/web-app/dist/assets/{upload-B9DFBcPG.js → upload-Dchovhld.js} +1 -1
  90. package/web-app/dist/assets/{usePolling-BryVC-T1.js → usePolling-DwLceXwF.js} +1 -1
  91. package/web-app/dist/assets/{user-DMRXwZiw.js → user-BqZM8CmD.js} +1 -1
  92. package/web-app/dist/index.html +2 -2
  93. package/web-app/server.py +52 -17
  94. package/web-app/dist/assets/CockpitPage-DVMk2RUK.js +0 -47
  95. package/web-app/dist/assets/ComparePage-NMLyE1xL.js +0 -1
  96. package/web-app/dist/assets/EvidenceReceiptPanel-D2LNKqUx.js +0 -1
  97. package/web-app/dist/assets/GitHubPRsPanel-BSlmoVTS.js +0 -17
@@ -8614,16 +8614,27 @@ async def get_pricing():
8614
8614
  # Completion Council API (v5.25.0)
8615
8615
  # =============================================================================
8616
8616
 
8617
+ def council_state(loki_dir: _Path) -> dict:
8618
+ """Read council state.json, distinguishing "no state yet" from "unreadable".
8619
+
8620
+ A missing state.json means the council genuinely has not recorded a vote:
8621
+ total_votes is really 0. A state.json that exists but fails to parse (torn
8622
+ write, corruption) means we do not know how many votes were recorded --
8623
+ total_votes must be None, not a fabricated 0 that reads as a real count.
8624
+ """
8625
+ state_file = loki_dir / "council" / "state.json"
8626
+ if not state_file.exists():
8627
+ return {"enabled": False, "total_votes": 0, "verdicts": []}
8628
+ try:
8629
+ return json.loads(state_file.read_text())
8630
+ except Exception:
8631
+ return {"enabled": None, "total_votes": None, "verdicts": None, "error": "unreadable_state"}
8632
+
8633
+
8617
8634
  @app.get("/api/council/state", dependencies=[Depends(auth.require_scope("read"))])
8618
8635
  async def get_council_state():
8619
8636
  """Get current Completion Council state."""
8620
- state_file = _get_loki_dir() / "council" / "state.json"
8621
- if state_file.exists():
8622
- try:
8623
- return json.loads(state_file.read_text())
8624
- except Exception:
8625
- pass
8626
- return {"enabled": False, "total_votes": 0, "verdicts": []}
8637
+ return council_state(_get_loki_dir())
8627
8638
 
8628
8639
 
8629
8640
  @app.get("/api/council/verdicts", dependencies=[Depends(auth.require_scope("read"))])
@@ -8873,30 +8884,41 @@ async def get_context():
8873
8884
  # Notification Trigger API (v5.40.0)
8874
8885
  # =============================================================================
8875
8886
 
8876
- @app.get("/api/notifications", dependencies=[Depends(auth.require_scope("read"))])
8877
- async def get_notifications(
8878
- severity: Optional[str] = Query(None, pattern="^(critical|warning|info)$"),
8879
- unread_only: bool = Query(False),
8880
- ):
8881
- """Get notification list from .loki/notifications/active.json."""
8882
- loki_dir = _get_loki_dir()
8887
+ _EMPTY_NOTIFICATION_SUMMARY = {"total": 0, "unacknowledged": 0, "critical": 0, "warning": 0, "info": 0}
8888
+
8889
+
8890
+ def read_active_notifications(loki_dir: _Path) -> dict:
8891
+ """Read notifications/active.json, distinguishing "none yet" from "unreadable".
8892
+
8893
+ A missing active.json means there genuinely are no active notifications:
8894
+ the zero summary is real. A file that exists but fails to parse (torn
8895
+ write, corruption) means we do not know what is active -- summary must be
8896
+ None, not a fabricated all-zero summary that reads as "nothing active".
8897
+ """
8883
8898
  active_file = loki_dir / "notifications" / "active.json"
8884
8899
 
8885
8900
  if not active_file.exists():
8886
- return {
8887
- "notifications": [],
8888
- "summary": {"total": 0, "unacknowledged": 0, "critical": 0, "warning": 0, "info": 0},
8889
- }
8901
+ return {"notifications": [], "summary": dict(_EMPTY_NOTIFICATION_SUMMARY)}
8890
8902
 
8891
8903
  try:
8892
8904
  data = json.loads(active_file.read_text())
8893
8905
  except (json.JSONDecodeError, OSError):
8894
- return {
8895
- "notifications": [],
8896
- "summary": {"total": 0, "unacknowledged": 0, "critical": 0, "warning": 0, "info": 0},
8897
- }
8906
+ return {"notifications": None, "summary": None, "error": "unreadable_active_notifications"}
8898
8907
 
8899
- notifications = data.get("notifications", [])
8908
+ return {"notifications": data.get("notifications", []), "summary": data.get("summary", {})}
8909
+
8910
+
8911
+ @app.get("/api/notifications", dependencies=[Depends(auth.require_scope("read"))])
8912
+ async def get_notifications(
8913
+ severity: Optional[str] = Query(None, pattern="^(critical|warning|info)$"),
8914
+ unread_only: bool = Query(False),
8915
+ ):
8916
+ """Get notification list from .loki/notifications/active.json."""
8917
+ result = read_active_notifications(_get_loki_dir())
8918
+ notifications = result["notifications"]
8919
+
8920
+ if notifications is None:
8921
+ return result
8900
8922
 
8901
8923
  # Apply filters
8902
8924
  if severity:
@@ -8906,7 +8928,7 @@ async def get_notifications(
8906
8928
 
8907
8929
  return {
8908
8930
  "notifications": notifications,
8909
- "summary": data.get("summary", {}),
8931
+ "summary": result["summary"],
8910
8932
  }
8911
8933
 
8912
8934