loki-mode 9.55.0 → 9.56.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.
- package/.github/actions/issue-to-pr/action.yml +165 -29
- package/.github/workflows/loki-issue-to-pr.yml +137 -24
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/proof-check.sh +9 -0
- package/autonomy/lib/proof-generator.py +12 -3
- package/autonomy/lib/workspace_diff.py +18 -7
- package/autonomy/loki +133 -3
- package/autonomy/run.sh +363 -19
- package/dashboard/__init__.py +1 -1
- package/dashboard/api_keys.py +12 -5
- package/dashboard/build_supervisor.py +25 -1
- package/dashboard/server.py +46 -24
- package/dashboard/static/index.html +57 -57
- package/docs/VERIFIED-COMPLETION-PLAN.md +7 -5
- package/docs/environment-variables.md +1 -0
- package/docs/v10/BACKLOG.md +33 -0
- package/docs/v10/BOARD.md +67 -10
- package/docs/v10/DECISIONS.md +43 -0
- package/docs/v10/PROGRESS.md +731 -0
- package/loki-ts/dist/loki.js +326 -325
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/providers/claude.sh +1 -1
- package/providers/model_catalog.json +12 -5
- package/providers/models.sh +1 -1
- package/references/core-workflow.md +1 -1
- package/web-app/dist/assets/{AdminPage-CZrBkzRF.js → AdminPage-Oyx-w2Ch.js} +1 -1
- package/web-app/dist/assets/{Avatar-gQIp6FBI.js → Avatar-D60m65JB.js} +1 -1
- package/web-app/dist/assets/{Badge-D2_fBTFY.js → Badge-CqfZNaem.js} +1 -1
- package/web-app/dist/assets/{Button-D5qDd2ef.js → Button-BqjzE4fz.js} +1 -1
- package/web-app/dist/assets/CockpitPage-Czk7o_ou.js +47 -0
- package/web-app/dist/assets/ComparePage-BEfTrTb1.js +1 -0
- package/web-app/dist/assets/{ErrorBoundary-BRABI-BT.js → ErrorBoundary-BrLk5nkO.js} +1 -1
- package/web-app/dist/assets/EvidenceReceiptPanel-9vEpi5ir.js +1 -0
- package/web-app/dist/assets/{GitHubIssuesPanel-BC5GzKUN.js → GitHubIssuesPanel-D6izZx0w.js} +1 -1
- package/web-app/dist/assets/GitHubPRsPanel-BTkG2FgA.js +17 -0
- package/web-app/dist/assets/{HomePage-D_CDMoen.js → HomePage-nsr4kpN1.js} +2 -2
- package/web-app/dist/assets/{LoginPage-BBNA_N9t.js → LoginPage-BVblQrr9.js} +1 -1
- package/web-app/dist/assets/{MagicPage-CnFRZCMx.js → MagicPage-CmnSyLq7.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CPfLMRlh.js → MetricsPage-BVfwU81j.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-lA0XSGTz.js → NotFoundPage-AYQ6uqqI.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-CNAPbr9z.js → ProjectPage-DMnbw9X9.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-CMtm8goN.js → ProjectsPage-CNVTAF2N.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-BhIjVMYE.js → SettingsPage-D1_qasFD.js} +3 -3
- package/web-app/dist/assets/{ShowcasePage-BndtGeYo.js → ShowcasePage-2dBCjLXn.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-euXI-KXE.js → SystemSettingsPage-Djo6IE4u.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-ClUKecun.js → TeamsPage-CY8p-yxD.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-BWHWVk0L.js → TemplatesPage-B6iFgH6t.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-Cv3N3Szf.js → TerminalOutput-B3yzZe-h.js} +1 -1
- package/web-app/dist/assets/{activity-dEhz-bXR.js → activity-CNfAjtRv.js} +1 -1
- package/web-app/dist/assets/{bell-B3XUMq1t.js → bell-CMETsHPH.js} +1 -1
- package/web-app/dist/assets/{bot-X-ssNlwR.js → bot-C9kXvk1i.js} +1 -1
- package/web-app/dist/assets/{check-C_9Nx7kb.js → check-BRK-zLB5.js} +1 -1
- package/web-app/dist/assets/{chevron-left-tvNswo3A.js → chevron-left-CxI5uD4g.js} +1 -1
- package/web-app/dist/assets/{circle-alert-CSB88nEs.js → circle-alert-CVFRPWpv.js} +1 -1
- package/web-app/dist/assets/{clock-C8p2e4NI.js → clock-CLYV8a_x.js} +1 -1
- package/web-app/dist/assets/{cloud-CKp2ZvhG.js → cloud-CiISiIOa.js} +1 -1
- package/web-app/dist/assets/{code-xml-dY70LCHD.js → code-xml-DHsgqwV-.js} +1 -1
- package/web-app/dist/assets/{database-DObn5fmn.js → database-DbvUqtz3.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-DSu6n3K3.js → dollar-sign-Ct0lRPHw.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-DpCnS73z.js → file-code-corner-D1sjFEh7.js} +1 -1
- package/web-app/dist/assets/{file-plus-D3IPKCf1.js → file-plus-DnmX18Fi.js} +1 -1
- package/web-app/dist/assets/{globe-C9QXkgH_.js → globe-bSpDNgoA.js} +1 -1
- package/web-app/dist/assets/{hammer-D_FtWe1y.js → hammer-Bj41Kvlq.js} +1 -1
- package/web-app/dist/assets/{index-CI54rara.css → index-BfQ0f3-S.css} +1 -1
- package/web-app/dist/assets/{index-Cz7q1bvC.js → index-CxajNJVu.js} +3 -3
- package/web-app/dist/assets/{layers-DsW7jnJX.js → layers-BNtBwYER.js} +1 -1
- package/web-app/dist/assets/{loader-circle-B3HspjKR.js → loader-circle-YY_VZofG.js} +1 -1
- package/web-app/dist/assets/{lock-DSI29pct.js → lock-rpjEPVoC.js} +1 -1
- package/web-app/dist/assets/{package-CLNxtA2x.js → package-desXU6XA.js} +1 -1
- package/web-app/dist/assets/{plus-DyI4WC4_.js → plus-7AoOU-I9.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-D2dv0xA0.js → refresh-cw-oNj-Xn4B.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-CBvihA-a.js → rotate-ccw-DeiFjfVO.js} +1 -1
- package/web-app/dist/assets/{scroll-text-DvoOvAl_.js → scroll-text-Q9AzWiNV.js} +1 -1
- package/web-app/dist/assets/{server-DenWvSUt.js → server-DKgVwfek.js} +1 -1
- package/web-app/dist/assets/{shield-alert-40cX_FvG.js → shield-alert-G6x-bS-I.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-BrjZ6QuV.js → thumbs-up-Qhk0yvw0.js} +1 -1
- package/web-app/dist/assets/{trash-2-C6evwkEH.js → trash-2-D23gvznl.js} +1 -1
- package/web-app/dist/assets/{trending-down-CfbZis3O.js → trending-down-CSQClPrr.js} +1 -1
- package/web-app/dist/assets/{trending-up-DWuEK3WC.js → trending-up-sjMSd1wc.js} +1 -1
- package/web-app/dist/assets/{upload-B9DFBcPG.js → upload-Dchovhld.js} +1 -1
- package/web-app/dist/assets/{usePolling-BryVC-T1.js → usePolling-DwLceXwF.js} +1 -1
- package/web-app/dist/assets/{user-DMRXwZiw.js → user-BqZM8CmD.js} +1 -1
- package/web-app/dist/index.html +2 -2
- package/web-app/server.py +52 -17
- package/web-app/dist/assets/CockpitPage-DVMk2RUK.js +0 -47
- package/web-app/dist/assets/ComparePage-NMLyE1xL.js +0 -1
- package/web-app/dist/assets/EvidenceReceiptPanel-D2LNKqUx.js +0 -1
- package/web-app/dist/assets/GitHubPRsPanel-BSlmoVTS.js +0 -17
package/dashboard/server.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
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
|
|
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":
|
|
8931
|
+
"summary": result["summary"],
|
|
8910
8932
|
}
|
|
8911
8933
|
|
|
8912
8934
|
|