@eventmodelers/cli 1.0.76 → 1.0.77

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventmodelers/cli",
3
- "version": "1.0.76",
3
+ "version": "1.0.77",
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": {
@@ -25,7 +25,7 @@ Server name: `eventmodelers`. Every tool takes `boardId` explicitly; none need `
25
25
  | `get_node_comments` | `boardId`, `nodeId` | List comments on a node | §1 `GET .../nodes/:nodeId/comments` |
26
26
  | `get_board_events` | `boardId` | All board events, in sequence | §1 `GET .../events` |
27
27
  | `search_board_events` | `boardId`, `name` | Search events by node name | §1 `GET .../events/search` |
28
- | `submit_node_events` | `boardId`, `events[]`, `autoConnect?`, `compact?` | Create/update nodes (raw `NodeChangeEvent`/edge events). `autoConnect: false` places freshly-created nodes without wiring them to their own/previous-column neighbors (avoids a stray nearest-left edge); `compact: true` returns `{persisted: <count>}` instead of the per-node hash map | §3 `POST .../nodes/events` |
28
+ | `submit_node_events` | `boardId`, `events[]`, `autoConnect?`, `compact?` | Create/update nodes (raw `NodeChangeEvent`/edge events). Every event property is described on the tool's own `events[]` schema — read that rather than this skill when all you need is the event shape. `autoConnect: false` places freshly-created nodes without wiring them to their own/previous-column neighbors (avoids a stray nearest-left edge); `compact: true` returns `{persisted: <count>}` instead of the per-node hash map | §3 `POST .../nodes/events` |
29
29
  | `delete_node` | `boardId`, `nodeId` | Delete a node. Deleting a chapter (timeline) cascades — every node placed in one of its cells, plus any node parented to it (e.g. SLICE_BORDER), is deleted too, along with all their edges | (via `node:deleted` event, §3) |
30
30
  | `create_drawing` / `create_drawings` | `boardId`, `kind`, `x`, `y`, `width`, `height`, ... (plural: `drawings[]`) | Freehand canvas annotation (path/rect/text/sticky) — never placed in a cell. Use the plural form whenever an annotation is more than one stroke (a loop plus its arrows and label is one annotation, not three calls) | — (REST `POST .../drawing/draw` accepts a single drawing or an array) |
31
31
  | `find_nodes_in_drawing` | `boardId`, `drawingId` | Nodes fully contained inside a drawing's bounding box | — (no REST equivalent; MCP-only) |
@@ -44,6 +44,7 @@ Server name: `eventmodelers`. Every tool takes `boardId` explicitly; none need `
44
44
  | `create_slice_definition` | `boardId`, `timelineId`, `columnId`, `title`, `status?`, `data?`, `meta?` | Create a SLICE_BORDER over an existing column. `status` sets its `sliceStatus` straight away instead of a follow-up `update_slice_status` | §5 `POST .../slice-definitions` |
45
45
  | `place_element` / `place_elements` | `boardId`, `timelineId`, `elementType`, `title`, `fields?`, `lane?`, `columnIndex?`, `compact?`, `autoConnect?` (plural: `elements[]`) | Find/create an empty cell in the right lane and place a COMMAND/READMODEL/EVENT. `fields` writes the element's attributes in the same call — don't follow a placement with a `submit_node_events` just to set them. The plural form places a whole slice's or column run's worth in one call, applied in order so each entry sees the columns the previous one added. `autoConnect: false` places without wiring to timeline neighbors — wire the edges yourself | — (MCP-only convenience; composes §2+§3) |
46
46
  | `list_slices` | `boardId` | List slices (id, title, status) | §8 `GET .../slicedata/slices` |
47
+ | `get_slice_rework` | `boardId`, `contextId` | How much each slice of one context has been reworked: changes, steps backwards, and reopens after Done, most reworked first, plus planning metrics over them. `contextId` is a MODEL_CONTEXT or a timeline (a timeline resolves to the context it belongs to). Always per context — there is no board-wide form | §8 `GET .../reporting/rework/contexts/:contextId` |
47
48
  | `update_slice_status` | `boardId`, `newStatus`, plus exactly one of `sliceId` / `sliceTitle` / `columnId` | Change a SLICE_BORDER's `sliceStatus`. With a title or column id there is no need to call `list_slices` first; an ambiguous title comes back with its candidates. A slice being created takes its status from `create_slice`/`create_slice_definition` instead | — (via `node:changed` event, §3) |
48
49
  | `get_slice_data` | `boardId`, `contextName?`, `contextId?`, `sliceId?` | Full element graph for slices in a context | §8 `GET /slicedata` |
49
50
  | `get_spec_info` | `boardId`, `timelineId`, `elementTypes?` | EVENT/COMMAND/READMODEL nodes valid in GWT steps. Pass `elementTypes` (subset of `EVENT`/`COMMAND`/`READMODEL`) to avoid pulling the full element list when only one or two types are needed — filtered server-side, not just after a full fetch | §6 `GET .../spec-info` |
@@ -57,7 +58,7 @@ Server name: `eventmodelers`. Every tool takes `boardId` explicitly; none need `
57
58
  | `link_element` | `boardId`, `nodeId`, plus either `targetNodeId` or `timelineId` (+ `columnIndex?`, `lane?`) | Turn a node into a linked copy of `nodeId` — it receives a full copy of that node's meta plus `meta.linkedTo`. Name an existing `targetNodeId`, or pass `timelineId` to have the copy placed and linked in this one call (inheriting the original's type and title), which is what a translation or automation chain wants | §3 `POST .../nodes/:nodeId/link` |
58
59
  | `add_comment` / `add_comments` | `boardId`, `nodeId`, `text`, `type?` (`'COMMENT'\|'TASK'\|'QUESTION'`), `author?` (plural: `comments[]`, each with its own `nodeId`) | Add a comment — `QUESTION` is the type for a gap/edge case raised during review. Use the plural form for a review that has a question per element: all of them go in one call | §1 `POST .../boards/:boardId/comments` (batch) |
59
60
  | `update_comment` | `boardId`, `nodeId`, `commentId`, `action` (`'resolve'\|'delete'`) | Resolve or delete a comment | — (via comment events) |
60
- | `create_screen` | `boardId`, `contentType` (`'image'\|'sketch'\|'html'`), `nodeId?`, `chapterId`, `cellId?`/`cellName?`, plus content fields (`imageBase64`/`mimeType`, `elements[]`, or `pages[]`/`backgroundColor`), `description?`, `fields?`, `autoConnect?` | Create + place a new screen node (SCREEN or HTML_SCREEN) atomically, in one call. Batch form `create_screens` takes `screens[]` (HTML only) + `autoConnect?`. `autoConnect: false` places without wiring to timeline neighbors | §4 `POST .../images/:id/sketch` + `image-nodes` |
61
+ | `create_screen` | `boardId`, `contentType` (`'image'\|'sketch'\|'html'`), `nodeId?`, `chapterId`, `cellId?`/`cellName?`, plus content fields (`imageBase64`/`mimeType`, `elements[]`, or `pages[]`/`backgroundColor`), `title?`, `description?`, `fields?`, `autoConnect?` | Create + place a new screen node (SCREEN or HTML_SCREEN) atomically, in one call. `title` names the node (`meta.title`) in the same call — no follow-up `node:changed` just to label the screen; `create_screens` takes it per entry. Batch form `create_screens` takes `screens[]` (HTML only) + `autoConnect?`. `autoConnect: false` places without wiring to timeline neighbors | §4 `POST .../images/:id/sketch` + `image-nodes` |
61
62
  | `render_screen` | `boardId`, `nodeId`, `elements[]?` (SCREEN) or `pages[]?`+`backgroundColor?` (HTML_SCREEN), `description?` | Update an existing screen's content — exactly one of `elements`/`pages` | §4 `POST .../images/:id/sketch` + `image-nodes` |
62
63
  | `add_field_examples` | `boardId`, `nodeId?`, `name?`, `cellName?`, `timelineId?` | Fill empty field examples using linked-node context | — (MCP-only convenience) |
63
64
  | `get_attribute_chain` | `boardId`, `timelineId`, `targetCellName`, `sourceCellName` | Resolve every node between two cells, ordered target→source | — (MCP-only convenience) |
@@ -514,7 +515,7 @@ Update an image snapshot.
514
515
  ### POST `/api/org/:orgId/boards/:boardId/image-nodes/:nodeId`
515
516
  Create an image node.
516
517
 
517
- **Request**: `multipart/form-data` — fields: `file`, `chapterId`, `cellName`
518
+ **Request**: `multipart/form-data` — fields: `file`, `chapterId`, `cellName`, `title?` (label shown on the node, `meta.title`)
518
519
  **Response**: `204`
519
520
 
520
521
  ---
@@ -543,6 +544,7 @@ Create a SCREEN node from a sketch description.
543
544
  cellName: string
544
545
  description: { elements: object[] }
545
546
  semanticDescription?: string
547
+ title?: string // label shown on the node (meta.title)
546
548
  }
547
549
  ```
548
550
  **Response**: `204` OR `400` (validation error)
@@ -730,6 +732,30 @@ List all slices on a board.
730
732
 
731
733
  ---
732
734
 
735
+ ### GET `/api/org/:orgId/boards/:boardId/reporting/rework/contexts/:contextId`
736
+ **File**: `src/slices/change/reporting/rework/routes.ts`
737
+
738
+ How much each slice of one context has been reworked — read-only, derived from the board event log; nothing is stored
739
+ for it.
740
+
741
+ A slice's rework is read from its own SLICE_BORDER history. Going backwards means a step down the progress order
742
+ (Created → Planned → Assigned → InProgress → Review → Done), or reaching `Blocked` from `Review`/`Done`;
743
+ `Informational` is never scored. `reopens` counts transitions leading away from `Done`, `changes` counts writes to the
744
+ slice itself. This says nothing about edits to the elements inside a slice.
745
+
746
+ `contextId` is a MODEL_CONTEXT node id, or a timeline id — a timeline resolves through the board's own effective
747
+ context (the same rule `slicedata` uses), so one that inherits a context is reported under that context and one with
748
+ none is its own. Any other node type is rejected. Always scoped to one context; there is no board-wide form.
749
+
750
+ **Response**: `200` — `{ contextId, contextName, metrics, slices[] }`, slices most reworked first.
751
+ `slices[]` = `{ sliceId, title, status, changes, reopens, regressions, everReachedDone }`.
752
+ `metrics` = `{ slices, everReachedDone, reopenedAfterDone, firstTimeRightRate, currentlyReopened, avgReopensPerSlice,
753
+ avgChangesPerSlice }` — `firstTimeRightRate` is the share of the slices that reached Done and never came back, or
754
+ `null` when none got there yet.
755
+ `400` `CONTEXT_ID_REQUIRED` / `CONTEXT_NODE_INVALID` · `404` `CONTEXT_NOT_FOUND`
756
+
757
+ ---
758
+
733
759
  ## 9. Extensions
734
760
 
735
761
  **File**: `src/slices/extensions/routes.ts`
@@ -309,6 +309,7 @@ mcp__eventmodelers__create_screen {
309
309
  "nodeId": "<SCREEN_NODE_ID>",
310
310
  "chapterId": "<CHAPTER_ID>",
311
311
  "cellId": "<CELL_ID>",
312
+ "title": "<screen.title>",
312
313
  "pages": ["<reconstructed HTML fragment for this screen>"],
313
314
  "description": "<screen.description — 'Shows X. Arrived via: Y. Actions: user can do A, user can do B.'>"
314
315
  }
@@ -325,6 +326,7 @@ mcp__eventmodelers__create_screen {
325
326
  "nodeId": "<SCREEN_NODE_ID>",
326
327
  "chapterId": "<CHAPTER_ID>",
327
328
  "cellName": "<CELL_NAME>",
329
+ "title": "<screen.title>",
328
330
  "imageBase64": "<base64-encoded contents of screen.filepath, no data: URI prefix>",
329
331
  "mimeType": "image/png",
330
332
  "description": "<screen.description — 'Shows X. Arrived via: Y. Actions: user can do A, user can do B.'>"
@@ -58,6 +58,7 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/image-nodes/$SCREEN_
58
58
  -H "x-token: $TOKEN" \
59
59
  -F "file=@<screen.filepath>" \
60
60
  -F "chapterId=$CHAPTER_ID" \
61
- -F "cellName=$CELL_NAME"
61
+ -F "cellName=$CELL_NAME" \
62
+ -F "title=<screen.title>"
62
63
  ```
63
64
  For the HTML path with no MCP, use the `html-screen-nodes` endpoint per the `html-screen` skill's fallback mechanics instead.
@@ -36,6 +36,7 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/html-screen-nodes/<n
36
36
  -d '{
37
37
  "chapterId": "<CHAPTER_ID>",
38
38
  "cellId": "<actorRowId>-<columnId>",
39
+ "title": "<Screen Title>",
39
40
  "pages": ["<div>...</div>"]
40
41
  }'
41
42
  ```
@@ -31,7 +31,7 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/html-screen-nodes/$N
31
31
  -H "x-board-id: $BOARD_ID" \
32
32
  -H "x-user-id: agent" \
33
33
  -H "Content-Type: application/json" \
34
- -d '{"chapterId": "'"$CHAPTER_ID"'", "cellName": "'"$CELL_NAME"'", "pages": ["<div>...</div>"]}'
34
+ -d '{"chapterId": "'"$CHAPTER_ID"'", "cellName": "'"$CELL_NAME"'", "title": "<Screen Title>", "pages": ["<div>...</div>"]}'
35
35
  ```
36
36
 
37
37
  ## Step 5 — Define field data lineage
@@ -278,6 +278,7 @@ mcp__eventmodelers__create_screen {
278
278
  "nodeId": "<node-uuid>",
279
279
  "chapterId": "<TIMELINE_ID>",
280
280
  "cellId": "<CELL_ID>",
281
+ "title": "<title>",
281
282
  "pages": ["<div>...</div>"],
282
283
  "description": "<title — what this screen shows>"
283
284
  }
@@ -296,6 +297,7 @@ mcp__eventmodelers__create_screen {
296
297
  "nodeId": "<node-uuid>",
297
298
  "chapterId": "<TIMELINE_ID>",
298
299
  "cellId": "<CELL_ID>",
300
+ "title": "<title>",
299
301
  "elements": [...],
300
302
  "description": "<title — what this screen shows>"
301
303
  }
@@ -95,6 +95,7 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/html-screen-nodes/<n
95
95
  -d '{
96
96
  "chapterId": "<TIMELINE_ID>",
97
97
  "cellId": "<CELL_ID>",
98
+ "title": "<title>",
98
99
  "pages": ["<div>...</div>"]
99
100
  }'
100
101
  ```
@@ -110,6 +111,7 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/image-nodes/<node-uu
110
111
  -d '{
111
112
  "chapterId": "<TIMELINE_ID>",
112
113
  "cellId": "<CELL_ID>",
114
+ "title": "<title>",
113
115
  "description": {"elements": [...]},
114
116
  "semanticDescription": "<title — what this screen shows>"
115
117
  }'
@@ -183,6 +183,7 @@ mcp__eventmodelers__create_screen {
183
183
  "nodeId": "<SCREEN_NODE_ID>",
184
184
  "chapterId": "<CHAPTER_ID>",
185
185
  "cellId": "<actorCellId>",
186
+ "title": "<screenTitle>",
186
187
  "pages": ["<div>...</div>"],
187
188
  "description": "<screenTitle — what this screen shows>"
188
189
  }
@@ -201,6 +202,7 @@ mcp__eventmodelers__create_screen {
201
202
  "nodeId": "<SCREEN_NODE_ID>",
202
203
  "chapterId": "<CHAPTER_ID>",
203
204
  "cellId": "<actorCellId>",
205
+ "title": "<screenTitle>",
204
206
  "elements": [...],
205
207
  "description": "<screenTitle — what this screen shows>"
206
208
  }
@@ -39,6 +39,7 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/html-screen-nodes/$S
39
39
  -d '{
40
40
  "chapterId": "<CHAPTER_ID>",
41
41
  "cellId": "<actorCellId>",
42
+ "title": "<screenTitle>",
42
43
  "pages": ["<div>...</div>"]
43
44
  }'
44
45
  ```
@@ -54,6 +55,7 @@ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/image-nodes/$SCREEN_
54
55
  -d '{
55
56
  "chapterId": "<CHAPTER_ID>",
56
57
  "cellId": "<actorCellId>",
58
+ "title": "<screenTitle>",
57
59
  "description": {"elements": [...]},
58
60
  "semanticDescription": "<screenTitle — what this screen shows>"
59
61
  }'