loki-mode 9.67.0 → 9.69.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 (72) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/dashboard/__init__.py +1 -1
  4. package/dashboard/migration_engine.py +38 -13
  5. package/dashboard/prompt_optimizer.py +19 -6
  6. package/dashboard/server.py +1 -1
  7. package/dashboard/static/index.html +66 -66
  8. package/dashboard/static/trust.html +21 -6
  9. package/docs/INSTALLATION.md +1 -1
  10. package/docs/v10/BOARD.md +30 -28
  11. package/docs/v10/PROGRESS.md +5 -0
  12. package/loki-ts/dist/loki.js +2 -2
  13. package/mcp/__init__.py +1 -1
  14. package/package.json +1 -1
  15. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  16. package/web-app/dist/assets/{AdminPage-ChUvLzkF.js → AdminPage-CPW7u9tJ.js} +1 -1
  17. package/web-app/dist/assets/{Avatar-Dpy96tAc.js → Avatar-BhRtaUAf.js} +1 -1
  18. package/web-app/dist/assets/{Badge-BOHHYZTu.js → Badge-s77pIGLL.js} +1 -1
  19. package/web-app/dist/assets/{Button-B_XqEF7a.js → Button-8cbxl-XL.js} +1 -1
  20. package/web-app/dist/assets/{CockpitPage-C0z5QwNJ.js → CockpitPage-ClXReCar.js} +1 -1
  21. package/web-app/dist/assets/{ComparePage-KWL6acQk.js → ComparePage-4YF0E8Y0.js} +1 -1
  22. package/web-app/dist/assets/{ErrorBoundary-BbyBJ4ZP.js → ErrorBoundary-Ddl2zJ-Q.js} +1 -1
  23. package/web-app/dist/assets/{EvidenceReceiptPanel-Btblkwfr.js → EvidenceReceiptPanel-DQz-lFwc.js} +1 -1
  24. package/web-app/dist/assets/{GitHubIssuesPanel-7Bi1t04Q.js → GitHubIssuesPanel-Dixk_nbH.js} +1 -1
  25. package/web-app/dist/assets/{GitHubPRsPanel-BxZtNprq.js → GitHubPRsPanel-D-mWUpjU.js} +1 -1
  26. package/web-app/dist/assets/{HomePage-BxDh3-CD.js → HomePage-BIP-AOaV.js} +2 -2
  27. package/web-app/dist/assets/{LoginPage-DpXq4rQe.js → LoginPage-CGXcRM1H.js} +1 -1
  28. package/web-app/dist/assets/{MagicPage-DP2k0ioE.js → MagicPage-w-7wL0Yx.js} +1 -1
  29. package/web-app/dist/assets/{MetricsPage-Dus04BUR.js → MetricsPage-jK92Q32u.js} +1 -1
  30. package/web-app/dist/assets/{NotFoundPage--54yr9Cy.js → NotFoundPage-ZJwD0l5Y.js} +1 -1
  31. package/web-app/dist/assets/{ProjectPage-Cs6LOI7R.js → ProjectPage-DPyO5DCA.js} +3 -3
  32. package/web-app/dist/assets/{ProjectsPage-5cpa0X1d.js → ProjectsPage-DPa_pwYV.js} +1 -1
  33. package/web-app/dist/assets/{SettingsPage-Duc5ApRj.js → SettingsPage-C2JFhnZx.js} +1 -1
  34. package/web-app/dist/assets/{ShowcasePage-C1wrPZgl.js → ShowcasePage-Dj5ZHpkm.js} +1 -1
  35. package/web-app/dist/assets/{SystemSettingsPage-CoD3LARj.js → SystemSettingsPage-y6nAFJoW.js} +1 -1
  36. package/web-app/dist/assets/{TeamsPage-GuQ4YDV5.js → TeamsPage-BOdmj8Ci.js} +1 -1
  37. package/web-app/dist/assets/{TemplatesPage-CvWecmzl.js → TemplatesPage-CPBTyO3Z.js} +1 -1
  38. package/web-app/dist/assets/{TerminalOutput-DFZw34kD.js → TerminalOutput-5w6qt3am.js} +1 -1
  39. package/web-app/dist/assets/{activity-BvHkXBYj.js → activity-WHG7RxVL.js} +1 -1
  40. package/web-app/dist/assets/{bell-Bw2j-HI7.js → bell-mrKJNTMd.js} +1 -1
  41. package/web-app/dist/assets/{bot-BRuEmshQ.js → bot-BO_6hrmU.js} +1 -1
  42. package/web-app/dist/assets/{check-B5uToWdF.js → check-BPynHeeg.js} +1 -1
  43. package/web-app/dist/assets/{chevron-left-D-tXeEPI.js → chevron-left-Dfy86g55.js} +1 -1
  44. package/web-app/dist/assets/{circle-alert-p3-Bg3sx.js → circle-alert-j0J21snc.js} +1 -1
  45. package/web-app/dist/assets/{clock-CJc_91vp.js → clock-B6g4PLdQ.js} +1 -1
  46. package/web-app/dist/assets/{cloud-lhmojUN8.js → cloud-CNniMSkg.js} +1 -1
  47. package/web-app/dist/assets/{code-xml-DMvQ2jw1.js → code-xml-DfbVZ8e6.js} +1 -1
  48. package/web-app/dist/assets/{database-EdwkplCN.js → database-D-3X-HfV.js} +1 -1
  49. package/web-app/dist/assets/{dollar-sign-BQiPo9Co.js → dollar-sign-61G2HLQb.js} +1 -1
  50. package/web-app/dist/assets/{file-code-corner-CXUzs2z1.js → file-code-corner-SX2tNRWt.js} +1 -1
  51. package/web-app/dist/assets/{file-plus-hS0xkTL5.js → file-plus-uBkhrSTF.js} +1 -1
  52. package/web-app/dist/assets/{globe-B6Xk69Fj.js → globe-Boxp5WvY.js} +1 -1
  53. package/web-app/dist/assets/{hammer-B_evoVEr.js → hammer-CH2dHEVO.js} +1 -1
  54. package/web-app/dist/assets/{index-XZrgDphJ.js → index-QkrBk17c.js} +2 -2
  55. package/web-app/dist/assets/{layers-Bb295b4u.js → layers-CNEFtp9e.js} +1 -1
  56. package/web-app/dist/assets/{loader-circle-C8cKZhjP.js → loader-circle-Bqrcv5u2.js} +1 -1
  57. package/web-app/dist/assets/{lock-DcC9B8sE.js → lock-B3JEFmN7.js} +1 -1
  58. package/web-app/dist/assets/{package-BFz4FYcR.js → package-CKGU_qVz.js} +1 -1
  59. package/web-app/dist/assets/{plus-aS4YpFPG.js → plus-C5JdVMit.js} +1 -1
  60. package/web-app/dist/assets/{refresh-cw-B9_ksndc.js → refresh-cw--TAFe9rs.js} +1 -1
  61. package/web-app/dist/assets/{rotate-ccw-CBogZEoT.js → rotate-ccw-Ctp9TQHw.js} +1 -1
  62. package/web-app/dist/assets/{scroll-text-DMGgO6uq.js → scroll-text-PBn0162f.js} +1 -1
  63. package/web-app/dist/assets/{server-CsEqUM8R.js → server-IDnQPQXH.js} +1 -1
  64. package/web-app/dist/assets/{shield-alert-Btnj6tmQ.js → shield-alert-TIxCJQgv.js} +1 -1
  65. package/web-app/dist/assets/{thumbs-up-C_NLSPqa.js → thumbs-up-Cln0A7Qt.js} +1 -1
  66. package/web-app/dist/assets/{trash-2-zqZc9cSK.js → trash-2-CgamkKFR.js} +1 -1
  67. package/web-app/dist/assets/{trending-down-BGQh2rVE.js → trending-down-BPzQ_tCr.js} +1 -1
  68. package/web-app/dist/assets/{trending-up-C31TrzUt.js → trending-up-Biap94MX.js} +1 -1
  69. package/web-app/dist/assets/{upload-CLwWKjCG.js → upload-D1ER7BVL.js} +1 -1
  70. package/web-app/dist/assets/{usePolling-8wwOP53Y.js → usePolling-Cj1AXL0Z.js} +1 -1
  71. package/web-app/dist/assets/{user-DUkbxibF.js → user-ytdejGkb.js} +1 -1
  72. package/web-app/dist/index.html +1 -1
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v9.67.0
6
+ # Loki Mode v9.69.0
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -470,4 +470,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
470
470
 
471
471
  ---
472
472
 
473
- **v9.67.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
473
+ **v9.69.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 9.67.0
1
+ 9.69.0
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "9.67.0"
10
+ __version__ = "9.69.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -766,19 +766,29 @@ class MigrationPipeline:
766
766
  current_phase = phase
767
767
  overall_status = "failed"
768
768
 
769
- # Feature stats
770
- features_total = 0
771
- features_passing = 0
769
+ # Feature stats. Missing/corrupt is NOT the same as a real empty
770
+ # plan (0 features): counts go to None with a reason so a consumer
771
+ # can tell "no features yet" apart from "could not read the file".
772
+ features_total: Optional[int] = 0
773
+ features_passing: Optional[int] = 0
774
+ features_error: Optional[str] = None
772
775
  try:
773
776
  features = self.load_features()
774
777
  features_total = len(features)
775
778
  features_passing = sum(1 for f in features if f.passes)
776
- except (FileNotFoundError, json.JSONDecodeError, TypeError):
777
- pass
778
-
779
- # Step stats
780
- steps_total = 0
781
- steps_completed = 0
779
+ except FileNotFoundError:
780
+ features_total = None
781
+ features_passing = None
782
+ features_error = "features.json not found"
783
+ except (json.JSONDecodeError, TypeError) as exc:
784
+ features_total = None
785
+ features_passing = None
786
+ features_error = f"features.json is corrupt: {exc}"
787
+
788
+ # Step stats. Same missing/corrupt-vs-empty distinction as features.
789
+ steps_total: Optional[int] = 0
790
+ steps_completed: Optional[int] = 0
791
+ steps_error: Optional[str] = None
782
792
  current_step = None
783
793
  current_step_index = 0
784
794
  try:
@@ -790,8 +800,14 @@ class MigrationPipeline:
790
800
  current_step = in_progress[0].id
791
801
  # Current step index: completed + 1 (1-based) or completed if all done
792
802
  current_step_index = min(steps_completed + 1, steps_total) if steps_total else 0
793
- except (FileNotFoundError, json.JSONDecodeError, TypeError):
794
- pass
803
+ except FileNotFoundError:
804
+ steps_total = None
805
+ steps_completed = None
806
+ steps_error = "migration-plan.json not found"
807
+ except (json.JSONDecodeError, TypeError) as exc:
808
+ steps_total = None
809
+ steps_completed = None
810
+ steps_error = f"migration-plan.json is corrupt: {exc}"
795
811
 
796
812
  # Last checkpoint metadata
797
813
  last_checkpoint_data: Optional[dict[str, Any]] = None
@@ -849,8 +865,17 @@ class MigrationPipeline:
849
865
  "source": source_path,
850
866
  "target": target_name,
851
867
  "current_step": current_step,
852
- "features": {"passing": features_passing, "total": features_total},
853
- "steps": {"current": current_step_index, "completed": steps_completed, "total": steps_total},
868
+ "features": {
869
+ "passing": features_passing,
870
+ "total": features_total,
871
+ **({"reason": features_error} if features_error else {}),
872
+ },
873
+ "steps": {
874
+ "current": current_step_index,
875
+ "completed": steps_completed,
876
+ "total": steps_total,
877
+ **({"reason": steps_error} if steps_error else {}),
878
+ },
854
879
  "last_checkpoint": last_checkpoint_data,
855
880
  "checkpoints_count": len(manifest.checkpoints),
856
881
  "seams": seams_data,
@@ -66,7 +66,11 @@ class PromptOptimizer:
66
66
  """Get the current (latest) prompt optimization version.
67
67
 
68
68
  Returns:
69
- The latest version data, or a default structure if none exists.
69
+ The latest version data on a clean read. If no version file
70
+ exists yet, a "never_ran" marker with null fields (distinct
71
+ from a real version 0). If the file exists but cannot be
72
+ parsed, an "error" marker (also null fields) so a corrupt file
73
+ is never mistaken for "never ran".
70
74
  """
71
75
  latest = self._latest_file()
72
76
  if latest.is_file():
@@ -74,13 +78,20 @@ class PromptOptimizer:
74
78
  return json.loads(latest.read_text(encoding="utf-8"))
75
79
  except (json.JSONDecodeError, OSError) as exc:
76
80
  logger.warning("Failed to read latest prompt version: %s", exc)
81
+ return self._sentinel("error")
77
82
 
83
+ return self._sentinel("never_ran")
84
+
85
+ @staticmethod
86
+ def _sentinel(status: str) -> dict[str, Any]:
87
+ """Build a never-ran/error marker. Never a fake version 0 or a fake count."""
78
88
  return {
79
- "version": 0,
89
+ "version": None,
80
90
  "generated_at": None,
81
- "based_on_sessions": 0,
82
- "failures_analyzed": 0,
91
+ "based_on_sessions": None,
92
+ "failures_analyzed": None,
83
93
  "changes": [],
94
+ "status": status,
84
95
  }
85
96
 
86
97
  def get_prompt_for_agent(self, agent_type: str) -> dict[str, Any] | None:
@@ -95,7 +106,7 @@ class PromptOptimizer:
95
106
  Dict with agent-specific prompt changes, or None if no optimizations exist.
96
107
  """
97
108
  current = self.get_current_version()
98
- if current["version"] == 0:
109
+ if not current["version"]:
99
110
  return None
100
111
 
101
112
  agent_changes = [c for c in current.get("changes", []) if c.get("agent_type") == agent_type]
@@ -225,7 +236,9 @@ class PromptOptimizer:
225
236
  changes = self._generate_changes(failure_data)
226
237
 
227
238
  with self._file_lock:
228
- current_version = self.get_current_version()["version"]
239
+ # Never-ran and error sentinels both carry version None; either
240
+ # way there is no real prior version, so the next one is 1.
241
+ current_version = self.get_current_version()["version"] or 0
229
242
  new_version = current_version + 1
230
243
 
231
244
  result = {
@@ -10350,7 +10350,7 @@ async def get_checklist_waivers():
10350
10350
  try:
10351
10351
  return json.loads(waivers_file.read_text())
10352
10352
  except (json.JSONDecodeError, IOError):
10353
- return {"waivers": [], "error": "Failed to read waivers file"}
10353
+ return JSONResponse(status_code=500, content={"error": "Failed to read waivers file"})
10354
10354
 
10355
10355
 
10356
10356
  @app.post("/api/checklist/waivers", dependencies=[Depends(auth.require_scope("control"))])