@hailer/mcp 1.0.29 → 1.1.2

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 (233) hide show
  1. package/.claude/.session-checked +1 -0
  2. package/.claude/agents/agent-ada-skill-builder.md +10 -2
  3. package/.claude/agents/agent-alejandro-function-fields.md +104 -37
  4. package/.claude/agents/agent-bjorn-config-audit.md +41 -21
  5. package/.claude/agents/agent-builder-agent-creator.md +13 -3
  6. package/.claude/agents/agent-code-simplifier.md +53 -0
  7. package/.claude/agents/agent-dmitri-activity-crud.md +126 -11
  8. package/.claude/agents/agent-giuseppe-app-builder.md +212 -22
  9. package/.claude/agents/agent-gunther-mcp-tools.md +7 -36
  10. package/.claude/agents/agent-helga-workflow-config.md +75 -10
  11. package/.claude/agents/agent-igor-activity-mover-automation.md +125 -0
  12. package/.claude/agents/agent-ingrid-doc-templates.md +164 -36
  13. package/.claude/agents/agent-ivan-monolith.md +154 -0
  14. package/.claude/agents/agent-kenji-data-reader.md +15 -8
  15. package/.claude/agents/agent-lars-code-inspector.md +56 -8
  16. package/.claude/agents/agent-marco-mockup-builder.md +110 -0
  17. package/.claude/agents/agent-marcus-api-documenter.md +323 -0
  18. package/.claude/agents/agent-marketplace-publisher.md +232 -72
  19. package/.claude/agents/agent-marketplace-reviewer.md +255 -79
  20. package/.claude/agents/agent-permissions-handler.md +208 -0
  21. package/.claude/agents/agent-simple-writer.md +48 -0
  22. package/.claude/agents/agent-svetlana-code-review.md +127 -14
  23. package/.claude/agents/agent-tanya-test-runner.md +333 -0
  24. package/.claude/agents/agent-ui-designer.md +100 -0
  25. package/.claude/agents/agent-viktor-sql-insights.md +19 -6
  26. package/.claude/agents/agent-web-search.md +55 -0
  27. package/.claude/agents/agent-yevgeni-discussions.md +7 -1
  28. package/.claude/agents/agent-zara-zapier.md +159 -0
  29. package/.claude/commands/app-squad.md +135 -0
  30. package/.claude/commands/audit-squad.md +158 -0
  31. package/.claude/commands/autoplan.md +563 -0
  32. package/.claude/commands/cleanup-squad.md +98 -0
  33. package/.claude/commands/config-squad.md +106 -0
  34. package/.claude/commands/crud-squad.md +87 -0
  35. package/.claude/commands/data-squad.md +97 -0
  36. package/.claude/commands/debug-squad.md +303 -0
  37. package/.claude/commands/doc-squad.md +65 -0
  38. package/.claude/commands/handoff.md +137 -0
  39. package/.claude/commands/health.md +49 -0
  40. package/.claude/commands/help.md +2 -1
  41. package/.claude/commands/help:agents.md +96 -16
  42. package/.claude/commands/help:commands.md +55 -11
  43. package/.claude/commands/help:faq.md +16 -1
  44. package/.claude/commands/help:skills.md +93 -0
  45. package/.claude/commands/hotfix-squad.md +112 -0
  46. package/.claude/commands/integration-squad.md +82 -0
  47. package/.claude/commands/janitor-squad.md +167 -0
  48. package/.claude/commands/learn-auto.md +120 -0
  49. package/.claude/commands/learn.md +120 -0
  50. package/.claude/commands/mcp-list.md +27 -0
  51. package/.claude/commands/onboard-squad.md +140 -0
  52. package/.claude/commands/plan-workspace.md +732 -0
  53. package/.claude/commands/prd.md +131 -0
  54. package/.claude/commands/project-status.md +82 -0
  55. package/.claude/commands/publish.md +138 -0
  56. package/.claude/commands/recap.md +69 -0
  57. package/.claude/commands/restore.md +64 -0
  58. package/.claude/commands/review-squad.md +152 -0
  59. package/.claude/commands/save.md +24 -0
  60. package/.claude/commands/stats.md +19 -0
  61. package/.claude/commands/swarm.md +210 -0
  62. package/.claude/commands/tool-builder.md +3 -1
  63. package/.claude/commands/ws-pull.md +1 -1
  64. package/.claude/commands/yolo-off.md +17 -0
  65. package/.claude/commands/yolo.md +82 -0
  66. package/.claude/hooks/_shared-memory.cjs +305 -0
  67. package/.claude/hooks/_utils.cjs +134 -0
  68. package/.claude/hooks/agent-failure-detector.cjs +164 -79
  69. package/.claude/hooks/agent-usage-logger.cjs +204 -0
  70. package/.claude/hooks/app-edit-guard.cjs +20 -4
  71. package/.claude/hooks/auto-learn.cjs +316 -0
  72. package/.claude/hooks/bash-guard.cjs +282 -0
  73. package/.claude/hooks/builder-mode-manager.cjs +183 -54
  74. package/.claude/hooks/bulk-activity-guard.cjs +283 -0
  75. package/.claude/hooks/context-watchdog.cjs +292 -0
  76. package/.claude/hooks/delegation-reminder.cjs +478 -0
  77. package/.claude/hooks/design-system-lint.cjs +283 -0
  78. package/.claude/hooks/post-scaffold-hook.cjs +16 -3
  79. package/.claude/hooks/prompt-guard.cjs +366 -0
  80. package/.claude/hooks/publish-template-guard.cjs +16 -0
  81. package/.claude/hooks/session-start.cjs +35 -0
  82. package/.claude/hooks/shared-memory-writer.cjs +147 -0
  83. package/.claude/hooks/skill-injector.cjs +140 -0
  84. package/.claude/hooks/skill-usage-logger.cjs +258 -0
  85. package/.claude/hooks/src-edit-guard.cjs +16 -1
  86. package/.claude/hooks/sync-marketplace-agents.cjs +53 -8
  87. package/.claude/scripts/yolo-toggle.cjs +142 -0
  88. package/.claude/settings.json +141 -14
  89. package/.claude/skills/SDK-activity-patterns/SKILL.md +428 -0
  90. package/.claude/skills/SDK-document-templates/SKILL.md +1033 -0
  91. package/.claude/skills/SDK-function-fields/SKILL.md +542 -0
  92. package/.claude/skills/SDK-generate-skill/SKILL.md +92 -0
  93. package/.claude/skills/SDK-init-skill/SKILL.md +127 -0
  94. package/.claude/skills/SDK-insight-queries/SKILL.md +787 -0
  95. package/.claude/skills/SDK-ws-config-skill/SKILL.md +1139 -0
  96. package/.claude/skills/agent-structure/SKILL.md +98 -0
  97. package/.claude/skills/api-documentation-patterns/SKILL.md +474 -0
  98. package/.claude/skills/chrome-mcp-reference/SKILL.md +370 -0
  99. package/.claude/skills/delegation-routing/SKILL.md +202 -0
  100. package/.claude/skills/frontend-design/SKILL.md +254 -0
  101. package/.claude/skills/hailer-activity-mover/SKILL.md +213 -0
  102. package/.claude/skills/hailer-api-client/SKILL.md +518 -0
  103. package/.claude/skills/hailer-app-builder/SKILL.md +939 -11
  104. package/.claude/skills/hailer-apps-pictures/SKILL.md +269 -0
  105. package/.claude/skills/hailer-design-system/SKILL.md +235 -0
  106. package/.claude/skills/hailer-monolith-automations/SKILL.md +686 -0
  107. package/.claude/skills/hailer-permissions-system/SKILL.md +121 -0
  108. package/.claude/skills/hailer-project-protocol/SKILL.md +488 -0
  109. package/.claude/skills/hailer-rest-api/SKILL.md +61 -0
  110. package/.claude/skills/hailer-rest-api/hailer-activities.md +184 -0
  111. package/.claude/skills/hailer-rest-api/hailer-admin.md +473 -0
  112. package/.claude/skills/hailer-rest-api/hailer-calendar.md +256 -0
  113. package/.claude/skills/hailer-rest-api/hailer-feed.md +249 -0
  114. package/.claude/skills/hailer-rest-api/hailer-insights.md +195 -0
  115. package/.claude/skills/hailer-rest-api/hailer-messaging.md +276 -0
  116. package/.claude/skills/hailer-rest-api/hailer-workflows.md +283 -0
  117. package/.claude/skills/insight-join-patterns/SKILL.md +3 -0
  118. package/.claude/skills/integration-patterns/SKILL.md +421 -0
  119. package/.claude/skills/json-only-output/SKILL.md +52 -12
  120. package/.claude/skills/lsp-setup/SKILL.md +160 -0
  121. package/.claude/skills/mcp-direct-tools/SKILL.md +153 -0
  122. package/.claude/skills/optional-parameters/SKILL.md +32 -23
  123. package/.claude/skills/publish-hailer-app/SKILL.md +76 -12
  124. package/.claude/skills/testing-patterns/SKILL.md +630 -0
  125. package/.claude/skills/tool-builder/SKILL.md +250 -0
  126. package/.claude/skills/tool-parameter-usage/SKILL.md +59 -45
  127. package/.claude/skills/tool-response-verification/SKILL.md +82 -48
  128. package/.claude/skills/zapier-hailer-patterns/SKILL.md +581 -0
  129. package/.env.example +26 -7
  130. package/CLAUDE.md +290 -224
  131. package/dist/CLAUDE.md +370 -0
  132. package/dist/app.d.ts +1 -1
  133. package/dist/app.js +101 -101
  134. package/dist/bot/bot-config.d.ts +26 -0
  135. package/dist/bot/bot-config.js +135 -0
  136. package/dist/bot/bot-manager.d.ts +40 -0
  137. package/dist/bot/bot-manager.js +137 -0
  138. package/dist/bot/bot.d.ts +127 -0
  139. package/dist/bot/bot.js +1328 -0
  140. package/dist/bot/operation-logger.d.ts +28 -0
  141. package/dist/bot/operation-logger.js +132 -0
  142. package/dist/bot/services/conversation-manager.d.ts +60 -0
  143. package/dist/bot/services/conversation-manager.js +246 -0
  144. package/dist/bot/services/index.d.ts +9 -0
  145. package/dist/bot/services/index.js +18 -0
  146. package/dist/bot/services/message-classifier.d.ts +42 -0
  147. package/dist/bot/services/message-classifier.js +228 -0
  148. package/dist/bot/services/message-formatter.d.ts +88 -0
  149. package/dist/bot/services/message-formatter.js +411 -0
  150. package/dist/bot/services/session-logger.d.ts +162 -0
  151. package/dist/bot/services/session-logger.js +724 -0
  152. package/dist/bot/services/token-billing.d.ts +78 -0
  153. package/dist/bot/services/token-billing.js +233 -0
  154. package/dist/bot/services/types.d.ts +169 -0
  155. package/dist/bot/services/types.js +12 -0
  156. package/dist/bot/services/typing-indicator.d.ts +23 -0
  157. package/dist/bot/services/typing-indicator.js +60 -0
  158. package/dist/bot/services/workspace-schema-cache.d.ts +122 -0
  159. package/dist/bot/services/workspace-schema-cache.js +506 -0
  160. package/dist/bot/tool-executor.d.ts +28 -0
  161. package/dist/bot/tool-executor.js +48 -0
  162. package/dist/bot/workspace-overview.d.ts +12 -0
  163. package/dist/bot/workspace-overview.js +94 -0
  164. package/dist/cli.d.ts +1 -8
  165. package/dist/cli.js +1 -253
  166. package/dist/config.d.ts +96 -3
  167. package/dist/config.js +148 -37
  168. package/dist/core.d.ts +5 -0
  169. package/dist/core.js +61 -8
  170. package/dist/lib/discussion-lock.d.ts +42 -0
  171. package/dist/lib/discussion-lock.js +110 -0
  172. package/dist/lib/logger.d.ts +0 -1
  173. package/dist/lib/logger.js +39 -23
  174. package/dist/lib/request-logger.d.ts +77 -0
  175. package/dist/lib/request-logger.js +147 -0
  176. package/dist/mcp/UserContextCache.js +16 -13
  177. package/dist/mcp/hailer-clients.js +18 -17
  178. package/dist/mcp/signal-handler.js +29 -13
  179. package/dist/mcp/tool-registry.d.ts +4 -15
  180. package/dist/mcp/tool-registry.js +94 -32
  181. package/dist/mcp/tools/activity.js +28 -69
  182. package/dist/mcp/tools/app-core.js +9 -4
  183. package/dist/mcp/tools/app-marketplace.js +22 -12
  184. package/dist/mcp/tools/app-member.js +5 -2
  185. package/dist/mcp/tools/app-scaffold.js +32 -18
  186. package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
  187. package/dist/mcp/tools/bot-config/constants.js +94 -0
  188. package/dist/mcp/tools/bot-config/core.d.ts +253 -0
  189. package/dist/mcp/tools/bot-config/core.js +2456 -0
  190. package/dist/mcp/tools/bot-config/index.d.ts +10 -0
  191. package/dist/mcp/tools/bot-config/index.js +59 -0
  192. package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
  193. package/dist/mcp/tools/bot-config/tools.js +15 -0
  194. package/dist/mcp/tools/bot-config/types.d.ts +50 -0
  195. package/dist/mcp/tools/bot-config/types.js +6 -0
  196. package/dist/mcp/tools/discussion.js +107 -77
  197. package/dist/mcp/tools/document.d.ts +11 -0
  198. package/dist/mcp/tools/document.js +741 -0
  199. package/dist/mcp/tools/file.js +5 -2
  200. package/dist/mcp/tools/insight.js +36 -12
  201. package/dist/mcp/tools/investigate.d.ts +9 -0
  202. package/dist/mcp/tools/investigate.js +254 -0
  203. package/dist/mcp/tools/user.d.ts +2 -4
  204. package/dist/mcp/tools/user.js +9 -50
  205. package/dist/mcp/tools/workflow.d.ts +1 -0
  206. package/dist/mcp/tools/workflow.js +164 -52
  207. package/dist/mcp/utils/hailer-api-client.js +26 -17
  208. package/dist/mcp/webhook-handler.d.ts +64 -3
  209. package/dist/mcp/webhook-handler.js +219 -9
  210. package/dist/mcp-server.d.ts +4 -0
  211. package/dist/mcp-server.js +237 -25
  212. package/dist/plugins/bug-fixer/index.d.ts +2 -0
  213. package/dist/plugins/bug-fixer/index.js +18 -0
  214. package/dist/plugins/bug-fixer/tools.d.ts +45 -0
  215. package/dist/plugins/bug-fixer/tools.js +1096 -0
  216. package/package.json +10 -10
  217. package/scripts/test-hal-tools.ts +154 -0
  218. package/.claude/agents/agent-nora-name-functions.md +0 -123
  219. package/.claude/assistant-knowledge.md +0 -23
  220. package/.claude/commands/install-plugin.md +0 -261
  221. package/.claude/commands/list-plugins.md +0 -42
  222. package/.claude/commands/marketplace-setup.md +0 -33
  223. package/.claude/commands/publish-plugin.md +0 -55
  224. package/.claude/commands/uninstall-plugin.md +0 -87
  225. package/.claude/hooks/interactive-mode.cjs +0 -87
  226. package/.claude/hooks/mcp-server-guard.cjs +0 -108
  227. package/.claude/skills/marketplace-publishing.md +0 -155
  228. package/dist/bot/chat-bot.d.ts +0 -31
  229. package/dist/bot/chat-bot.js +0 -357
  230. package/dist/mcp/tools/metrics.d.ts +0 -13
  231. package/dist/mcp/tools/metrics.js +0 -546
  232. package/dist/stdio-server.d.ts +0 -14
  233. package/dist/stdio-server.js +0 -114
@@ -0,0 +1,421 @@
1
+ ---
2
+ name: integration-patterns
3
+ description: Hailer integration microservice patterns - activity movers, webhooks, SCIM, Kafka consumers
4
+ version: 1.0.0
5
+ triggers: Build integration, activity mover, webhook handler, SCIM endpoint, Kafka consumer
6
+ ---
7
+
8
+ # Integration Patterns
9
+
10
+ ## Architecture Overview
11
+
12
+ ```
13
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
14
+ │ External │ │ Integration │ │ Hailer API │
15
+ │ System │────▶│ Service │────▶│ │
16
+ │ (Kafka/HTTP) │ │ (Node.js) │ │ (WebSocket) │
17
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
18
+
19
+
20
+ ┌─────────────────┐
21
+ │ Logging & │
22
+ │ Monitoring │
23
+ └─────────────────┘
24
+ ```
25
+
26
+ ---
27
+
28
+ ## 1. Activity Mover Pattern
29
+
30
+ Monitors activities and moves linked activities when triggers fire.
31
+
32
+ ### Configuration Structure
33
+
34
+ ```typescript
35
+ interface ActivityMoverConfig {
36
+ logDiscussionId: string; // Discussion for audit logging
37
+ email: string; // Integration user email
38
+ password: string; // Or "ENV:HAILER_PASSWORD"
39
+ project: string; // Project identifier
40
+ triggers: Trigger[];
41
+ }
42
+
43
+ interface Trigger {
44
+ processId: string; // Source workflow ID
45
+ phaseId: string; // Phase that triggers action
46
+ metaDataId: string; // Hidden field for tracking ("Seen"/"Not seen")
47
+ linkedProcesses: LinkedProcess[];
48
+ }
49
+
50
+ interface LinkedProcess {
51
+ processId: string; // Target workflow ID
52
+ sourcePhases: string[]; // Move FROM these phases
53
+ targetPhase: string; // Move TO this phase
54
+ }
55
+ ```
56
+
57
+ ### Example Config
58
+
59
+ ```json
60
+ {
61
+ "logDiscussionId": "694c9536acfa30f6df13201b",
62
+ "email": "integration@workspace.com",
63
+ "password": "ENV:HAILER_PASSWORD",
64
+ "project": "orders-sync",
65
+ "triggers": [
66
+ {
67
+ "processId": "67dc1b7d3d2c9f6cf9a5468d",
68
+ "phaseId": "67dc1b7d3d2c9f6cf9a546c4",
69
+ "metaDataId": "67e697da6ada809b961c35b5",
70
+ "linkedProcesses": [
71
+ {
72
+ "processId": "67dc1b7d3d2c9f6cf9a54690",
73
+ "sourcePhases": ["67dc1b7d3d2c9f6cf9a54691", "67dc1b7d3d2c9f6cf9a54692"],
74
+ "targetPhase": "67dc1b7d3d2c9f6cf9a54695"
75
+ }
76
+ ]
77
+ }
78
+ ]
79
+ }
80
+ ```
81
+
82
+ ### Hailer Setup Requirements
83
+
84
+ 1. **Metadata field** on trigger workflow:
85
+ - Type: TEXT (hidden)
86
+ - Default value: "Not seen"
87
+ - Used to track processed activities
88
+
89
+ 2. **Link field** connecting workflows:
90
+ - Activity link from trigger workflow to target workflow
91
+
92
+ 3. **Integration user**:
93
+ - Dedicated user account
94
+ - Edit permissions on both workflows
95
+
96
+ 4. **Discussion activity**:
97
+ - For audit logging
98
+ - Integration user must have access
99
+
100
+ ### Core Logic
101
+
102
+ ```typescript
103
+ // Listen for activity updates
104
+ client.on('activities.updated', async (data) => {
105
+ for (const trigger of config.triggers) {
106
+ if (data.processId === trigger.processId && data.phaseId === trigger.phaseId) {
107
+ await processTrigger(data.activityId, trigger);
108
+ }
109
+ }
110
+ });
111
+
112
+ async function processTrigger(activityId: string, trigger: Trigger) {
113
+ // Check if already processed
114
+ const activity = await client.request('v3.activity.get', [activityId]);
115
+ if (activity.fields[trigger.metaDataId]?.value === 'Seen') return;
116
+
117
+ // Get linked activities
118
+ const linked = await client.request('v3.activity.linkedFrom.overview', [activityId]);
119
+
120
+ // Move matching activities
121
+ for (const process of trigger.linkedProcesses) {
122
+ const toMove = linked.filter(a =>
123
+ a.processId === process.processId &&
124
+ process.sourcePhases.includes(a.phaseId)
125
+ );
126
+
127
+ if (toMove.length > 0) {
128
+ await client.request('v3.activity.updateMany', [
129
+ toMove.map(a => a._id),
130
+ { phaseId: process.targetPhase }
131
+ ]);
132
+ }
133
+ }
134
+
135
+ // Mark as processed
136
+ await client.request('v3.activity.update', [activityId, {
137
+ fields: { [trigger.metaDataId]: 'Seen' }
138
+ }]);
139
+ }
140
+ ```
141
+
142
+ ---
143
+
144
+ ## 2. Webhook Handler Pattern
145
+
146
+ HTTP endpoints that trigger Hailer operations.
147
+
148
+ ### Express Setup
149
+
150
+ ```typescript
151
+ import express from 'express';
152
+ import crypto from 'crypto';
153
+
154
+ const app = express();
155
+ app.use(express.json());
156
+
157
+ // Webhook signature validation
158
+ function validateSignature(req: express.Request, secret: string): boolean {
159
+ const signature = req.headers['x-webhook-signature'];
160
+ const payload = JSON.stringify(req.body);
161
+ const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
162
+ return signature === expected;
163
+ }
164
+
165
+ // Webhook endpoint
166
+ app.post('/api/v1/webhook/:type', async (req, res) => {
167
+ const { type } = req.params;
168
+
169
+ if (!validateSignature(req, config.webhookSecret)) {
170
+ return res.status(401).json({ error: 'Invalid signature' });
171
+ }
172
+
173
+ try {
174
+ switch (type) {
175
+ case 'order.created':
176
+ await handleOrderCreated(req.body);
177
+ break;
178
+ case 'order.updated':
179
+ await handleOrderUpdated(req.body);
180
+ break;
181
+ default:
182
+ logger.warn({ type }, 'Unknown webhook type');
183
+ }
184
+ res.json({ status: 'ok' });
185
+ } catch (error) {
186
+ logger.error({ error, type }, 'Webhook processing failed');
187
+ res.status(500).json({ error: 'Processing failed' });
188
+ }
189
+ });
190
+ ```
191
+
192
+ ### Webhook Handler Example
193
+
194
+ ```typescript
195
+ async function handleOrderCreated(payload: OrderPayload) {
196
+ // Map external data to Hailer fields
197
+ const fields = {
198
+ [FieldIds.external_id]: payload.orderId,
199
+ [FieldIds.customer_name]: payload.customer.name,
200
+ [FieldIds.total_amount]: payload.total,
201
+ [FieldIds.order_date]: new Date(payload.createdAt).getTime()
202
+ };
203
+
204
+ // Create activity in Hailer
205
+ const result = await hailerClient.createActivity(
206
+ WorkflowIds.orders,
207
+ PhaseIds.new,
208
+ fields
209
+ );
210
+
211
+ logger.info({ orderId: payload.orderId, activityId: result._id }, 'Order created in Hailer');
212
+ }
213
+ ```
214
+
215
+ ---
216
+
217
+ ## 3. SCIM 2.0 Pattern
218
+
219
+ User provisioning from identity providers (Microsoft Entra, Okta).
220
+
221
+ ### Endpoints
222
+
223
+ | Method | Path | Description |
224
+ |--------|------|-------------|
225
+ | POST | /scim/v2/Users | Create user |
226
+ | GET | /scim/v2/Users/:id | Get user |
227
+ | PATCH | /scim/v2/Users/:id | Update user |
228
+ | DELETE | /scim/v2/Users/:id | Deactivate user |
229
+ | GET | /scim/v2/Users | List/filter users |
230
+
231
+ ### User Mapping
232
+
233
+ ```typescript
234
+ interface ScimUser {
235
+ schemas: string[];
236
+ userName: string;
237
+ name: { givenName: string; familyName: string };
238
+ emails: { value: string; primary: boolean }[];
239
+ active: boolean;
240
+ roles?: { value: string }[];
241
+ }
242
+
243
+ function mapScimToHailer(scim: ScimUser): HailerUserPayload {
244
+ return {
245
+ email: scim.emails.find(e => e.primary)?.value || scim.userName,
246
+ firstName: scim.name.givenName,
247
+ lastName: scim.name.familyName,
248
+ active: scim.active,
249
+ teams: mapRolesToTeams(scim.roles)
250
+ };
251
+ }
252
+
253
+ function mapRolesToTeams(roles?: { value: string }[]): string[] {
254
+ const teamMapping: Record<string, string> = {
255
+ 'admin': TeamIds.admins,
256
+ 'manager': TeamIds.managers,
257
+ 'user': TeamIds.users
258
+ };
259
+ return (roles || [])
260
+ .map(r => teamMapping[r.value])
261
+ .filter(Boolean);
262
+ }
263
+ ```
264
+
265
+ ### SCIM Response Format
266
+
267
+ ```typescript
268
+ function toScimUser(hailerUser: HailerUser, baseUrl: string): ScimUser {
269
+ return {
270
+ schemas: ['urn:ietf:params:scim:schemas:core:2.0:User'],
271
+ id: hailerUser._id,
272
+ userName: hailerUser.email,
273
+ name: {
274
+ givenName: hailerUser.firstName,
275
+ familyName: hailerUser.lastName
276
+ },
277
+ emails: [{ value: hailerUser.email, primary: true }],
278
+ active: hailerUser.active,
279
+ meta: {
280
+ resourceType: 'User',
281
+ location: `${baseUrl}/scim/v2/Users/${hailerUser._id}`
282
+ }
283
+ };
284
+ }
285
+ ```
286
+
287
+ ---
288
+
289
+ ## 4. Kafka Consumer Pattern
290
+
291
+ Event-driven processing from message queues.
292
+
293
+ ### Consumer Setup
294
+
295
+ ```typescript
296
+ import { Kafka, Consumer, EachMessagePayload } from 'kafkajs';
297
+
298
+ const kafka = new Kafka({
299
+ clientId: 'hailer-integration',
300
+ brokers: config.kafkaBrokers,
301
+ ssl: {
302
+ ca: [fs.readFileSync(config.caCertPath)],
303
+ key: fs.readFileSync(config.keyPath),
304
+ cert: fs.readFileSync(config.certPath)
305
+ }
306
+ });
307
+
308
+ const consumer = kafka.consumer({ groupId: 'hailer-consumer-group' });
309
+
310
+ async function startConsumer() {
311
+ await consumer.connect();
312
+ await consumer.subscribe({ topic: 'events', fromBeginning: false });
313
+
314
+ await consumer.run({
315
+ eachMessage: async ({ topic, partition, message }: EachMessagePayload) => {
316
+ const event = JSON.parse(message.value.toString());
317
+
318
+ try {
319
+ await processEvent(event);
320
+ logger.info({ eventId: event.id, offset: message.offset }, 'Event processed');
321
+ } catch (error) {
322
+ logger.error({ error, event }, 'Event processing failed');
323
+ await sendToDeadLetterQueue(message);
324
+ }
325
+ }
326
+ });
327
+ }
328
+ ```
329
+
330
+ ### Event Processing
331
+
332
+ ```typescript
333
+ async function processEvent(event: ExternalEvent) {
334
+ switch (event.type) {
335
+ case 'student.created':
336
+ await createStudent(event.data);
337
+ break;
338
+ case 'student.updated':
339
+ await updateStudent(event.data);
340
+ break;
341
+ case 'student.deleted':
342
+ await deactivateStudent(event.data);
343
+ break;
344
+ default:
345
+ logger.warn({ eventType: event.type }, 'Unknown event type');
346
+ }
347
+ }
348
+ ```
349
+
350
+ ---
351
+
352
+ ## Common Patterns
353
+
354
+ ### Retry with Exponential Backoff
355
+
356
+ ```typescript
357
+ async function withRetry<T>(
358
+ fn: () => Promise<T>,
359
+ maxRetries: number = 3,
360
+ baseDelay: number = 1000
361
+ ): Promise<T> {
362
+ let lastError: Error;
363
+
364
+ for (let i = 0; i < maxRetries; i++) {
365
+ try {
366
+ return await fn();
367
+ } catch (error) {
368
+ lastError = error;
369
+ const delay = baseDelay * Math.pow(2, i);
370
+ logger.warn({ attempt: i + 1, delay, error: error.message }, 'Retrying...');
371
+ await sleep(delay);
372
+ }
373
+ }
374
+
375
+ throw lastError;
376
+ }
377
+ ```
378
+
379
+ ### Graceful Shutdown
380
+
381
+ ```typescript
382
+ async function gracefulShutdown(signal: string) {
383
+ logger.info({ signal }, 'Shutdown signal received');
384
+
385
+ // Stop accepting new requests
386
+ server.close();
387
+
388
+ // Disconnect from Hailer
389
+ await hailerClient.disconnect();
390
+
391
+ // Disconnect from Kafka
392
+ await consumer.disconnect();
393
+
394
+ logger.info('Graceful shutdown complete');
395
+ process.exit(0);
396
+ }
397
+
398
+ process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
399
+ process.on('SIGINT', () => gracefulShutdown('SIGINT'));
400
+ ```
401
+
402
+ ### Health Check
403
+
404
+ ```typescript
405
+ app.get('/api/v1/health', async (req, res) => {
406
+ const checks = {
407
+ hailer: await checkHailerConnection(),
408
+ kafka: await checkKafkaConnection(),
409
+ uptime: process.uptime(),
410
+ memory: process.memoryUsage(),
411
+ lastActivity: lastActivityTimestamp
412
+ };
413
+
414
+ const healthy = checks.hailer.connected && checks.kafka.connected;
415
+ res.status(healthy ? 200 : 503).json({
416
+ status: healthy ? 'healthy' : 'unhealthy',
417
+ timestamp: new Date().toISOString(),
418
+ checks
419
+ });
420
+ });
421
+ ```
@@ -1,21 +1,65 @@
1
1
  ---
2
2
  name: json-only-output
3
3
  description: Fix agents adding prose after JSON responses
4
+ version: 1.0.1
4
5
  triggers: Agent outputs explanation text after valid JSON
5
6
  ---
6
7
 
7
- <problem>
8
- Agents violate JSON-only protocol by adding prose explanations AFTER their JSON response.
9
- </problem>
8
+ # JSON Only Output
9
+
10
+ <purpose>
11
+ Ensure agents output ONLY valid JSON with no prose, explanations, or commentary after the closing brace.
12
+ </purpose>
13
+
14
+ <why-this-happens>
15
+ ## Why Agents Add Prose
16
+
17
+ LLMs have a natural tendency to be helpful and explanatory. After completing a task, they want to:
18
+ - Explain what they did
19
+ - Suggest next steps
20
+ - Provide context
21
+ - Confirm their understanding
22
+
23
+ This is normally good behavior, but for **subagents** returning structured data to an orchestrator, it breaks JSON parsing.
24
+
25
+ **The `<protocol>` section isn't enough** because:
26
+ - LLMs treat protocol as "guidelines" not hard rules
27
+ - The helpful instinct overrides weak instructions
28
+ - Protocol is at the end of the prompt, less salient
29
+
30
+ **Why identity/rules work:**
31
+ - `<identity>` shapes the agent's core persona ("I output JSON. Full stop.")
32
+ - `<rules>` are processed as constraints, not suggestions
33
+ - Positioned early in prompt, higher salience
34
+ - Explicit prohibition is stronger than implicit expectation
35
+ </why-this-happens>
36
+
37
+ <patterns>
38
+ ## Pattern 1: Stop at the Closing Brace
39
+
40
+ Output JSON. Full stop. Nothing after the closing brace.
41
+
42
+ ## Pattern 2: Agent Configuration Fix
43
+
44
+ 1. Add to `<identity>`: "Output JSON. Full stop."
45
+ 2. Add to `<rules>`: **JSON ONLY** - Output closing brace, then STOP. Zero prose after JSON.
46
+ 3. Protocol section is NOT enough - agents ignore it without identity/rules reinforcement.
47
+
48
+ ## Pattern 3: Include Summary Inside JSON
49
+
50
+ If context is helpful, include it IN the JSON `summary` field, not after the JSON.
51
+ </patterns>
52
+
53
+ <examples>
54
+ ## Example 1: Correct - Pure JSON Output
10
55
 
11
- <correct>
12
56
  ```json
13
57
  {"status":"success","result":{"fields":["taskName","priority"]},"summary":"Read 2 fields"}
14
58
  ```
15
59
  **STOP HERE. Nothing after closing brace.**
16
- </correct>
17
60
 
18
- <wrong>
61
+ ## Example 2: Wrong - Prose After JSON
62
+
19
63
  ```json
20
64
  {"status":"success","result":{"fields":["taskName","priority"]},"summary":"Read 2 fields"}
21
65
  ```
@@ -23,10 +67,6 @@ Agents violate JSON-only protocol by adding prose explanations AFTER their JSON
23
67
  The workflow has 2 fields defined in workspace/Tasks_123/fields.ts. You can now use these field IDs with dmitri for activity creation.
24
68
 
25
69
  **Action Required**: Run `npm run pull` to refresh.
26
- </wrong>
27
70
 
28
- <fix>
29
- 1. Add to `<identity>`: "Output JSON. Full stop."
30
- 2. Add to `<rules>`: **JSON ONLY** - Output closing brace, then STOP. Zero prose after JSON.
31
- 3. Protocol section is NOT enough - agents ignore it without identity/rules reinforcement.
32
- </fix>
71
+ This violates JSON-only protocol by adding explanation text AFTER the valid JSON response.
72
+ </examples>
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: lsp-setup
3
+ description: How to set up LSP (Language Server Protocol) for Claude Code - enables code intelligence for Lars and other agents
4
+ version: 1.0.0
5
+ triggers:
6
+ - LSP not available
7
+ - typescript-language-server
8
+ - code intelligence setup
9
+ - Lars can't find unused code
10
+ ---
11
+
12
+ # LSP Setup for Claude Code
13
+
14
+ LSP (Language Server Protocol) enables code intelligence features like go-to-definition, find-references, and accurate dead code detection.
15
+
16
+ ## Why LSP?
17
+
18
+ Without LSP, agents like Lars must guess about code usage via grep/file reads. With LSP:
19
+ - **Accurate dead code detection** - knows if exports are used elsewhere
20
+ - **Type error detection** - without running compiler
21
+ - **Find all references** - across entire codebase
22
+ - **Go to definition** - jump to where symbols are defined
23
+
24
+ ## Requirements
25
+
26
+ Three things needed for LSP to work:
27
+
28
+ | Requirement | How to Check | How to Install |
29
+ |-------------|--------------|----------------|
30
+ | `ENABLE_LSP_TOOL=1` | Check `.claude/settings.json` | Add to env section |
31
+ | `typescript-lsp` plugin | `claude plugin list` | `claude plugin install typescript-lsp@claude-plugins-official` |
32
+ | Language server binary | `which typescript-language-server` | `npm install -g typescript-language-server typescript` |
33
+
34
+ ## Setup Steps
35
+
36
+ ### Step 1: Install the language server binary
37
+
38
+ ```bash
39
+ npm install -g typescript-language-server typescript
40
+ ```
41
+
42
+ Verify:
43
+ ```bash
44
+ typescript-language-server --version
45
+ # Should show version like: 5.1.3
46
+ ```
47
+
48
+ ### Step 2: Install Claude Code plugin
49
+
50
+ ```bash
51
+ claude plugin install typescript-lsp@claude-plugins-official
52
+ ```
53
+
54
+ Verify:
55
+ ```bash
56
+ claude plugin list
57
+ # Should show: typescript-lsp@claude-plugins-official ✔ enabled
58
+ ```
59
+
60
+ ### Step 3: Ensure settings.json has LSP enabled
61
+
62
+ Check `.claude/settings.json` (project) or `~/.claude/settings.json` (global):
63
+
64
+ ```json
65
+ {
66
+ "env": {
67
+ "ENABLE_LSP_TOOL": "1"
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### Step 4: Restart Claude
73
+
74
+ LSP plugin activates on Claude restart:
75
+ ```bash
76
+ claude -c
77
+ ```
78
+
79
+ ### Step 5: Test
80
+
81
+ Ask Lars to find unused code in a TypeScript file:
82
+ ```
83
+ Find unused code in src/App.tsx
84
+ ```
85
+
86
+ Or test LSP directly:
87
+ ```
88
+ Use LSP documentSymbol on src/App.tsx
89
+ ```
90
+
91
+ ## Supported File Types
92
+
93
+ The `typescript-lsp` plugin supports:
94
+ - `.ts`, `.tsx` - TypeScript + React
95
+ - `.js`, `.jsx` - JavaScript + React
96
+ - `.mts`, `.cts` - TypeScript ES modules / CommonJS
97
+ - `.mjs`, `.cjs` - JavaScript ES modules / CommonJS
98
+
99
+ ## LSP Operations Available
100
+
101
+ | Operation | Purpose |
102
+ |-----------|---------|
103
+ | `documentSymbol` | List all symbols in a file |
104
+ | `findReferences` | Find all usages of a symbol |
105
+ | `goToDefinition` | Jump to where symbol is defined |
106
+ | `hover` | Get type info and documentation |
107
+ | `goToImplementation` | Find implementations of interface |
108
+ | `incomingCalls` | What calls this function |
109
+ | `outgoingCalls` | What this function calls |
110
+ | `prepareCallHierarchy` | Get call hierarchy at position |
111
+
112
+ ## Agents That Use LSP
113
+
114
+ | Agent | How They Use LSP |
115
+ |-------|------------------|
116
+ | **Lars** | Primary user - dead code, unused imports, type errors |
117
+ | **Svetlana** | Type checking during code review (optional) |
118
+ | **Giuseppe** | Verify code compiles before build (optional) |
119
+
120
+ ## Troubleshooting
121
+
122
+ ### "No LSP server available"
123
+
124
+ 1. Check binary is installed: `which typescript-language-server`
125
+ 2. Check plugin is installed: `claude plugin list`
126
+ 3. Restart Claude: `claude -c`
127
+
128
+ ### LSP times out on first query
129
+
130
+ Normal - language server is indexing the project. Wait a few seconds and retry.
131
+
132
+ ### LSP works for .ts but not .tsx
133
+
134
+ Check `typescript` is installed alongside `typescript-language-server`:
135
+ ```bash
136
+ npm install -g typescript-language-server typescript
137
+ ```
138
+
139
+ ### "Executable not found in $PATH"
140
+
141
+ The binary isn't in your PATH. Either:
142
+ - Install globally: `npm install -g typescript-language-server`
143
+ - Or add npm global bin to PATH: `export PATH="$PATH:$(npm bin -g)"`
144
+
145
+ ## Without LSP (Fallback)
146
+
147
+ If LSP isn't available, agents can fall back to:
148
+
149
+ ```bash
150
+ # Type errors
151
+ npx tsc --noEmit 2>&1
152
+
153
+ # Unused variables (requires eslint config)
154
+ npx eslint --rule '@typescript-eslint/no-unused-vars: error' src/
155
+
156
+ # Find references (grep-based, less accurate)
157
+ grep -r "functionName" src/
158
+ ```
159
+
160
+ This is less accurate but works without setup.