@hailer/mcp 0.0.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 (163) hide show
  1. package/.claude/commands/tool-builder.md +37 -0
  2. package/.claude/commands/ws-pull.md +44 -0
  3. package/.claude/settings.json +8 -0
  4. package/.claude/settings.local.json +49 -0
  5. package/.claude/skills/activity-api/SKILL.md +96 -0
  6. package/.claude/skills/activity-api/references/activity-endpoints.md +845 -0
  7. package/.claude/skills/add-app-member-skill/SKILL.md +977 -0
  8. package/.claude/skills/agent-building/SKILL.md +243 -0
  9. package/.claude/skills/agent-building/references/architecture-patterns.md +446 -0
  10. package/.claude/skills/agent-building/references/code-examples.md +587 -0
  11. package/.claude/skills/agent-building/references/implementation-guide.md +619 -0
  12. package/.claude/skills/app-api/SKILL.md +219 -0
  13. package/.claude/skills/app-api/references/app-endpoints.md +759 -0
  14. package/.claude/skills/building-hailer-apps-skill/SKILL.md +548 -0
  15. package/.claude/skills/create-app-skill/SKILL.md +1101 -0
  16. package/.claude/skills/create-insight-skill/SKILL.md +1317 -0
  17. package/.claude/skills/get-insight-data-skill/SKILL.md +1053 -0
  18. package/.claude/skills/hailer-api/SKILL.md +283 -0
  19. package/.claude/skills/hailer-api/references/activities.md +620 -0
  20. package/.claude/skills/hailer-api/references/authentication.md +216 -0
  21. package/.claude/skills/hailer-api/references/datasets.md +437 -0
  22. package/.claude/skills/hailer-api/references/files.md +301 -0
  23. package/.claude/skills/hailer-api/references/insights.md +469 -0
  24. package/.claude/skills/hailer-api/references/workflows.md +720 -0
  25. package/.claude/skills/hailer-api/references/workspaces-users.md +445 -0
  26. package/.claude/skills/insight-api/SKILL.md +185 -0
  27. package/.claude/skills/insight-api/references/insight-endpoints.md +514 -0
  28. package/.claude/skills/install-workflow-skill/SKILL.md +1056 -0
  29. package/.claude/skills/list-apps-skill/SKILL.md +1010 -0
  30. package/.claude/skills/list-workflows-minimal-skill/SKILL.md +992 -0
  31. package/.claude/skills/local-first-skill/SKILL.md +570 -0
  32. package/.claude/skills/mcp-tools/SKILL.md +419 -0
  33. package/.claude/skills/mcp-tools/references/api-endpoints.md +499 -0
  34. package/.claude/skills/mcp-tools/references/data-structures.md +554 -0
  35. package/.claude/skills/mcp-tools/references/implementation-patterns.md +717 -0
  36. package/.claude/skills/preview-insight-skill/SKILL.md +1290 -0
  37. package/.claude/skills/publish-hailer-app-skill/SKILL.md +453 -0
  38. package/.claude/skills/remove-app-member-skill/SKILL.md +671 -0
  39. package/.claude/skills/remove-app-skill/SKILL.md +985 -0
  40. package/.claude/skills/remove-insight-skill/SKILL.md +1011 -0
  41. package/.claude/skills/remove-workflow-skill/SKILL.md +920 -0
  42. package/.claude/skills/scaffold-hailer-app-skill/SKILL.md +1034 -0
  43. package/.claude/skills/skill-testing/README.md +137 -0
  44. package/.claude/skills/skill-testing/SKILL.md +348 -0
  45. package/.claude/skills/skill-testing/references/test-patterns.md +705 -0
  46. package/.claude/skills/skill-testing/references/testing-guide.md +603 -0
  47. package/.claude/skills/skill-testing/references/validation-checklist.md +537 -0
  48. package/.claude/skills/tool-builder/SKILL.md +328 -0
  49. package/.claude/skills/update-app-skill/SKILL.md +970 -0
  50. package/.claude/skills/update-workflow-field-skill/SKILL.md +1098 -0
  51. package/.env.example +81 -0
  52. package/.mcp.json +13 -0
  53. package/README.md +297 -0
  54. package/dist/app.d.ts +4 -0
  55. package/dist/app.js +74 -0
  56. package/dist/cli.d.ts +3 -0
  57. package/dist/cli.js +5 -0
  58. package/dist/client/adaptive-documentation-bot.d.ts +108 -0
  59. package/dist/client/adaptive-documentation-bot.js +475 -0
  60. package/dist/client/adaptive-documentation-types.d.ts +66 -0
  61. package/dist/client/adaptive-documentation-types.js +9 -0
  62. package/dist/client/agent-activity-bot.d.ts +51 -0
  63. package/dist/client/agent-activity-bot.js +166 -0
  64. package/dist/client/agent-tracker.d.ts +499 -0
  65. package/dist/client/agent-tracker.js +659 -0
  66. package/dist/client/description-updater.d.ts +56 -0
  67. package/dist/client/description-updater.js +259 -0
  68. package/dist/client/log-parser.d.ts +72 -0
  69. package/dist/client/log-parser.js +387 -0
  70. package/dist/client/mcp-client.d.ts +50 -0
  71. package/dist/client/mcp-client.js +532 -0
  72. package/dist/client/message-processor.d.ts +35 -0
  73. package/dist/client/message-processor.js +352 -0
  74. package/dist/client/multi-bot-manager.d.ts +24 -0
  75. package/dist/client/multi-bot-manager.js +74 -0
  76. package/dist/client/providers/anthropic-provider.d.ts +19 -0
  77. package/dist/client/providers/anthropic-provider.js +631 -0
  78. package/dist/client/providers/llm-provider.d.ts +47 -0
  79. package/dist/client/providers/llm-provider.js +367 -0
  80. package/dist/client/providers/openai-provider.d.ts +23 -0
  81. package/dist/client/providers/openai-provider.js +621 -0
  82. package/dist/client/simple-llm-caller.d.ts +19 -0
  83. package/dist/client/simple-llm-caller.js +100 -0
  84. package/dist/client/skill-generator.d.ts +81 -0
  85. package/dist/client/skill-generator.js +386 -0
  86. package/dist/client/test-adaptive-bot.d.ts +9 -0
  87. package/dist/client/test-adaptive-bot.js +82 -0
  88. package/dist/client/token-pricing.d.ts +38 -0
  89. package/dist/client/token-pricing.js +127 -0
  90. package/dist/client/token-tracker.d.ts +232 -0
  91. package/dist/client/token-tracker.js +457 -0
  92. package/dist/client/token-usage-bot.d.ts +53 -0
  93. package/dist/client/token-usage-bot.js +153 -0
  94. package/dist/client/tool-executor.d.ts +69 -0
  95. package/dist/client/tool-executor.js +159 -0
  96. package/dist/client/tool-schema-loader.d.ts +60 -0
  97. package/dist/client/tool-schema-loader.js +178 -0
  98. package/dist/client/types.d.ts +69 -0
  99. package/dist/client/types.js +7 -0
  100. package/dist/config.d.ts +162 -0
  101. package/dist/config.js +296 -0
  102. package/dist/core.d.ts +26 -0
  103. package/dist/core.js +147 -0
  104. package/dist/lib/context-manager.d.ts +111 -0
  105. package/dist/lib/context-manager.js +431 -0
  106. package/dist/lib/logger.d.ts +74 -0
  107. package/dist/lib/logger.js +277 -0
  108. package/dist/lib/materialize.d.ts +3 -0
  109. package/dist/lib/materialize.js +101 -0
  110. package/dist/lib/normalizedName.d.ts +7 -0
  111. package/dist/lib/normalizedName.js +48 -0
  112. package/dist/lib/prompt-length-manager.d.ts +81 -0
  113. package/dist/lib/prompt-length-manager.js +457 -0
  114. package/dist/lib/terminal-prompt.d.ts +9 -0
  115. package/dist/lib/terminal-prompt.js +108 -0
  116. package/dist/mcp/UserContextCache.d.ts +56 -0
  117. package/dist/mcp/UserContextCache.js +163 -0
  118. package/dist/mcp/auth.d.ts +2 -0
  119. package/dist/mcp/auth.js +29 -0
  120. package/dist/mcp/hailer-clients.d.ts +42 -0
  121. package/dist/mcp/hailer-clients.js +246 -0
  122. package/dist/mcp/signal-handler.d.ts +45 -0
  123. package/dist/mcp/signal-handler.js +317 -0
  124. package/dist/mcp/tool-registry.d.ts +100 -0
  125. package/dist/mcp/tool-registry.js +306 -0
  126. package/dist/mcp/tools/activity.d.ts +15 -0
  127. package/dist/mcp/tools/activity.js +955 -0
  128. package/dist/mcp/tools/app.d.ts +20 -0
  129. package/dist/mcp/tools/app.js +1488 -0
  130. package/dist/mcp/tools/discussion.d.ts +19 -0
  131. package/dist/mcp/tools/discussion.js +950 -0
  132. package/dist/mcp/tools/file.d.ts +15 -0
  133. package/dist/mcp/tools/file.js +119 -0
  134. package/dist/mcp/tools/insight.d.ts +17 -0
  135. package/dist/mcp/tools/insight.js +806 -0
  136. package/dist/mcp/tools/skill.d.ts +10 -0
  137. package/dist/mcp/tools/skill.js +279 -0
  138. package/dist/mcp/tools/user.d.ts +10 -0
  139. package/dist/mcp/tools/user.js +108 -0
  140. package/dist/mcp/tools/workflow-template.d.ts +19 -0
  141. package/dist/mcp/tools/workflow-template.js +822 -0
  142. package/dist/mcp/tools/workflow.d.ts +18 -0
  143. package/dist/mcp/tools/workflow.js +1362 -0
  144. package/dist/mcp/utils/api-errors.d.ts +45 -0
  145. package/dist/mcp/utils/api-errors.js +160 -0
  146. package/dist/mcp/utils/data-transformers.d.ts +102 -0
  147. package/dist/mcp/utils/data-transformers.js +194 -0
  148. package/dist/mcp/utils/file-upload.d.ts +33 -0
  149. package/dist/mcp/utils/file-upload.js +148 -0
  150. package/dist/mcp/utils/hailer-api-client.d.ts +120 -0
  151. package/dist/mcp/utils/hailer-api-client.js +323 -0
  152. package/dist/mcp/utils/index.d.ts +13 -0
  153. package/dist/mcp/utils/index.js +39 -0
  154. package/dist/mcp/utils/logger.d.ts +42 -0
  155. package/dist/mcp/utils/logger.js +103 -0
  156. package/dist/mcp/utils/types.d.ts +286 -0
  157. package/dist/mcp/utils/types.js +7 -0
  158. package/dist/mcp/workspace-cache.d.ts +42 -0
  159. package/dist/mcp/workspace-cache.js +97 -0
  160. package/dist/mcp-server.d.ts +42 -0
  161. package/dist/mcp-server.js +280 -0
  162. package/package.json +56 -0
  163. package/tsconfig.json +23 -0
@@ -0,0 +1,570 @@
1
+ ---
2
+ name: local-first-skill
3
+ description: Complete guide to local-first data access - check workspace configs before API calls to save tokens and reduce latency
4
+ ---
5
+
6
+ # Local-First Data Access Skill
7
+
8
+ Complete guide to using local workspace configurations before making API calls. This optimization saves 2-3 API calls per operation and hundreds of tokens by reading cached TypeScript files.
9
+
10
+ ## Table of Contents
11
+ - [Quick Reference](#quick-reference)
12
+ - [Overview](#overview)
13
+ - [Helper Functions](#helper-functions)
14
+ - [Decision Tree](#decision-tree)
15
+ - [Common Patterns](#common-patterns)
16
+ - [Benefits](#benefits)
17
+ - [Limitations](#limitations)
18
+ - [Best Practices](#best-practices)
19
+ - [Troubleshooting](#troubleshooting)
20
+
21
+ ## Quick Reference
22
+
23
+ ### Get workflows from local cache
24
+ ```typescript
25
+ const workflows = await getLocalWorkflows() || await list_workflows();
26
+ ```
27
+
28
+ ### Get field definitions from local cache
29
+ ```typescript
30
+ const fields = await getLocalFields("Players") || await get_workflow_schema({...});
31
+ ```
32
+
33
+ ### Get phases from local cache
34
+ ```typescript
35
+ const phases = await getLocalPhases("Players") || await list_workflow_phases({...});
36
+ ```
37
+
38
+ ### Get type-safe enums
39
+ ```typescript
40
+ const enums = await getEnums();
41
+ console.log(enums.Players_FieldIds.player_name_694);
42
+ ```
43
+
44
+ ## Overview
45
+
46
+ The local-first strategy caches workspace metadata (workflows, fields, phases) as TypeScript files that can be imported directly. This eliminates unnecessary API calls for data that rarely changes.
47
+
48
+ **What gets cached:**
49
+ - ✅ Workflow names, IDs, structure
50
+ - ✅ Field definitions (types, labels, keys, options)
51
+ - ✅ Phase definitions (names, IDs, transitions)
52
+ - ✅ Type-safe enums for field/phase IDs
53
+
54
+ **What doesn't get cached:**
55
+ - ❌ Activity data (always from API)
56
+ - ❌ Activity counts (always from API)
57
+ - ❌ Live status information
58
+
59
+ **Performance impact:**
60
+ - **Before**: 4 API calls to list activities (workflows → phases → schema → activities)
61
+ - **After**: 1 API call (activities only)
62
+ - **Savings**: 75% reduction in API calls + hundreds of tokens saved
63
+
64
+ ## Helper Functions
65
+
66
+ Copy these functions to use local-first access:
67
+
68
+ ```typescript
69
+ const WORKSPACE_PATH = process.env.WORKSPACE_CONFIG_PATH || '/home/brodolf/Desktop/footballmanager';
70
+
71
+ /**
72
+ * Get all workflows from local cache
73
+ * Returns: Array of workflow objects with _id, name, folder properties
74
+ * Fallback: list_workflows() API call
75
+ */
76
+ async function getLocalWorkflows() {
77
+ try {
78
+ const { workflows } = await import(`${WORKSPACE_PATH}/workspace/workflows.ts`);
79
+ return workflows;
80
+ } catch (error) {
81
+ console.log('Local workflows not found, falling back to API');
82
+ return null;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Get field definitions for a workflow from local cache
88
+ * @param workflowName - Human-readable workflow name (e.g., "Players")
89
+ * Returns: Array of field objects with _id, key, label, type, data properties
90
+ * Fallback: get_workflow_schema() API call
91
+ */
92
+ async function getLocalFields(workflowName: string) {
93
+ try {
94
+ const workflows = await getLocalWorkflows();
95
+ const workflow = workflows?.find(w => w.name === workflowName);
96
+ if (!workflow) {
97
+ console.log(`Workflow "${workflowName}" not found in local cache`);
98
+ return null;
99
+ }
100
+
101
+ const { fields } = await import(`${WORKSPACE_PATH}/workspace/${workflow.folder}/fields.ts`);
102
+ return fields;
103
+ } catch (error) {
104
+ console.log(`Fields for "${workflowName}" not found, falling back to API`);
105
+ return null;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Get phase definitions for a workflow from local cache
111
+ * @param workflowName - Human-readable workflow name (e.g., "Players")
112
+ * Returns: Array of phase objects with _id, name, isInitial, possibleNextPhase properties
113
+ * Fallback: list_workflow_phases() API call
114
+ */
115
+ async function getLocalPhases(workflowName: string) {
116
+ try {
117
+ const workflows = await getLocalWorkflows();
118
+ const workflow = workflows?.find(w => w.name === workflowName);
119
+ if (!workflow) {
120
+ console.log(`Workflow "${workflowName}" not found in local cache`);
121
+ return null;
122
+ }
123
+
124
+ const { phases } = await import(`${WORKSPACE_PATH}/workspace/${workflow.folder}/phases.ts`);
125
+ return phases;
126
+ } catch (error) {
127
+ console.log(`Phases for "${workflowName}" not found, falling back to API`);
128
+ return null;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Get type-safe enums for all workflows
134
+ * Returns: Object with workflow-specific enum exports (e.g., Players_FieldIds, Players_PhaseIds)
135
+ * Use for type-safe field/phase ID access
136
+ */
137
+ async function getEnums() {
138
+ try {
139
+ return await import(`${WORKSPACE_PATH}/workspace/enums.ts`);
140
+ } catch (error) {
141
+ console.log('Enums not found in local cache');
142
+ return null;
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Get workflow main config (permissions, order, etc.)
148
+ * @param workflowName - Human-readable workflow name
149
+ * Returns: Workflow configuration object
150
+ */
151
+ async function getLocalWorkflowConfig(workflowName: string) {
152
+ try {
153
+ const workflows = await getLocalWorkflows();
154
+ const workflow = workflows?.find(w => w.name === workflowName);
155
+ if (!workflow) return null;
156
+
157
+ const { workflowConfig } = await import(`${WORKSPACE_PATH}/workspace/${workflow.folder}/main.ts`);
158
+ return workflowConfig;
159
+ } catch (error) {
160
+ console.log(`Config for "${workflowName}" not found`);
161
+ return null;
162
+ }
163
+ }
164
+ ```
165
+
166
+ ## Decision Tree
167
+
168
+ Use this flowchart to decide local vs API:
169
+
170
+ ```
171
+ ┌─────────────────────────────┐
172
+ │ What data do you need? │
173
+ └──────────┬──────────────────┘
174
+
175
+ ├─> Workflow list (names, IDs, folders)
176
+ │ → getLocalWorkflows() || list_workflows()
177
+
178
+ ├─> Field definitions (types, labels, keys)
179
+ │ → getLocalFields("WorkflowName") || get_workflow_schema()
180
+
181
+ ├─> Phase definitions (names, transitions)
182
+ │ → getLocalPhases("WorkflowName") || list_workflow_phases()
183
+
184
+ ├─> Type-safe field/phase IDs
185
+ │ → getEnums()
186
+
187
+ └─> Activity data (records, counts, live values)
188
+ → ALWAYS use API (list_activities, show_activity_by_id)
189
+ ```
190
+
191
+ ## Common Patterns
192
+
193
+ ### Pattern 1: List Activities in a Workflow
194
+
195
+ ```typescript
196
+ // ❌ BAD - Makes 4 API calls
197
+ const workflows = await list_workflows();
198
+ const playersWorkflow = workflows.find(w => w.name === "Players");
199
+ const phases = await list_workflow_phases({ workflowId: playersWorkflow._id });
200
+ const schema = await get_workflow_schema({ workflowId: playersWorkflow._id, phaseId: phases[0]._id });
201
+ const activities = await list_activities({ workflowId: playersWorkflow._id, phaseId: phases[0]._id, fields: [...] });
202
+
203
+ // ✅ GOOD - Makes 1 API call
204
+ const workflows = await getLocalWorkflows();
205
+ const playersWorkflow = workflows.find(w => w.name === "Players");
206
+ const phases = await getLocalPhases("Players");
207
+ const fields = await getLocalFields("Players");
208
+ const activities = await list_activities({
209
+ workflowId: playersWorkflow._id,
210
+ phaseId: phases[0]._id,
211
+ fields: fields.slice(0, 5).map(f => f.key)
212
+ });
213
+ ```
214
+
215
+ **Savings**: 3 fewer API calls, ~500-1000 tokens saved
216
+
217
+ ### Pattern 2: Create Activity with Proper Field IDs
218
+
219
+ ```typescript
220
+ // ❌ BAD - Hardcoded field IDs (breaks if schema changes)
221
+ await create_activity({
222
+ workflowId: "691ffdf84217e9e8434e5693",
223
+ fields: {
224
+ "691ffdf84217e9e8434e5694": "Bruno Fernandes",
225
+ "691ffdf84217e9e8434e5695": 8
226
+ }
227
+ });
228
+
229
+ // ✅ GOOD - Use local cache to get field keys
230
+ const fields = await getLocalFields("Players");
231
+ const playerNameField = fields.find(f => f.label === "Player Name");
232
+ const jerseyField = fields.find(f => f.label === "Jersey Number");
233
+
234
+ await create_activity({
235
+ workflowId: "691ffdf84217e9e8434e5693",
236
+ fields: {
237
+ [playerNameField.key]: "Bruno Fernandes",
238
+ [jerseyField.key]: 8
239
+ }
240
+ });
241
+
242
+ // ✅ BEST - Use key property directly (if fields have keys)
243
+ await create_activity({
244
+ workflowId: "691ffdf84217e9e8434e5693",
245
+ fields: {
246
+ playerName: "Bruno Fernandes",
247
+ jerseyNumber: 8
248
+ }
249
+ });
250
+ ```
251
+
252
+ ### Pattern 3: Type-Safe Field Access with Enums
253
+
254
+ ```typescript
255
+ // ✅ EXCELLENT - Type-safe with enums
256
+ const enums = await getEnums();
257
+ const fields = await getLocalFields("Players");
258
+
259
+ // Access field by enum (autocomplete + compile-time safety)
260
+ const playerNameFieldId = enums.Players_FieldIds.player_name_694;
261
+ const activeSquadPhaseId = enums.Players_PhaseIds.active_squad_69f;
262
+
263
+ await list_activities({
264
+ workflowId: "691ffdf84217e9e8434e5693",
265
+ phaseId: activeSquadPhaseId,
266
+ fields: [
267
+ enums.Players_FieldIds.player_name_694,
268
+ enums.Players_FieldIds.jersey_number_695,
269
+ enums.Players_FieldIds.position_696
270
+ ]
271
+ });
272
+ ```
273
+
274
+ ### Pattern 4: Bulk Operations with Field Validation
275
+
276
+ ```typescript
277
+ // ✅ GOOD - Validate field types before bulk create
278
+ const fields = await getLocalFields("Players");
279
+ const positionField = fields.find(f => f.key === "position");
280
+ const validPositions = positionField.data; // ["Goalkeeper", "Defender", "Midfielder", "Forward"]
281
+
282
+ // Validate before creating
283
+ const players = [
284
+ { name: "Player 1", position: "Midfielder" }, // ✅ Valid
285
+ { name: "Player 2", position: "Striker" } // ❌ Invalid - will fail!
286
+ ];
287
+
288
+ // Pre-validate
289
+ players.forEach(p => {
290
+ if (!validPositions.includes(p.position)) {
291
+ console.error(`Invalid position: ${p.position}. Valid: ${validPositions.join(", ")}`);
292
+ }
293
+ });
294
+
295
+ // Then bulk create
296
+ await create_activity({
297
+ workflowId: "xxx",
298
+ activities: players.map(p => ({
299
+ name: p.name,
300
+ fields: { position: p.position }
301
+ }))
302
+ });
303
+ ```
304
+
305
+ ## Benefits
306
+
307
+ ### 1. Performance Improvement
308
+
309
+ | Operation | API Calls (Before) | API Calls (After) | Improvement |
310
+ |-----------|-------------------|-------------------|-------------|
311
+ | List activities | 4 | 1 | 75% faster |
312
+ | Create activity with validation | 3 | 0 + 1 | 66% faster |
313
+ | Update activity field | 2 | 0 + 1 | 50% faster |
314
+ | Bulk operations | N × 3 | 0 + 1 | 90%+ faster |
315
+
316
+ ### 2. Token Savings
317
+
318
+ - Workflow list: ~200-500 tokens saved
319
+ - Field schema: ~300-800 tokens saved
320
+ - Phase definitions: ~100-300 tokens saved
321
+ - **Total per operation**: 600-1600 tokens saved
322
+
323
+ ### 3. Offline Capability
324
+
325
+ Work with workflow structure without network:
326
+ - Browse field definitions
327
+ - Understand phase transitions
328
+ - Validate data against schemas
329
+ - Generate code with type-safe IDs
330
+
331
+ ### 4. Type Safety
332
+
333
+ Enums provide compile-time safety:
334
+ ```typescript
335
+ // TypeScript knows these exist and autocompletes!
336
+ Players_FieldIds.player_name_694
337
+ Players_PhaseIds.active_squad_69f
338
+ ```
339
+
340
+ ## Limitations
341
+
342
+ ### 1. Stale Data Risk
343
+
344
+ **Problem**: Local cache doesn't update automatically when workspace changes.
345
+
346
+ **Solution**: Re-run `/ws-pull` after schema changes:
347
+ ```bash
348
+ /ws-pull # or: npm run ws-pull
349
+ ```
350
+
351
+ **When to refresh:**
352
+ - After adding/removing workflows
353
+ - After adding/removing fields
354
+ - After modifying field types/options
355
+ - After adding/removing phases
356
+
357
+ ### 2. No Activity Data
358
+
359
+ **Problem**: Local cache has no activity records or counts.
360
+
361
+ **Solution**: Always use API for activity operations:
362
+ - `list_activities()` - Get activities
363
+ - `show_activity_by_id()` - Get single activity
364
+ - `create_activity()` - Create activities
365
+ - `update_activity()` - Update activities
366
+
367
+ ### 3. No Live Counts
368
+
369
+ **Problem**: Workflow activity counts in local cache are outdated.
370
+
371
+ **Solution**: Call `list_workflows()` API if you need current counts.
372
+
373
+ ## Best Practices
374
+
375
+ ### ✅ Do This
376
+
377
+ 1. **Always try local first**
378
+ ```typescript
379
+ const data = await getLocalData() || await apiCall();
380
+ ```
381
+
382
+ 2. **Use meaningful workflow names**
383
+ ```typescript
384
+ // ✅ Good - readable
385
+ await getLocalFields("Players")
386
+
387
+ // ❌ Bad - requires ID lookup
388
+ await get_workflow_schema({ workflowId: "691..." })
389
+ ```
390
+
391
+ 3. **Cache helper results if used multiple times**
392
+ ```typescript
393
+ const workflows = await getLocalWorkflows();
394
+ // Use workflows multiple times without re-importing
395
+ ```
396
+
397
+ 4. **Run `/ws-pull` regularly**
398
+ - Daily for active development
399
+ - After schema changes
400
+ - When starting new features
401
+
402
+ 5. **Use enums for type safety**
403
+ ```typescript
404
+ const enums = await getEnums();
405
+ // Use enums.Players_FieldIds.* everywhere
406
+ ```
407
+
408
+ ### ❌ Avoid This
409
+
410
+ 1. **Don't skip local check**
411
+ ```typescript
412
+ // ❌ BAD
413
+ const workflows = await list_workflows();
414
+
415
+ // ✅ GOOD
416
+ const workflows = await getLocalWorkflows() || await list_workflows();
417
+ ```
418
+
419
+ 2. **Don't use local cache for activity data**
420
+ ```typescript
421
+ // ❌ WRONG - activities not in local cache!
422
+ const activities = await getLocalActivities("Players");
423
+
424
+ // ✅ CORRECT
425
+ const activities = await list_activities({...});
426
+ ```
427
+
428
+ 3. **Don't forget to fallback to API**
429
+ ```typescript
430
+ // ❌ BAD - fails if cache missing
431
+ const workflows = await getLocalWorkflows();
432
+
433
+ // ✅ GOOD - graceful fallback
434
+ const workflows = await getLocalWorkflows() || await list_workflows();
435
+ ```
436
+
437
+ 4. **Don't use outdated cache without warning**
438
+ ```typescript
439
+ // ✅ GOOD - Check timestamp
440
+ const cacheAge = Date.now() - fs.statSync(`${WORKSPACE_PATH}/workspace/workflows.ts`).mtimeMs;
441
+ if (cacheAge > 24 * 60 * 60 * 1000) {
442
+ console.warn('Local cache is >24h old. Consider running /ws-pull');
443
+ }
444
+ ```
445
+
446
+ ## Troubleshooting
447
+
448
+ ### Issue: "Cannot find module" error
449
+
450
+ **Symptom:**
451
+ ```
452
+ Error: Cannot find module '/path/to/workspace/workflows.ts'
453
+ ```
454
+
455
+ **Cause**: Local cache doesn't exist or path is wrong.
456
+
457
+ **Solutions:**
458
+ 1. Run `/ws-pull` to download configs
459
+ 2. Check `WORKSPACE_CONFIG_PATH` in `.env.local`
460
+ 3. Verify path exists: `ls $WORKSPACE_CONFIG_PATH/workspace/`
461
+
462
+ ### Issue: Workflow not found by name
463
+
464
+ **Symptom:**
465
+ ```typescript
466
+ const fields = await getLocalFields("Players"); // Returns null
467
+ ```
468
+
469
+ **Cause**: Workflow name doesn't match exactly.
470
+
471
+ **Solutions:**
472
+ 1. Check exact spelling/capitalization
473
+ 2. List available workflows:
474
+ ```typescript
475
+ const workflows = await getLocalWorkflows();
476
+ console.log(workflows.map(w => w.name));
477
+ ```
478
+ 3. Use workflow ID directly if name is ambiguous
479
+
480
+ ### Issue: Field/phase data seems outdated
481
+
482
+ **Symptom**: Local data doesn't match what's in Hailer.
483
+
484
+ **Cause**: Cache is stale (workspace was modified).
485
+
486
+ **Solutions:**
487
+ 1. Re-run `/ws-pull` to refresh
488
+ 2. Compare timestamps:
489
+ ```bash
490
+ ls -la $WORKSPACE_CONFIG_PATH/workspace/
491
+ ```
492
+ 3. For critical operations, use API directly
493
+
494
+ ### Issue: Import fails in production
495
+
496
+ **Symptom**: Works locally but fails in deployed environment.
497
+
498
+ **Cause**: Workspace configs not deployed or path incorrect.
499
+
500
+ **Solutions:**
501
+ 1. Ensure `WORKSPACE_CONFIG_PATH` is set correctly in production
502
+ 2. Copy workspace configs to production environment
503
+ 3. Use API fallback for production reliability
504
+
505
+ ### Issue: Type errors with enums
506
+
507
+ **Symptom:**
508
+ ```typescript
509
+ const enums = await getEnums();
510
+ enums.Players_FieldIds.player_name_694; // Type error
511
+ ```
512
+
513
+ **Cause**: TypeScript doesn't recognize dynamic imports.
514
+
515
+ **Solutions:**
516
+ 1. Use type assertion:
517
+ ```typescript
518
+ const enums = await getEnums() as any;
519
+ ```
520
+ 2. Or use direct imports (static):
521
+ ```typescript
522
+ import { Players_FieldIds } from './workspace/enums';
523
+ ```
524
+
525
+ ## Integration with MCP Tools
526
+
527
+ ### When to use local-first with each tool:
528
+
529
+ | Tool | Local First? | Notes |
530
+ |------|-------------|-------|
531
+ | `list_workflows` | ✅ Yes | Use `getLocalWorkflows()` |
532
+ | `list_workflow_phases` | ✅ Yes | Use `getLocalPhases()` |
533
+ | `get_workflow_schema` | ✅ Yes | Use `getLocalFields()` |
534
+ | `list_activities` | ❌ No | Always API |
535
+ | `show_activity_by_id` | ❌ No | Always API |
536
+ | `create_activity` | Validate with local | Get field types for validation |
537
+ | `update_activity` | Validate with local | Check field types before update |
538
+ | `update_workflow_field` | Check local first | Know current state before update |
539
+
540
+ ## Summary
541
+
542
+ **Key Takeaway**: Always check local cache before API calls for workflow metadata.
543
+
544
+ **Pattern to remember:**
545
+ ```typescript
546
+ const data = await getLocalData() || await apiCall();
547
+ ```
548
+
549
+ **Benefits:**
550
+ - 75% fewer API calls
551
+ - 600-1600 tokens saved per operation
552
+ - Faster response times
553
+ - Offline-capable development
554
+ - Type-safe field/phase access
555
+
556
+ **Next steps:**
557
+ 1. Run `/ws-pull` to set up local cache
558
+ 2. Copy helper functions into your code
559
+ 3. Replace direct API calls with local-first pattern
560
+ 4. Use enums for type-safe IDs
561
+ 5. Refresh cache regularly
562
+
563
+ ---
564
+
565
+ **Related Skills:**
566
+ - `list-workflows-minimal-skill` - Minimal API calls for workflow listing
567
+ - `install-workflow-skill` - Creating workflows (uses local patterns)
568
+ - `update-workflow-field-skill` - Modifying fields (validate with local data)
569
+
570
+ **Last Updated**: 2025-11-24