loki-mode 11.7.1 → 11.9.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 (92) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/backlog.py +40 -4
  4. package/autonomy/lib/chat.sh +3 -2
  5. package/autonomy/lib/workspace.py +95 -4
  6. package/autonomy/loki +185 -106
  7. package/autonomy/trigger-server.py +550 -5
  8. package/autonomy/verify.sh +5 -0
  9. package/bin/loki +1 -1
  10. package/completions/_loki +34 -1
  11. package/completions/loki.bash +10 -3
  12. package/dashboard/__init__.py +1 -1
  13. package/docs/ARCHITECTURE.md +0 -1
  14. package/docs/CLI-REFERENCE.md +1 -1
  15. package/docs/COMPONENTS.md +1 -1
  16. package/docs/DEPLOY-PLAN.md +13 -3
  17. package/docs/INSTALLATION.md +1 -1
  18. package/docs/WORKSPACES.md +1 -1
  19. package/docs/dev/architecture-reference.md +1 -1
  20. package/docs/sentry-intake.md +36 -0
  21. package/docs/v10/D61-SPEED.md +14 -0
  22. package/docs/v10/PROGRESS.md +22 -0
  23. package/loki-ts/dist/loki.js +962 -879
  24. package/mcp/__init__.py +1 -1
  25. package/package.json +2 -2
  26. package/packages/control-plane/dist/ask-tools-server.js +13 -4
  27. package/packages/control-plane/dist/server.js +614 -456
  28. package/packages/control-plane/src/server/diffstat.ts +10 -2
  29. package/packages/control-plane/src/server/legacy/routes-control.ts +8 -4
  30. package/packages/control-plane/src/server/routes/checkpoints.ts +11 -2
  31. package/packages/control-plane/ui/dist/assets/index-u8cd6TRQ.js +190 -0
  32. package/packages/control-plane/ui/dist/index.html +1 -1
  33. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  34. package/web-app/dist/assets/{AdminPage-S3BYeapm.js → AdminPage-BdH9iL2I.js} +1 -1
  35. package/web-app/dist/assets/{Avatar-C1rHwLgn.js → Avatar-C-WixxR6.js} +1 -1
  36. package/web-app/dist/assets/{Badge-CzlnN5aQ.js → Badge-BFWpRd_L.js} +1 -1
  37. package/web-app/dist/assets/{Button-B1w5AeGC.js → Button-CE5vG66Y.js} +1 -1
  38. package/web-app/dist/assets/{CockpitPage-Dyeqjfkc.js → CockpitPage-BAVn10bY.js} +1 -1
  39. package/web-app/dist/assets/{ComparePage-C6y2GkGR.js → ComparePage-DOecIGfM.js} +1 -1
  40. package/web-app/dist/assets/{ErrorBoundary-Dg2fcGkR.js → ErrorBoundary-1rNA5v7f.js} +1 -1
  41. package/web-app/dist/assets/{EvidenceReceiptPanel-CxbyjvTj.js → EvidenceReceiptPanel-DjOaWfdH.js} +1 -1
  42. package/web-app/dist/assets/{GitHubIssuesPanel-Dpys1xDb.js → GitHubIssuesPanel-NNPBuRPD.js} +1 -1
  43. package/web-app/dist/assets/{GitHubPRsPanel-CRVjWoFl.js → GitHubPRsPanel-CL1b--tV.js} +1 -1
  44. package/web-app/dist/assets/{HomePage-BKnv-oYw.js → HomePage-BsLDN6MW.js} +2 -2
  45. package/web-app/dist/assets/{LoginPage-BGksmFRd.js → LoginPage-CVIv5bCS.js} +1 -1
  46. package/web-app/dist/assets/{MagicPage-OCvhp16M.js → MagicPage-BgMBB9lK.js} +1 -1
  47. package/web-app/dist/assets/{MetricsPage-CJOJpXWC.js → MetricsPage-BHeJlqPC.js} +1 -1
  48. package/web-app/dist/assets/{NotFoundPage-C04p3QvN.js → NotFoundPage-DDzwfyDK.js} +1 -1
  49. package/web-app/dist/assets/{ProjectPage-BRB8txsY.js → ProjectPage-CuQWEYBF.js} +3 -3
  50. package/web-app/dist/assets/{ProjectsPage-CoUYeQEh.js → ProjectsPage-OoD0RFDZ.js} +1 -1
  51. package/web-app/dist/assets/{SettingsPage-BkjmJGfM.js → SettingsPage-tMFMKkK5.js} +1 -1
  52. package/web-app/dist/assets/{ShowcasePage-B4vU9TjQ.js → ShowcasePage-DVfLoWdz.js} +1 -1
  53. package/web-app/dist/assets/{SystemSettingsPage-Z2jiVsni.js → SystemSettingsPage-CThV9N4l.js} +1 -1
  54. package/web-app/dist/assets/{TeamsPage-Ulm8SISq.js → TeamsPage-CV0nvXI8.js} +1 -1
  55. package/web-app/dist/assets/{TemplatesPage-C_7MM6Ey.js → TemplatesPage-D81EI1L8.js} +1 -1
  56. package/web-app/dist/assets/{TerminalOutput-Cumd7Tgs.js → TerminalOutput-Bj7uKRIe.js} +1 -1
  57. package/web-app/dist/assets/{activity-CZAUkbiY.js → activity-DoNfNkOL.js} +1 -1
  58. package/web-app/dist/assets/{bell-BOvSXpEr.js → bell-BWO3OU50.js} +1 -1
  59. package/web-app/dist/assets/{bot-DOTZxBYj.js → bot-DcvWv_zD.js} +1 -1
  60. package/web-app/dist/assets/{check-BxpE0B5u.js → check-CfG09Z18.js} +1 -1
  61. package/web-app/dist/assets/{chevron-left-D6KPvBOA.js → chevron-left-z0fh4x2h.js} +1 -1
  62. package/web-app/dist/assets/{circle-alert-Bajq86oe.js → circle-alert-C_7GlYul.js} +1 -1
  63. package/web-app/dist/assets/{clock-CnlHAVJc.js → clock-BsYUp070.js} +1 -1
  64. package/web-app/dist/assets/{cloud-DjaymjwM.js → cloud-BVWAJ7Rv.js} +1 -1
  65. package/web-app/dist/assets/{code-xml-BADEw2Ld.js → code-xml-CdZT-6zu.js} +1 -1
  66. package/web-app/dist/assets/{database-B4aKb5Cq.js → database-Dbkm9t2D.js} +1 -1
  67. package/web-app/dist/assets/{dollar-sign-DrldXpja.js → dollar-sign-CfIUM5Pd.js} +1 -1
  68. package/web-app/dist/assets/{file-code-corner-DVebDVR-.js → file-code-corner-CrUKhnj-.js} +1 -1
  69. package/web-app/dist/assets/{file-plus-BD-N_-Tl.js → file-plus-Cf6u0xHY.js} +1 -1
  70. package/web-app/dist/assets/{globe-C7ieInC-.js → globe-DsIqaI7w.js} +1 -1
  71. package/web-app/dist/assets/{hammer-BSugKIji.js → hammer-CA14BeMp.js} +1 -1
  72. package/web-app/dist/assets/{index-nLQgfvOn.js → index-DpJ_GJuZ.js} +3 -3
  73. package/web-app/dist/assets/{layers-CHXxU2on.js → layers-Dh5Oqhrj.js} +1 -1
  74. package/web-app/dist/assets/{loader-circle-BEEz0LbD.js → loader-circle-B0WHIGqt.js} +1 -1
  75. package/web-app/dist/assets/{lock-CzQGfcnE.js → lock-DkgfEGYF.js} +1 -1
  76. package/web-app/dist/assets/{package-CcHYQLGd.js → package-LzjmwD1S.js} +1 -1
  77. package/web-app/dist/assets/{plus-DdzgFEXn.js → plus-BNjA0KSV.js} +1 -1
  78. package/web-app/dist/assets/{refresh-cw-7x0HbH9Y.js → refresh-cw-k3IacuDX.js} +1 -1
  79. package/web-app/dist/assets/{rotate-ccw-DBahX1Sp.js → rotate-ccw-BFON_xv-.js} +1 -1
  80. package/web-app/dist/assets/{scroll-text-BB8y8a9Z.js → scroll-text-CaIlSPZB.js} +1 -1
  81. package/web-app/dist/assets/{server-CfkbW2MH.js → server-CKFUccCG.js} +1 -1
  82. package/web-app/dist/assets/{shield-alert-DUgD8rBF.js → shield-alert-Q4-rPo5r.js} +1 -1
  83. package/web-app/dist/assets/{thumbs-up-DGoyY6QC.js → thumbs-up-BYMeh8oV.js} +1 -1
  84. package/web-app/dist/assets/{trash-2-B6xrSUMr.js → trash-2-BHSUEIHw.js} +1 -1
  85. package/web-app/dist/assets/{trending-down-B6RGKTOx.js → trending-down-BC_FR2VT.js} +1 -1
  86. package/web-app/dist/assets/{trending-up-B44DCrt1.js → trending-up-CmA-WmLW.js} +1 -1
  87. package/web-app/dist/assets/{upload-4kWm33ZY.js → upload-BxLgBa1B.js} +1 -1
  88. package/web-app/dist/assets/{usePolling-zkUtRQG6.js → usePolling-DKNgwt5n.js} +1 -1
  89. package/web-app/dist/assets/{user-04cEVIe2.js → user-CA2DlmLc.js} +1 -1
  90. package/web-app/dist/index.html +1 -1
  91. package/memory/rag_injector.py +0 -161
  92. package/packages/control-plane/ui/dist/assets/index-DbLzr87u.js +0 -190
@@ -1,161 +0,0 @@
1
- #!/usr/bin/env python3
2
- """RAG context injector -- builds knowledge context for RARV prompts.
3
-
4
- CLI usage: python3 -m memory.rag_injector --query "description" --max-tokens 2000
5
-
6
- Reads from the organization knowledge graph and returns relevant context
7
- for injection into the RARV prompt cycle.
8
- """
9
-
10
- import argparse
11
- import json
12
- import re
13
- import sys
14
- from pathlib import Path
15
-
16
-
17
- # Per-field hard cap so a single oversized/garbage memory entry cannot dominate
18
- # the injected context or push real signal out of the token budget.
19
- _MAX_FIELD_CHARS = 600
20
-
21
- # Control characters (excluding ordinary whitespace handled separately) that
22
- # must never reach the prompt: they can corrupt rendering or smuggle hidden
23
- # directives. Covers C0 controls and DEL.
24
- _CONTROL_CHARS_RE = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]")
25
-
26
-
27
- def _sanitize_field(value, max_chars=_MAX_FIELD_CHARS):
28
- """Neutralize a single field from stored memory before it enters a prompt.
29
-
30
- Memory entries are untrusted input: a malicious or garbage pattern could
31
- contain prompt-injection payloads (fake instructions, fabricated section
32
- headers, code-fence breakers, or directives that try to override the RARV
33
- prompt). This collapses each field to a single safe inline line so it can
34
- only ever read as data, never as structure or instructions.
35
-
36
- Steps:
37
- - Coerce non-strings to str (a dict/list value would otherwise break
38
- formatting or interpolate unexpected structure).
39
- - Drop control characters (keeps the visible text intact).
40
- - Collapse ALL newlines/tabs/carriage-returns to single spaces so the
41
- field cannot add new lines, fake "### " section headers, close the
42
- knowledge block, or open/close a markdown code fence.
43
- - Defang leading structural markdown markers (#, >, -, *, backticks) so the
44
- field cannot pose as a heading/list/fence even after collapsing.
45
- - Truncate to a bounded length.
46
- """
47
- if value is None:
48
- return ''
49
- if not isinstance(value, str):
50
- value = str(value)
51
- # Remove control characters first.
52
- value = _CONTROL_CHARS_RE.sub('', value)
53
- # Collapse any vertical whitespace and tabs into single spaces. This is the
54
- # core injection defense: without newlines the field cannot introduce new
55
- # markdown structure or standalone instruction lines.
56
- value = re.sub(r'[\r\n\t]+', ' ', value)
57
- # Collapse runs of spaces left behind.
58
- value = re.sub(r' {2,}', ' ', value).strip()
59
- # Defang leading structural markdown so the field cannot masquerade as a
60
- # heading, blockquote, list item, or code fence.
61
- value = re.sub(r'^[#>\-*`]+\s*', '', value)
62
- # Defang markdown header markers anywhere in the (now single-line) value so
63
- # a collapsed payload cannot reintroduce a "### " section marker inline.
64
- # Backticks are neutralized too so a field cannot open/close a code fence.
65
- value = re.sub(r'#{1,6}\s', '', value)
66
- value = value.replace('`', '')
67
- if len(value) > max_chars:
68
- value = value[:max_chars].rstrip() + '...'
69
- return value
70
-
71
-
72
- def build_rag_context(query, max_tokens=2000, knowledge_dir=None):
73
- """Build RAG context from the knowledge graph.
74
-
75
- Args:
76
- query: Search query (usually PRD summary or task description)
77
- max_tokens: Maximum approximate tokens (chars / 4)
78
- knowledge_dir: Override knowledge directory
79
-
80
- Returns:
81
- Formatted context string for prompt injection, or empty string
82
- if no matching patterns are found.
83
- """
84
- from .knowledge_graph import OrganizationKnowledgeGraph
85
-
86
- kg = OrganizationKnowledgeGraph(knowledge_dir)
87
- patterns = kg.query_patterns(query, max_results=10)
88
-
89
- if not patterns:
90
- return ''
91
-
92
- max_chars = max_tokens * 4 # Rough chars-to-tokens ratio
93
-
94
- sections = []
95
- total_chars = 0
96
-
97
- for p in patterns:
98
- # Support both 'name'/'pattern' and 'description' fields.
99
- # Every field is sanitized: memory entries are untrusted input and must
100
- # not be able to inject instructions or break the prompt structure.
101
- # `or` chaining, not .get(a, .get(b, default)): a present-but-empty
102
- # 'description' would otherwise shadow a real 'correct_approach', and a
103
- # row missing BOTH name keys would resolve to the literal string
104
- # 'Unknown Pattern' -- truthy, so the substance check below could never
105
- # fire on it.
106
- name = _sanitize_field(p.get('name') or p.get('pattern') or '')
107
- desc = _sanitize_field(p.get('description') or p.get('correct_approach') or '')
108
- category = _sanitize_field(p.get('category', ''))
109
-
110
- # Substance check: a pattern that matched only on its category (or
111
- # whose fields sanitized away to nothing) has no memory to inject.
112
- # Rendering it as "### Unknown Pattern" under the "patterns were found
113
- # in the organization knowledge base" header presents a fabricated
114
- # memory as a real one and burns prompt budget. Name OR description is
115
- # enough -- category alone is a bucket label, not a memory, and a named
116
- # pattern with no description is still genuine signal.
117
- if not name and not desc:
118
- continue
119
- source_raw = p.get('_source_project', '')
120
- # Path().name strips any directory traversal; sanitize the basename too.
121
- source = _sanitize_field(Path(str(source_raw)).name) if source_raw else ''
122
-
123
- # name may be empty after sanitization (e.g. a field that was only
124
- # markdown markers); fall back so the heading is never blank.
125
- if not name:
126
- name = 'Unknown Pattern'
127
-
128
- section = '### ' + name
129
- if category:
130
- section += ' (' + category + ')'
131
- section += '\n'
132
- if desc:
133
- section += desc + '\n'
134
- if source:
135
- section += '_Source: ' + source + '_\n'
136
-
137
- if total_chars + len(section) > max_chars:
138
- break
139
- sections.append(section)
140
- total_chars += len(section)
141
-
142
- if not sections:
143
- return ''
144
-
145
- return 'The following patterns were found in the organization knowledge base:\n\n' + '\n'.join(sections)
146
-
147
-
148
- def main():
149
- parser = argparse.ArgumentParser(description='RAG context injector for RARV prompts')
150
- parser.add_argument('--query', required=True, help='Search query')
151
- parser.add_argument('--max-tokens', type=int, default=2000, help='Max tokens for context')
152
- parser.add_argument('--knowledge-dir', help='Override knowledge directory')
153
- args = parser.parse_args()
154
-
155
- context = build_rag_context(args.query, args.max_tokens, args.knowledge_dir)
156
- if context:
157
- print(context)
158
-
159
-
160
- if __name__ == '__main__':
161
- main()