@eventmodelers/cli 0.0.39 → 1.0.0
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/README.md +116 -69
- package/cli.js +98 -32
- package/package.json +4 -2
- package/shared/build-kit/lib/adapters/pocketbase-realtime-adapter.js +29 -0
- package/shared/build-kit/lib/adapters/realtime-adapter.js +27 -0
- package/shared/build-kit/lib/adapters/supabase-realtime-adapter.js +24 -0
- package/shared/build-kit/lib/ralph.js +30 -31
- package/shared/build-kit/package.json +3 -1
- package/shared/build-kit/ralph-claude.js +63 -5
- package/shared/skills/connect/SKILL.md +52 -5
- package/shared/skills/learn-eventmodelers-api/SKILL.md +86 -3
- package/shared/skills/load-slice/SKILL.md +16 -0
- package/shared/skills/update-slice-status/SKILL.md +15 -5
- package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/SKILL.md +86 -0
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +28 -0
- package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +46 -4
- package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +77 -45
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +99 -13
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +21 -1
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +29 -3
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +71 -11
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +65 -8
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +28 -4
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +8 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +36 -2
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +113 -26
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +14 -2
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +12 -1
- package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +44 -6
- package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +27 -0
- package/stacks/modeling-kit/templates/.claude/skills/html-screen/SKILL.md +50 -5
- package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +171 -5
- package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +110 -10
- package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +36 -3
- package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +110 -11
- package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/SKILL.md +9 -0
- package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +23 -4
- package/stacks/modeling-kit/templates/kit/CLAUDE.md +7 -3
- package/stacks/node/templates/.claude/skills/build-state-view/SKILL.md +13 -7
- package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +13 -7
|
@@ -7,6 +7,8 @@ description: Live event storming facilitator — asks questions about any busine
|
|
|
7
7
|
|
|
8
8
|
> **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_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.
|
|
9
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.
|
|
11
|
+
|
|
10
12
|
You are a live event storming facilitator. You discover domain events through conversation — or from any input (pasted text, documents, notes) — and **immediately place them on the board as they emerge**. The timeline grows and evolves in real time. You don't wait until the end.
|
|
11
13
|
|
|
12
14
|
A **domain event** is something that happened in the business domain. Past tense. Meaningful to a business person. Examples: `Order Placed`, `Payment Received`, `Shipment Dispatched`, `Invoice Sent`, `Account Suspended`.
|
|
@@ -29,8 +31,14 @@ From `$ARGUMENTS` and the conversation, extract:
|
|
|
29
31
|
|
|
30
32
|
### 1a — Discover existing timelines
|
|
31
33
|
|
|
32
|
-
Before doing anything else, fetch all chapters (timelines) on the board
|
|
34
|
+
Before doing anything else, fetch all chapters (timelines) on the board.
|
|
35
|
+
|
|
36
|
+
**Prefer MCP:**
|
|
37
|
+
```
|
|
38
|
+
mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "CHAPTER" }
|
|
39
|
+
```
|
|
33
40
|
|
|
41
|
+
**Fallback (no MCP):**
|
|
34
42
|
```bash
|
|
35
43
|
curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
|
|
36
44
|
```
|
|
@@ -50,8 +58,14 @@ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
|
|
|
50
58
|
|
|
51
59
|
A chapter and a timeline are the same thing — the terms are interchangeable.
|
|
52
60
|
|
|
53
|
-
If `timelineId` is provided, first resolve it to a UUID if a name was given instead
|
|
61
|
+
If `timelineId` is provided, first resolve it to a UUID if a name was given instead.
|
|
62
|
+
|
|
63
|
+
**Prefer MCP:**
|
|
64
|
+
```
|
|
65
|
+
mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "CHAPTER" }
|
|
66
|
+
```
|
|
54
67
|
|
|
68
|
+
**Fallback (no MCP):**
|
|
55
69
|
```bash
|
|
56
70
|
curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
|
|
57
71
|
```
|
|
@@ -60,8 +74,14 @@ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
|
|
|
60
74
|
- If it looks like a name, find the CHAPTER node whose `meta.title` matches (case-insensitive) and use its `id` as `CHAPTER_ID`.
|
|
61
75
|
- If no match is found, tell the user and stop.
|
|
62
76
|
|
|
63
|
-
Fetch the chapter node to read its grid structure
|
|
77
|
+
Fetch the chapter node to read its grid structure.
|
|
64
78
|
|
|
79
|
+
**Prefer MCP:**
|
|
80
|
+
```
|
|
81
|
+
mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Fallback (no MCP):**
|
|
65
85
|
```bash
|
|
66
86
|
curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$CHAPTER_ID"
|
|
67
87
|
```
|
|
@@ -71,8 +91,14 @@ From `meta.timelineData`:
|
|
|
71
91
|
- `columns` — ordered list of columns, each with an `id`
|
|
72
92
|
- `cells` — each cell has `colId`, `rowId`, and optionally `nodeId`
|
|
73
93
|
|
|
74
|
-
Then load the existing EVENT nodes
|
|
94
|
+
Then load the existing EVENT nodes.
|
|
75
95
|
|
|
96
|
+
**Prefer MCP:**
|
|
97
|
+
```
|
|
98
|
+
mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "EVENT" }
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Fallback (no MCP):**
|
|
76
102
|
```bash
|
|
77
103
|
curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=EVENT"
|
|
78
104
|
```
|
|
@@ -93,8 +119,14 @@ Tell the user which timeline was loaded and how many events already exist (one l
|
|
|
93
119
|
|
|
94
120
|
### 1c — Creating a new timeline
|
|
95
121
|
|
|
96
|
-
If no `timelineId` is provided, **create the chapter immediately** — before any events are known
|
|
122
|
+
If no `timelineId` is provided, **create the chapter immediately** — before any events are known.
|
|
97
123
|
|
|
124
|
+
**Prefer MCP:**
|
|
125
|
+
```
|
|
126
|
+
mcp__eventmodelers__create_chapter { "boardId": "<BOARD_ID>", "x": 0, "y": 0 }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Fallback (no MCP):**
|
|
98
130
|
```bash
|
|
99
131
|
curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/chapters" \
|
|
100
132
|
-H "Content-Type: application/json" \
|
|
@@ -152,8 +184,14 @@ Compare against the current `events` state:
|
|
|
152
184
|
|
|
153
185
|
### 3c — Inspect the timeline and maintain continuity
|
|
154
186
|
|
|
155
|
-
Before placing any new events, fetch the chapter node to get the current grid state
|
|
187
|
+
Before placing any new events, fetch the chapter node to get the current grid state.
|
|
156
188
|
|
|
189
|
+
**Prefer MCP:**
|
|
190
|
+
```
|
|
191
|
+
mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Fallback (no MCP):**
|
|
157
195
|
```bash
|
|
158
196
|
curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$CHAPTER_ID"
|
|
159
197
|
```
|
|
@@ -171,6 +209,12 @@ emptyColumns = [columnId, ...] // in column order, ready to reuse
|
|
|
171
209
|
- If you have new events to place: **reuse empty columns first** (see Step 4a) before creating new ones. This keeps the timeline contiguous.
|
|
172
210
|
- After all placements, delete any columns still left in the `emptyColumns` pool — they are gaps that should not remain.
|
|
173
211
|
|
|
212
|
+
**Prefer MCP:**
|
|
213
|
+
```
|
|
214
|
+
mcp__eventmodelers__delete_column { "boardId": "<BOARD_ID>", "timelineId": "<CHAPTER_ID>", "columnId": "<columnId>" }
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Fallback (no MCP):**
|
|
174
218
|
```bash
|
|
175
219
|
curl -s -X DELETE "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$CHAPTER_ID/columns/<columnId>"
|
|
176
220
|
```
|
|
@@ -215,8 +259,27 @@ Compute the cell ID directly: **`CELL_ID = swimlaneRowId + "-" + columnId`**
|
|
|
215
259
|
|
|
216
260
|
(Cell IDs are always `<rowId>-<columnId>` — no cell array search needed.)
|
|
217
261
|
|
|
218
|
-
Then create the EVENT node directly (place-element Steps 6–7)
|
|
262
|
+
Then create the EVENT node directly (place-element Steps 6–7).
|
|
263
|
+
|
|
264
|
+
**Prefer MCP:**
|
|
265
|
+
```
|
|
266
|
+
mcp__eventmodelers__submit_node_events {
|
|
267
|
+
"boardId": "<BOARD_ID>",
|
|
268
|
+
"events": [{
|
|
269
|
+
"id": "<event-uuid>",
|
|
270
|
+
"eventType": "node:created",
|
|
271
|
+
"nodeId": "<node-uuid>",
|
|
272
|
+
"boardId": "<BOARD_ID>",
|
|
273
|
+
"timestamp": <Date.now()>,
|
|
274
|
+
"chapterId": "<CHAPTER_ID>",
|
|
275
|
+
"cellId": "<CELL_ID>",
|
|
276
|
+
"meta": { "type": "EVENT", "title": "<EventName>" },
|
|
277
|
+
"node": { "id": "<node-uuid>", "data": { "title": "<EventName>" } }
|
|
278
|
+
}]
|
|
279
|
+
}
|
|
280
|
+
```
|
|
219
281
|
|
|
282
|
+
**Fallback (no MCP):**
|
|
220
283
|
```bash
|
|
221
284
|
curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
|
|
222
285
|
-H "Content-Type: application/json" \
|
|
@@ -236,7 +299,13 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
|
|
|
236
299
|
|
|
237
300
|
#### If no empty column is available — create one
|
|
238
301
|
|
|
239
|
-
|
|
302
|
+
**Prefer MCP:** this whole "find/create a column, compute the cell, place the node" sequence collapses into one call:
|
|
303
|
+
```
|
|
304
|
+
mcp__eventmodelers__place_element { "boardId": "<BOARD_ID>", "timelineId": "<CHAPTER_ID>", "elementType": "EVENT", "title": "<EventName>", "columnIndex": <index> }
|
|
305
|
+
```
|
|
306
|
+
Extract `nodeId` and `columnId` directly from the tool result.
|
|
307
|
+
|
|
308
|
+
**Fallback (no MCP):** invoke the **place-element skill** with:
|
|
240
309
|
|
|
241
310
|
| Parameter | Value |
|
|
242
311
|
|-----------|-------|
|
|
@@ -262,8 +331,26 @@ events.splice(index, 0, { index, title: "<EventName>", eventNodeId: "<nodeId>",
|
|
|
262
331
|
|
|
263
332
|
### 4b — Rename an existing event
|
|
264
333
|
|
|
265
|
-
Use `eventNodeId` from your local state. Send a `node:changed` event
|
|
334
|
+
Use `eventNodeId` from your local state. Send a `node:changed` event.
|
|
266
335
|
|
|
336
|
+
**Prefer MCP:**
|
|
337
|
+
```
|
|
338
|
+
mcp__eventmodelers__submit_node_events {
|
|
339
|
+
"boardId": "<BOARD_ID>",
|
|
340
|
+
"events": [{
|
|
341
|
+
"id": "<new-uuid>",
|
|
342
|
+
"eventType": "node:changed",
|
|
343
|
+
"nodeId": "<eventNodeId>",
|
|
344
|
+
"boardId": "<BOARD_ID>",
|
|
345
|
+
"timestamp": <Date.now()>,
|
|
346
|
+
"changedAttributes": ["meta.title"],
|
|
347
|
+
"meta": { "type": "EVENT", "title": "<NewTitle>" },
|
|
348
|
+
"node": { "id": "<eventNodeId>", "data": {} }
|
|
349
|
+
}]
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Fallback (no MCP):**
|
|
267
354
|
```bash
|
|
268
355
|
curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
|
|
269
356
|
-H "Content-Type: application/json" \
|
|
@@ -288,6 +375,12 @@ Two steps — delete the node, then delete the column:
|
|
|
288
375
|
|
|
289
376
|
**1. Delete the EVENT node:**
|
|
290
377
|
|
|
378
|
+
**Prefer MCP:**
|
|
379
|
+
```
|
|
380
|
+
mcp__eventmodelers__delete_node { "boardId": "<BOARD_ID>", "nodeId": "<eventNodeId>" }
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**Fallback (no MCP):**
|
|
291
384
|
```bash
|
|
292
385
|
curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
|
|
293
386
|
-H "Content-Type: application/json" \
|
|
@@ -301,13 +394,19 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
|
|
|
301
394
|
}]'
|
|
302
395
|
```
|
|
303
396
|
|
|
304
|
-
**2. Delete the column** using `columnId` from local state
|
|
397
|
+
**2. Delete the column** using `columnId` from local state.
|
|
398
|
+
|
|
399
|
+
**Prefer MCP:**
|
|
400
|
+
```
|
|
401
|
+
mcp__eventmodelers__delete_column { "boardId": "<BOARD_ID>", "timelineId": "<CHAPTER_ID>", "columnId": "<columnId>" }
|
|
402
|
+
```
|
|
305
403
|
|
|
404
|
+
**Fallback (no MCP):**
|
|
306
405
|
```bash
|
|
307
406
|
curl -s -X DELETE "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$CHAPTER_ID/columns/<columnId>"
|
|
308
407
|
```
|
|
309
408
|
|
|
310
|
-
If `columnId` is not in local state, fetch the chapter node, scan `meta.timelineData.cells` for the cell where `nodeId === eventNodeId`, and use that cell's `colId`.
|
|
409
|
+
If `columnId` is not in local state, fetch the chapter node (`mcp__eventmodelers__get_node { "boardId": "<BOARD_ID>", "nodeId": "<CHAPTER_ID>" }`, or the curl fallback above), scan `meta.timelineData.cells` for the cell where `nodeId === eventNodeId`, and use that cell's `colId`.
|
|
311
410
|
|
|
312
411
|
Remove from local state and re-number remaining indexes.
|
|
313
412
|
|
|
@@ -7,6 +7,8 @@ description: Update the lifecycle status (and optionally a progress comment) of
|
|
|
7
7
|
|
|
8
8
|
> **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `ORG_ID`, and `BASE_URL`. Do not proceed until the connect skill has completed.
|
|
9
9
|
|
|
10
|
+
Prefer `mcp__eventmodelers__update_prompt_status` when available (registered by the `connect` skill) — the curl block below is the fallback for sessions without MCP connected. This is the one prompt-queue operation MCP does expose (submission, claiming, and deletion remain curl-only — the MCP server otherwise doesn't own this lifecycle).
|
|
11
|
+
|
|
10
12
|
Every prompt drained from a board's queue (`/api/org/:orgId/prompts/next`) carries a `PROMPT_ID` — passed into this session as the `prompt_id` field of the current turn. This skill flips that prompt's status so the board UI reflects what the agent is doing with it in real time.
|
|
11
13
|
|
|
12
14
|
---
|
|
@@ -36,6 +38,13 @@ If `newStatus` is not one of these exact values, stop and tell the user the vali
|
|
|
36
38
|
|
|
37
39
|
## Step 2 — Update the status
|
|
38
40
|
|
|
41
|
+
**Prefer MCP:**
|
|
42
|
+
```
|
|
43
|
+
mcp__eventmodelers__update_prompt_status { "promptId": "<PROMPT_ID>", "newStatus": "<newStatus>", "comment": "<comment>" }
|
|
44
|
+
```
|
|
45
|
+
Omit `comment` entirely when there isn't one — don't pass an empty string.
|
|
46
|
+
|
|
47
|
+
**Fallback (no MCP):**
|
|
39
48
|
```bash
|
|
40
49
|
curl -s -X POST "$BASE_URL/api/org/$ORG_ID/prompts/$PROMPT_ID/status" \
|
|
41
50
|
-H "Content-Type: application/json" \
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wdyt
|
|
3
|
-
description: Business analyst exploration of an event model board. Reads all slices, analyzes them from a business perspective, and posts questions/observations as QUESTION-type comments on relevant nodes
|
|
3
|
+
description: Business analyst exploration of an event model board. Reads all slices, analyzes them from a business perspective, and posts questions/observations as QUESTION-type comments on relevant nodes. Findings about a relationship between elements or a cluster of elements are always additionally drawn on the canvas (arrows, group loops) — comments carry every textual question, drawings carry every visual/structural hint.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# WDYT — What Do You Think?
|
|
@@ -95,7 +95,14 @@ Every question and every summary theme must be written in plain business languag
|
|
|
95
95
|
|
|
96
96
|
---
|
|
97
97
|
|
|
98
|
-
## Step 4 —
|
|
98
|
+
## Step 4 — Comments carry every textual question; drawings carry every visual/structural hint
|
|
99
|
+
|
|
100
|
+
The two channels have a strict division of labor, always applied the same way — never swap them:
|
|
101
|
+
|
|
102
|
+
- **Every textual question is a comment.** If the finding is "what happens / who does this / what do we expect" about a single element, it is worded and lives only in a `QUESTION` comment. Never draw a text callout on the canvas to carry a question — that content belongs in 4.1, full stop.
|
|
103
|
+
- **Every visual/structural hint is a drawing.** If the finding is inherently about *where things are relative to each other* — a relationship between two elements, or a cluster of elements sharing one concern — it is always additionally drawn on the canvas (4.2), not left as text alone. This isn't a selective "top 3" step; it's determined by the shape of the finding itself: relational or clustered → draw it, every time.
|
|
104
|
+
|
|
105
|
+
### 4.1 Comments (every textual question, always)
|
|
99
106
|
|
|
100
107
|
For each question you want to ask, post it as a `QUESTION`-type comment on the most relevant node (the COMMAND, EVENT, SCREEN, or READMODEL the question is about). If a question is about the whole slice rather than a specific element, post it on the first/primary EVENT of the slice.
|
|
101
108
|
|
|
@@ -109,6 +116,17 @@ The comment API has no batch endpoint — `handle-comment` sends one request per
|
|
|
109
116
|
|
|
110
117
|
Only post questions that are **genuinely unclear or missing** — don't post observations that are clearly intentional design decisions.
|
|
111
118
|
|
|
119
|
+
### 4.2 Drawings (every relational or clustered finding, always)
|
|
120
|
+
|
|
121
|
+
Use `POST /api/org/{orgId}/boards/{boardId}/drawing/draw` (auth headers same as every other call — `x-token`, `x-board-id`, `x-user-id: wdyt`). There are two kinds — no text-callout kind; a drawing never carries the question itself, only the shape of the concern:
|
|
122
|
+
|
|
123
|
+
- **Arrow** (`kind: "path"`, `arrowEnd: true`) — the concern is about a missing or unclear relationship *between two elements* (e.g. "does this event actually reach this automation?"). Draw a straight line from one element's position to the other's. `path` is `M 0 0 L <dx> <dy>` in the box's own local coordinates; `x`/`y`/`width`/`height` describe that box in canvas space (so `width`/`height` = the delta between the two elements' positions). Get element positions from the slice data already loaded in Step 2 (or `GET .../nodes/{nodeId}` if not present).
|
|
124
|
+
- **Group loop** (`kind: "rect"`, drawn around a computed bounding box) — the concern spans a *cluster* of elements together (e.g. "this whole flow assumes nothing ever fails"). There's no dedicated group endpoint — union the elements' own `x`/`y`/`width`/`height` (plus some padding) yourself and draw one `rect` around that box via `.../drawing/draw`. This is a visual grouping only — unrelated to the `MODEL_CONTEXT` node type; never touch a `modelContext` field to satisfy this.
|
|
125
|
+
|
|
126
|
+
Every arrow/group loop is paired with a `QUESTION` comment on the relevant node(s) from 4.1 — the drawing makes the concern visible at a glance on the canvas itself, the comment carries the actual worded question. Post both; neither replaces the other.
|
|
127
|
+
|
|
128
|
+
A finding about a single element with no relational or cluster dimension gets a comment only — don't manufacture an arrow or loop for it just to add a drawing.
|
|
129
|
+
|
|
112
130
|
---
|
|
113
131
|
|
|
114
132
|
## Step 5 — Report back to the user
|
|
@@ -117,8 +135,9 @@ After posting all comments, give the user a concise summary:
|
|
|
117
135
|
|
|
118
136
|
1. **Flows analysed**: count and list them by their business name
|
|
119
137
|
2. **Total questions posted**: count (it is perfectly fine if this is 0 — don't force questions)
|
|
120
|
-
3. **
|
|
121
|
-
4. **
|
|
138
|
+
3. **Visual annotations added**: count and a one-line description of each (e.g. "arrow from OrderPlaced to ShipOrder — unclear if it always fires")
|
|
139
|
+
4. **Top themes** as business questions, not modelling observations. Examples of good themes: "What happens when registration fails?", "Who is allowed to register a customer?", "What do we expect when invalid data is submitted?" — never: "No failure modelling", "No specs", "No actor on command"
|
|
140
|
+
5. **One concrete next step** — only if there's a clear gap worth highlighting
|
|
122
141
|
|
|
123
142
|
Keep the report tight. If there are no meaningful questions, say so — don't pad it out.
|
|
124
143
|
|
|
@@ -35,7 +35,9 @@ At the start of every session, read `.agent-modeling-kit/AGENTS.md` if it exists
|
|
|
35
35
|
**Resolve `NODE_ID`** from the first entry of this turn's `context.selectedNodes`, if that array is present and non-empty; otherwise use this turn's `node_id` field. `context.selectedNodes` reflects what was actually selected on the canvas when the prompt was issued, which can differ from `node_id` — set only when the prompt originated from a specific node/comment — so it wins whenever both are present.
|
|
36
36
|
**Resolve `CELL_ID`** from this turn's `context.selectedCell.id`, if present and non-null. When present, it overrules any cell reference (e.g. `"A2"`) parsed from the prompt text itself — it reflects the actual cell the user had selected on the canvas when they issued the prompt, and is more reliable than free-text parsing.
|
|
37
37
|
4. **Mark the prompt as started** — invoke `/update-prompt-status` with this turn's `prompt_id` and `newStatus=IN_PROGRESS`, before doing any of the actual work below. This is what makes the board UI show the prompt as being actively worked on.
|
|
38
|
-
5. Execute the prompt using the skill matched in the Skill Selection table below, passing the resolved `TIMELINE_ID`, `NODE_ID`, and `CELL_ID` from step 3 as that skill's `timelineId`/node-reference/`cellName` arguments (not the raw `timeline_id`/`node_id` fields, and not a cell reference parsed from the prompt text). For a skill like `/place-element` that accepts a `cellName`, pass the resolved `CELL_ID` as `cellName` whenever it's present — skip parsing the prompt text for a cell reference entirely in that case.
|
|
38
|
+
5. **Invoke the matched skill — never substitute direct tool calls for it.** Execute the prompt using the skill matched in the Skill Selection table below, passing the resolved `TIMELINE_ID`, `NODE_ID`, and `CELL_ID` from step 3 as that skill's `timelineId`/node-reference/`cellName` arguments (not the raw `timeline_id`/`node_id` fields, and not a cell reference parsed from the prompt text). For a skill like `/place-element` that accepts a `cellName`, pass the resolved `CELL_ID` as `cellName` whenever it's present — skip parsing the prompt text for a cell reference entirely in that case.
|
|
39
|
+
|
|
40
|
+
`mcp__eventmodelers__*` tools (and the REST fallback) are building blocks a skill calls *internally* once you've invoked it — they are not a substitute for invoking the skill. Being able to see `mcp__eventmodelers__get_node`/`create_slice`/etc. in your tool list does not mean you should reach for them directly to satisfy a prompt that matches a row in the Skill Selection table: e.g. "add the next slice" always goes through `/eventmodeling-slicing-event-models` (falling through to `/add-next-slice` when nothing existing is left to slice) or `/place-element`, even though technically a couple of raw MCP calls could produce something on the board. The skill is what encodes the actual domain reasoning (which node type follows which, naming, field derivation, dependency notes) — a raw tool call skips all of that and produces a shallower result even when it "works." Only call MCP/REST directly when no row in the table matches the prompt's intent at all.
|
|
39
41
|
**Questioning rule**: you are running autonomously — no human is available to answer questions. If you need clarification, do not pause or ask interactively — post a `QUESTION`-type comment (`/handle-comment` with `action=place`, `type=QUESTION`) on the most relevant node. Then:
|
|
40
42
|
- If a reasonable default interpretation exists, continue with it.
|
|
41
43
|
- If it doesn't — the prompt is ambiguous enough that any guess risks doing the wrong thing — stop instead of guessing. Skip straight to step 6 and mark the prompt `DONE` with a comment explaining what's unclear and pointing to the `QUESTION` comment you just posted. Never leave a prompt neither progressed nor closed.
|
|
@@ -52,13 +54,15 @@ At the start of every session, read `.agent-modeling-kit/AGENTS.md` if it exists
|
|
|
52
54
|
| Add, rename, or reorder events on a timeline | `/timeline` |
|
|
53
55
|
| Place a COMMAND, READMODEL, or EVENT at a position | `/place-element` |
|
|
54
56
|
| Generate a full storyboard with multiple screens | `/storyboard` |
|
|
55
|
-
| Design or update a single
|
|
56
|
-
| Design or update a single
|
|
57
|
+
| Design or update a single screen | `/html-screen` |
|
|
58
|
+
| Design or update a single wireframe/sketch screen (explicit request only) | `/storyboard-screen` |
|
|
57
59
|
| Business analysis, gap spotting, posting questions | `/wdyt` |
|
|
58
60
|
| Analyse the existing model structure, slice coverage, element counts | `/analyze-existing-model` |
|
|
59
61
|
| Look up any API endpoint or element type | `/learn-eventmodelers-api` |
|
|
60
62
|
| Add or rename an attribute across a chain of elements | `/attributes` |
|
|
61
63
|
| Add or improve example data on element fields | `/examples` |
|
|
64
|
+
| Make an existing timeline element's (COMMAND/READMODEL/AUTOMATION) slice explicit | `/eventmodeling-slicing-event-models` |
|
|
65
|
+
| Add the next slice when nothing existing is left to slice | `/add-next-slice` |
|
|
62
66
|
| Update the status of a slice (e.g. done, in-progress) | `/update-slice-status` |
|
|
63
67
|
| Update the status of the current prompt (e.g. in-progress, done) | `/update-prompt-status` |
|
|
64
68
|
|
|
@@ -43,16 +43,22 @@ CREATE TABLE IF NOT EXISTS "public"."{tablename}"
|
|
|
43
43
|
);
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
**Column type guide
|
|
46
|
+
**Column type guide** — field `type` values are the canonical set from the [event-modeling-spec schema](https://github.com/dilgerma/event-modeling-spec/blob/main/eventmodeling.schema.json):
|
|
47
47
|
|
|
48
48
|
| Field type | SQL type |
|
|
49
49
|
|-----------|---------|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
50
|
+
| `String` | `TEXT` |
|
|
51
|
+
| `UUID` | `TEXT` |
|
|
52
|
+
| `Int` | `INTEGER` |
|
|
53
|
+
| `Long` | `BIGINT` |
|
|
54
|
+
| `Double` | `DOUBLE PRECISION` |
|
|
55
|
+
| `Decimal` | `NUMERIC` |
|
|
56
|
+
| `Boolean` | `BOOLEAN` |
|
|
57
|
+
| `Date` | `DATE` |
|
|
58
|
+
| `DateTime` | `TIMESTAMP` |
|
|
59
|
+
| `Custom` | `JSONB` |
|
|
60
|
+
|
|
61
|
+
Nullable columns (`optional: true` on the field): allow `NULL` instead of adding a default.
|
|
56
62
|
|
|
57
63
|
The PRIMARY KEY column is the one used in `.onConflict(...)` in the projection.
|
|
58
64
|
|
|
@@ -43,16 +43,22 @@ CREATE TABLE IF NOT EXISTS "public"."{tablename}"
|
|
|
43
43
|
);
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
**Column type guide
|
|
46
|
+
**Column type guide** — field `type` values are the canonical set from the [event-modeling-spec schema](https://github.com/dilgerma/event-modeling-spec/blob/main/eventmodeling.schema.json):
|
|
47
47
|
|
|
48
48
|
| Field type | SQL type |
|
|
49
49
|
|-----------|---------|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
50
|
+
| `String` | `TEXT` |
|
|
51
|
+
| `UUID` | `TEXT` |
|
|
52
|
+
| `Int` | `INTEGER` |
|
|
53
|
+
| `Long` | `BIGINT` |
|
|
54
|
+
| `Double` | `DOUBLE PRECISION` |
|
|
55
|
+
| `Decimal` | `NUMERIC` |
|
|
56
|
+
| `Boolean` | `BOOLEAN` |
|
|
57
|
+
| `Date` | `DATE` |
|
|
58
|
+
| `DateTime` | `TIMESTAMP` |
|
|
59
|
+
| `Custom` | `JSONB` |
|
|
60
|
+
|
|
61
|
+
Nullable columns (`optional: true` on the field): allow `NULL` instead of adding a default.
|
|
56
62
|
|
|
57
63
|
The PRIMARY KEY column is the one used in `.onConflict(...)` in the projection.
|
|
58
64
|
|