@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
@@ -9,7 +9,9 @@ allowed-tools:
9
9
 
10
10
  # Identifying Inputs
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
 
@@ -342,11 +344,11 @@ If an event field has **no** corresponding command field and **no** derivation r
342
344
  "type": "COMMAND",
343
345
  "title": "ReserveBike",
344
346
  "fields": [
345
- {"name": "customerId", "type": "String", "example": "cust-42", "mapping": "session:customerId", "generated": false},
346
- {"name": "bikeId", "type": "String", "example": "bike-17", "mapping": "user-input", "generated": false},
347
- {"name": "stationId", "type": "String", "example": "stn-03", "mapping": "user-input", "generated": false},
348
- {"name": "startTime", "type": "Date", "example": "2026-06-01T09:00:00Z", "mapping": "user-input", "generated": false},
349
- {"name": "endTime", "type": "Date", "example": "2026-06-01T17:00:00Z", "mapping": "user-input", "generated": false}
347
+ {"name": "customerId", "type": "String", "example": "cust-42", "mapping": "session:customerId", "generated": false},
348
+ {"name": "bikeId", "type": "String", "example": "bike-17", "mapping": "user-input", "generated": false},
349
+ {"name": "stationId", "type": "String", "example": "stn-03", "mapping": "user-input", "generated": false},
350
+ {"name": "startTime", "type": "DateTime", "example": "2026-06-01T09:00:00Z", "mapping": "user-input", "generated": false},
351
+ {"name": "endTime", "type": "DateTime", "example": "2026-06-01T17:00:00Z", "mapping": "user-input", "generated": false}
350
352
  ]
351
353
  }
352
354
  ```
@@ -366,7 +368,41 @@ Commands go in the `interaction` lane — same column as their resulting event.
366
368
 
367
369
  **Every `node:created` call MUST include `cellId`.** Without it the node has no cell reference and will appear stranded at position 0,0 — not in any timeline column.
368
370
 
369
- Commands go in the **interaction lane**, same column as the event they produce. Before creating each command:
371
+ Commands go in the **interaction lane**, same column as the event they produce.
372
+
373
+ **Prefer MCP** — `place_element` collapses the entire find-row → find/append-column → compute-cellId → create-node → auto-connect sequence (Steps A–D below) into one call:
374
+ ```
375
+ mcp__eventmodelers__place_element {
376
+ "boardId": "<BOARD_ID>",
377
+ "timelineId": "<CHAPTER_ID>",
378
+ "elementType": "COMMAND",
379
+ "title": "ReserveBike"
380
+ }
381
+ ```
382
+ `place_element` finds/creates the empty cell in the interaction lane in the correct column and places the node — but it does not accept `fields`. Immediately follow up with `submit_node_events` (`node:changed`) to set `meta.fields` (with `mapping`/`generated`/`cardinality` per the rules above) on the node it returned:
383
+ ```
384
+ mcp__eventmodelers__submit_node_events {
385
+ "boardId": "<BOARD_ID>",
386
+ "events": [{
387
+ "id": "<event-uuid>",
388
+ "eventType": "node:changed",
389
+ "nodeId": "<returned-node-id>",
390
+ "boardId": "<BOARD_ID>",
391
+ "timestamp": 1234567890,
392
+ "meta": {
393
+ "type": "COMMAND",
394
+ "title": "ReserveBike",
395
+ "fields": [
396
+ {"name": "customerId", "type": "String", "example": "cust-42", "mapping": "session:customerId"},
397
+ {"name": "bikeId", "type": "String", "example": "bike-17", "mapping": "user-input"},
398
+ {"name": "startTime", "type": "DateTime", "example": "2026-06-01T09:00:00Z","mapping": "user-input"}
399
+ ]
400
+ }
401
+ }]
402
+ }
403
+ ```
404
+
405
+ **Fallback (no MCP)** — the full manual sequence `place_element` replaces. Before creating each command:
370
406
 
371
407
  **Step A — Find the event's column ID.** Query the event node to read its current cell:
372
408
  ```bash
@@ -406,9 +442,9 @@ curl -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
406
442
  "type": "COMMAND",
407
443
  "title": "ReserveBike",
408
444
  "fields": [
409
- {"name": "customerId", "type": "String", "example": "cust-42", "mapping": "session:customerId"},
410
- {"name": "bikeId", "type": "String", "example": "bike-17", "mapping": "user-input"},
411
- {"name": "startTime", "type": "Date", "example": "2026-06-01T09:00:00Z","mapping": "user-input"}
445
+ {"name": "customerId", "type": "String", "example": "cust-42", "mapping": "session:customerId"},
446
+ {"name": "bikeId", "type": "String", "example": "bike-17", "mapping": "user-input"},
447
+ {"name": "startTime", "type": "DateTime", "example": "2026-06-01T09:00:00Z","mapping": "user-input"}
412
448
  ]
413
449
  }
414
450
  }]'
@@ -432,7 +468,18 @@ The timeline must always read left-to-right: SCREEN and COMMAND belong in the sa
432
468
 
433
469
  After `place-element` returns the COMMAND node ID, create the arrows that complete the slice:
434
470
 
435
- 1. **SCREEN → COMMAND** — find the SCREEN node in the actor row of the same column:
471
+ 1. **SCREEN → COMMAND** — find the SCREEN node in the actor row of the same column.
472
+
473
+ **Prefer MCP** — there is no `cellId` filter on `get_nodes` (see note below), so read the chapter's cell map instead:
474
+ ```
475
+ mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }
476
+ ```
477
+ Read `meta.timelineData.cells["<actorRowId>-<columnId>"]` for the occupying node id (a cell id absent from that sparse array is empty — no SCREEN placed yet). Then connect with the type-checked edge tool, which auto-corrects direction and skips duplicates:
478
+ ```
479
+ mcp__eventmodelers__set_connection { "boardId": "<BOARD_ID>", "source": "<screenNodeId>", "target": "<commandNodeId>", "action": "connect" }
480
+ ```
481
+
482
+ **Fallback (no MCP):**
436
483
  ```bash
437
484
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?cellId=<actorRowId>-<columnId>" \
438
485
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-inputs"
@@ -445,7 +492,18 @@ After `place-element` returns the COMMAND node ID, create the arrows that comple
445
492
  -d '{"source":"<screenNodeId>","target":"<commandNodeId>"}'
446
493
  ```
447
494
 
448
- 2. **COMMAND → EVENT** — find the EVENT node in the swimlane row of the same column:
495
+ 2. **COMMAND → EVENT** — find the EVENT node in the swimlane row of the same column.
496
+
497
+ **Prefer MCP** — same cell-map lookup, then connect:
498
+ ```
499
+ mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }
500
+ ```
501
+ Read `meta.timelineData.cells["<swimlaneRowId>-<columnId>"]` for the occupying node id, then:
502
+ ```
503
+ mcp__eventmodelers__set_connection { "boardId": "<BOARD_ID>", "source": "<commandNodeId>", "target": "<eventNodeId>", "action": "connect" }
504
+ ```
505
+
506
+ **Fallback (no MCP):**
449
507
  ```bash
450
508
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?cellId=<swimlaneRowId>-<columnId>" \
451
509
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-inputs"
@@ -458,6 +516,8 @@ After `place-element` returns the COMMAND node ID, create the arrows that comple
458
516
  -d '{"source":"<commandNodeId>","target":"<eventNodeId>"}'
459
517
  ```
460
518
 
519
+ *Note:* `get_nodes` has no `cellId` filter (only `type`) — the `get_node`-on-CHAPTER + `meta.timelineData.cells` lookup above is the only way to check single-cell occupancy via MCP.
520
+
461
521
  Skip a connection silently if the target cell is empty (the element may be placed in a later step). Log each created arrow: `→ connected SCREEN→COMMAND "PlaceOrder"` or `→ connected COMMAND→EVENT "PlaceOrder"→"OrderPlaced"`.
462
522
 
463
523
  After all commands are placed and wired, present the Command Catalog summary as text to the user.
@@ -9,7 +9,9 @@ allowed-tools:
9
9
 
10
10
  # Identifying Outputs
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
 
@@ -408,12 +410,12 @@ Every field must also set `"cardinality"` — use `"Single"` unless the field ge
408
410
  "type": "READMODEL",
409
411
  "title": "ActiveReservationView",
410
412
  "fields": [
411
- {"name": "reservationId", "type": "String", "example": "res-001", "mapping": "BikeReserved.reservationId", "generated": false},
412
- {"name": "customerId", "type": "String", "example": "cust-42", "mapping": "BikeReserved.customerId", "generated": false},
413
- {"name": "bikeId", "type": "String", "example": "bike-17", "mapping": "BikeReserved.bikeId", "generated": false},
414
- {"name": "stationId", "type": "String", "example": "stn-03", "mapping": "BikeReserved.stationId", "generated": false},
415
- {"name": "expiresAt", "type": "Date", "example": "2026-06-01T09:30:00Z", "mapping": "ReservationConfirmed.expiresAt", "generated": false},
416
- {"name": "status", "type": "String", "example": "confirmed", "mapping": "latest:ReservationConfirmed.status", "generated": false}
413
+ {"name": "reservationId", "type": "String", "example": "res-001", "mapping": "BikeReserved.reservationId", "generated": false},
414
+ {"name": "customerId", "type": "String", "example": "cust-42", "mapping": "BikeReserved.customerId", "generated": false},
415
+ {"name": "bikeId", "type": "String", "example": "bike-17", "mapping": "BikeReserved.bikeId", "generated": false},
416
+ {"name": "stationId", "type": "String", "example": "stn-03", "mapping": "BikeReserved.stationId", "generated": false},
417
+ {"name": "expiresAt", "type": "DateTime", "example": "2026-06-01T09:30:00Z", "mapping": "ReservationConfirmed.expiresAt", "generated": false},
418
+ {"name": "status", "type": "String", "example": "confirmed", "mapping": "latest:ReservationConfirmed.status", "generated": false}
417
419
  ]
418
420
  }
419
421
  ```
@@ -428,6 +430,35 @@ Read models go in the `interaction` lane — **in the same column as the SCREEN
428
430
 
429
431
  **For a READMODEL** (interaction lane):
430
432
 
433
+ **Prefer MCP** — `place_element` collapses finding/creating the empty interaction cell (including inserting a new column when the target column is already occupied by a COMMAND) and creating the node into one call:
434
+ ```
435
+ mcp__eventmodelers__place_element {
436
+ "boardId": "<BOARD_ID>",
437
+ "timelineId": "<CHAPTER_ID>",
438
+ "elementType": "READMODEL",
439
+ "title": "ActiveReservationView",
440
+ "columnIndex": <consumerScreenOrAutomationColumnIndex>
441
+ }
442
+ ```
443
+ Then set `meta.fields` (with `mapping`/`generated`/`cardinality`) on the returned node id:
444
+ ```
445
+ mcp__eventmodelers__submit_node_events {
446
+ "boardId": "<BOARD_ID>",
447
+ "events": [{
448
+ "id": "<event-uuid>", "eventType": "node:changed", "nodeId": "<returned-node-id>",
449
+ "boardId": "<BOARD_ID>", "timestamp": 1234567890,
450
+ "meta": {"type": "READMODEL", "title": "ActiveReservationView", "fields": [...]}
451
+ }]
452
+ }
453
+ ```
454
+ To determine the consumer's column index beforehand, or to check whether a specific interaction cell is already occupied (there is no `cellId` filter on `get_nodes` — see the note under "Wire connections" below), fetch the chapter and read its cell map:
455
+ ```
456
+ mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }
457
+ # → meta.timelineData.rows (find "interaction"/"actor" rows) and meta.timelineData.cells (sparse; absent id = empty)
458
+ ```
459
+
460
+ **Fallback (no MCP)** — the full manual sequence:
461
+
431
462
  1. Find the column where the consumer SCREEN or AUTOMATION lives. Fetch the timeline to get the interaction row ID:
432
463
  ```bash
433
464
  curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
@@ -460,6 +491,9 @@ Read models go in the `interaction` lane — **in the same column as the SCREEN
460
491
 
461
492
  **For an AUTOMATION** (actor lane, same column as its READMODEL):
462
493
 
494
+ **Prefer MCP** — same `place_element` call with `"elementType": "AUTOMATION"`, then `submit_node_events` for fields, as above.
495
+
496
+ **Fallback (no MCP):**
463
497
  1. Get the actor row ID from the same timeline fetch (row where `type === "actor"`).
464
498
  2. `cellId = actorRow.id + "-" + columnId`
465
499
  3. Create the AUTOMATION node using the same `node:created` pattern above with `"type": "AUTOMATION"` in `meta`.
@@ -492,7 +526,16 @@ For each view screen S that queries this read model:
492
526
 
493
527
  After `place-element` returns the READMODEL node ID, create the arrows that complete the slice:
494
528
 
495
- 1. **EVENT → READMODEL** — find the primary source EVENT node in the swimlane row of the same column:
529
+ 1. **EVENT → READMODEL** — find the primary source EVENT node in the swimlane row of the same column.
530
+
531
+ **Prefer MCP** — `get_nodes` has no `cellId` filter (only `type`); look up occupancy via the chapter's cell map instead, then connect with the type-checked edge tool (auto-corrects direction, skips duplicates):
532
+ ```
533
+ mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }
534
+ # → read meta.timelineData.cells["<swimlaneRowId>-<columnId>"] for the occupying node id
535
+ mcp__eventmodelers__set_connection { "boardId": "<BOARD_ID>", "source": "<eventNodeId>", "target": "<readmodelNodeId>", "action": "connect" }
536
+ ```
537
+
538
+ **Fallback (no MCP):**
496
539
  ```bash
497
540
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?cellId=<swimlaneRowId>-<columnId>" \
498
541
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-outputs"
@@ -505,7 +548,14 @@ After `place-element` returns the READMODEL node ID, create the arrows that comp
505
548
  -d '{"source":"<eventNodeId>","target":"<readmodelNodeId>"}'
506
549
  ```
507
550
 
508
- 2. **READMODEL → SCREEN** — connect to the existing SCREEN node in the actor row of the next column (screens are typically already placed from Step 3):
551
+ 2. **READMODEL → SCREEN** — connect to the existing SCREEN node in the actor row of the next column (screens are typically already placed from Step 3).
552
+
553
+ **Prefer MCP:**
554
+ ```
555
+ mcp__eventmodelers__set_connection { "boardId": "<BOARD_ID>", "source": "<readmodelNodeId>", "target": "<screenNodeId>", "action": "connect" }
556
+ ```
557
+
558
+ **Fallback (no MCP):**
509
559
  ```bash
510
560
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/connections" \
511
561
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-outputs" \
@@ -516,6 +566,13 @@ After `place-element` returns the READMODEL node ID, create the arrows that comp
516
566
  3. **READMODEL → AUTOMATION** — if the read model is consumed by an automatic process (scheduler, background job, external trigger), place the AUTOMATION node and connect it:
517
567
  - Place the AUTOMATION in the automation lane, in the column immediately to the right of its read model (same rule as screens).
518
568
  - Then connect:
569
+
570
+ **Prefer MCP:**
571
+ ```
572
+ mcp__eventmodelers__set_connection { "boardId": "<BOARD_ID>", "source": "<readmodelNodeId>", "target": "<automationNodeId>", "action": "connect" }
573
+ ```
574
+
575
+ **Fallback (no MCP):**
519
576
  ```bash
520
577
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/connections" \
521
578
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-outputs" \
@@ -9,7 +9,7 @@ allowed-tools:
9
9
 
10
10
  # Integrating Legacy Systems
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 (Critical - Not Optional)
15
15
 
@@ -9,7 +9,9 @@ allowed-tools:
9
9
 
10
10
  # Orchestrating Event Modeling
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
  Coordinates the 10-step Event Modeling workflow. Each step delegates to a
15
17
  specialized skill — this skill holds the sequence, transition conditions, and
@@ -37,7 +39,15 @@ Placing all read models in new columns at the very end of the timeline severs th
37
39
 
38
40
  After each step that creates elements (Steps 1–5), scan for any nodes that have no cell reference and are stranded at the default canvas position (0,0). These arise when `node:created` is called without `cellId`.
39
41
 
40
- For each timeline in scope, check all node types that should be in cells:
42
+ For each timeline in scope, check all node types that should be in cells.
43
+
44
+ **Prefer MCP:** call `get_nodes` once per type (each call returns the full node objects, including `meta.chapterId`/cell placement, so no separate cell-occupancy lookup is needed):
45
+ ```
46
+ mcp__eventmodelers__get_nodes { "boardId": "$BOARD_ID", "type": "EVENT" }
47
+ ```
48
+ Repeat with `"type": "COMMAND"`, `"READMODEL"`, `"SCREEN"`, `"AUTOMATION"`.
49
+
50
+ **Fallback (no MCP):**
41
51
  ```bash
42
52
  for TYPE in EVENT COMMAND READMODEL SCREEN AUTOMATION; do
43
53
  curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
@@ -48,7 +58,14 @@ done
48
58
  For each returned node, check whether it has a valid cell assignment. A node without a `cellId` (or with `chapterId` missing) is unplaced.
49
59
 
50
60
  **For each unplaced node:**
51
- - **If it belongs in the current model** → compute the correct `cellId` and call `node:changed` to assign it:
61
+ - **If it belongs in the current model** → compute the correct `cellId` and place it.
62
+
63
+ **Prefer MCP:** the node already exists but has never been assigned a cell, so this is a placement, not a repositioning — use `drop_node_to_cell` (not `move_node_in_timeline`, which is for moving a node that already occupies a different cell):
64
+ ```
65
+ mcp__eventmodelers__drop_node_to_cell { "boardId": "$BOARD_ID", "timelineId": "<chapterId>", "cellId": "<rowId>-<colId>", "nodeId": "<nodeId>", "nodeType": "<TYPE>" }
66
+ ```
67
+
68
+ **Fallback (no MCP):**
52
69
  ```bash
53
70
  curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
54
71
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: orchestrator" \
@@ -57,7 +74,14 @@ For each returned node, check whether it has a valid cell assignment. A node wit
57
74
  "timestamp":1234567890,"chapterId":"<chapterId>","cellId":"<rowId>-<colId>",
58
75
  "meta":{"type":"<TYPE>","title":"<title>"}}]'
59
76
  ```
60
- - **If it is an orphan (duplicate or no longer needed)** → delete it:
77
+ - **If it is an orphan (duplicate or no longer needed)** → delete it.
78
+
79
+ **Prefer MCP:**
80
+ ```
81
+ mcp__eventmodelers__delete_node { "boardId": "$BOARD_ID", "nodeId": "<nodeId>" }
82
+ ```
83
+
84
+ **Fallback (no MCP):**
61
85
  ```bash
62
86
  curl -s -X DELETE "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/<nodeId>" \
63
87
  -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID"
@@ -194,7 +218,7 @@ Invoke `eventmodeling-storyboarding-events`.
194
218
  human role, showing what data each screen displays and collects.
195
219
  **Gate**: Every human role from the Role Catalog has at least one screen.
196
220
 
197
- Use the Story-Board-Screen skill to sketch and provide Mockups.
221
+ Use the `html-screen` skill to render a real HTML/CSS mockup for every screen — this is the default for each screen. Fall back to `storyboard-screen` (wireframe sketch) only when the user explicitly asked for sketches/wireframes.
198
222
 
199
223
  You can reuse columns if screens can be matched to existing events, place the screen in the same
200
224
  column as the event in the actor lane
@@ -8,7 +8,9 @@ allowed-tools:
8
8
 
9
9
  # Plotting Events
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
  Arrange all brainstormed events chronologically to create a logical sequence that makes sense as a narrative timeline. Show how events flow and depend on each other.
14
16
 
@@ -101,6 +103,12 @@ Timelines (chapters) are **created and assigned during Step 1 (Brainstorming)**.
101
103
 
102
104
  Before placing events, resolve the target timeline:
103
105
 
106
+ Prefer MCP:
107
+ ```
108
+ mcp__eventmodelers__get_nodes { "boardId": "$BOARD_ID", "type": "CHAPTER" }
109
+ ```
110
+
111
+ **Fallback (no MCP):**
104
112
  ```bash
105
113
  curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
106
114
  "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: eventmodeling-slicing-event-models
3
- description: "Identify feature slices directly from a completed event model's timeline and create slice definitions on the board — each COMMAND becomes a state-change slice, each READMODEL becomes a state-view slice, each AUTOMATION becomes an automation slice. Use after completing event modeling to define slice boundaries and note event dependencies between them. Do not use for: organizational team structure based on Conway's Law (use eventmodeling-applying-conways-law) or planning before the event model is complete (complete the full model first using eventmodeling-orchestrating-event-modeling)."
3
+ description: "Identify feature slices directly from a completed event model's timeline and create slice definitions on the board — each COMMAND becomes a state-change slice, each READMODEL becomes a state-view slice, each AUTOMATION becomes an automation slice. Use after completing event modeling to define slice boundaries and note event dependencies between them. Do not use for: organizational team structure based on Conway's Law (use eventmodeling-applying-conways-law), planning before the event model is complete (complete the full model first using eventmodeling-orchestrating-event-modeling), or 'add the next slice' when every existing element already has one (use add-next-slice — this skill only makes existing elements explicit, it never invents new ones)."
4
4
  allowed-tools:
5
5
  - AskUserQuestion
6
6
  - Write
@@ -9,7 +9,9 @@ allowed-tools:
9
9
 
10
10
  # Slicing 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 (in particular the **Slices** section). 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` (in particular the **Slices** section) 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
  **Purpose**: Turn a completed event model's timeline into explicit slice definitions on the board, and note the event dependencies between them.
15
17
 
@@ -55,6 +57,12 @@ Walk the timeline column by column:
55
57
 
56
58
  `$TL` (the timeline/chapter UUID) is required for every call below. If it wasn't given up front, resolve it before doing anything else:
57
59
 
60
+ Prefer MCP:
61
+ ```
62
+ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "CHAPTER" }
63
+ ```
64
+
65
+ **Fallback (no MCP):**
58
66
  ```bash
59
67
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
60
68
  ```
@@ -67,6 +75,12 @@ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
67
75
 
68
76
  Use `spec-info` (or existing board knowledge) to list every COMMAND, READMODEL, and AUTOMATION node across the resolved timeline:
69
77
 
78
+ Prefer MCP:
79
+ ```
80
+ mcp__eventmodelers__get_spec_info { "boardId": "<BOARD_ID>", "timelineId": "<TL>" }
81
+ ```
82
+
83
+ **Fallback (no MCP):**
70
84
  ```bash
71
85
  curl "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/spec-info" -H "x-token: $TOKEN"
72
86
  # → { timelineId, elements: [{ id, title, type }] }
@@ -76,6 +90,12 @@ Filter to `type` in `COMMAND`, `READMODEL`, `AUTOMATION`.
76
90
 
77
91
  `spec-info` doesn't include the column each element sits in, so fetch the chapter node to resolve it:
78
92
 
93
+ Prefer MCP:
94
+ ```
95
+ mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<TL>" }
96
+ ```
97
+
98
+ **Fallback (no MCP):**
79
99
  ```bash
80
100
  curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$TL" -H "x-token: $TOKEN"
81
101
  # → meta.timelineData.columns: [{ id, index }]
@@ -86,6 +106,12 @@ For each filtered element, find the cell whose `nodeId` matches the element's `i
86
106
 
87
107
  Check which columns already have a slice, so you don't create duplicates:
88
108
 
109
+ Prefer MCP:
110
+ ```
111
+ mcp__eventmodelers__list_slices { "boardId": "<BOARD_ID>" }
112
+ ```
113
+
114
+ **Fallback (no MCP):**
89
115
  ```bash
90
116
  curl $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/slicedata/slices -H "x-token: $TOKEN"
91
117
  # → { slices: [{ id, title, status }] }
@@ -97,6 +123,12 @@ A column already has a slice if its element's title matches an existing slice's
97
123
 
98
124
  For each column from Step 2 that doesn't already have a matching slice, mark that **existing** column as a slice via the **slice-definitions** endpoint:
99
125
 
126
+ Prefer MCP:
127
+ ```
128
+ mcp__eventmodelers__create_slice_definition { "boardId": "<BOARD_ID>", "timelineId": "<TL>", "columnId": "<colId>", "title": "PlaceOrder" }
129
+ ```
130
+
131
+ **Fallback (no MCP):**
100
132
  ```bash
101
133
  curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/slice-definitions \
102
134
  -H "x-token: $TOKEN" -H "Content-Type: application/json" \
@@ -108,7 +140,9 @@ curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/slice-defi
108
140
  - READMODEL column → title = read model name (state-view slice)
109
141
  - AUTOMATION column → title = automation name, or the command it issues (automation slice)
110
142
 
111
- Use **`slice-definitions`**, never the plain **`slices`** endpoint here — `slices` creates a brand-new column with its own swimlane/content nodes, which would duplicate the element already placed on the timeline. `slice-definitions` only adds a `SLICE_BORDER` node to the column you already resolved in Step 2. `title` always comes from the request body — it is never derived automatically from the command/read model/automation node.
143
+ Use **`create_slice_definition`/`slice-definitions`**, never `create_slice`/the plain **`slices`** endpoint here — `create_slice`/`slices` creates a brand-new column with its own swimlane/content nodes, which would duplicate the element already placed on the timeline. `create_slice_definition`/`slice-definitions` only adds a `SLICE_BORDER` node to the column you already resolved in Step 2. `title` always comes from the request body — it is never derived automatically from the command/read model/automation node.
144
+
145
+ **If Step 2 finds nothing to slice** (every COMMAND/READMODEL/AUTOMATION on the timeline already has a matching `SLICE_BORDER`), this skill's job is done — there is no existing element left to make explicit. Do not invent new model content here; that is out of scope for a skill whose whole design assumes the model is already complete. Invoke the `add-next-slice` skill instead — it owns deciding on and creating a genuinely new slice from scratch.
112
146
 
113
147
  ## Step 4 (Optional): Note Dependencies Between Slices
114
148