@eventmodelers/cli 1.0.29 → 1.0.31

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.29",
3
+ "version": "1.0.31",
4
4
  "description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, Cratis, or modeling-only)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -51,6 +51,7 @@ Server name: `eventmodelers`. Every tool takes `boardId` explicitly; none need `
51
51
  | `add_storyline` | `boardId`, `timelineId`, `columnId`, `storylines[]` | **Experimental — only use when explicitly asked for a storyline/walkthrough.** Append storyline(s) (ordered, branchable beats over existing elements) to a column's spec node | §6 `POST .../storylines` |
52
52
  | `set_connection` | `boardId`, `source`, `target`, `action` (`'connect'\|'remove'`) | Add or remove a type-checked directed edge | — (via `edges` on §3 events) |
53
53
  | `auto_connect_node` | `boardId`, `nodeId` | Re-run auto-connect for a node | §3 `POST .../nodes/:nodeId/auto-connect` |
54
+ | `link_element` | `boardId`, `nodeId`, `targetNodeId` | Link two existing same-type nodes: `targetNodeId` is replaced with a full copy of `nodeId`'s meta plus `meta.linkedTo`. Linking means first create, then link | §3 `POST .../nodes/:nodeId/link` |
54
55
  | `add_comment` | `boardId`, `nodeId`, `text`, `type?` (`'COMMENT'\|'TASK'\|'QUESTION'`), `author?` | Add a comment — `QUESTION` flags gaps/edge cases during review | — (via comment events) |
55
56
  | `update_comment` | `boardId`, `nodeId`, `commentId`, `action` (`'resolve'\|'delete'`) | Resolve or delete a comment | — (via comment events) |
56
57
  | `create_screen` | `boardId`, `contentType` (`'image'\|'sketch'\|'html'`), `nodeId?`, `chapterId`, `cellId?`/`cellName?`, plus content fields (`imageBase64`/`mimeType`, `elements[]`, or `pages[]`/`backgroundColor`), `description?` | Create + place a new screen node (SCREEN or HTML_SCREEN) atomically, in one call | §4 `POST .../images/:id/sketch` + `image-nodes` |
@@ -342,7 +343,7 @@ interface NodeChangeEvent {
342
343
  backgroundColor?: string
343
344
  title?: string
344
345
  url?: string
345
- linkedTo?: string // origin node idmarks this node as a linked copy (see below)
346
+ linkedTo?: string // rendering mirror onlymeta.linkedTo (below) is authoritative
346
347
  // ...other node data fields
347
348
  // Do NOT set a "type" here — the server derives the node's render type from
348
349
  // meta.type automatically. Setting one yourself risks it being read as the
@@ -354,6 +355,7 @@ interface NodeChangeEvent {
354
355
  title?: string
355
356
  description?: string
356
357
  fields?: Record<string, unknown>
358
+ linkedTo?: string // origin node id — the authoritative linked-copy pointer
357
359
  // ...
358
360
  }
359
361
  edges?: Array<{
@@ -396,7 +398,7 @@ A COMMAND is driven by exactly one upstream trigger — one SCREEN or one AUTOMA
396
398
 
397
399
  **Connections (both auto-connect and `set_connection`) only ever pair nodes on the same timeline** — a node in Chapter A can never be wired directly to a node in Chapter B, even when the type pair is otherwise valid (e.g. EVENT→READMODEL). No direct cross-timeline connection is possible.
398
400
 
399
- **The supported workaround is a linked copy**: place a copy of the source EVENT into its own swimlane on the *consuming* timeline, with `node.data.linkedTo` set to the origin node's id (see `linkedTo` in the `NodeChangeEvent` shape above; `eventmodeling-checking-completeness` documents how to recognize one when reading the board — it's an intentional copy, never a duplicate to clean up). Once the copy exists on the consuming timeline, it's a same-timeline node like any other and can be wired normally (e.g. linked-EVENT→READMODEL→SCREEN) to satisfy that context's local data need. Only fall back to documenting an integration gap when a linked copy genuinely isn't the right shape for the need (e.g. the consuming context needs live/aggregate data no single event copy can represent).
401
+ **The supported workaround is a linked copy**: place a plain EVENT node into its own swimlane on the *consuming* timeline, then call `link_element` (below) to link it to the origin node. Linking means first create, then link. `eventmodeling-checking-completeness` documents how to recognize a linked copy when reading the board — it's an intentional copy, never a duplicate to clean up.
400
402
 
401
403
  **Response**:
402
404
  - `200` — `{ connected: [{edgeId, source, target, created}], skipped: [{nodeId, reason}] }`
@@ -415,6 +417,20 @@ Create a single type-checked directed edge between two existing nodes — the RE
415
417
 
416
418
  ---
417
419
 
420
+ ### POST `/api/org/:orgId/boards/:boardId/nodes/:nodeId/link`
421
+ Link two existing same-type nodes — the REST fallback for `link_element`. Linking means first create, then link: `targetNodeId` must already exist. It's replaced with a full copy of `:nodeId`'s meta (not a merge) plus `meta.linkedTo`. COMMAND/EVENT/READMODEL only; `:nodeId` must not itself already be a linked copy.
422
+
423
+ **Request body**:
424
+ ```typescript
425
+ {
426
+ targetNodeId: string // existing same-type node to convert into a linked copy
427
+ }
428
+ ```
429
+
430
+ **Response**: `200` — `{ nodeId, linkedTo, type }` · `400` — missing `targetNodeId`, type mismatch, self-link, unsupported element type, or the original is itself a linked copy · `404` — the original or `targetNodeId` doesn't exist
431
+
432
+ ---
433
+
418
434
  ## 4. Images
419
435
 
420
436
  **File**: `src/slices/change/api-images/routes.ts`
@@ -370,7 +370,7 @@ An event left without a chapter and cell reference will never appear in any time
370
370
 
371
371
  **Use swimlanes sparingly — a swimlane exists for exactly one purpose: marking where integration with another system happens. Nothing else justifies one.** Not a different actor, not a different role, not visual grouping, not "an explicit business rule" in the abstract. Every chapter starts with, and in the common case keeps, a single default swimlane holding all of this bounded context's own domain events. Before adding a lane, check whether an existing lane already covers the element's type. If yes, place the element in that lane.
372
372
 
373
- **The only valid reason to create a second `swimlane`-type lane: another system's own events cross into this chapter as integration triggers for an automation** (see `eventmodeling-identifying-outputs` Step 5b). Label it for that system and place its trigger events there — never fold them into this chapter's own event swimlane (they are not this bounded context's domain facts) and never treat them as an informal "signal" with no EVENT node at all.
373
+ **The only valid reason to create a second `swimlane`-type lane: another system's own events cross into this chapter as integration triggers for a translation automation** (see `eventmodeling-identifying-outputs` Step 5b). Label it for that system and place its trigger events there — never fold them into this chapter's own event swimlane (they are not this bounded context's domain facts) and never treat them as an informal "signal" with no EVENT node at all. An external EVENT may only ever open the *translation* automation's todo list — never the todo list of the automation that does the actual domain work; that automation is triggered solely by the internal event the translation automation produces (Step 5b covers the full two-automation chain).
374
374
 
375
375
  **Never** add a swimlane for any other reason — not a new actor, not a new role, not visual grouping. Human roles get their own **actor** lane during Step 3 (Storyboarding) — a different row type entirely — never a new swimlane here.
376
376
 
@@ -555,7 +555,9 @@ The model is **complete** when:
555
555
  ## Next Steps
556
556
 
557
557
  If completeness check passes:
558
- → Proceed to code generation
558
+ → Proceed to Step 9 (`eventmodeling-validating-event-models`) — completeness is not the
559
+ final gate; validation, slicing, and documentation (Steps 9–11) still follow before
560
+ the model is ready for code generation.
559
561
 
560
562
  If gaps found:
561
563
  → Return to appropriate step to fix
@@ -133,7 +133,7 @@ Append findings to the project's event modeling file:
133
133
  Use Write tool to add/update this section:
134
134
 
135
135
  ```markdown
136
- ## 9. Scenarios (eventmodeling-elaborating-scenarios)
136
+ ## 7. Scenarios (eventmodeling-elaborating-scenarios)
137
137
 
138
138
  ### Coverage Goals
139
139
  [From Q1: Happy path / Comprehensive / Deep]
@@ -172,10 +172,12 @@ Use Write tool to add/update this section:
172
172
 
173
173
  Update Interview Trail:
174
174
  ```markdown
175
- | 9 | eventmodeling-elaborating-scenarios | [today] | Scenario coverage, testing strategy, edge cases |
175
+ | 7 | eventmodeling-elaborating-scenarios | [today] | Scenario coverage, testing strategy, edge cases |
176
176
  ```
177
177
 
178
- At this point, EVENTMODELING.md is complete and ready for implementation!
178
+ Scenarios are done, but the model is not yet ready for implementation — Steps 8–11
179
+ (Completeness, Validation, Slicing, Documentation) still follow. Proceed to Step 8
180
+ (`eventmodeling-checking-completeness`).
179
181
 
180
182
  ---
181
183
 
@@ -809,7 +811,7 @@ After posting, tell the user:
809
811
  **Per read model — this is a separate, equally mandatory pass, not an afterthought of the command pass above:**
810
812
  - [ ] **Every READMODEL on the board has at least one view scenario** — GWT (`given`: source EVENTs, `when`: empty, `then`: the READMODEL) or a storyline. A model with dozens of command scenarios and 0 read-model scenarios is not a complete Step 7 — it's easy to walk away thinking coverage is thorough because the command side looks exhaustive, so check the read-model side explicitly before reporting this step done.
811
813
  - [ ] **Population scenario** — the view shows correct data after its source event(s)
812
- - [ ] **Removal/update scenario, where applicable** — a row disappears or changes (`expectEmptyList: true` for list-type views) after an event that supersedes it (expiry, return, archival, withdrawal, status change, etc.). `EVENT → READMODEL` is exempt from column ordering **only when the read model already feeds an AUTOMATION** (`READMODEL → AUTOMATION` edge; see `learn-eventmodelers-api` §3) — a later event connecting back to an earlier-placed read model is normal for that accumulator shape, so add the connection if it's missing rather than assuming the scenario is impossible. If the read model has no automation to feed, the backward connection is rejected — model the removal/update the forward way instead (the superseding event lives in a later column, so express it as a scenario on a read model placed in that later column, or as a new version/copy of the read model there). Only skip this scenario, with a documented gap (TASK comment), when the superseding event genuinely lives in a different chapter.
814
+ - [ ] **Removal/update scenario, where applicable** — a row disappears or changes (`expectEmptyList: true` for list-type views) after an event that supersedes it (expiry, return, archival, withdrawal, status change, etc.). `EVENT → READMODEL` is exempt from column ordering **only when the read model already feeds an AUTOMATION** (`READMODEL → AUTOMATION` edge; see `learn-eventmodelers-api` §3 and `eventmodeling-orchestrating-event-modeling`'s "No backward arrows") — a later event connecting back to an earlier-placed todo-list read model is normal for that accumulator shape, so add the connection if it's missing rather than assuming the scenario is impossible. If the read model has no automation to feed, the backward connection is rejected — by Step 5 this should already have been modeled the forward way (see `eventmodeling-identifying-outputs` Step 5g's copy pattern: a new read model + screen copy in the later event's column, never a link back). If it wasn't, write the scenario against that forward-placed copy rather than the original. Only skip this scenario, with a documented gap (TASK comment), when the superseding event genuinely lives in a different chapter.
813
815
  - [ ] **GWT vs. storyline decided per read model, not applied uniformly** — reach for a storyline wherever the *same* read model row genuinely walks through multiple states worth narrating; the rest of the read models in the same model may be correctly GWT-only. Don't default to one format for every read model just because it worked for the first one, and don't judge "multiple states" by counting *distinct connected event types* — that undercounts real candidates. **A single event type recurring with different data is just as valid a storyline driver as several different event types**: `AccountFunded($40)` then `AccountFunded($70)` walking a balance read model from $40 to $110 is exactly as strong a storyline as a multi-event lifecycle. In practice this means almost every list/aggregate read model qualifies — a titles list growing from one row to two as the same `TitleAdded`-shaped event recurs, a dashboard's counters incrementing as the same `CopyAdded` event recurs, are both genuine storylines, not "just" GWT territory. Ask "does replaying this read model's *actually connected* event(s) more than once produce an interesting accumulated/changed state?" — not "how many different event types feed this."
814
816
  - [ ] **No redundancy or contradiction between a read model's GWT scenarios and its storyline** — if both exist for the same read model, read the storyline's beats before finalizing the GWTs. A GWT that asserts the same state a beat already shows is redundant (delete it); a GWT written without tracing the same causal sequence the storyline encodes can end up asserting something the storyline's beats actually contradict (e.g. claiming two entities coexist in a view when the storyline correctly shows one superseding the other) — delete or fix it, never leave a contradiction on the board.
815
817
  - [ ] **Cross-context read models handled honestly** — if a read model's true source events live in a different chapter, `given` can't reference them (same-timeline-only, like connections); write the scenario with an empty `given` and say so explicitly in the scenario title, rather than silently omitting the scenario or fabricating a same-timeline event that isn't the real source
@@ -405,12 +405,18 @@ After this step is done, **every SCREEN and every AUTOMATION on the board must b
405
405
  - `NotificationSent` (the event this automation's own resulting command produces) **closes** that row (removes it — the list only ever shows outstanding work).
406
406
  - The automation (`Send Welcome Notification`) reads `NotificationsToSend`, and for every open row issues `SendNotification`.
407
407
 
408
- Even an automation that looks like a "pure signal relay" (e.g. translating an external system's trigger straight into a local command with no visible decision) still has a todo list — model it anyway: it documents that the automation is idempotent/complete once its own event fires, and keeps every automation consistent with the same `READMODEL → AUTOMATION → COMMAND → EVENT` pattern instead of silently exempting some as "too simple to need one." This applies without exception even when the automation's trigger comes from another team's system (Step 6 territory) whose upstream decision logic is out of scope for this model.
408
+ Even an automation that looks like a "pure signal relay" still has a todo list — model it anyway: it documents that the automation is idempotent/complete once its own event fires, and keeps every automation consistent with the same `READMODEL → AUTOMATION → COMMAND → EVENT` pattern instead of silently exempting some as "too simple to need one."
409
409
 
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.** Do not model an externally-triggered automation's todo list as "opened and closed by the same event" — that conflates the external trigger with this chapter's own resulting fact and produces a todo list that is never meaningfully open. Instead:
411
- 1. Add a second `swimlane`-type lane to the chapter (`add_lane` with `type: "swimlane"`, labeled for the external system, e.g. "Reservation & Pickup System (external)") — a chapter can have more than one lane of the same type, and this lane holds that other system's own events as this chapter sees them, distinct from this chapter's own swimlane.
412
- 2. Place one EVENT per integration trigger point in that second swimlane, in the **same column** as the AUTOMATION/COMMAND/EVENT triplet it feeds (e.g. `ReservationRequested` in the same column as the `ReserveCopy` automation/command/`CopyReserved` event). This event represents that other system's own domain fact arriving at the boundary it is a real, first-class EVENT, not a comment or a placeholder.
413
- 3. Wire the todo list the standard way: the external EVENT (second swimlane) **opens** the row, this chapter's own resulting EVENT (first swimlane, the same event the automation's command produces) **closes** it — the typical, expected shape for this kind of automation, matching the general open/close pattern above exactly. `EVENT → READMODEL` connections from both swimlanes are unaffected by which swimlane the event sits in.
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
+
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 (Step 6 territory), model it as **two chained automations**, never one:
413
+
414
+ 1. **Translation automation** — its only job is converting the external fact into an internal one; the upstream decision logic on the other system's side is out of scope. Its todo list is opened by the external EVENT (second swimlane) and closed by the internal EVENT its own command produces — this is the one and only place an external EVENT is allowed to open a todo list.
415
+ - Second swimlane: place one EVENT per integration trigger point there, in the **same column** as this translation automation's AUTOMATION/COMMAND/EVENT triplet (e.g. `ReservationRequested` in the same column as a `Record Reservation Request` automation/command/`ReservationRequestReceived` event). This event represents that other system's own domain fact arriving at the boundary — it is a real, first-class EVENT, not a comment or a placeholder.
416
+ - Its command and resulting event carry no business decision of their own — they exist to produce the internal event the next automation needs, nothing more.
417
+ 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
+ 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.
414
420
 
415
421
  **Fields**: a todo-list read model's fields describe the pending item — the identity it's about (e.g. `customerId`) plus enough context to act on it (e.g. `email`, `notificationType`). Do not add a `status` field to mark items done — a todo list's "open" state is *membership in the list itself* (the row exists at all), not a status flag on a row that never leaves. If the same underlying data is also useful with an explicit status column for a different consumer, that is a different read model, not this one.
416
422
 
@@ -584,6 +590,8 @@ For each view screen S that queries this read model:
584
590
 
585
591
  **View screens go in the column immediately to the right of the read model they display** — either because they were placed there in Step 3, or because you move them here now.
586
592
 
593
+ **The same rule applies to `EVENT → READMODEL`.** If a later event needs to update data a read model already feeds to a SCREEN, do not connect that later event back into the existing read model — the platform only accepts an `EVENT → READMODEL` backward connection when the read model already has a `READMODEL → AUTOMATION` edge (the todo-list pattern from Step 5b). For any read model feeding a SCREEN, resolve the update the same way Step 5c resolves multi-component screens: place a **new copy of the read model** in (or immediately after) the later event's column, connect the later event forward into that copy, and place a matching copy of the same screen there — same title, updated data, optionally re-marked/highlighted via `html-screen`'s Marks feature. Never link the new copy back to the earlier read model instance.
594
+
587
595
  ### Step 5h — Wire connections after placing each READMODEL (and its SCREEN)
588
596
 
589
597
  After `place-element` returns the READMODEL node ID, create the arrows that complete the slice:
@@ -771,6 +779,7 @@ Identify UI needs without event sources:
771
779
  - [ ] **Typical pattern applied**: most screens follow `READ MODEL → SCREEN → COMMAND → EVENT`
772
780
  - [ ] **Every SCREEN from storyboarding is connected to at least one read model** (via `READMODEL → SCREEN`); only blank creation forms may be exempt — verified via the mandatory per-node pass above, not assumed
773
781
  - [ ] **Every AUTOMATION from storyboarding is connected to at least one todo-list read model** (via `READMODEL → AUTOMATION`, Step 5b) — no exemption for automations, unlike screens; even a simple relay automation gets one
782
+ - [ ] **No automation's todo list is opened directly by another system's (second-swimlane) EVENT unless that automation is itself the translation automation** (Step 5b) — an automation doing the actual domain work is only ever opened by an internal event; a second-swimlane EVENT feeding straight into a work automation's todo list is a missing translation automation
774
783
  - [ ] **No read model is placed without a connected SCREEN or AUTOMATION consumer**
775
784
  - [ ] **No read model spans more than one component** — a screen with N distinct components gets N read models and N highlighted screen copies (same screen name, one component crisp per copy), not one screen-wide read model
776
785
  - [ ] **Every multi-component screen was broken apart in Step 5c** — each copy keeps the original screen's name, differs only in which component is marked/highlighted
@@ -113,7 +113,11 @@ Never leave an unplaced node on the board when proceeding to the next step.
113
113
  ### No backward arrows
114
114
  The timeline must always progress left-to-right — this is the goal to design toward, not just a validation check to run afterward. Every connection arrow — SCREEN→COMMAND, COMMAND→EVENT, READMODEL→SCREEN, READMODEL→AUTOMATION, AUTOMATION→COMMAND — must point to the right or downward (within the same column). A right-to-left arrow among these is always a layout error, full stop.
115
115
 
116
- **`EVENT → READMODEL` is the one exception and it stays an exception, not a second acceptable default.** Confirmed against the platform API (`learn-eventmodelers-api` §3`POST .../connections`): an event in a later column may legitimately connect to a read model in an earlier column, and vice versa, because a read model is a continuously-listening projection, not a point-in-time action it can be fed by an event anywhere on its timeline, including one placed after it. Always try to place a read model so its connections read forward first; reach for this exception only when a genuine roll-up's wide fan-in makes an all-forward layout impractical (see "God read models" above), not as a default way to avoid column planning. When you do rely on it, don't "fix" the wide-fan-in read model by relocating it to sit after its last source event just to eliminate the backward arrows — that column surgery is unnecessary and, for a genuine roll-up, often impossible to do cleanly without breaking other consumers. The one real signal to watch for is a **connected event that isn't actually used by any field** on the read model that's a prunable connection regardless of column position, not a column-ordering problem.
116
+ **`EVENT → READMODEL` has exactly one exception, and it is narrow.** A read model that already carries a `READMODEL AUTOMATION` edgei.e. a todo-list read model feeding an automation, per `eventmodeling-identifying-outputs` Step 5bmay also be fed by a later-column event closing an item it opened earlier. That accumulator shape is what the todo-list pattern exists for, and it is confirmed against the platform API (`learn-eventmodelers-api` §3 `POST .../connections`). **Outside that one case, the platform rejects the connection, for good reason:** without it, a read model would become a moving target for whatever screen or scenario later reaches back into it.
117
+
118
+ For every other read model — in particular one feeding a SCREEN rather than an AUTOMATION — never connect a later event back into it, no matter how convenient. If a later event needs to update what a screen already shows, resolve it the same way Step 5c resolves multi-component screens: place a **new copy of the read model** in (or immediately after) the later event's column, connect the later event forward into that copy, and place a matching copy of the same screen there (same title, updated data, optionally re-marked/highlighted per `html-screen`'s Marks feature). Never link the new copy back to the earlier instance.
119
+
120
+ A wide fan-in read model (many connected events, one column) is a different problem with a different fix — see "one read model per component" and the >3-events heuristic above. It is never a justification for a backward arrow. The one real signal to treat as a prunable connection regardless of column position is a **connected event that isn't actually used by any field** on the read model.
117
121
 
118
122
  Before wiring any of the five forward-only pairs, verify that `column(source) ≤ column(target)`. If this is violated:
119
123
  - Move the earlier-placed element to the correct column, OR
@@ -338,7 +342,7 @@ If FAIL: address findings and re-invoke `eventmodeling-validating-event-models`.
338
342
 
339
343
  **Optional — Production Readiness Checklist**: Invoke
340
344
  `eventmodeling-validating-event-models-checklist` when the model is destined
341
- for production. It runs 23 architectural checks across 7 phases and returns a
345
+ for production. It runs 17 architectural checks across 7 phases and returns a
342
346
  PASS / PASS WITH WARNINGS / FAIL verdict independently of Step 9. A PASS on
343
347
  Step 9 does not substitute for this checklist when production readiness is
344
348
  required.
@@ -463,6 +467,7 @@ specific needs:
463
467
  ## Quality Checklist
464
468
 
465
469
  - [ ] No elements stranded at 0,0 — every EVENT, COMMAND, READMODEL, SCREEN, and AUTOMATION has a valid `cellId` in its chapter
470
+ - [ ] No `EVENT → READMODEL` connection points backward unless the read model already has a `READMODEL → AUTOMATION` edge (todo-list pattern) — every other later-event update uses a new read model + screen copy, never a link back to the earlier instance
466
471
  - [ ] All 11 modeling steps completed — no step skipped without explicit reason
467
472
  - [ ] Every COMMAND, READMODEL, and AUTOMATION has a matching slice definition on the board
468
473
  - [ ] Every chapter has a Modeling Reasoning MARKDOWN node in its first column, written after that chapter's model was complete
@@ -17,8 +17,8 @@ Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect`
17
17
  **Applies To**: Any domain - e-commerce, banking, SaaS, marketplace, healthcare, etc.
18
18
 
19
19
  **When to Use**:
20
- - After completing Step 2 (Event Plot) of 7-step event modeling
21
- - After completing Step 7 (Scenarios) before declaring model complete
20
+ - After completing Step 2 (Event Plot) of the 11-step event modeling workflow, as an early structural check
21
+ - Alongside Step 9 (Validate), as the optional production-readiness pass before declaring model complete
22
22
  - When reviewing an existing event model for production readiness
23
23
  - When suspicious of architectural issues in event design
24
24
 
@@ -311,11 +311,13 @@ Step 2: The Plot (Sequence)
311
311
 
312
312
  Fix any violations
313
313
 
314
- Step 3-7: Complete remaining steps
314
+ Step 3-8: Storyboard, Inputs, Outputs, Conway's Law, Scenarios, Completeness
315
315
 
316
- RUN eventmodeling-validating-event-models-checklist again (final validation)
316
+ Step 9: Validate (eventmodeling-validating-event-models)
317
317
 
318
- PASS Code generation
318
+ RUN eventmodeling-validating-event-models-checklist again (production-readiness pass)
319
+
320
+ PASS → Step 10: Slice, Step 11: Document Reasoning → Code generation
319
321
  FAIL → Fix identified issues
320
322
  ```
321
323
 
@@ -368,7 +370,7 @@ The principle is the same across all domains: **immutable facts as events, calcu
368
370
 
369
371
  ## Related Skills
370
372
 
371
- - **eventmodeling-orchestrating-event-modeling**: Main skill coordinating the 7-step event modeling process
373
+ - **eventmodeling-orchestrating-event-modeling**: Main skill coordinating the 11-step event modeling process
372
374
  - **eventmodeling-brainstorming-events**: Extract events from requirements (Step 1)
373
375
  - **eventmodeling-plotting-events**: Sequence events chronologically (Step 2)
374
376
  - **eventmodeling-designing-event-models**: Design your complete event model
@@ -280,6 +280,20 @@ If no matching row is found, stop and report the error — the timeline may be m
280
280
 
281
281
  ---
282
282
 
283
+ ## Step 6a — Referencing a node on a different timeline
284
+
285
+ **Connections only ever pair nodes on the same timeline** — a node in Chapter A can never be wired directly to a node in Chapter B, even for an otherwise-valid type pair (e.g. `EVENT → READMODEL`). If the element you're placing needs to connect to something that lives on a *different* timeline, do not place it and then attempt `set_connection`/auto-connect across timelines — it will fail.
286
+
287
+ Instead, create a **linked copy**: place the new node normally (Step 7, same title/type as the origin), then call `link_element` to mark it as a copy of the origin node:
288
+
289
+ ```
290
+ mcp__eventmodelers__link_element { "boardId": "<BOARD_ID>", "nodeId": "<origin-node-id>", "targetNodeId": "<newly-placed-node-id>" }
291
+ ```
292
+
293
+ (REST fallback: `POST .../nodes/:nodeId/link` with `{ "targetNodeId": "<newly-placed-node-id>" }` — see `learn-eventmodelers-api` §3.) This replaces the new node's meta with a full copy of the origin's, sets `meta.linkedTo`, and only works for COMMAND/EVENT/READMODEL. Once linked, wire the local copy to its neighbors with normal same-timeline `set_connection`/auto-connect calls. `eventmodeling-checking-completeness` treats any `linkedTo`-marked node it finds as this intentional pattern, never a duplicate to flag.
294
+
295
+ ---
296
+
283
297
  ## Step 7 — Create the node
284
298
 
285
299
  ### Step 7a — SCREEN only: create and render in one atomic call