@eventmodelers/cli 1.0.125 → 1.0.127

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 CHANGED
@@ -106,7 +106,7 @@ Use skills in Claude Code with `/skill-name`:
106
106
  | `/connect` | Set up board connection |
107
107
  | `/timeline` | Live event storming facilitator |
108
108
  | `/wdyt` | Business analyst review of your event model |
109
- | `/walkthrough` | Step-by-step player through a process, or through everything a planned change touches |
109
+ | `/walkthrough` | Slice-by-slice player through a feature, or through every slice a planned feature needs (existing, to adjust, new) |
110
110
  | `/storyboard` | Build a full visual storyboard |
111
111
  | `/html-screen` | Design individual real HTML/CSS screens (default) |
112
112
  | `/storyboard-screen` | Design individual wireframe/sketch screens (explicit request only) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventmodelers/cli",
3
- "version": "1.0.125",
3
+ "version": "1.0.127",
4
4
  "description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, OpenCQRS, UmaDB, Kurrent, or modeling-only)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -26,7 +26,7 @@ Write tools take their items as an array (`nodeIds[]`, `elements[]`, `connection
26
26
  | Tool | Args | Purpose | REST equivalent |
27
27
  |---|---|---|---|
28
28
  | `list_boards` | — | List boards for the org | §1 `GET /api/boards` (org-scoped) |
29
- | `get_nodes` | `boardId`, `type?`, `name?`, `chapterId?`, `nodeIds?`, `projection?` (`"line"`) | List nodes, optionally by type and/or a partial case-insensitive title match. **Unscoped with full `meta` it is expensive** — about 2 KB per node, ~1 MB on a 500-node board — so always pass a filter or `projection: "line"`. `chapterId` scopes to one timeline — prefer this over an unscoped board-wide call whenever the step is working within one chapter (the common case); `nodeIds` fetches a known, scattered subset in one call (e.g. re-verifying exactly the nodes just touched by a batch write) instead of a full `type` refetch; `projection: "line"` maps each match to `{id, type, title, fields}` — `fields` being just the attribute names. No `cellName` — an existing node is addressed by its `id`; when a cell address is needed (placing into a cell), read it from `get_board_outline`. No `sliceStatus` — take it per column from `get_board_outline` | §3 `GET .../nodes` (REST records carry no `cellName`, `projection=line` included) |
29
+ | `get_nodes` | `boardId`, `type?`, `name?`, `chapterId?`, `nodeIds?`, `projection?` (`"line"` \| `"fields"`) | List nodes, optionally by type and/or a partial case-insensitive title match. **Unscoped with full `meta` it is expensive** — about 2 KB per node, ~1 MB on a 500-node board — so always pass a filter or a projection. `chapterId` scopes to one timeline — prefer this over an unscoped board-wide call whenever the step is working within one chapter (the common case); `nodeIds` fetches a known, scattered subset in one call (e.g. re-verifying exactly the nodes just touched by a batch write) instead of a full `type` refetch; `projection: "line"` maps each match to `{id, type, title, fields}` — `fields` being just the attribute names; `projection: "fields"` to `{id, type, title, parentId, fields}` with the full field definitions (type, example, idAttribute, …) but no html, description, sketch or grid data. No `cellName` — an existing node is addressed by its `id`; when a cell address is needed (placing into a cell), read it from `get_board_outline`. No `sliceStatus` — take it per column from `get_board_outline` | §3 `GET .../nodes` (REST records carry no `cellName`, `projection=line`/`fields` included) |
30
30
  | `get_node` | `boardId`, `nodeId`, `projection?` (`"cells"` \| `"edges"`) | Get one node (no `cellName` — address it by `nodeId`; cell addresses come only from `get_board_outline`). `projection: "cells"` (CHAPTER nodes only) returns just `{rows, columns, cells}` instead of the full `timelineData` — use whenever only the grid/occupancy is needed, not the whole chapter; `projection: "edges"` returns just that node's inbound/outbound connections instead of `findNodeById`'s full record. Both are opt-in — omitting `projection` is the unchanged full response. An unknown id is a `NODE_NOT_FOUND` error | §3 `GET .../nodes/:nodeId` (REST returns the node as stored, without `cellName`; `404` carries `code: 'NODE_NOT_FOUND'`) |
31
31
  | `get_node_comments` | `boardId`, `nodeId` | List comments on a node | §1 `GET .../nodes/:nodeId/comments` |
32
32
  | `get_chat_attachment` | `boardId`, `sessionId`, `attachmentId` | The file a chat message came with — the message's `attachments` list `{id, type, ending}`. Images come back as images, a PDF as an embedded resource, csv / xml / txt / json as text. Only the agent the message was addressed to can read it (`CHAT_ATTACHMENT_NOT_FOUND`); needs the connection's `x-agent-id` (`CHAT_AGENT_REQUIRED`). Max 5 MB per file. | §15 `GET /api/org/:orgId/chat/sessions/:sessionId/attachments/:attachmentId` |
@@ -83,13 +83,14 @@ Pick the cheapest read that answers the step's question, and name the reason in
83
83
  | a chapter's grid / cell occupancy | `get_node { nodeId: <chapterId>, projection: "cells" }` |
84
84
  | one node's connections | `get_node { nodeId, projection: "edges" }` |
85
85
  | what is where in a chapter (incl. cell names for placement), plus `sliceStatus` per column | `get_board_outline` |
86
- | field types, examples, descriptions, positions, HTML | full `get_nodes`, scoped by `chapterId` or `nodeIds` — never board-wide when avoidable |
86
+ | field types, examples, field descriptions | `get_nodes` with `projection: "fields"`, scoped by `chapterId` or `nodeIds` |
87
+ | a node's description, position, HTML | full `get_nodes`, scoped by `chapterId` or `nodeIds` — never board-wide when avoidable |
87
88
  | finding slices / their elements / element counts | `get_slice_data` with `projection: "outline"` (format `json`/`yaml`/`toon`) |
88
89
  | attribute, field-flow or completeness work | `get_slice_data` with `projection: "fields"` |
89
90
  | scenario / spec review, spec coverage | `get_slice_data` with `projection: "specs"` (format `json`/`yaml`/`toon`) |
90
91
  | elements **and** specs **and** comments/prompts together (e.g. a business review) | full `get_slice_data` — say why |
91
92
 
92
- Two cheap projected calls (e.g. `outline` + `specs`) beat one full call when the step doesn't need comments, prompts or field bodies. `projection: "line"` never carries `sliceStatus`, `meta`, positions, field types or examples — if a later step reads any of those, use the full read. `get_nodes { type: "CHAPTER" }` without a projection returns every chapter's full grid; to just list or pick chapters, add `projection: "line"`.
93
+ Two cheap projected calls (e.g. `outline` + `specs`) beat one full call when the step doesn't need comments, prompts or field bodies. `projection: "line"` never carries `sliceStatus`, `meta`, positions, field types or examples; `projection: "fields"` adds the full field definitions and `parentId`, still no `sliceStatus`, positions or node description — if a later step reads any of those, use the full read. `get_nodes { type: "CHAPTER" }` without a projection returns every chapter's full grid; to just list or pick chapters, add `projection: "line"`.
93
94
 
94
95
  ---
95
96
 
@@ -473,21 +474,21 @@ List all nodes on a board.
473
474
  - `type?: ElementType` — exact match.
474
475
  - `name?: string` — partial, case-insensitive title match.
475
476
  - `chapterId?: string` — only nodes placed in this chapter (timeline).
476
- - `projection?: "line"` — compact `{id, type, title, fields?}` per node (`fields` = attribute names only, absent on nodes without fields) instead of the full record. Neither form carries `cellName` — address existing nodes by `id`. Any other value is `400 PROJECTION_INVALID`.
477
+ - `projection?: "line" | "fields"` — `line`: compact `{id, type, title, fields?}` per node (`fields` = attribute names only, absent on nodes without fields); `fields`: `{id, type, title, parentId, fields?}` with the full field definitions as stored, but no html, description, sketch or grid data. Either instead of the full record. Neither form carries `cellName` — address existing nodes by `id`. Any other value is `400 PROJECTION_INVALID`.
477
478
  - `cellId?: string` — return only the node occupying this timeline cell (format `<rowId>-<colId>`). Requires `timelineId`. Empty array if the cell is unoccupied.
478
479
  - `colId?: string` — return every node occupying this column, across *all* rows of the timeline (e.g. to check for an existing COMMAND/READMODEL/SCREEN/AUTOMATION before placing one, since the server caps those at one per column even across separate lane rows). Requires `timelineId`. Combine with `type` to narrow to one element type.
479
480
  - `timelineId?: string` — the CHAPTER node `cellId`/`colId` are resolved against. Required together with either of those two; `400` if omitted.
480
481
 
481
482
  Cell/column occupancy lives only in the CHAPTER node's `meta.timelineData.cells`, never on the node rows themselves — this endpoint resolves `cellId`/`colId` against that timeline internally so callers don't have to fetch and parse the whole chapter node just to check occupancy.
482
483
 
483
- **Response**: `200` — node record array (or `line` projections). `400` — `cellId`/`colId` given without `timelineId`, `PROJECTION_INVALID`, or `QUERY_PARAM_INVALID`. `404` — `timelineId` doesn't reference an existing CHAPTER node with grid data.
484
+ **Response**: `200` — node record array (or `line`/`fields` projections). `400` — `cellId`/`colId` given without `timelineId`, `PROJECTION_INVALID`, or `QUERY_PARAM_INVALID`. `404` — `timelineId` doesn't reference an existing CHAPTER node with grid data.
484
485
 
485
486
  ---
486
487
 
487
488
  ### POST `/api/org/:orgId/boards/:boardId/nodes/query`
488
489
  Fetch a known set of nodes in one call.
489
490
 
490
- **Body**: `{ "ids": string[], "projection"?: "line" }` — `ids` non-empty. Missing ids are silently omitted. Without `projection`, full stored records; `line` gives the compact shape above. Neither carries `cellName`.
491
+ **Body**: `{ "ids": string[], "projection"?: "line" | "fields" }` — `ids` non-empty. Missing ids are silently omitted. Without `projection`, full stored records; `line`/`fields` give the shapes above. Neither carries `cellName`.
491
492
 
492
493
  **Response**: `200` — node array. `400` — `ids` empty/not an array, or `PROJECTION_INVALID`.
493
494
 
@@ -1120,7 +1121,7 @@ Rule of thumb: if you are about to write "Shall I…?", "Want me to…?", "A or
1120
1121
  | to show a picture | `image` | nothing |
1121
1122
  | to show a command or payload | `code` | nothing |
1122
1123
  | to show numbers as a diagram (counts per slice, a trend, shares of a whole) | `report` | nothing |
1123
- | to explain how a process works, or walk through what a planned change touches, step by step ("how does registration work?", "we need to add an email — walk me through it") | `walkthrough` | nothing — selecting a step pans the canvas |
1124
+ | to explain how a feature works, or walk through what a planned feature takes, slice by slice ("how does registration work?", "we need to add an email — walk me through it") | `walkthrough` | nothing — selecting a step pans the canvas |
1124
1125
 
1125
1126
  `confirm`, `poll`, `tasks` and `changes` are questions: a person answers once, then they show as answered. `link`, `image`, `code`, `report` and `walkthrough` are display only and never wait for anything.
1126
1127
 
@@ -1144,13 +1145,17 @@ Rule of thumb: if you are about to write "Shall I…?", "Want me to…?", "A or
1144
1145
  labels: string[], // 1–50 points: x axis, or the pie slices
1145
1146
  series: Array<{ name: string, values: number[] }>, // one number per label; bar/line up to 6 series, pie uses only the first (no negatives)
1146
1147
  confirm?: { headline: string, yesLabel?: string, noLabel?: string } } // optional yes/no question under the diagram, like a confirm snippet
1147
- { kind: 'walkthrough', title: string, intro?: string, // a step-by-step player through a process
1148
- steps: Array<{ title: string, // 1+, in the order the process runs
1149
- description?: string, // what happens in this step, in business words
1150
- nodeId?: string, // the element, slice (SLICE_BORDER) or scenario (SCENARIO) of this step — selecting the step zooms to it
1151
- screenId?: string, // the SCREEN / HTML_SCREEN the person sees in this step
1152
- rules?: string[], // business rules that apply in this step
1153
- changes?: string[] }> } // for a planned change: what has to change here
1148
+ { kind: 'walkthrough', title: string, // a slice-by-slice player through a feature
1149
+ summary: string, // 1–3 sentences on how it works, shown on the first page under the slice count
1150
+ steps: Array<{ title: string, // 1+, one per slice, in the order the feature runs
1151
+ description?: string, // what happens in this slice, in business words
1152
+ nodeId?: string, // the slice's SLICE_BORDER — drawn in its lanes, selecting the step zooms to it; none for a new slice
1153
+ status?: 'existing' | 'changed' | 'new', // planned feature: used as is / needs adjustment / built from scratch
1154
+ elements?: Array<{ type: 'SCREEN' | 'COMMAND' | 'EVENT' | 'READMODEL' | 'AUTOMATION',
1155
+ title: string, fields?: string[] }>, // a new slice only: its sketch, drawn in lanes
1156
+ screenId?: string, // a SCREEN / HTML_SCREEN outside the slice the person sees in this step
1157
+ rules?: string[], // business rules of this slice
1158
+ changes?: string[] }> } // planned feature: what has to change or be built here
1154
1159
  ```
1155
1160
 
1156
1161
  ### How to use them
@@ -1161,7 +1166,7 @@ Rule of thumb: if you are about to write "Shall I…?", "Want me to…?", "A or
1161
1166
  - **Answers are text.** For a `tasks` answer, match the titles (or ids) back to your list; an element the person left unticked was declined, not forgotten. A `poll` option with a `message` of your own makes the answer unambiguous.
1162
1167
  - `get_chat_session` shows your snippet on the message as `snippet`, and the person's answer is the user message after it, carrying `context.snippetReply.messageId` (your message's id) — useful to tell an answer to a snippet from a new message.
1163
1168
  - **`report`** draws the numbers you send — it computes nothing, so aggregate first. A series whose length differs from `labels`, or a non-number, makes the whole snippet invisible. Keep `text` as a one-line summary of what the diagram shows. Add `confirm` when the diagram leads to a follow-up question ("Want me to look into the backward arrows?"): the answer comes back like a `confirm` answer, and without it the report is display only.
1164
- - **`walkthrough`** answers "how does X work?" and "walk me through what changes for Y": the person steps back and forth through the process in the chat, each step zooming the canvas to its element, and **Play** opens it full-screen as a movie strip of the steps' screens with description and rules underneath. Build it from the board, never from memory — the `walkthrough` skill (modeling kit) has the procedure. Every `nodeId`/`screenId` must be a real id from this board; a step without a screen just shows its element. Keep `text` to one line naming the process and the number of steps.
1169
+ - **`walkthrough`** answers "how does X work?" and "walk me through what changes for Y", **one step per slice**. It opens with a summary page — the slice count (with `status`: how many exist, need adjustment, are new) above your `summary` — then shows each slice in its lanes like Slice View (screen, command / read model, events), a `new` slice sketched from its `elements`; each step zooms the canvas to its slice, and **Play** opens it full-screen with description, changes and rules underneath. Build it from the board, never from memory — the `walkthrough` skill (modeling kit) has the procedure. Every `nodeId`/`screenId` must be a real id from this board. Keep `text` to one line naming the feature and the number of slices.
1165
1170
  - A snippet is shown exactly as you send it — keep secrets and tokens out of `code` and `image`.
1166
1171
 
1167
1172
  ---
@@ -37,7 +37,7 @@ with a `confirm` snippet — `CLAUDE.md` § *Locked slices in a chat* — and po
37
37
 
38
38
  `target` is singular, but the common real request is "fill in the examples across this chapter". When you have more than one target, **do not run this skill once per element and do not fetch context a node at a time.**
39
39
 
40
- 1. Read the chapter **once**: `mcp__eventmodelers__get_nodes { "boardId": "$BOARD_ID", "chapterId": "$CHAPTER_ID" }`. That single response carries every element's `meta.fields` *including the `example` values already filled in* — which is exactly the canonical-value pool Step 3c asks for, for the whole chapter, in one call.
40
+ 1. Read the chapter **once**: `mcp__eventmodelers__get_nodes { "boardId": "$BOARD_ID", "chapterId": "$CHAPTER_ID", "projection": "fields" }`. That single response carries every element's `fields` *including the `example` values already filled in*, without the html, descriptions and grid data a full read drags along — which is exactly the canonical-value pool Step 3c asks for, for the whole chapter, in one call.
41
41
  2. Pick the canonical value per field name from that pool (e.g. `customerId: "cust-123"`, `email: "jane@example.com"`) before writing anything, so every element ends up consistent.
42
42
  3. Then generate every target's values and write them all in a single `submit_node_events { events: [...] }` call — one `node:changed` event per element, never one call per element.
43
43
 
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  name: walkthrough
3
- description: Walk a person through the board step by step, as a player in the chat. Two modes — explain ("how does registration work?") follows a process through its screens, commands, events and read models; impact ("we need to add an email — walk me through the changes") lists, in order, every slice, element and scenario a planned change touches and what has to change there. Each step carries a description, the business rules that apply, a link that zooms the canvas to it, and its screen; the person can play it full-screen like the screen movie strip. Read-only — changes nothing on the board.
3
+ description: Walk a person through a feature slice by slice, as a player in the chat. It opens with a summary page (how many slices, how the feature works in 1–3 sentences), then one step per slice, each shown in its lanes like Slice View (screen, command / read model, events). Two modes — explain ("how does registration work?") follows the feature's slices in the order they run; impact ("we need to add an email — walk me through the changes") lists every slice a planned feature needs, marked as existing, needing adjustment or new, with new slices sketched. Each step carries a description, the business rules that apply, what changes there and a link that zooms the canvas to the slice. Read-only — changes nothing on the board.
4
4
  ---
5
5
 
6
- # Walkthrough — step by step through the board
6
+ # Walkthrough — slice by slice through a feature
7
7
 
8
8
  > **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.
9
9
 
10
10
  Prefer `mcp__eventmodelers__*` tools. See `learn-eventmodelers-api` for the curl fallback and §16 *Chat snippets* for the `walkthrough` shape.
11
11
 
12
- The result is **one `walkthrough` snippet** in the chat. The person steps back and forth through it; selecting a step zooms the canvas to that step's element, slice or scenario, and **Play** opens all steps full-screen as a strip of their screens with the description, the changes and the rules underneath. The walkthrough is only as good as its links: every step points at a real node on this board.
12
+ The result is **one `walkthrough` snippet** in the chat. **Its unit is the slice**: one step per slice, never per element. The player always opens with a **summary page** — "This feature consists of 6 slices" (for a planned feature: "…: 2 of them exist, 1 existing one needs adjustment and 3 have to be implemented from scratch"), worked out from the steps, plus your 1–3 sentence `summary` of how it works. Each step after that shows its slice the way Slice View does — the screen on top, command / read model in the next lane, events at the bottom — and a slice that doesn't exist yet is drawn as a sketch from the elements you give it. Selecting a step zooms the canvas to the slice; **Play** opens everything full-screen with the description, the changes and the rules underneath. The walkthrough is only as good as its links: every existing slice points at its real `SLICE_BORDER` on this board.
13
13
 
14
14
  **This skill never writes to the board.** In impact mode it shows what would change; making those changes is separate work the person asks for afterwards.
15
15
 
@@ -21,11 +21,13 @@ From `$ARGUMENTS` / the message, and the turn's `context=` (selected nodes, `tim
21
21
 
22
22
  | Mode | Typical message | The steps are |
23
23
  |---|---|---|
24
- | `explain` | "How does registration work?", "walk me through checkout", "/walkthrough Registration" | the process in the order it runs, as a person experiences it |
25
- | `impact` | "We need to add an email — walk me through the changes", "what does it take to support refunds?" | every place in the model the change touches, in the order it should be changed |
24
+ | `explain` | "How does registration work?", "walk me through checkout", "/walkthrough Registration" | the feature's slices in the order they run, as a person experiences them |
25
+ | `impact` | "We need to add an email — walk me through the changes", "what does it take to support refunds?" | every slice the planned feature needs — existing ones it uses, existing ones to adjust, new ones to build — in the order they run |
26
26
 
27
27
  The **subject** is the process or the change, in the person's words. "This"/"here" means what they have selected or zoomed to.
28
28
 
29
+ **Which mode** — decide by whether the subject is on the board yet, not by the phrasing. Anything the person calls *new*, *planned*, *a feature we want/need*, *support for X*, or that the board doesn't model yet (a new license type, a new field, a new flow) is **impact**, even when they say "walk me through the X feature". Only a flow that is fully modelled as it should work is **explain**. In doubt, impact — an impact walkthrough of an unchanged flow just marks every slice `existing`, while an explain walkthrough of a planned feature hides which slices are new.
30
+
29
31
  ### No subject yet — ask first
30
32
 
31
33
  Called without one (a bare `/walkthrough`, the chat menu's entry sent as is, "walk me through" with nothing named), **ask before reading anything in detail** — the selection or the chapter in view is not enough on its own to guess which flow or which feature they mean. One cheap read for the options: `get_nodes { boardId, type: "CHAPTER", projection: "line" }` (and, for a single chapter, `list_slices`). Then reply once and **end the turn**:
@@ -60,46 +62,57 @@ Orient cheaply before reading anything in detail — the board can be large, and
60
62
 
61
63
  1. **Chapters**: `get_nodes { boardId, type: "CHAPTER", projection: "line" }` — pick the chapter(s) the subject belongs to by title. With a `timelineId` in context, start there.
62
64
  2. **Context notes**: for each candidate chapter, `get_board_outline { boardId, chapterId }`, then read the MARKDOWN note in the first column's `feedback` lane (`get_node`, `meta.description`) if there is one. It says what the chapter is for and often names the decisions behind it — use it in the descriptions.
63
- 3. **Slices**: `list_slices { boardId, contextName }` and `get_slice_data { boardId, contextName, projection: "outline", format: "toon" }` — every slice with its elements as `{id, title, type}`.
64
- 4. **Find the nodes that matter.** With the outline in hand, decide which slices and elements belong to the subject:
65
- - **explain**: the slices whose commands, events, read models or screens are about the subject; follow the edges in the outline (screen → command → event → read model → next screen, events → automations) from where the process starts to where it ends. Other chapters only when the flow crosses into them (an external or translated event).
66
- - **impact**: start from the element the change lands on first (the screen or command where the new data enters, or the event whose meaning changes), then follow the flow **downstream** — every event that would carry it, every read model and automation fed by those events, every screen that shows those read models — and **upstream** where the data has to come from. A name search helps: `get_nodes { boardId, name: "<term>", projection: "line" }` for the field or concept ("email") finds the places that mention it already.
65
+ 3. **Slices**: `list_slices { boardId, contextName }` and `get_slice_data { boardId, contextName, projection: "outline", format: "toon" }` — every slice with its elements as `{id, title, type}`. This trimmed outline is your overview of the feature: pick the slices from it, and read nothing else board-wide.
66
+ 4. **Find the slices that matter.** With the outline in hand, decide which **slices** belong to the subject — elements only tell you which slice to pick:
67
+ - **explain**: the slices whose commands, events, read models or screens are about the subject; follow the edges in the outline (screen → command → event → read model → next screen, events → automations) from the slice where the feature starts to the one where it ends. Other chapters only when the flow crosses into them (an external or translated event).
68
+ - **impact**: start from the slice the change lands on first (where the new data enters, or whose event changes meaning), then follow the flow **downstream** — every slice whose events would carry it, every state view and automation fed by those events, every screen that shows them — and **upstream** where the data has to come from. A name search helps: `get_nodes { boardId, name: "<term>", projection: "line" }` for the field or concept ("email") finds the slices that mention it already. Then work out the slices the feature needs that **don't exist yet** (a new command, a new state view, a new automation) — each is one new slice.
67
69
 
68
- Stop widening when a further step adds nothing the person asked about. A walkthrough of 4–12 steps is typical; 20+ means the subject is really several — say so in the text and walk the first one.
70
+ Stop widening when a further slice adds nothing the person asked about. A walkthrough of 3–12 slices is typical; 20+ means the subject is really several features — say so in the text and walk the first one.
69
71
 
70
72
  ---
71
73
 
72
74
  ## Step 3 — Read only those
73
75
 
74
- Now read the working set in detail — never the whole board:
76
+ Now read the chosen slices in detail — never the whole board:
75
77
 
76
- - `get_slice_data { boardId, contextName, sliceId, projection: "fields" }` per relevant slice — fields and dependencies.
78
+ - `get_slice_data { boardId, contextName, sliceId, projection: "fields", format: "toon" }` per chosen slice — fields and dependencies, compact. Not the `textual` format: it repeats the slice's specs under every element.
77
79
  - `get_slice_data { boardId, contextName, sliceId, projection: "specs", format: "toon" }` — the **scenarios**: these are the business rules. A scenario's title in business words ("Email must be unique") is a rule; its Given/When/Then says when it applies.
78
- - `get_nodes { boardId, type: "SCENARIO", chapterId, projection: "line" }` — the ids of the scenario nodes, so an impact step can point at a scenario directly.
79
80
  - Full `get_nodes { boardId, nodeIds: [...] }` only for the few nodes whose `description` you need.
80
81
 
81
82
  ---
82
83
 
83
- ## Step 4 — Build the steps
84
+ ## Step 4 — Build the summary and the steps
85
+
86
+ **One step per slice**, in the order the feature runs. Never split a slice into element steps (no separate "command" and "event" steps) — the player already draws the slice's screen, commands, read models and events in its lanes. Scenarios are not steps either: their rules go into the slice's `rules`, new or changed cases into its `changes`.
87
+
88
+ **explain** — the slices as the person living the feature experiences them: *what they see and do → what is recorded → what that makes visible or triggers*.
84
89
 
85
- One step per thing the person should look at, in order.
90
+ **impact** — every slice the feature needs, existing or not, in the order the feature runs (not grouped by status). **Every step carries a `status`** — it is what the summary page counts ("8 slices: 3 exist, 2 need adjustment, 3 are new") and what each slice's chip shows; a step without one leaves the person guessing what is new:
91
+
92
+ | `status` | When |
93
+ |---|---|
94
+ | `existing` | the slice is used as it is — the person should see it to understand the feature, but nothing changes |
95
+ | `changed` | the slice exists and needs adjustment — say what in `changes` |
96
+ | `new` | the slice doesn't exist yet and is built from scratch — sketch it with `elements`, say what it does in `description` |
86
97
 
87
- **explain** — follow the process as the person living it experiences it. One step per meaningful moment, usually one slice: *what they see → what they do → what is recorded → what that makes visible or triggers*. Merge a command and its event into one step when nothing happens between them; give an automation its own step.
98
+ Leave out existing slices that are neither changed nor needed to follow the feature. Say what is *not* affected only if the person would reasonably expect it to be.
88
99
 
89
- **impact** — one step per place that has to change, ordered so each step builds on the previous one (where the data enters → the command → the event → read models → screens → automations → scenarios). Include **scenarios** as their own steps when they need a new case or an update (e.g. "add: Register with an email that is already taken → rejected"). Say what is *not* affected only if the person would reasonably expect it to be.
100
+ **Summary** (snippet level) — always. 1–3 sentences on how the feature works (explain) or what it adds and how (impact), in the board's language. Don't count the slices in it — the player puts the count above it ("This feature consists of 6 slices: 2 of them exist, …"), computed from the steps and their `status`.
90
101
 
91
102
  Per step:
92
103
 
93
104
  | Field | What goes in |
94
105
  |---|---|
95
- | `title` | short, business words — the moment ("Customer submits registration") or the place ("Register Customer — command") |
96
- | `description` | 1–3 sentences: what happens here and why it matters, in the board's language. No ids, no cell addresses. |
97
- | `nodeId` | the node to zoom to: the **slice** (its `SLICE_BORDER` id from `list_slices`) when the step is about the slice as a whole, the **element** when it is about one element, the **scenario** node when the step is a scenario |
98
- | `screenId` | the SCREEN / HTML_SCREEN shown in this step, if there is one — that is what the player shows. Leave it out otherwise; don't point at an unrelated screen to fill the frame |
99
- | `rules` | the business rules that apply here, taken from the scenarios (and the context note); one line each, thresholds verbatim. Empty when there are none — never invent one |
100
- | `changes` | **impact mode only**: what has to change here, one line each — "add field `email` (String)", "new scenario: duplicate email is rejected", "show email in the confirmation screen" |
106
+ | `title` | the slice's name as on the board; for a new slice a name in the board's style ("Confirm Email") |
107
+ | `description` | 1–3 sentences: what happens in this slice and why it matters, in the board's language. No ids, no cell addresses. |
108
+ | `nodeId` | the slice's `SLICE_BORDER` id from `list_slices` — the player draws the slice from it and zooms the canvas to it. Left out for a `new` slice |
109
+ | `status` | **impact mode: required on every step** — `existing`, `changed` or `new` (table above). Omitted in explain mode |
110
+ | `elements` | **`new` slices only**: the sketch — `[{ "type": "SCREEN" \| "COMMAND" \| "EVENT" \| "READMODEL" \| "AUTOMATION", "title": "…", "fields": ["…"] }]`, the elements the slice will have (a state change: screen → command → event; a state view: event(s) → read model → screen; an automation: read model → automation → command → event). Titles and fields in the board's style; reuse the names of existing events the slice reads from |
111
+ | `screenId` | only when the screen a person sees in this step is not part of the slice itself |
112
+ | `rules` | the business rules of this slice, taken from its scenarios (and the context note); one line each, thresholds verbatim. Empty when there are none — never invent one |
113
+ | `changes` | **impact mode only**: what has to change or be built in this slice, one line each — "add field `email` (String) to Register Customer", "new scenario: duplicate email is rejected" |
101
114
 
102
- **Faithfulness.** Everything comes from the board. A rule nobody modelled is not a rule — if the walkthrough reveals a gap ("nothing says what happens when confirmation never arrives"), mention it in the step's `description` as an open question, not as a rule.
115
+ **Faithfulness.** Existing slices come from the board. A rule nobody modelled is not a rule — if the walkthrough reveals a gap ("nothing says what happens when confirmation never arrives"), mention it in the step's `description` as an open question, not as a rule. A sketched new slice is a proposal, and the `description` should read like one.
103
116
 
104
117
  ---
105
118
 
@@ -111,36 +124,49 @@ Per step:
111
124
  mcp__eventmodelers__post_chat_message {
112
125
  "boardId": "$BOARD_ID",
113
126
  "replyTo": "<message_id>",
114
- "text": "Registration in 5 steps — step through it here, or press Play.",
127
+ "text": "Registration in 4 slices — step through it here, or press Play.",
115
128
  "snippet": {
116
129
  "kind": "walkthrough",
117
130
  "title": "How registration works",
118
- "intro": "From the sign-up form to a confirmed account.",
131
+ "summary": "A customer signs up with name, email and password. The account stays inactive until the email is confirmed through the link sent to them.",
119
132
  "steps": [
120
- { "title": "Customer fills in the sign-up form", "nodeId": "<slice id>", "screenId": "<screen id>",
121
- "description": "Name, email and password are entered on the registration screen.",
133
+ { "title": "Register Customer", "nodeId": "<slice border id>",
134
+ "description": "Name, email and password are entered on the registration screen and recorded as Customer Registered.",
122
135
  "rules": ["Email must be unique", "Password at least 12 characters"] },
123
- { "title": "Customer registered", "nodeId": "<event id>",
124
- "description": "The registration is recorded; the account is not active yet." }
136
+ { "title": "Send Confirmation Mail", "nodeId": "<slice border id>",
137
+ "description": "An automation picks up every new registration and sends the confirmation link." }
125
138
  ]
126
139
  }
127
140
  }
128
141
  ```
129
142
 
130
- Impact mode, same shape with `changes` per step:
143
+ Impact mode, same shape with `status` (and `changes`, or `elements` for a new slice) per step:
131
144
 
132
145
  ```
133
- { "title": "Register Customer — command", "nodeId": "<command id>",
134
- "description": "The email enters here and has to be validated before anything is recorded.",
135
- "changes": ["Add field email (String)", "Reject the command when the email is already registered"],
136
- "rules": ["Customer name is required"] },
137
- { "title": "Scenario: duplicate email", "nodeId": "<scenario id>",
138
- "changes": ["New case: Given Customer registered with x@y.z, When Register Customer with x@y.z, Then rejected"] }
146
+ "summary": "Customers register with an email that has to be confirmed before the account becomes active. Registration stores the email, and a new confirmation flow sends and checks the link.",
147
+ "steps": [
148
+ { "title": "Register Customer", "nodeId": "<slice border id>", "status": "changed",
149
+ "description": "The email enters here and has to be validated before anything is recorded.",
150
+ "changes": ["Add field email (String) to Register Customer and Customer Registered", "New scenario: duplicate email is rejected"],
151
+ "rules": ["Customer name is required"] },
152
+ { "title": "Confirm Email", "status": "new",
153
+ "description": "Proposed: the customer opens the link and the email is marked as confirmed.",
154
+ "elements": [
155
+ { "type": "SCREEN", "title": "Confirm Email Page" },
156
+ { "type": "COMMAND", "title": "Confirm Email", "fields": ["customerId", "token"] },
157
+ { "type": "EVENT", "title": "Email Confirmed", "fields": ["customerId", "confirmedAt"] }
158
+ ],
159
+ "changes": ["New slice: Confirm Email (state change)"] },
160
+ { "title": "Customer List", "nodeId": "<slice border id>", "status": "existing",
161
+ "description": "Shows the customers as before; confirmation doesn't change it." }
162
+ ]
139
163
  ```
140
164
 
141
- - `text` is one line: the subject and the number of steps. It is the fallback, so it must make sense alone.
142
- - Every `nodeId` / `screenId` is an id you read in Steps 2–3 — never a guessed or remembered one.
165
+ - `text` is one line: the subject and the number of slices — in impact mode with the split ("Startup license in 8 slices: 3 new, 2 to adjust"). It is the fallback, so it must make sense alone.
166
+ - Impact mode: before posting, check that every step has a `status`, every `changed` step has `changes` and every `new` step has `elements` and no `nodeId`.
167
+ - `summary` is always there — the first page shows it under the slice count.
168
+ - Every `nodeId` / `screenId` is an id you read in Steps 2–3 — never a guessed or remembered one. A `new` slice has no `nodeId`.
143
169
  - The snippet is at most 64 KB; keep descriptions short rather than dropping steps.
144
170
  - **Impact mode** ends there: the walkthrough is the proposal. If the person then asks for the changes, that is ordinary work (prompts per the kit's CLAUDE.md) — and a slice that is not `Created` still needs their confirmation first.
145
171
 
146
- **No chat** (run from a terminal): print the steps as a numbered list with the same fields instead of posting.
172
+ **No chat** (run from a terminal): print the slice count and the summary, then the steps as a numbered list with the same fields, instead of posting.
@@ -204,9 +204,9 @@ for it. Instead:
204
204
  *"On it — looking at Registration."*
205
205
  - **walkthrough** — "how does X work?", "walk me through …", "what does it take to add …?", or `/walkthrough …`:
206
206
  run the `/walkthrough` skill **in this turn** — it only reads the board, so no prompt is needed. It finds the
207
- slices, elements and scenarios involved and its `walkthrough` snippet is your one reply (step 4). Without a
207
+ slices involved (one step per slice, after a summary page) and its `walkthrough` snippet is your one reply (step 4). Without a
208
208
  subject (a bare `/walkthrough`) it asks first — which flow, or which new feature — and that question is the reply. A planned change
209
- ("we need to add an email") is its impact mode: the walkthrough is the proposal, and the changes become work only
209
+ ("we need to add an email") is its impact mode: every slice marked existing / needs adjustment / new, new ones sketched — the walkthrough is the proposal, and the changes become work only
210
210
  when the person asks for them afterwards.
211
211
  - **a skill by name** — the message starts with `/<name>` of one of your skills (the chat panel's menu
212
212
  writes these: `/analyze-existing-model`, `/analyze-code-base`, `/detect-model-drift`, `/add-next-slice`, `/examples`, `/timeline …`,
@@ -364,7 +364,7 @@ nothing to sanitize either, since a board change is not user text.
364
364
  | Analyse the existing model structure, slice coverage, element counts | `/analyze-existing-model` |
365
365
  | Reverse-engineer the business process of an existing code base into the model, as an interview — all chapters first, then one chapter at a time | `/analyze-code-base` |
366
366
  | Find where the model and the code have drifted apart (fields, specs, screens, edges, missing/extra slices) and propose fixes | `/detect-model-drift` |
367
- | Walk someone through a process step by step, or through every slice, element and scenario a planned change touches, as a player in the chat | `/walkthrough` |
367
+ | Walk someone through a feature slice by slice, or through every slice a planned feature needs (existing, to adjust, new), as a player in the chat | `/walkthrough` |
368
368
  | Turn a document or image (e.g. a tender/RFP) into a chaptered event model with screens, scenarios and a written blueprint summary | `/summarize` |
369
369
  | Look up any API endpoint or element type not already covered by the skill you're executing | `/learn-eventmodelers-api` |
370
370
  | Add or rename an attribute across a chain of elements | `/attributes` |