@hailer/mcp 0.0.4 → 0.0.6
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.
- package/.claude/hooks/post-scaffold-hook.cjs +125 -0
- package/.claude/hooks/prompt-skill-loader.cjs +106 -5
- package/.claude/hooks/publish-template-guard.cjs +123 -0
- package/.claude/hooks/skill-loader.cjs +1 -1
- package/.claude/settings.json +22 -0
- package/.claude/skills/MCP-build-data-app-skill/SKILL.md +372 -0
- package/.claude/skills/MCP-publish-template-skill/SKILL.md +278 -0
- package/.claude/skills/MCP-scaffold-hailer-app-skill/SKILL.md +329 -49
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +274 -9
- package/.claude/skills/hailer-app-builder/SKILL.md +340 -0
- package/.claude/skills/spawn-app-builder/SKILL.md +366 -0
- package/CHANGELOG.md +24 -0
- package/dist/app.js +8 -0
- package/dist/mcp/tools/app.d.ts +7 -0
- package/dist/mcp/tools/app.js +997 -1
- package/package.json +1 -1
|
@@ -7,6 +7,61 @@ description: Complete guide to ONE-SHOT Hailer app creation - scaffolds project,
|
|
|
7
7
|
|
|
8
8
|
Complete guide to using the `scaffold_hailer_app` tool - a ONE-SHOT solution that scaffolds your project, creates the dev app entry in Hailer, shares it with your workspace, updates manifest.json, and starts the dev server automatically.
|
|
9
9
|
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ⚠️ MANDATORY: SPAWN BUILDER AGENT AFTER SCAFFOLDING
|
|
13
|
+
|
|
14
|
+
**THIS IS NOT OPTIONAL.** After `scaffold_hailer_app` completes successfully, you MUST:
|
|
15
|
+
|
|
16
|
+
1. **IMMEDIATELY spawn the app builder agent** using the Task tool
|
|
17
|
+
2. **DO NOT** start building components in the current session
|
|
18
|
+
3. **DO NOT** skip this step
|
|
19
|
+
|
|
20
|
+
### Why This Is Required
|
|
21
|
+
|
|
22
|
+
- The builder agent has **isolated context** for focused work
|
|
23
|
+
- It's **pre-loaded with TypeScript + SDK patterns**
|
|
24
|
+
- Building in main session leads to **context overflow** and **mistakes**
|
|
25
|
+
- The agent produces **higher quality code**
|
|
26
|
+
|
|
27
|
+
### Exact Steps After Scaffold Succeeds
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
// Step 1: Get workflow context (REQUIRED)
|
|
31
|
+
list_workflows_minimal()
|
|
32
|
+
|
|
33
|
+
// Step 2: Spawn the builder agent with Task tool
|
|
34
|
+
Task({
|
|
35
|
+
subagent_type: "general-purpose",
|
|
36
|
+
description: "Build Hailer app components",
|
|
37
|
+
prompt: `You are building a Hailer app.
|
|
38
|
+
|
|
39
|
+
PROJECT: <project-path>
|
|
40
|
+
DESCRIPTION: <from scaffold description>
|
|
41
|
+
WORKFLOWS: <paste list_workflows_minimal output>
|
|
42
|
+
|
|
43
|
+
Load these skills FIRST:
|
|
44
|
+
1. Skill("building-hailer-apps-skill")
|
|
45
|
+
2. Skill("hailer-app-builder")
|
|
46
|
+
|
|
47
|
+
Then build the app components following the patterns in those skills.
|
|
48
|
+
|
|
49
|
+
Requirements:
|
|
50
|
+
- Use Chakra UI for components
|
|
51
|
+
- Follow TypeScript strict mode
|
|
52
|
+
- Use hailer.activity.list(workflowId, phaseId, options) - 3 params
|
|
53
|
+
- Access fields via activity.fields?.[fieldId]
|
|
54
|
+
- Build full CRUD: list, create, edit, delete
|
|
55
|
+
`
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### DO NOT PROCEED WITHOUT SPAWNING
|
|
60
|
+
|
|
61
|
+
If you find yourself writing React components after scaffolding WITHOUT spawning an agent first, **STOP** and spawn the agent.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
10
65
|
## Table of Contents
|
|
11
66
|
- [Quick Reference](#quick-reference)
|
|
12
67
|
- [Overview](#overview)
|
|
@@ -583,6 +638,42 @@ npm run dev
|
|
|
583
638
|
|
|
584
639
|
App is already created in Hailer, just needs server running.
|
|
585
640
|
|
|
641
|
+
### Infinite Loop When Loading Data
|
|
642
|
+
|
|
643
|
+
**Problem:** App keeps re-fetching data infinitely, causing performance issues.
|
|
644
|
+
|
|
645
|
+
**Cause:** Using `hailer` object in useEffect dependencies. The `hailer` object from `useHailer()` changes reference on every render.
|
|
646
|
+
|
|
647
|
+
**Solution:**
|
|
648
|
+
```typescript
|
|
649
|
+
// ❌ WRONG - causes infinite loop
|
|
650
|
+
useEffect(() => {
|
|
651
|
+
if (!hailer) return;
|
|
652
|
+
hailer.activity.list(...);
|
|
653
|
+
}, [hailer]); // hailer changes every render!
|
|
654
|
+
|
|
655
|
+
// ✅ CORRECT - use `inside` and access hailer from window
|
|
656
|
+
useEffect(() => {
|
|
657
|
+
if (!inside) return;
|
|
658
|
+
const hailer = (window as any).hailerApiInstance;
|
|
659
|
+
if (!hailer) return;
|
|
660
|
+
hailer.activity.list(...);
|
|
661
|
+
}, [inside]); // inside is a stable boolean
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### Chakra UI Table Not Showing Text
|
|
665
|
+
|
|
666
|
+
**Problem:** Table rows render but text is invisible/white.
|
|
667
|
+
|
|
668
|
+
**Cause:** CSS inheritance issues when running inside Hailer iframe.
|
|
669
|
+
|
|
670
|
+
**Solution:** Add explicit `color="black"` to Td components:
|
|
671
|
+
```typescript
|
|
672
|
+
<Tr key={activity._id} bg="white">
|
|
673
|
+
<Td color="black">{value}</Td>
|
|
674
|
+
</Tr>
|
|
675
|
+
```
|
|
676
|
+
|
|
586
677
|
### CORS Error When Opening App in Hailer
|
|
587
678
|
|
|
588
679
|
**Problem:** Browser console shows "Access to fetch at 'http://localhost:3000/manifest.json' from origin 'https://next.hailer.com' has been blocked by CORS policy"
|
|
@@ -682,10 +773,10 @@ const activities = await hailer.activity.list(
|
|
|
682
773
|
options // Third parameter: options object
|
|
683
774
|
);
|
|
684
775
|
|
|
685
|
-
// Example with
|
|
776
|
+
// Example with generic IDs (replace with actual IDs from your workspace)
|
|
686
777
|
const activities = await hailer.activity.list(
|
|
687
|
-
|
|
688
|
-
|
|
778
|
+
workflowId, // Get from list_workflows_minimal() or hailer.workflow.list()
|
|
779
|
+
phaseId, // Get from hailer.workflow.get(workflowId).phases
|
|
689
780
|
{
|
|
690
781
|
sortBy: 'created',
|
|
691
782
|
sortOrder: 'asc',
|
|
@@ -752,43 +843,56 @@ const competition = match.competition; // undefined
|
|
|
752
843
|
|
|
753
844
|
### Complete Working Example
|
|
754
845
|
|
|
846
|
+
**⚠️ CRITICAL: Do NOT use `hailer` in useEffect dependencies - it causes infinite loops!**
|
|
847
|
+
|
|
755
848
|
```typescript
|
|
756
|
-
import { useEffect, useState } from 'react';
|
|
849
|
+
import { useEffect, useState, useRef } from 'react';
|
|
757
850
|
import useHailer from './hailer/use-hailer';
|
|
758
851
|
|
|
759
|
-
interface
|
|
852
|
+
// Define your activity interface based on workflow fields
|
|
853
|
+
interface Activity {
|
|
760
854
|
_id: string;
|
|
761
855
|
name: string;
|
|
762
856
|
fields?: {
|
|
763
|
-
|
|
764
|
-
matchDate?: number;
|
|
765
|
-
competition?: string;
|
|
766
|
-
venue?: string;
|
|
857
|
+
[fieldId: string]: { type: string; value: unknown }; // Fields have type and value
|
|
767
858
|
};
|
|
768
859
|
}
|
|
769
860
|
|
|
770
|
-
|
|
861
|
+
interface Props {
|
|
862
|
+
workflowId: string;
|
|
863
|
+
phaseId: string;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
export default function ActivityList({ workflowId, phaseId }: Props) {
|
|
771
867
|
const { hailer, inside } = useHailer();
|
|
772
|
-
const [
|
|
868
|
+
const [activities, setActivities] = useState<Activity[]>([]);
|
|
773
869
|
const [loading, setLoading] = useState(true);
|
|
870
|
+
const loadedRef = useRef(false);
|
|
774
871
|
|
|
775
872
|
useEffect(() => {
|
|
776
|
-
|
|
873
|
+
// ✅ Use `inside` as trigger - it's stable
|
|
874
|
+
if (!inside) return;
|
|
875
|
+
if (loadedRef.current) return;
|
|
777
876
|
|
|
778
|
-
|
|
877
|
+
// ✅ Access hailer from window to avoid reference changes
|
|
878
|
+
const hailerApi = (window as any).hailerApiInstance;
|
|
879
|
+
if (!hailerApi) return;
|
|
880
|
+
|
|
881
|
+
async function fetchActivities() {
|
|
779
882
|
try {
|
|
780
883
|
// ✅ CORRECT: activity.list with separate parameters
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
884
|
+
const result = await hailerApi.activity.list(
|
|
885
|
+
workflowId,
|
|
886
|
+
phaseId,
|
|
784
887
|
{
|
|
785
888
|
sortBy: 'created',
|
|
786
889
|
sortOrder: 'asc',
|
|
787
|
-
limit:
|
|
890
|
+
limit: 50
|
|
788
891
|
}
|
|
789
892
|
);
|
|
790
893
|
|
|
791
|
-
|
|
894
|
+
setActivities(result || []);
|
|
895
|
+
loadedRef.current = true;
|
|
792
896
|
} catch (err) {
|
|
793
897
|
console.error('Failed to fetch:', err);
|
|
794
898
|
} finally {
|
|
@@ -796,19 +900,17 @@ export default function MatchesList() {
|
|
|
796
900
|
}
|
|
797
901
|
}
|
|
798
902
|
|
|
799
|
-
|
|
800
|
-
}, [
|
|
903
|
+
fetchActivities();
|
|
904
|
+
}, [inside, workflowId, phaseId]); // ✅ NO hailer in deps!
|
|
801
905
|
|
|
802
906
|
if (loading) return <div>Loading...</div>;
|
|
803
907
|
|
|
804
908
|
return (
|
|
805
909
|
<div>
|
|
806
|
-
{
|
|
807
|
-
<div key={
|
|
808
|
-
{
|
|
809
|
-
|
|
810
|
-
<p>Competition: {match.fields?.competition}</p>
|
|
811
|
-
<p>Venue: {match.fields?.venue}</p>
|
|
910
|
+
{activities.map((activity) => (
|
|
911
|
+
<div key={activity._id}>
|
|
912
|
+
<h3>{activity.name}</h3>
|
|
913
|
+
{/* Access fields: activity.fields?.[fieldId]?.value */}
|
|
812
914
|
</div>
|
|
813
915
|
))}
|
|
814
916
|
</div>
|
|
@@ -846,14 +948,16 @@ await hailer.activity.update(
|
|
|
846
948
|
await hailer.activity.remove(['activity-id-1', 'activity-id-2']);
|
|
847
949
|
```
|
|
848
950
|
|
|
849
|
-
#### Workflow
|
|
951
|
+
#### Workflow Operations
|
|
850
952
|
|
|
851
953
|
```typescript
|
|
852
|
-
// Get workflow phases
|
|
853
|
-
const
|
|
954
|
+
// Get workflow with fields and phases
|
|
955
|
+
const workflow = await hailer.workflow.get(workflowId);
|
|
956
|
+
// workflow.fields = { fieldId: { label, type, key, ... } }
|
|
957
|
+
// workflow.phases = { phaseId: { name, fields: [...] } }
|
|
854
958
|
|
|
855
|
-
//
|
|
856
|
-
const
|
|
959
|
+
// List all workflows
|
|
960
|
+
const workflows = await hailer.workflow.list();
|
|
857
961
|
```
|
|
858
962
|
|
|
859
963
|
#### User Operations
|
|
@@ -1007,28 +1111,204 @@ That's it! The one-shot approach eliminates all manual setup steps.
|
|
|
1007
1111
|
|
|
1008
1112
|
---
|
|
1009
1113
|
|
|
1010
|
-
## Next Steps:
|
|
1114
|
+
## Next Steps: SPAWN THE BUILDER AGENT (MANDATORY)
|
|
1011
1115
|
|
|
1012
|
-
|
|
1116
|
+
**⚠️ DO NOT BUILD IN CURRENT SESSION.** After scaffolding completes:
|
|
1013
1117
|
|
|
1014
|
-
###
|
|
1118
|
+
### Step 1: Get Workflow Context
|
|
1015
1119
|
|
|
1016
|
-
```
|
|
1017
|
-
|
|
1018
|
-
await get_skill({ skillName: "building-hailer-apps-skill" })
|
|
1120
|
+
```javascript
|
|
1121
|
+
list_workflows_minimal()
|
|
1019
1122
|
```
|
|
1020
1123
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1124
|
+
### Step 2: Spawn the Builder Agent
|
|
1125
|
+
|
|
1126
|
+
```javascript
|
|
1127
|
+
Task({
|
|
1128
|
+
subagent_type: "general-purpose",
|
|
1129
|
+
description: "Build Hailer app components",
|
|
1130
|
+
prompt: `You are building a Hailer app.
|
|
1131
|
+
|
|
1132
|
+
PROJECT PATH: /path/to/project
|
|
1133
|
+
DESCRIPTION: <description from scaffold>
|
|
1134
|
+
APP TYPE: Full CRUD application
|
|
1135
|
+
|
|
1136
|
+
WORKFLOWS IN WORKSPACE:
|
|
1137
|
+
<paste list_workflows_minimal output here>
|
|
1138
|
+
|
|
1139
|
+
## MANDATORY: Load Skills First
|
|
1140
|
+
|
|
1141
|
+
Before writing ANY code, load these skills:
|
|
1142
|
+
1. Skill("building-hailer-apps-skill") - SDK API patterns
|
|
1143
|
+
2. Skill("hailer-app-builder") - TypeScript standards
|
|
1144
|
+
|
|
1145
|
+
## ⚠️ CRITICAL FIRST STEP: Fix main.tsx
|
|
1146
|
+
|
|
1147
|
+
**THE TEMPLATE IS MISSING ChakraProvider!** You MUST fix this FIRST or styles won't work:
|
|
1148
|
+
|
|
1149
|
+
\`\`\`typescript
|
|
1150
|
+
// src/main.tsx - REPLACE the entire file with this:
|
|
1151
|
+
import React from 'react'
|
|
1152
|
+
import ReactDOM from 'react-dom/client'
|
|
1153
|
+
import { ChakraProvider } from '@chakra-ui/react'
|
|
1154
|
+
import App from './App.tsx'
|
|
1155
|
+
import './index.css'
|
|
1156
|
+
|
|
1157
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
1158
|
+
<React.StrictMode>
|
|
1159
|
+
<ChakraProvider>
|
|
1160
|
+
<App />
|
|
1161
|
+
</ChakraProvider>
|
|
1162
|
+
</React.StrictMode>,
|
|
1163
|
+
)
|
|
1164
|
+
\`\`\`
|
|
1165
|
+
|
|
1166
|
+
**If you skip this, the app will render with NO STYLES!**
|
|
1167
|
+
|
|
1168
|
+
## Data Loading Pattern (CRITICAL - PREVENTS INFINITE LOOPS)
|
|
1169
|
+
|
|
1170
|
+
**⚠️ THE `hailer` OBJECT CHANGES ON EVERY RENDER!** Using `hailer` in useEffect dependencies causes infinite loops.
|
|
1171
|
+
|
|
1172
|
+
Use `inside` boolean as the trigger and access hailer from window:
|
|
1173
|
+
|
|
1174
|
+
\`\`\`typescript
|
|
1175
|
+
import { useState, useEffect, useRef } from 'react';
|
|
1176
|
+
|
|
1177
|
+
// Hook takes `inside` boolean, NOT hailer object
|
|
1178
|
+
function useMyData(inside: boolean) {
|
|
1179
|
+
const [data, setData] = useState([]);
|
|
1180
|
+
const [loading, setLoading] = useState(true);
|
|
1181
|
+
const [error, setError] = useState<string | null>(null);
|
|
1182
|
+
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
|
1183
|
+
const loadedRef = useRef(false);
|
|
1184
|
+
|
|
1185
|
+
useEffect(() => {
|
|
1186
|
+
// Use `inside` as trigger - it's a stable boolean
|
|
1187
|
+
if (!inside) return;
|
|
1188
|
+
if (loadedRef.current && refreshTrigger === 0) return;
|
|
1189
|
+
|
|
1190
|
+
// Access hailer from window to avoid reference changes
|
|
1191
|
+
const hailer = (window as any).hailerApiInstance;
|
|
1192
|
+
if (!hailer) return;
|
|
1193
|
+
|
|
1194
|
+
async function loadData() {
|
|
1195
|
+
try {
|
|
1196
|
+
setLoading(true);
|
|
1197
|
+
setError(null);
|
|
1198
|
+
|
|
1199
|
+
// 3 positional params: workflowId, phaseId, options
|
|
1200
|
+
const result = await hailer.activity.list(
|
|
1201
|
+
WORKFLOW_ID,
|
|
1202
|
+
PHASE_ID,
|
|
1203
|
+
{ limit: 100 }
|
|
1204
|
+
);
|
|
1205
|
+
|
|
1206
|
+
setData(result || []);
|
|
1207
|
+
loadedRef.current = true;
|
|
1208
|
+
} catch (err) {
|
|
1209
|
+
setError(err instanceof Error ? err.message : 'Failed to load');
|
|
1210
|
+
} finally {
|
|
1211
|
+
setLoading(false);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
loadData();
|
|
1216
|
+
}, [inside, refreshTrigger]); // ✅ inside is stable, hailer is NOT
|
|
1217
|
+
|
|
1218
|
+
const refresh = () => {
|
|
1219
|
+
loadedRef.current = false;
|
|
1220
|
+
setRefreshTrigger(prev => prev + 1);
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
return { data, loading, error, refresh };
|
|
1224
|
+
}
|
|
1225
|
+
\`\`\`
|
|
1226
|
+
|
|
1227
|
+
**In App.tsx, pass `inside` not `hailer`:**
|
|
1228
|
+
\`\`\`typescript
|
|
1229
|
+
export default function App() {
|
|
1230
|
+
const { hailer, inside } = useHailer();
|
|
1231
|
+
const { data, loading, error } = useMyData(inside); // ✅ Pass inside, not hailer
|
|
1232
|
+
|
|
1233
|
+
if (!hailer || !inside) {
|
|
1234
|
+
return <Spinner />;
|
|
1235
|
+
}
|
|
1236
|
+
// ...
|
|
1237
|
+
}
|
|
1238
|
+
\`\`\`
|
|
1239
|
+
|
|
1240
|
+
**KEY RULES:**
|
|
1241
|
+
1. ❌ NEVER use `hailer` in useEffect dependencies - causes infinite loops
|
|
1242
|
+
2. ✅ Use `inside` boolean as the stable trigger
|
|
1243
|
+
3. ✅ Access hailer via `(window as any).hailerApiInstance` inside useEffect
|
|
1244
|
+
4. ✅ Use `loadedRef` to prevent duplicate loads
|
|
1245
|
+
|
|
1246
|
+
## Field Access Pattern
|
|
1247
|
+
|
|
1248
|
+
Fields are keyed by FIELD IDs, not readable names:
|
|
1249
|
+
|
|
1250
|
+
\`\`\`typescript
|
|
1251
|
+
// Get field IDs from get_workflow_schema() first!
|
|
1252
|
+
const FIELDS = {
|
|
1253
|
+
PLAYER_NAME: '691ffdf84217e9e8434e5694', // From schema
|
|
1254
|
+
JERSEY_NUMBER: '691ffdf84217e9e8434e5695',
|
|
1255
|
+
};
|
|
1256
|
+
|
|
1257
|
+
// Helper function
|
|
1258
|
+
function getFieldValue<T>(fields: Record<string, {value: unknown}> | undefined, fieldId: string): T | null {
|
|
1259
|
+
return (fields?.[fieldId]?.value as T) ?? null;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// Usage
|
|
1263
|
+
const name = getFieldValue<string>(activity.fields, FIELDS.PLAYER_NAME);
|
|
1264
|
+
\`\`\`
|
|
1265
|
+
|
|
1266
|
+
## Requirements
|
|
1267
|
+
|
|
1268
|
+
Build a functional app with:
|
|
1269
|
+
- Dashboard showing overview stats
|
|
1270
|
+
- List view with data from workflows
|
|
1271
|
+
- Proper error handling and loading states
|
|
1272
|
+
- Styled with Chakra UI (AFTER fixing main.tsx!)
|
|
1273
|
+
|
|
1274
|
+
## Technical Requirements
|
|
1275
|
+
|
|
1276
|
+
- Fix main.tsx with ChakraProvider FIRST
|
|
1277
|
+
- Chakra UI components for all UI
|
|
1278
|
+
- TypeScript strict mode (no 'any')
|
|
1279
|
+
- hailer.activity.list(workflowId, phaseId, options) - 3 params
|
|
1280
|
+
- Access fields via getFieldValue helper with field IDs
|
|
1281
|
+
- Simple useEffect pattern (no useCallback/useRef for data loading)
|
|
1282
|
+
|
|
1283
|
+
## Deliverables
|
|
1284
|
+
|
|
1285
|
+
1. **FIRST**: Fix src/main.tsx with ChakraProvider
|
|
1286
|
+
2. Create src/constants.ts with workflow/field IDs
|
|
1287
|
+
3. Create src/hooks/ with data fetching hooks
|
|
1288
|
+
4. Create src/components/ with UI components
|
|
1289
|
+
5. Update src/App.tsx with the dashboard
|
|
1290
|
+
|
|
1291
|
+
## Verification
|
|
1292
|
+
|
|
1293
|
+
After building, the app should:
|
|
1294
|
+
1. Show styled UI (not plain HTML) - confirms ChakraProvider works
|
|
1295
|
+
2. Load data without infinite loops - confirms useEffect pattern works
|
|
1296
|
+
3. Display field values correctly - confirms field access works
|
|
1297
|
+
|
|
1298
|
+
Report back what was created and confirm the 3 checks above pass.
|
|
1299
|
+
`
|
|
1300
|
+
})
|
|
1301
|
+
```
|
|
1302
|
+
|
|
1303
|
+
### Why Spawn Is Required
|
|
1304
|
+
|
|
1305
|
+
| Current Session | Spawned Agent |
|
|
1306
|
+
|-----------------|---------------|
|
|
1307
|
+
| Context gets cluttered | Clean, focused context |
|
|
1308
|
+
| May forget patterns | Skills pre-loaded |
|
|
1309
|
+
| Easier to make mistakes | Follows patterns strictly |
|
|
1310
|
+
| Can't see full picture | Dedicated to this task |
|
|
1028
1311
|
|
|
1029
|
-
|
|
1030
|
-
- `Cannot read properties of undefined (reading 'activity')`
|
|
1031
|
-
- `"processId" must be a string`
|
|
1032
|
-
- Fields showing as `undefined` even though data loads
|
|
1312
|
+
### DO NOT Skip This Step
|
|
1033
1313
|
|
|
1034
|
-
|
|
1314
|
+
If you catch yourself writing components without spawning, **STOP** and spawn the agent first.
|