@eventmodelers/cli 1.0.34 → 1.0.36
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/package.json +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +41 -13
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +5 -4
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +9 -0
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: discover-storyboard
|
|
3
|
-
description: Navigate an existing web app using browser automation MCP (Puppeteer/Playwright/Chrome DevTools), capture
|
|
3
|
+
description: Navigate an existing web app using browser automation MCP (Puppeteer/Playwright/Chrome DevTools), capture each step, and build one or more storyboard timelines on the board as HTML_SCREEN nodes reconstructed from the real page markup — ready for event modeling
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Discover Storyboard
|
|
7
7
|
|
|
8
8
|
> **FIRST — before invoking `connect` or anything else**: check for a browser automation MCP (Step 0). If none is found, stop immediately.
|
|
9
9
|
|
|
10
|
-
You are discovering the UI flows of an existing system by navigating it with a browser,
|
|
10
|
+
You are discovering the UI flows of an existing system by navigating it with a browser, capturing each screen, and uploading it to the eventmodelers board as a SCREEN node — one per column, arranged chronologically in timelines so the team can build an event model from the real application.
|
|
11
|
+
|
|
12
|
+
**Default rendering mode is HTML, not raw screenshots.** Every SCREEN node this skill places is by default an `HTML_SCREEN` — a real, editable HTML/CSS reconstruction of the captured page (built from `CONTENT_TOOL`'s markup, cleaned up with Bulma classes per the `html-screen` skill's conventions), not a flat image. Raw screenshot images (`contentType: "image"`) are used **only** when the user explicitly asks for screenshots/images during Step 2 — never as the default, and never as a fallback chosen for convenience. An HTML reconstruction is editable, themeable, and consistent with every other screen produced elsewhere in this toolkit; a screenshot is an inert picture. See Step 7b for the two paths.
|
|
11
13
|
|
|
12
14
|
---
|
|
13
15
|
|
|
@@ -77,6 +79,10 @@ Ask the user:
|
|
|
77
79
|
|
|
78
80
|
Wait for the answer (or a blank/skip). Save as `discoveryGuidance`. If blank, set to `"explore all visible flows"`.
|
|
79
81
|
|
|
82
|
+
### Rendering mode
|
|
83
|
+
|
|
84
|
+
Default `renderMode` to `"html"` — screens are placed as `HTML_SCREEN` reconstructions, never raw images, unless the user's answer to Question 2 (or `$ARGUMENTS`) explicitly asks for screenshots/images (e.g. "use screenshots", "capture images", "I want the actual pixels"). Only in that case set `renderMode = "image"`. Do not ask a separate question for this — infer it from the guidance already given, defaulting to `"html"` when nothing image-related was said.
|
|
85
|
+
|
|
80
86
|
### Additional parameters (from `$ARGUMENTS` only — do not ask)
|
|
81
87
|
|
|
82
88
|
| Field | How to find it | Default |
|
|
@@ -107,8 +113,8 @@ Use the browser tools identified in Step 0. Process screens **one at a time**
|
|
|
107
113
|
|
|
108
114
|
1. Navigate to `startUrl` using `NAVIGATE_TOOL`
|
|
109
115
|
2. Wait briefly for the page to settle
|
|
110
|
-
3.
|
|
111
|
-
4. Use `CONTENT_TOOL` to read the page structure and
|
|
116
|
+
3. If `renderMode == "image"`: take a screenshot using `SCREENSHOT_TOOL` — save to `/tmp/discover-storyboard/screen-001.png`. If `renderMode == "html"` (default): skip the screenshot — `CONTENT_TOOL`'s markup (next step) is what gets placed.
|
|
117
|
+
4. Use `CONTENT_TOOL` to read the page structure. When `renderMode == "html"`, also capture the markup needed to reconstruct this screen (Step 7b) — the visible content, layout structure, form fields/labels, buttons, and any status/data values shown, enough to rebuild a faithful HTML mockup, not just a text summary. Compose a `description` for this screen covering three things:
|
|
112
118
|
- **What it shows**: the main content and purpose of this screen
|
|
113
119
|
- **How the user got here**: `"Initial load"` for the entry screen
|
|
114
120
|
- **What actions are possible**: list the primary user actions available (buttons, forms, links that lead somewhere meaningful) — expressed as intent, not UI labels (e.g. "user can submit a new order", "user can filter products by category")
|
|
@@ -120,7 +126,8 @@ screens = [
|
|
|
120
126
|
index: 1,
|
|
121
127
|
title: "<page title or heading>",
|
|
122
128
|
url: "<current url>",
|
|
123
|
-
filepath: "/tmp/discover-storyboard/screen-001.png",
|
|
129
|
+
filepath: "/tmp/discover-storyboard/screen-001.png", // only populated when renderMode == "image"
|
|
130
|
+
capturedMarkup: "<captured content/structure used to rebuild the HTML mockup>", // only populated when renderMode == "html"
|
|
124
131
|
flowHint: "<which flow this belongs to, e.g. 'Navigation / Home'>",
|
|
125
132
|
description: "Shows <what>. Arrived via: initial load. Actions: <user can do X>, <user can do Y>, <user can do Z>."
|
|
126
133
|
}
|
|
@@ -151,15 +158,16 @@ For each subsequent screen (up to `maxScreenshots`):
|
|
|
151
158
|
- Repeated UI patterns with identical structure
|
|
152
159
|
|
|
153
160
|
After each interaction:
|
|
154
|
-
1.
|
|
155
|
-
2. Use `CONTENT_TOOL` to read the page and
|
|
161
|
+
1. If `renderMode == "image"`: take a screenshot → save to `/tmp/discover-storyboard/screen-NNN.png` (increment counter). If `renderMode == "html"` (default): skip the screenshot.
|
|
162
|
+
2. Use `CONTENT_TOOL` to read the page and, when `renderMode == "html"`, capture the markup needed to rebuild this screen (same bar as Step 4a — enough to reconstruct a faithful mockup, not just a summary). Compose a `description` covering:
|
|
156
163
|
- **What it shows**: the main content and purpose of this screen
|
|
157
164
|
- **How the user got here**: the action taken to reach this screen (e.g. "clicked 'Add to cart'", "submitted login form")
|
|
158
165
|
- **What actions are possible**: primary user actions expressed as intent (e.g. "user can confirm the order", "user can apply a discount code")
|
|
159
166
|
3. Append to `screens` array with:
|
|
160
167
|
- `title` — the page/modal title
|
|
161
168
|
- `url` — current URL
|
|
162
|
-
- `filepath` — local file path
|
|
169
|
+
- `filepath` — local file path (only when `renderMode == "image"`)
|
|
170
|
+
- `capturedMarkup` — captured content/structure (only when `renderMode == "html"`)
|
|
163
171
|
- `flowHint` — which logical flow this screen belongs to
|
|
164
172
|
- `description` — "Shows <what>. Arrived via: <interaction>. Actions: <user can do X>, <user can do Y>."
|
|
165
173
|
|
|
@@ -316,7 +324,7 @@ Response includes `{ columnId, index, totalColumns }` — `index` is the new `co
|
|
|
316
324
|
|
|
317
325
|
Extract `columnId`. Compute `CELL_ID = actorRowId + "-" + columnId` and `CELL_NAME` per the convention above.
|
|
318
326
|
|
|
319
|
-
### 7b — Create the SCREEN node
|
|
327
|
+
### 7b — Create the SCREEN node, atomically
|
|
320
328
|
|
|
321
329
|
Generate a UUID for `SCREEN_NODE_ID`:
|
|
322
330
|
|
|
@@ -324,9 +332,28 @@ Generate a UUID for `SCREEN_NODE_ID`:
|
|
|
324
332
|
python3 -c "import uuid; print(uuid.uuid4())"
|
|
325
333
|
```
|
|
326
334
|
|
|
327
|
-
This step must create the node and attach the
|
|
335
|
+
This step must create the node and attach its content (HTML pages, or the screenshot) in a single call — never split into "upload content" then "create node" (or vice versa), which leaves a window where the node exists with no content.
|
|
336
|
+
|
|
337
|
+
**Default path — `renderMode == "html"` (use unless the user explicitly asked for screenshots/images in Step 2):**
|
|
338
|
+
|
|
339
|
+
Reconstruct the captured screen as a real HTML/CSS fragment from `screen.capturedMarkup`, following the `html-screen` skill's conventions: full-size markup (16px body text, generous padding), one self-contained fragment per page (no `<html>`/`<head>`/`<body>` wrapper), no `<script>`/inline handlers, Bulma CSS classes (`title`, `button`, `is-primary`, `field`/`control`/`input`, tables, tags for status badges, etc.). Reproduce the real layout, labels, form fields, buttons, and any live data/status values seen on the actual page — this is a faithful reconstruction of the discovered screen, not a generic mockup.
|
|
340
|
+
|
|
341
|
+
```
|
|
342
|
+
mcp__eventmodelers__create_screen {
|
|
343
|
+
"boardId": "<BOARD_ID>",
|
|
344
|
+
"contentType": "html",
|
|
345
|
+
"nodeId": "<SCREEN_NODE_ID>",
|
|
346
|
+
"chapterId": "<CHAPTER_ID>",
|
|
347
|
+
"cellId": "<CELL_ID>",
|
|
348
|
+
"pages": ["<reconstructed HTML fragment for this screen>"],
|
|
349
|
+
"description": "<screen.description — 'Shows X. Arrived via: Y. Actions: user can do A, user can do B.'>"
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**Never pass an empty `pages` array** — an empty array produces a blank placeholder, same as in `html-screen`/`eventmodeling-storyboarding-events`.
|
|
354
|
+
|
|
355
|
+
**Image path — `renderMode == "image"` only, when the user explicitly asked for screenshots:**
|
|
328
356
|
|
|
329
|
-
**Prefer MCP:**
|
|
330
357
|
```
|
|
331
358
|
mcp__eventmodelers__create_screen {
|
|
332
359
|
"boardId": "<BOARD_ID>",
|
|
@@ -340,7 +367,7 @@ mcp__eventmodelers__create_screen {
|
|
|
340
367
|
}
|
|
341
368
|
```
|
|
342
369
|
|
|
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):
|
|
370
|
+
**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) — image path only:
|
|
344
371
|
```bash
|
|
345
372
|
curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/image-nodes/$SCREEN_NODE_ID" \
|
|
346
373
|
-H "x-token: $TOKEN" \
|
|
@@ -348,8 +375,9 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/image-nodes/$SCREEN_
|
|
|
348
375
|
-F "chapterId=$CHAPTER_ID" \
|
|
349
376
|
-F "cellName=$CELL_NAME"
|
|
350
377
|
```
|
|
378
|
+
For the HTML path with no MCP, use the `html-screen-nodes` endpoint per the `html-screen` skill's fallback mechanics instead.
|
|
351
379
|
|
|
352
|
-
Response: `204
|
|
380
|
+
Response: `204`/success on success. Log failures in the final report but continue to the next screen — do not stop the entire run.
|
|
353
381
|
|
|
354
382
|
### 7d — Report per-screen progress
|
|
355
383
|
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md
CHANGED
|
@@ -409,11 +409,12 @@ Even an automation that looks like a "pure signal relay" still has a todo list
|
|
|
409
409
|
|
|
410
410
|
**There is no such thing as an invisible or informal "signal" — a trigger is always a real EVENT node, placed in a second swimlane when it belongs to another system.**
|
|
411
411
|
|
|
412
|
-
**An automation can only ever be directly triggered by an internal event — never by another system's event.** A "trigger" arriving from a second swimlane is not itself the thing that drives your domain's work; it first has to be *translated* into an internal event. Do not model this as one automation whose todo list is opened by the external EVENT and that also does the real work (e.g. an automation reading a todo list opened by `ReservationRequested` from another system's swimlane and directly issuing `ReserveCopy`) — that lets an external system trigger domain work with no translation step, which this model doesn't allow. When an integration trigger comes from another team's system
|
|
412
|
+
**An automation can only ever be directly triggered by an internal event — never by another system's event.** A "trigger" arriving from a second swimlane is not itself the thing that drives your domain's work; it first has to be *translated* into an internal event. Do not model this as one automation whose todo list is opened by the external EVENT and that also does the real work (e.g. an automation reading a todo list opened by `ReservationRequested` from another system's swimlane and directly issuing `ReserveCopy`) — that lets an external system trigger domain work with no translation step, which this model doesn't allow. **Apply this now, in Step 5** — Conway's Law (Step 6) only confirms the boundary, it doesn't introduce the chain. When an integration trigger comes from another team's system, model it as **two chained automations**, never one:
|
|
413
413
|
|
|
414
|
-
1. **Translation automation** —
|
|
415
|
-
-
|
|
416
|
-
-
|
|
414
|
+
1. **Translation automation** — converts the external fact into an internal one; the other system's own decision logic is out of scope. Its todo list is opened by the external EVENT and closed by the internal EVENT its own command produces — the one and only place an external EVENT may open a todo list.
|
|
415
|
+
- **Three separate columns**, left to right: `[external EVENT] → [todo-list READMODEL] → [AUTOMATION + COMMAND + internal EVENT]`. Never crammed into one or two — the "one EVENT per column" rule applies here too.
|
|
416
|
+
- **Name the internal EVENT for its business meaning, not the transport** — usually the same name as the external EVENT (e.g. external `CopyReserved` → internal `CopyReserved`; the swimlane already shows which is which), never a mechanical `<X>SignalReceived`/`<X>RequestReceived` suffix. Same for the automation/command: `Record Reservation`/`RecordReservation`, not `Record Reservation Signal`/`RecordReservationSignal`.
|
|
417
|
+
- Its command and event carry no business decision — they only exist to produce the internal fact the next automation needs.
|
|
417
418
|
2. **Worker automation** — the one that does the actual work (the domain reaction the process is really about, e.g. `ReserveCopy`). Its todo list is opened **only** by the internal EVENT the translation automation produced (this chapter's own swimlane) — never by the external EVENT directly — and closed by whatever event marks that work done.
|
|
418
419
|
|
|
419
420
|
Wire the todo lists the standard way for each automation separately: for the translation automation, the external EVENT (second swimlane) **opens** the row and its own resulting internal EVENT **closes** it; for the worker automation, that same internal EVENT **opens** its row and its own resulting EVENT **closes** it. `EVENT → READMODEL` connections from both swimlanes are unaffected by which swimlane the event sits in.
|
|
@@ -17,6 +17,15 @@ Coordinates the 11-step Event Modeling workflow. Each step delegates to a
|
|
|
17
17
|
specialized skill — this skill holds the sequence, transition conditions, and
|
|
18
18
|
what to carry forward between steps.
|
|
19
19
|
|
|
20
|
+
## Do not cut corners to save tokens or effort
|
|
21
|
+
|
|
22
|
+
A correct model is the entire point of this workflow — it is not optional scope that can be traded away when a step gets expensive or a placement rule turns out to be inconvenient. If satisfying a rule (a todo-list automation, a missing read model for a command screen, a proper translation-automation chain for an external trigger) requires more columns, more nodes, or more tool calls than expected, that is not a signal to remove the requirement or invent an exemption — it is a signal to spend the additional calls. Budget and token cost are never a valid reason to:
|
|
23
|
+
- delete an automation, event, or read model that the rules call for, in order to avoid a placement conflict — solve the placement conflict instead (see the column-layout patterns throughout this file and in `eventmodeling-identifying-outputs`);
|
|
24
|
+
- label a command screen's missing read model as "session-context" or "accepted debt" when the rules don't actually exempt it — only a genuinely blank creation form is exempt; every other command screen needs a real read model, even a small identity/lookup one;
|
|
25
|
+
- collapse a two-chained-translation-automation requirement (external EVENT → translation automation → internal EVENT → worker automation) into a single direct connection because it's simpler.
|
|
26
|
+
|
|
27
|
+
If you catch yourself reasoning "this would need N more columns/nodes, let me simplify instead" — that is exactly the moment to stop and do the correct, larger version. A model with more nodes that is right is a better outcome than a smaller one that skips required elements. Flag genuine scope trade-offs to the user explicitly rather than resolving them unilaterally by cutting the model.
|
|
28
|
+
|
|
20
29
|
---
|
|
21
30
|
|
|
22
31
|
## Timeline Alignment Rules
|