@eventmodelers/cli 0.0.39 → 1.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 (44) hide show
  1. package/README.md +116 -69
  2. package/cli.js +98 -32
  3. package/package.json +4 -2
  4. package/shared/build-kit/lib/adapters/pocketbase-realtime-adapter.js +29 -0
  5. package/shared/build-kit/lib/adapters/realtime-adapter.js +27 -0
  6. package/shared/build-kit/lib/adapters/supabase-realtime-adapter.js +24 -0
  7. package/shared/build-kit/lib/ralph.js +30 -31
  8. package/shared/build-kit/package.json +3 -1
  9. package/shared/build-kit/ralph-claude.js +63 -5
  10. package/shared/skills/connect/SKILL.md +54 -5
  11. package/shared/skills/learn-eventmodelers-api/SKILL.md +88 -3
  12. package/shared/skills/load-slice/SKILL.md +16 -0
  13. package/shared/skills/update-slice-status/SKILL.md +15 -5
  14. package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/SKILL.md +86 -0
  15. package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +29 -1
  16. package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +47 -5
  17. package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +73 -59
  18. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +1 -1
  19. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +100 -14
  20. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +22 -2
  21. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +1 -1
  22. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +30 -4
  23. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +72 -12
  24. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +66 -9
  25. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +1 -1
  26. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +29 -5
  27. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +9 -1
  28. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +37 -3
  29. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +114 -27
  30. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +1 -1
  31. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +15 -3
  32. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +13 -2
  33. package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +45 -7
  34. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +28 -1
  35. package/stacks/modeling-kit/templates/.claude/skills/html-screen/SKILL.md +45 -19
  36. package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +172 -6
  37. package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +104 -25
  38. package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +31 -17
  39. package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +111 -12
  40. package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/SKILL.md +10 -1
  41. package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +24 -5
  42. package/stacks/modeling-kit/templates/kit/CLAUDE.md +12 -4
  43. package/stacks/node/templates/.claude/skills/build-state-view/SKILL.md +13 -7
  44. package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +13 -7
@@ -5,7 +5,9 @@ description: Add a new attribute or rename an existing attribute across a chain
5
5
 
6
6
  # Attributes
7
7
 
8
- > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, and `BASE_URL`. Do not proceed until the connect skill has completed.
8
+ > **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, and `BASE_URL`. Do not proceed until the connect skill has completed.
9
+
10
+ Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect` skill) — the curl blocks below are the fallback for sessions without MCP connected.
9
11
 
10
12
  You are propagating an attribute change (add or rename) across a chain of elements on an eventmodelers board. You start at the target cell, apply the change, then walk backwards through inbound dependencies until you reach the source cell, applying the change to every element along the way.
11
13
 
@@ -25,7 +27,22 @@ If any of these were already provided in `$ARGUMENTS`, skip asking for them.
25
27
 
26
28
  ---
27
29
 
28
- ## Step 2 — Resolve both cells to nodes
30
+ ## Step 2 — Resolve the chain
31
+
32
+ **Prefer MCP:** `get_attribute_chain` resolves every node between the source and target cells (inclusive), ordered target→source, each with its full `fields[]` — this collapses the manual cell-resolution and inbound-edge walk below into one call. You still need `TIMELINE_ID` (the chapter to search): if multiple chapters exist on the board, resolve which one first (see 2a fallback below, or `mcp__eventmodelers__get_nodes { "boardId": "$BOARD_ID", "type": "CHAPTER" }`) and ask the user if ambiguous.
33
+
34
+ ```
35
+ mcp__eventmodelers__get_attribute_chain {
36
+ "boardId": "$BOARD_ID",
37
+ "timelineId": "$CHAPTER_ID",
38
+ "targetCellName": "<target cell, e.g. B2>",
39
+ "sourceCellName": "<source cell, e.g. A2>"
40
+ }
41
+ ```
42
+
43
+ The result gives you the ordered chain directly — save it as the chain used in Step 4, and skip the manual walk in 2a–3c below. Continue with the fallback only if MCP isn't connected.
44
+
45
+ ### Fallback (no MCP) — resolve both cells to nodes
29
46
 
30
47
  For each cell (target and source), resolve it to a node using the same cell-resolution strategy as the `examples` skill. Always fetch fresh:
31
48
 
@@ -49,7 +66,7 @@ Decode the cell name:
49
66
  s- Find the matching column in `columns` and row in `rows`.
50
67
  - Compute: **`CELL_ID = row.id + "-" + column.id`** (cell IDs are always `<rowId>-<columnId>`).
51
68
 
52
- 3. Always fetch the cell live:
69
+ 3. Always fetch the cell live. No MCP equivalent: `get_nodes` only filters by `type`, not `cellId` — the alternative is `get_node` on the CHAPTER node, reading `meta.timelineData.cells` (a sparse array; an absent cell id means the cell is empty), but that reuses the same chapter fetch from step 2 rather than guaranteeing the freshest live state, so this curl call has no direct MCP replacement:
53
70
  ```bash
54
71
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?cellId=$CELL_ID" \
55
72
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: attributes-skill"
@@ -61,7 +78,7 @@ Save as `TARGET_NODE` and `SOURCE_NODE`.
61
78
 
62
79
  ---
63
80
 
64
- ## Step 3Build the dependency chain
81
+ ### Fallback (no MCP) build the dependency chain
65
82
 
66
83
  Walk backwards from `TARGET_NODE` to `SOURCE_NODE` by following inbound edges. Build an ordered list: `[TARGET_NODE, …intermediate nodes…, SOURCE_NODE]`.
67
84
 
@@ -71,6 +88,13 @@ Each node may have an `edges` array:
71
88
  edges: [{ id, source, target, sourceHandle, targetHandle }]
72
89
  ```
73
90
  An **inbound** edge is one where `edge.target === currentNode.id`. For each inbound edge, fetch the source node:
91
+
92
+ **Prefer MCP:**
93
+ ```
94
+ mcp__eventmodelers__get_node { "boardId": "$BOARD_ID", "nodeId": "$EDGE_SOURCE_ID" }
95
+ ```
96
+
97
+ **Fallback (no MCP):**
74
98
  ```bash
75
99
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$EDGE_SOURCE_ID" \
76
100
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: attributes-skill"
@@ -123,7 +147,25 @@ For each node:
123
147
  - Find the field where `name === oldName` (case-insensitive). If not found in this node, skip it (log it).
124
148
  - Update only the `name` property to `newName`. Leave all other field properties unchanged.
125
149
 
126
- Build the updated `fields` array and send a `node:changed` event using Python to avoid JSON escaping issues:
150
+ Build the updated `fields` array and send a `node:changed` event.
151
+
152
+ **Prefer MCP** — same event body, passed as a tool arg instead of `-d`:
153
+ ```
154
+ mcp__eventmodelers__submit_node_events {
155
+ "boardId": "$BOARD_ID",
156
+ "events": [{
157
+ "id": "<uuid>",
158
+ "eventType": "node:changed",
159
+ "nodeId": "<NODE_ID>",
160
+ "boardId": "$BOARD_ID",
161
+ "timestamp": <epoch-ms>,
162
+ "changedAttributes": ["meta.fields"],
163
+ "meta": { "fields": "<updated_fields_array>" }
164
+ }]
165
+ }
166
+ ```
167
+
168
+ **Fallback (no MCP)** — build the payload with Python to avoid JSON escaping issues, then POST it:
127
169
 
128
170
  ```bash
129
171
  python3 - <<EOF > /tmp/attributes_payload.json
@@ -49,7 +49,9 @@ Do NOT invoke `connect`. Do NOT proceed to Step 1.
49
49
 
50
50
  ## Step 1 — Connect
51
51
 
52
- Invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until all four are available.
52
+ Invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until all four are available.
53
+
54
+ > Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect` skill) — the curl blocks below (Steps 5–7, the eventmodelers board-API calls) are the fallback for sessions without MCP connected. This is unrelated to the browser automation MCP checked in Step 0, which stays as-is.
53
55
 
54
56
  ---
55
57
 
@@ -201,8 +203,14 @@ Discovered N screens across M flows:
201
203
 
202
204
  **If `chapterId` was provided** — use it as the single `CHAPTER_ID` for all screens. Skip this step.
203
205
 
204
- **Otherwise** — for each flow, create one chapter:
206
+ **Otherwise** — for each flow, create one chapter.
207
+
208
+ **Prefer MCP:**
209
+ ```
210
+ mcp__eventmodelers__create_chapter { "boardId": "<BOARD_ID>", "x": 0, "y": 0 }
211
+ ```
205
212
 
213
+ **Fallback (no MCP):**
206
214
  ```bash
207
215
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/chapters" \
208
216
  -H "x-token: $TOKEN" \
@@ -212,8 +220,26 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/chapters" \
212
220
 
213
221
  Extract `id` → `CHAPTER_ID` for this flow.
214
222
 
215
- Update the chapter title to the flow name using `node:changed`:
223
+ Update the chapter title to the flow name using `node:changed`.
216
224
 
225
+ **Prefer MCP:**
226
+ ```
227
+ mcp__eventmodelers__submit_node_events {
228
+ "boardId": "<BOARD_ID>",
229
+ "events": [{
230
+ "id": "<uuid>",
231
+ "eventType": "node:changed",
232
+ "nodeId": "<CHAPTER_ID>",
233
+ "boardId": "<BOARD_ID>",
234
+ "timestamp": <NOW_MS>,
235
+ "changedAttributes": ["meta.title"],
236
+ "meta": { "type": "CHAPTER", "title": "<flow name>" },
237
+ "node": { "id": "<CHAPTER_ID>", "data": {} }
238
+ }]
239
+ }
240
+ ```
241
+
242
+ **Fallback (no MCP):**
217
243
  ```bash
218
244
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
219
245
  -H "x-token: $TOKEN" \
@@ -238,18 +264,24 @@ Save `CHAPTER_ID` against each flow.
238
264
 
239
265
  ## Step 6 — Fetch chapter grid and build column queue
240
266
 
241
- For each chapter, fetch its current grid state:
267
+ For each chapter, fetch its current grid state.
268
+
269
+ **Prefer MCP:**
270
+ ```
271
+ mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }
272
+ ```
242
273
 
274
+ **Fallback (no MCP):**
243
275
  ```bash
244
276
  curl -s -H "x-token: $TOKEN" \
245
277
  "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$CHAPTER_ID"
246
278
  ```
247
279
 
248
280
  From `meta.timelineData`:
249
- - `rows` — find the row with `type === "actor"` → save its `id` as `actorRowId`
250
- - `columns` — ordered list; build an empty-column queue
281
+ - `rows` — find the row with `type === "actor"` → save its `id` as `actorRowId` and its 0-based position in `rows` as `actorRowIndex`
282
+ - `columns` — ordered list; build an empty-column queue, remembering each entry's 0-based position in `columns` as its `columnIndex`
251
283
 
252
- **Cell ID convention**: `<rowId>-<columnId>` — always computed directly, never looked up.
284
+ **Cell ID convention**: `<rowId>-<columnId>` — always computed directly, never looked up. **Cell name convention** (spreadsheet-style, needed for the MCP tool in Step 7b): `<columnLetter><rowNumber>`, where `columnLetter` is `columnIndex` converted to spreadsheet letters (0→A, 1→B, …25→Z, 26→AA, …) and `rowNumber` is `actorRowIndex + 1`.
253
285
 
254
286
  ---
255
287
 
@@ -261,10 +293,17 @@ For each screen:
261
293
 
262
294
  ### 7a — Acquire a column slot
263
295
 
264
- **If the empty-column queue is non-empty** — pop the first entry → `columnId`. Compute `CELL_ID = actorRowId + "-" + columnId`.
296
+ **If the empty-column queue is non-empty** — pop the first entry → `columnId` and its remembered `columnIndex`. Compute `CELL_ID = actorRowId + "-" + columnId` and `CELL_NAME` per the convention above.
297
+
298
+ **If the empty-column queue is empty** — create a new column.
265
299
 
266
- **If the empty-column queue is empty** — create a new column:
300
+ **Prefer MCP:**
301
+ ```
302
+ mcp__eventmodelers__add_column { "boardId": "<BOARD_ID>", "timelineId": "<CHAPTER_ID>" }
303
+ ```
304
+ The result's `index` field is the new column's `columnIndex` (use it directly for `CELL_NAME` — no need to recompute from the full column list).
267
305
 
306
+ **Fallback (no MCP):**
268
307
  ```bash
269
308
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$CHAPTER_ID/columns" \
270
309
  -H "x-token: $TOKEN" \
@@ -273,70 +312,46 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$CHAPTER_I
273
312
  -H "Content-Type: application/json" \
274
313
  -d '{}'
275
314
  ```
315
+ Response includes `{ columnId, index, totalColumns }` — `index` is the new `columnIndex`.
276
316
 
277
- Extract `columnId`. Compute `CELL_ID = actorRowId + "-" + columnId`.
317
+ Extract `columnId`. Compute `CELL_ID = actorRowId + "-" + columnId` and `CELL_NAME` per the convention above.
278
318
 
279
- ### 7b — Generate UUID and upload the screenshot
319
+ ### 7b — Create the SCREEN node with its screenshot, atomically
280
320
 
281
- Generate UUIDs for `SCREEN_NODE_ID` and `EVT_ID`:
321
+ Generate a UUID for `SCREEN_NODE_ID`:
282
322
 
283
323
  ```bash
284
324
  python3 -c "import uuid; print(uuid.uuid4())"
285
325
  ```
286
326
 
287
- Upload the saved screenshot file using `SCREEN_NODE_ID` **before** creating the node:
327
+ This step must create the node and attach the real screenshot in a single call never split into "upload image" then "create node" (or vice versa), which leaves a window where the node exists with no image or an image with no node.
288
328
 
289
- ```bash
290
- curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/images/$SCREEN_NODE_ID" \
291
- -H "x-token: $TOKEN" \
292
- -F "file=@<screen.filepath>"
329
+ **Prefer MCP:**
293
330
  ```
294
-
295
- > **Note**: This uploads the real screenshot to the SCREEN node — it is a different endpoint from the sketch API. The sketch API (`/images/$NODE/sketch`) renders AI-generated wireframe elements. This endpoint (`/images/$NODE`) uploads an actual image file.
296
-
297
- Log success or failure. On failure, note it in the final report but continue.
298
-
299
- ### 7c — Create the SCREEN node
300
-
301
- Now create the SCREEN node using the same `SCREEN_NODE_ID` (the image is already uploaded for it):
302
-
303
- ```bash
304
- curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
305
- -H "x-token: $TOKEN" \
306
- -H "x-board-id: $BOARD_ID" \
307
- -H "x-user-id: discover-storyboard" \
308
- -H "Content-Type: application/json" \
309
- -d '[{
310
- "id": "<EVT_ID>",
311
- "eventType": "node:created",
312
- "nodeId": "<SCREEN_NODE_ID>",
313
- "boardId": "<BOARD_ID>",
314
- "timestamp": <NOW_MS>,
315
- "chapterId": "<CHAPTER_ID>",
316
- "cellId": "<CELL_ID>",
317
- "meta": {
318
- "type": "SCREEN",
319
- "title": "<screen.title>",
320
- "description": "<screen.description — 'Shows X. Arrived via: Y. Actions: user can do A, user can do B.'>"
321
- },
322
- "node": { "id": "<SCREEN_NODE_ID>", "data": {} }
323
- }]'
331
+ mcp__eventmodelers__create_screen {
332
+ "boardId": "<BOARD_ID>",
333
+ "contentType": "image",
334
+ "nodeId": "<SCREEN_NODE_ID>",
335
+ "chapterId": "<CHAPTER_ID>",
336
+ "cellName": "<CELL_NAME>",
337
+ "imageBase64": "<base64-encoded contents of screen.filepath, no data: URI prefix>",
338
+ "mimeType": "image/png",
339
+ "description": "<screen.description — 'Shows X. Arrived via: Y. Actions: user can do A, user can do B.'>"
340
+ }
324
341
  ```
325
342
 
326
- Verify the response contains `"hashes"`. If it fails, log the error and continue to the next screen do not stop the entire run.
327
-
328
- ### 7d — Verify the screen
329
-
330
- Confirm the node and its uploaded screenshot both actually exist:
331
-
343
+ **Fallback (no MCP)** — the same atomic operation via the `image-nodes` endpoint (not the plain `images/:id` endpoint, which only updates an existing node's image and does not place it):
332
344
  ```bash
333
- curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/screens/$SCREEN_NODE_ID/verify" \
334
- -H "x-token: $TOKEN"
345
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/image-nodes/$SCREEN_NODE_ID" \
346
+ -H "x-token: $TOKEN" \
347
+ -F "file=@<screen.filepath>" \
348
+ -F "chapterId=$CHAPTER_ID" \
349
+ -F "cellName=$CELL_NAME"
335
350
  ```
336
351
 
337
- If `valid` is `false`, read the `error` field. If `imageExists` is `false`, the screenshot upload in 7b failed silently retry it once. Log any screen that still fails verification in the final report and continue to the next screen.
352
+ Response: `204` on success. Log failures in the final report but continue to the next screen do not stop the entire run.
338
353
 
339
- ### 7e — Report per-screen progress
354
+ ### 7d — Report per-screen progress
340
355
 
341
356
  After each screen: print one line, e.g.:
342
357
  ```
@@ -355,8 +370,7 @@ Discover Storyboard complete.
355
370
  Flows created (N total):
356
371
  • "Login & Authentication" — chapter <id> — 3 screens
357
372
  • "Product Browsing" — chapter <id> — 5 screens
358
-
359
- Screens uploaded: N of M (list any failures, including screens that failed 7d verification)
373
+ Screens uploaded: N of M (list any failures)
360
374
 
361
375
  Next steps:
362
376
  - Open the board to review the storyboard timelines
@@ -9,7 +9,7 @@ allowed-tools:
9
9
 
10
10
  # Applying Conway's Law
11
11
 
12
- > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Then invoke the `learn-eventmodelers-api` skill to load the full API reference. Do not proceed until both skills have been loaded.
12
+ > **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover don't load it eagerly.
13
13
 
14
14
  ## Interview Phase (Optional)
15
15
 
@@ -9,7 +9,9 @@ allowed-tools:
9
9
 
10
10
  # Brainstorming Events
11
11
 
12
- > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Then invoke the `learn-eventmodelers-api` skill to load the full API reference. Do not proceed until both skills have been loaded.
12
+ > **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover don't load it eagerly.
13
+
14
+ Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect` skill) — the curl blocks below are the fallback for sessions without MCP connected.
13
15
 
14
16
  ## Interview Phase (Optional)
15
17
 
@@ -118,6 +120,12 @@ This section feeds into subsequent steps (plotting, storyboarding, etc.)
118
120
 
119
121
  Before brainstorming, check for EVENT nodes already on the board to avoid duplicating events from a previous session:
120
122
 
123
+ **Prefer MCP:**
124
+ ```
125
+ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "EVENT" }
126
+ ```
127
+
128
+ **Fallback (no MCP):**
121
129
  ```bash
122
130
  curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
123
131
  "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=EVENT"
@@ -125,6 +133,12 @@ curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
125
133
 
126
134
  If events already exist, treat them as the starting list and focus on discovering what might be missing. Also check for existing chapters (timelines) so you can reuse them:
127
135
 
136
+ **Prefer MCP:**
137
+ ```
138
+ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "CHAPTER" }
139
+ ```
140
+
141
+ **Fallback (no MCP):**
128
142
  ```bash
129
143
  curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
130
144
  "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
@@ -147,7 +161,13 @@ If all events belong to a single flow, one timeline is correct — do not split
147
161
 
148
162
  For each group, create a chapter on the board **before placing any events**. Reuse an existing chapter if one already matches the workflow name.
149
163
 
150
- **Create a chapter:**
164
+ **Prefer MCP — create a chapter:**
165
+ ```
166
+ mcp__eventmodelers__create_chapter { "boardId": "<BOARD_ID>", "x": 0, "y": 1200 }
167
+ ```
168
+ (`x`/`y` are optional — see the vertical-stacking note below. Response includes the new `timelineId`.)
169
+
170
+ **Fallback (no MCP) — create a chapter:**
151
171
  ```bash
152
172
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/chapters" \
153
173
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
@@ -156,6 +176,23 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/chapters" \
156
176
  ```
157
177
 
158
178
  **Immediately set its title** (use the workflow / bounded-context name):
179
+
180
+ **Prefer MCP:**
181
+ ```
182
+ mcp__eventmodelers__submit_node_events {
183
+ "boardId": "<BOARD_ID>",
184
+ "events": [{
185
+ "id": "<uuid>",
186
+ "eventType": "node:changed",
187
+ "nodeId": "<chapterId>",
188
+ "boardId": "<BOARD_ID>",
189
+ "timestamp": 1234567890,
190
+ "meta": {"type": "CHAPTER", "title": "Reservation & Lending"}
191
+ }]
192
+ }
193
+ ```
194
+
195
+ **Fallback (no MCP):**
159
196
  ```bash
160
197
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
161
198
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
@@ -171,8 +208,14 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
171
208
  ```
172
209
 
173
210
  **Stack timelines vertically so they do not overlap.**
174
- After creating each chapter, position it below the previous one. Use `y = index * 1200` (0-based creation order), `x = 0`. If existing chapters are already on the board, query their positions first and place the new chapter below the lowest one (`y = maxExistingY + 1200`):
211
+ After creating each chapter, position it below the previous one. Use `y = index * 1200` (0-based creation order), `x = 0`. If existing chapters are already on the board, query their positions first and place the new chapter below the lowest one (`y = maxExistingY + 1200`). Pass this directly as `x`/`y` on `create_chapter` above, or reposition an existing chapter with:
175
212
 
213
+ **Prefer MCP:**
214
+ ```
215
+ mcp__eventmodelers__move_timeline_position { "boardId": "<BOARD_ID>", "timelineId": "<TL>", "x": 0, "y": 1200 }
216
+ ```
217
+
218
+ **Fallback (no MCP):**
176
219
  ```bash
177
220
  curl -s -X PUT "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/position" \
178
221
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
@@ -197,11 +240,11 @@ Fields use this structure inside `meta`:
197
240
  "type": "EVENT",
198
241
  "title": "OrderPlaced",
199
242
  "fields": [
200
- {"name": "orderId", "type": "String", "example": "order-abc123"},
201
- {"name": "customerId", "type": "String", "example": "cust-456"},
202
- {"name": "total", "type": "Number", "example": "149.99"},
203
- {"name": "status", "type": "String", "example": "Draft"},
204
- {"name": "placedAt", "type": "Date", "example": "2026-05-29T10:00:00Z"}
243
+ {"name": "orderId", "type": "String", "example": "order-abc123"},
244
+ {"name": "customerId", "type": "String", "example": "cust-456"},
245
+ {"name": "total", "type": "Decimal", "example": "149.99"},
246
+ {"name": "status", "type": "String", "example": "Draft"},
247
+ {"name": "placedAt", "type": "DateTime", "example": "2026-05-29T10:00:00Z"}
205
248
  ]
206
249
  }
207
250
  ```
@@ -225,6 +268,13 @@ When a chapter is available, place each event directly into it. **Include `cellI
225
268
  For each event:
226
269
 
227
270
  **Step A — Create a column** (append at end of the chapter):
271
+
272
+ **Prefer MCP:**
273
+ ```
274
+ mcp__eventmodelers__add_column { "boardId": "<BOARD_ID>", "timelineId": "<CHAPTER_ID>" }
275
+ ```
276
+
277
+ **Fallback (no MCP):**
228
278
  ```bash
229
279
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$CHAPTER_ID/columns" \
230
280
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: brainstorming-events" \
@@ -233,6 +283,13 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$CHAPTER_I
233
283
  ```
234
284
 
235
285
  **Step B — Fetch the chapter to find the swimlane row ID** (only needed once per chapter):
286
+
287
+ **Prefer MCP:**
288
+ ```
289
+ mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }
290
+ ```
291
+
292
+ **Fallback (no MCP):**
236
293
  ```bash
237
294
  curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
238
295
  "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$CHAPTER_ID"
@@ -241,7 +298,36 @@ curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
241
298
 
242
299
  **Step C — Compute:** `cellId = swimlaneRow.id + "-" + columnId`
243
300
 
244
- **Step D — Create the event with `cellId`:**
301
+ **Step D — Create the event with `cellId`.**
302
+
303
+ **Prefer MCP** — pass the same shape to `submit_node_events` (`events` is a tool arg, not a `-d` body):
304
+ ```
305
+ mcp__eventmodelers__submit_node_events {
306
+ "boardId": "<BOARD_ID>",
307
+ "events": [{
308
+ "id": "<event-uuid>",
309
+ "eventType": "node:created",
310
+ "nodeId": "<node-uuid>",
311
+ "boardId": "<BOARD_ID>",
312
+ "timestamp": 1234567890,
313
+ "chapterId": "<chapterId>",
314
+ "cellId": "<swimlaneRowId>-<columnId>",
315
+ "meta": {
316
+ "type": "EVENT",
317
+ "title": "BookReserved",
318
+ "fields": [
319
+ {"name": "reservationId", "type": "String", "example": "res-789"},
320
+ {"name": "copyId", "type": "String", "example": "copy-42"},
321
+ {"name": "memberId", "type": "String", "example": "mbr-101"},
322
+ {"name": "expiresAt", "type": "DateTime", "example": "2026-06-01T00:00:00Z"},
323
+ {"name": "reservedAt", "type": "DateTime", "example": "2026-05-29T10:00:00Z"}
324
+ ]
325
+ }
326
+ }]
327
+ }
328
+ ```
329
+
330
+ **Fallback (no MCP) — same body via `POST .../nodes/events`:**
245
331
  ```json
246
332
  [{
247
333
  "id": "<event-uuid>",
@@ -255,11 +341,11 @@ curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
255
341
  "type": "EVENT",
256
342
  "title": "BookReserved",
257
343
  "fields": [
258
- {"name": "reservationId", "type": "String", "example": "res-789"},
259
- {"name": "copyId", "type": "String", "example": "copy-42"},
260
- {"name": "memberId", "type": "String", "example": "mbr-101"},
261
- {"name": "expiresAt", "type": "Date", "example": "2026-06-01T00:00:00Z"},
262
- {"name": "reservedAt", "type": "Date", "example": "2026-05-29T10:00:00Z"}
344
+ {"name": "reservationId", "type": "String", "example": "res-789"},
345
+ {"name": "copyId", "type": "String", "example": "copy-42"},
346
+ {"name": "memberId", "type": "String", "example": "mbr-101"},
347
+ {"name": "expiresAt", "type": "DateTime", "example": "2026-06-01T00:00:00Z"},
348
+ {"name": "reservedAt", "type": "DateTime", "example": "2026-05-29T10:00:00Z"}
263
349
  ]
264
350
  }
265
351
  }]
@@ -8,12 +8,22 @@ allowed-tools:
8
8
 
9
9
  # Checking Completeness
10
10
 
11
- > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Then invoke the `learn-eventmodelers-api` skill to load the full API reference. Do not proceed until both skills have been loaded.
11
+ > **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover don't load it eagerly.
12
+
13
+ Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect` skill) — the curl blocks below are the fallback for sessions without MCP connected.
12
14
 
13
15
  ## Board Context
14
16
 
15
17
  Before starting, read the current board state to drive the analysis from what is actually on the board rather than relying solely on conversation context:
16
18
 
19
+ **Prefer MCP:**
20
+ ```
21
+ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "EVENT" }
22
+ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "COMMAND" }
23
+ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "READMODEL" }
24
+ ```
25
+
26
+ **Fallback (no MCP):**
17
27
  ```bash
18
28
  # All nodes (events, commands, read models, screens)
19
29
  curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
@@ -152,6 +162,16 @@ Status: All fields sourced
152
162
 
153
163
  Every column that holds a COMMAND or READMODEL node must have a slice defined (a SLICE_BORDER node on that column) — otherwise it can never be built as a feature. Skip columns whose COMMAND/READMODEL node has `data.linkedTo` set: it's a linked copy (see Board Context above), and only the original's column needs a slice.
154
164
 
165
+ **Prefer MCP** — `list_slices` is lighter than filtering all nodes, and also returns each slice's status:
166
+ ```
167
+ mcp__eventmodelers__list_slices { "boardId": "<BOARD_ID>" }
168
+ ```
169
+ Or, to get the full SLICE_BORDER nodes (with `columnId`) the same way as the curl fallback:
170
+ ```
171
+ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "SLICE_BORDER" }
172
+ ```
173
+
174
+ **Fallback (no MCP):**
155
175
  ```bash
156
176
  curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
157
177
  "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=SLICE_BORDER"
@@ -435,7 +455,7 @@ Present as:
435
455
  ### Issues Found
436
456
  1. Estimated delivery date missing
437
457
  - Fix: Add to OrderShipped event
438
- - Type: string (ISO 8601 date)
458
+ - Type: DateTime (ISO 8601)
439
459
  - Source: Calculated from carrier API
440
460
  - Status: Will add in next iteration
441
461
 
@@ -9,7 +9,7 @@ allowed-tools:
9
9
 
10
10
  # Designing Event Models
11
11
 
12
- > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Then invoke the `learn-eventmodelers-api` skill to load the full API reference. Do not proceed until both skills have been loaded.
12
+ > **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover don't load it eagerly.
13
13
 
14
14
  ## Interview Phase (Optional)
15
15
 
@@ -9,7 +9,9 @@ allowed-tools:
9
9
 
10
10
  # Elaborating Scenarios
11
11
 
12
- > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Then invoke the `learn-eventmodelers-api` skill to load the full API reference. Do not proceed until both skills have been loaded.
12
+ > **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover don't load it eagerly.
13
+
14
+ Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect` skill) — the curl blocks below are the fallback for sessions without MCP connected.
13
15
 
14
16
  ## Interview Phase (Optional)
15
17
 
@@ -571,8 +573,14 @@ After designing all scenarios, post them to the board using the timeline/column
571
573
 
572
574
  ### Step 1 — Identify the target timeline and column
573
575
 
574
- Fetch all CHAPTER nodes to find the timeline:
576
+ Fetch all CHAPTER nodes to find the timeline.
577
+
578
+ **Prefer MCP:**
579
+ ```
580
+ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "CHAPTER" }
581
+ ```
575
582
 
583
+ **Fallback (no MCP):**
576
584
  ```bash
577
585
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER" \
578
586
  -H "x-token: $TOKEN"
@@ -584,8 +592,14 @@ For each command or view being specified, find its column: fetch the chapter nod
584
592
 
585
593
  ### Step 2 — Load valid step elements
586
594
 
587
- For each target timeline, call spec-info to discover the node IDs that may appear in given/when/then:
595
+ For each target timeline, call spec-info to discover the node IDs that may appear in given/when/then.
588
596
 
597
+ **Prefer MCP:**
598
+ ```
599
+ mcp__eventmodelers__get_spec_info { "boardId": "<BOARD_ID>", "timelineId": "<TL>" }
600
+ ```
601
+
602
+ **Fallback (no MCP):**
589
603
  ```bash
590
604
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/spec-info" \
591
605
  -H "x-token: $TOKEN"
@@ -602,8 +616,20 @@ See `learn-eventmodelers-api` for the full step item format, scenario object sha
602
616
 
603
617
  ### Step 4 — Post all scenarios for a column in one call
604
618
 
605
- Group all scenarios for the same column and POST them as an array. The SCENARIO spec node is created automatically — no pre-creation needed.
619
+ Group all scenarios for the same column and post them as an array. The SCENARIO spec node is created automatically — no pre-creation needed.
620
+
621
+ **Prefer MCP:**
622
+ ```
623
+ mcp__eventmodelers__add_scenario {
624
+ "boardId": "<BOARD_ID>",
625
+ "timelineId": "<TL>",
626
+ "columnId": "<COL>",
627
+ "scenarios": [...scenario objects, same shape as below...]
628
+ }
629
+ ```
630
+ `given`/`when`/`then` are arrays of `{id, title?, type?, ...}` objects — **not** bare nodeId strings (this differs from the raw REST body shown in the fallback below). The examples in Steps 4b/4c/§Rejection already use this object shape; pass them straight through as the `scenarios` array. For a state-view scenario whose `when` needs to represent a query rather than a COMMAND, `when` may hold a single inline object that is **not** a board node: `{"id": "<generated-uuid>", "type": "QUERY", "title": "...", "fields": [{"name": "...", "example": "..."}]}`. Same server-side rules apply either way (see below).
606
631
 
632
+ **Fallback (no MCP):**
607
633
  ```bash
608
634
  curl -s -X POST \
609
635
  "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/columns/$COL/scenarios" \