loki-mode 11.5.1 → 11.7.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 (116) hide show
  1. package/README.md +19 -2
  2. package/SKILL.md +2 -2
  3. package/VERSION +1 -1
  4. package/autonomy/lib/backlog.py +11 -2
  5. package/autonomy/lib/chat.sh +57 -1
  6. package/autonomy/lib/loki_yaml.py +8 -2
  7. package/autonomy/lib/workspace.py +267 -11
  8. package/autonomy/loki +327 -222
  9. package/autonomy/notification-checker.py +1 -1
  10. package/autonomy/trigger-server.py +185 -2
  11. package/autonomy/verify.sh +4 -0
  12. package/completions/_loki +4 -0
  13. package/completions/loki.bash +20 -2
  14. package/dashboard/__init__.py +3 -10
  15. package/dashboard/control.py +5 -435
  16. package/docs/ARCHITECTURE.md +1 -2
  17. package/docs/CLI-CORE-VERBS.md +2 -6
  18. package/docs/CLI-REFERENCE.md +2 -1
  19. package/docs/COMPONENTS.md +0 -2
  20. package/docs/DEPLOY-PLAN.md +17 -8
  21. package/docs/EVALUATING.md +8 -0
  22. package/docs/INSTALLATION.md +1 -1
  23. package/docs/WORKSPACES.md +15 -2
  24. package/docs/authentication.md +19 -1
  25. package/docs/dev/architecture-reference.md +8 -0
  26. package/docs/dev/release-checklist.md +9 -8
  27. package/docs/enterprise/security.md +3 -234
  28. package/docs/sentry-intake.md +11 -0
  29. package/docs/v10/ARCHITECT-CUTS.md +304 -0
  30. package/docs/v10/CLI-MODERN.md +1 -1
  31. package/docs/v10/DECISIONS.md +5 -5
  32. package/docs/v10/ENGINE.md +735 -299
  33. package/docs/v10/GUARDS.md +16 -14
  34. package/docs/v10/GUIDE.md +5 -7
  35. package/docs/v10/PROGRESS.md +12 -1
  36. package/docs/v11/MARKET-SLICES.md +1 -5
  37. package/integrations/openclaw/README.md +20 -0
  38. package/integrations/vibe-kanban.md +12 -50
  39. package/loki-ts/dist/loki.js +1213 -1178
  40. package/mcp/__init__.py +1 -1
  41. package/mcp/_sdk_loader.py +1 -1
  42. package/package.json +2 -2
  43. package/packages/control-plane/dist/server.js +1090 -924
  44. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  45. package/references/quality-control.md +1 -116
  46. package/schemas/loki-yaml.schema.json +5 -2
  47. package/skills/00-index.md +2 -2
  48. package/skills/artifacts.md +0 -22
  49. package/skills/production.md +2 -38
  50. package/src/policies/engine.js +41 -2
  51. package/src/policies/types.js +49 -0
  52. package/web-app/dist/assets/{AdminPage-Cbu3pXL8.js → AdminPage-S3BYeapm.js} +1 -1
  53. package/web-app/dist/assets/{Avatar-DGqGGcGx.js → Avatar-C1rHwLgn.js} +1 -1
  54. package/web-app/dist/assets/{Badge-Bhlipt6v.js → Badge-CzlnN5aQ.js} +1 -1
  55. package/web-app/dist/assets/{Button-CpN2sO61.js → Button-B1w5AeGC.js} +1 -1
  56. package/web-app/dist/assets/{CockpitPage-BqeDJwdL.js → CockpitPage-Dyeqjfkc.js} +1 -1
  57. package/web-app/dist/assets/{ComparePage-DUieA2ba.js → ComparePage-C6y2GkGR.js} +1 -1
  58. package/web-app/dist/assets/{ErrorBoundary-DTWsYrOm.js → ErrorBoundary-Dg2fcGkR.js} +1 -1
  59. package/web-app/dist/assets/{EvidenceReceiptPanel-BU_B9X19.js → EvidenceReceiptPanel-CxbyjvTj.js} +1 -1
  60. package/web-app/dist/assets/{GitHubIssuesPanel-DEZoLOsP.js → GitHubIssuesPanel-Dpys1xDb.js} +1 -1
  61. package/web-app/dist/assets/{GitHubPRsPanel-BEsnrq7Y.js → GitHubPRsPanel-CRVjWoFl.js} +1 -1
  62. package/web-app/dist/assets/{HomePage-BoUVuq7h.js → HomePage-BKnv-oYw.js} +2 -2
  63. package/web-app/dist/assets/{LoginPage-CmOED7vb.js → LoginPage-BGksmFRd.js} +1 -1
  64. package/web-app/dist/assets/{MagicPage-DATZitrZ.js → MagicPage-OCvhp16M.js} +1 -1
  65. package/web-app/dist/assets/{MetricsPage-DGL1v0I-.js → MetricsPage-CJOJpXWC.js} +1 -1
  66. package/web-app/dist/assets/{NotFoundPage-C2WgOjZd.js → NotFoundPage-C04p3QvN.js} +1 -1
  67. package/web-app/dist/assets/{ProjectPage-BMi1tepj.js → ProjectPage-BRB8txsY.js} +3 -3
  68. package/web-app/dist/assets/{ProjectsPage-vc3y5YPh.js → ProjectsPage-CoUYeQEh.js} +1 -1
  69. package/web-app/dist/assets/{SettingsPage-kbq0Ftvi.js → SettingsPage-BkjmJGfM.js} +1 -1
  70. package/web-app/dist/assets/{ShowcasePage-Bn6Q8Kbg.js → ShowcasePage-B4vU9TjQ.js} +1 -1
  71. package/web-app/dist/assets/{SystemSettingsPage-Basmhs_b.js → SystemSettingsPage-Z2jiVsni.js} +1 -1
  72. package/web-app/dist/assets/{TeamsPage-BTqOc4TR.js → TeamsPage-Ulm8SISq.js} +1 -1
  73. package/web-app/dist/assets/{TemplatesPage-2P9002VL.js → TemplatesPage-C_7MM6Ey.js} +1 -1
  74. package/web-app/dist/assets/{TerminalOutput-CAoSPBrg.js → TerminalOutput-Cumd7Tgs.js} +1 -1
  75. package/web-app/dist/assets/{activity-BcWVWCqU.js → activity-CZAUkbiY.js} +1 -1
  76. package/web-app/dist/assets/{bell-CYRqqgZ6.js → bell-BOvSXpEr.js} +1 -1
  77. package/web-app/dist/assets/{bot-CU7gdn3g.js → bot-DOTZxBYj.js} +1 -1
  78. package/web-app/dist/assets/{check-DLlCpz9V.js → check-BxpE0B5u.js} +1 -1
  79. package/web-app/dist/assets/{chevron-left-CE9Cb30C.js → chevron-left-D6KPvBOA.js} +1 -1
  80. package/web-app/dist/assets/{circle-alert-uou4bjua.js → circle-alert-Bajq86oe.js} +1 -1
  81. package/web-app/dist/assets/{clock-C_dSJcDX.js → clock-CnlHAVJc.js} +1 -1
  82. package/web-app/dist/assets/{cloud-DZ22ITF6.js → cloud-DjaymjwM.js} +1 -1
  83. package/web-app/dist/assets/{code-xml-BrJS0hhS.js → code-xml-BADEw2Ld.js} +1 -1
  84. package/web-app/dist/assets/{database-D2HOmxtl.js → database-B4aKb5Cq.js} +1 -1
  85. package/web-app/dist/assets/{dollar-sign-CQ1vK_6q.js → dollar-sign-DrldXpja.js} +1 -1
  86. package/web-app/dist/assets/{file-code-corner-w2vpGm5d.js → file-code-corner-DVebDVR-.js} +1 -1
  87. package/web-app/dist/assets/{file-plus-DlF6wjkD.js → file-plus-BD-N_-Tl.js} +1 -1
  88. package/web-app/dist/assets/{globe-Dy3lBJg1.js → globe-C7ieInC-.js} +1 -1
  89. package/web-app/dist/assets/{hammer-C3xIiRXN.js → hammer-BSugKIji.js} +1 -1
  90. package/web-app/dist/assets/{index-4t-_IW2y.js → index-nLQgfvOn.js} +3 -3
  91. package/web-app/dist/assets/{layers-Y8Fs8qXI.js → layers-CHXxU2on.js} +1 -1
  92. package/web-app/dist/assets/{loader-circle-CxgN1v4m.js → loader-circle-BEEz0LbD.js} +1 -1
  93. package/web-app/dist/assets/{lock-DFFNbXDs.js → lock-CzQGfcnE.js} +1 -1
  94. package/web-app/dist/assets/{package-5e6qCTUg.js → package-CcHYQLGd.js} +1 -1
  95. package/web-app/dist/assets/{plus-C0Go_ytj.js → plus-DdzgFEXn.js} +1 -1
  96. package/web-app/dist/assets/{refresh-cw-D4i-NW3o.js → refresh-cw-7x0HbH9Y.js} +1 -1
  97. package/web-app/dist/assets/{rotate-ccw-YlKkiUW6.js → rotate-ccw-DBahX1Sp.js} +1 -1
  98. package/web-app/dist/assets/{scroll-text-4qXOHTap.js → scroll-text-BB8y8a9Z.js} +1 -1
  99. package/web-app/dist/assets/{server-BB6zXNp9.js → server-CfkbW2MH.js} +1 -1
  100. package/web-app/dist/assets/{shield-alert-D4tzjB1H.js → shield-alert-DUgD8rBF.js} +1 -1
  101. package/web-app/dist/assets/{thumbs-up-DZiRwdFj.js → thumbs-up-DGoyY6QC.js} +1 -1
  102. package/web-app/dist/assets/{trash-2-Dv_LkRIK.js → trash-2-B6xrSUMr.js} +1 -1
  103. package/web-app/dist/assets/{trending-down-BJYp9PQe.js → trending-down-B6RGKTOx.js} +1 -1
  104. package/web-app/dist/assets/{trending-up-BTcXLklK.js → trending-up-B44DCrt1.js} +1 -1
  105. package/web-app/dist/assets/{upload-fcHqwOxr.js → upload-4kWm33ZY.js} +1 -1
  106. package/web-app/dist/assets/{usePolling-BeJYw_4L.js → usePolling-zkUtRQG6.js} +1 -1
  107. package/web-app/dist/assets/{user-BcDwUCsO.js → user-04cEVIe2.js} +1 -1
  108. package/web-app/dist/index.html +1 -1
  109. package/dashboard/run.py +0 -63
  110. package/docs/openclaw-integration.md +0 -52
  111. package/docs/v10/HANDOFF-NEXT-WEEK.md +0 -40
  112. package/docs/v10/MORNING-BRIEF-1003.md +0 -25
  113. package/docs/v10/MORNING-BRIEF.md +0 -52
  114. package/docs/v10/TODO.md +0 -35
  115. package/mcp/resources.py +0 -351
  116. package/mcp/tools.py +0 -200
package/mcp/tools.py DELETED
@@ -1,200 +0,0 @@
1
- """
2
- Loki Mode MCP Tools
3
-
4
- Additional tool definitions that can be imported into the server.
5
- These are helper functions and utilities for the MCP tools.
6
- Uses StateManager for centralized state access with caching.
7
- """
8
-
9
- import os
10
- import sys
11
- import json
12
- from datetime import datetime, timezone
13
- from typing import Dict, Any, List, Optional
14
-
15
- # Add parent directory to path for state manager import
16
- sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
17
-
18
- # Import StateManager for centralized state access
19
- try:
20
- from state.manager import StateManager, ManagedFile, get_state_manager
21
- HAS_STATE_MANAGER = True
22
- except ImportError:
23
- HAS_STATE_MANAGER = False
24
- StateManager = None
25
- ManagedFile = None
26
- get_state_manager = None
27
-
28
-
29
- def get_loki_base_path() -> str:
30
- """Get the base .loki directory path."""
31
- return os.path.join(os.getcwd(), '.loki')
32
-
33
-
34
- # Module-level StateManager instance
35
- _state_manager = None
36
-
37
-
38
- def _get_state_manager() -> Optional['StateManager']:
39
- """Get or create the StateManager instance."""
40
- global _state_manager
41
- if not HAS_STATE_MANAGER:
42
- return None
43
- if _state_manager is None:
44
- _state_manager = get_state_manager(
45
- loki_dir=get_loki_base_path(),
46
- enable_watch=False,
47
- enable_events=False
48
- )
49
- return _state_manager
50
-
51
-
52
- def ensure_loki_initialized() -> bool:
53
- """Check if Loki Mode is initialized in current directory."""
54
- return os.path.exists(get_loki_base_path())
55
-
56
-
57
- def get_task_queue_path() -> str:
58
- """Get path to the task queue file."""
59
- return os.path.join(get_loki_base_path(), 'state', 'task-queue.json')
60
-
61
-
62
- def get_memory_path() -> str:
63
- """Get path to the memory directory."""
64
- return os.path.join(get_loki_base_path(), 'memory')
65
-
66
-
67
- def load_task_queue() -> Dict[str, Any]:
68
- """Load the task queue from disk using StateManager."""
69
- manager = _get_state_manager()
70
- if manager:
71
- result = manager.get_state("state/task-queue.json")
72
- if result:
73
- return result
74
- # Fallback to direct file read if StateManager not available
75
- queue_path = get_task_queue_path()
76
- if os.path.exists(queue_path):
77
- with open(queue_path, 'r') as f:
78
- return json.load(f)
79
- return {"tasks": [], "version": "1.0"}
80
-
81
-
82
- def save_task_queue(queue: Dict[str, Any]) -> None:
83
- """Save the task queue to disk using StateManager."""
84
- manager = _get_state_manager()
85
- if manager:
86
- manager.set_state("state/task-queue.json", queue, source="mcp-tools")
87
- return
88
- # Fallback to direct file write if StateManager not available
89
- queue_path = get_task_queue_path()
90
- os.makedirs(os.path.dirname(queue_path), exist_ok=True)
91
- with open(queue_path, 'w') as f:
92
- json.dump(queue, f, indent=2)
93
-
94
-
95
- def create_task(
96
- title: str,
97
- description: str,
98
- priority: str = "medium",
99
- phase: str = "development"
100
- ) -> Dict[str, Any]:
101
- """Create a new task dictionary."""
102
- queue = load_task_queue()
103
- next_id = queue.get("_next_id", len(queue['tasks']) + 1)
104
- task_id = f"task-{next_id:04d}"
105
- queue["_next_id"] = next_id + 1
106
-
107
- task = {
108
- "id": task_id,
109
- "title": title,
110
- "description": description,
111
- "priority": priority,
112
- "phase": phase,
113
- "status": "pending",
114
- "created_at": datetime.now(timezone.utc).isoformat()
115
- }
116
-
117
- # Persist _next_id so it survives across calls
118
- save_task_queue(queue)
119
-
120
- return task
121
-
122
-
123
- def filter_tasks_by_status(tasks: List[Dict], status: str) -> List[Dict]:
124
- """Filter tasks by their status."""
125
- return [t for t in tasks if t.get("status") == status]
126
-
127
-
128
- def filter_tasks_by_priority(tasks: List[Dict], priority: str) -> List[Dict]:
129
- """Filter tasks by their priority."""
130
- return [t for t in tasks if t.get("priority") == priority]
131
-
132
-
133
- def filter_tasks_by_phase(tasks: List[Dict], phase: str) -> List[Dict]:
134
- """Filter tasks by their SDLC phase."""
135
- return [t for t in tasks if t.get("phase") == phase]
136
-
137
-
138
- def get_task_summary(queue: Dict[str, Any]) -> Dict[str, Any]:
139
- """Get a summary of the task queue."""
140
- tasks = queue.get("tasks", [])
141
-
142
- return {
143
- "total": len(tasks),
144
- "by_status": {
145
- "pending": len(filter_tasks_by_status(tasks, "pending")),
146
- "in_progress": len(filter_tasks_by_status(tasks, "in_progress")),
147
- "completed": len(filter_tasks_by_status(tasks, "completed")),
148
- "blocked": len(filter_tasks_by_status(tasks, "blocked"))
149
- },
150
- "by_priority": {
151
- "critical": len(filter_tasks_by_priority(tasks, "critical")),
152
- "high": len(filter_tasks_by_priority(tasks, "high")),
153
- "medium": len(filter_tasks_by_priority(tasks, "medium")),
154
- "low": len(filter_tasks_by_priority(tasks, "low"))
155
- },
156
- "by_phase": {
157
- "discovery": len(filter_tasks_by_phase(tasks, "discovery")),
158
- "architecture": len(filter_tasks_by_phase(tasks, "architecture")),
159
- "development": len(filter_tasks_by_phase(tasks, "development")),
160
- "testing": len(filter_tasks_by_phase(tasks, "testing")),
161
- "deployment": len(filter_tasks_by_phase(tasks, "deployment"))
162
- }
163
- }
164
-
165
-
166
- def format_task_for_display(task: Dict[str, Any]) -> str:
167
- """Format a task for human-readable display."""
168
- lines = [
169
- f"Task: {task.get('id', 'unknown')}",
170
- f"Title: {task.get('title', 'Untitled')}",
171
- f"Status: {task.get('status', 'unknown')}",
172
- f"Priority: {task.get('priority', 'medium')}",
173
- f"Phase: {task.get('phase', 'development')}",
174
- f"Description: {task.get('description', 'No description')}",
175
- ]
176
-
177
- if task.get('created_at'):
178
- lines.append(f"Created: {task['created_at']}")
179
- if task.get('updated_at'):
180
- lines.append(f"Updated: {task['updated_at']}")
181
-
182
- return "\n".join(lines)
183
-
184
-
185
- def validate_task_status(status: str) -> bool:
186
- """Validate a task status value."""
187
- valid_statuses = ["pending", "in_progress", "completed", "blocked"]
188
- return status in valid_statuses
189
-
190
-
191
- def validate_task_priority(priority: str) -> bool:
192
- """Validate a task priority value."""
193
- valid_priorities = ["low", "medium", "high", "critical"]
194
- return priority in valid_priorities
195
-
196
-
197
- def validate_task_phase(phase: str) -> bool:
198
- """Validate a task SDLC phase value."""
199
- valid_phases = ["discovery", "architecture", "development", "testing", "deployment"]
200
- return phase in valid_phases