@eventmodelers/cli 2.0.46 → 2.0.48
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/shared/skills/learn-eventmodelers-api/references/basics-architecture-element-types.md +7 -0
- package/shared/skills/learn-eventmodelers-api/references/mcp-tool-catalog.md +1 -1
- package/shared/skills/request-feedback/SKILL.md +6 -3
- package/shared/skills/update-slice-status/SKILL.md +14 -4
- package/stacks/modeling-kit/templates/.claude/skills/analyze-code-base/SKILL.md +24 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eventmodelers/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.48",
|
|
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": {
|
package/shared/skills/learn-eventmodelers-api/references/basics-architecture-element-types.md
CHANGED
|
@@ -36,6 +36,13 @@ INFOGRAPHIC // Pinned infographic poster (an `infographic` chat snippet saved
|
|
|
36
36
|
REPORT // Pinned report chart (a `report` chat snippet saved to the board): `meta.reportJson` (the snippet's JSON
|
|
37
37
|
// as a string, without `kind`/`confirm`), `meta.title`. Free-floating, view only. To change it, send a
|
|
38
38
|
// `node:changed` that sets `meta.reportJson` (the `/regenerate-report` skill does).
|
|
39
|
+
PDF // A PDF pasted onto the board (Ctrl/Cmd+V of a PDF file, ≤ 2 MB): `meta.title` is the file name. The file
|
|
40
|
+
// itself is a blob in the board's image storage under the node id (like an image, `images/<nodeId>`; a
|
|
41
|
+
// `GET .../images/<nodeId>` returns the PDF bytes) — there is no text, field or data on the node.
|
|
42
|
+
// Free-floating, resizable, in no chapter or cell, never part of a slice. Ignore it when building slices,
|
|
43
|
+
// wiring edges or counting elements; it is reference material for people. To put one on the board, upload
|
|
44
|
+
// the file to `POST .../images/<nodeId>` (the server keeps a PDF as it is) and create the node with
|
|
45
|
+
// `submit_node_events` (type `PDF`, position, no chapterId/cellId). A picture pasted the same way becomes an OUTLINE.
|
|
39
46
|
TIMELINE_REFERENCE // Read-only view of a timeline (chapter) from ANOTHER board:
|
|
40
47
|
// `meta.data.reference = {boardId, timelineId}`. Created in the UI only. It is not a real
|
|
41
48
|
// chapter: no children, no handles, nothing can connect to it, and it is never part of a
|
|
@@ -35,7 +35,7 @@ Write tools take their items as an array (`nodeIds[]`, `elements[]`, `connection
|
|
|
35
35
|
| `place_element` | `boardId`, `timelineId`, `elements[]` (each `action?` = `create` (default) with `elementType`, `title`, `fields?`, `lane?`, `columnIndex?`, `autoConnect?` · `move` with `nodeId` + target `cellName` · `clear` with `nodeId` (preferred for an existing node) or `cellName`), `compact?` | Find/create an empty cell in the right lane and place a COMMAND/READMODEL/EVENT/AUTOMATION/MARKDOWN/TABLE. `action: "move"` puts an existing node of any type into that (empty) cell, moving it if it already sits elsewhere on the timeline; `action: "clear"` unplaces a node without deleting it (`delete_node` deletes) — pass its `nodeId` to empty the cell it sits in, or a `cellName`. These replace `drop_node_to_cell`, `move_node_in_timeline` and `clear_cell`, which still exist but are deprecated — don't use them. `fields` writes the element's attributes in the same call — don't follow a placement with a `submit_node_events` just to set them. A whole slice's or column run's worth goes in one call, applied in order so each entry sees the columns the previous one added; answers `{results}` (`compact: true` → `{nodeId, cellName, columnIndex}` per entry). `autoConnect: false` places without wiring to timeline neighbors — wire the edges yourself | — (MCP-only convenience; composes §2+§3) |
|
|
36
36
|
| `list_slices` | `boardId`, `contextName?` | List slices (id, title, status). `contextName` restricts to one MODEL_CONTEXT (or timeline) — an unknown name is a `CONTEXT_NOT_FOUND` error, not an empty list | §8 `GET .../slicedata/slices` |
|
|
37
37
|
| `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` |
|
|
38
|
-
| `update_slice_status` | `boardId`, `newStatus`, plus exactly one of `sliceId` / `sliceTitle` | Change a SLICE_BORDER's `sliceStatus`. With a title 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) |
|
|
38
|
+
| `update_slice_status` | `boardId`, `newStatus`, `statusReason?` (optional, but you should set it: one sentence — why; shown as an info icon in the planning view; stored as `meta.statusReason` next to `sliceStatus`), plus exactly one of `sliceId` / `sliceTitle` | Change a SLICE_BORDER's `sliceStatus`. With a title 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) |
|
|
39
39
|
| `get_slice_data` | `boardId`, `contextName?`, `contextId?`, `sliceId?`, `projection?` (`"outline"` \| `"fields"` \| `"specs"`), `format?` | Full element graph for slices in a context. `projection` trims it first: `outline` = slice header + each element as `{id, title, type}`; `fields` = elements with fields and dependencies, no specs/comments/prompts; `specs` = specifications and storylines, no elements — prefer one over the full graph when only part is needed. `outline`/`specs` encode only as `json`, `yaml` or `toon` (other formats are a `PROJECTION_FORMAT_UNSUPPORTED` error); an unknown `sliceId` is `SLICE_NOT_FOUND` | §8 `GET /slicedata` |
|
|
40
40
|
| `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` |
|
|
41
41
|
| `get_board_outline` | `boardId`, `chapterId` | One chapter's structure, compact: per-column node lists (`{id, type, title, lane, cellName}`) + a flat edge list, no HTML pages / field bodies / meta. `cellName` is each node's real cell address (column letter + row number) — the only read that returns cell names at all; use it when a placement needs a cell address. For an empty target cell, take the column's `letter` plus the lane's 1-based position in the outline's `lanes` list (e.g. `letter: "C"`, second lane → `C2`) — never convert array indexes yourself. The cheap "what is where and how is it wired" read — prefer over `get_nodes` (no projection) for orientation checks | — (MCP-only convenience) |
|
|
@@ -129,10 +129,12 @@ or contradictory — not just "please clarify this slice."
|
|
|
129
129
|
|
|
130
130
|
## Step 4 — Mark the slice Blocked
|
|
131
131
|
|
|
132
|
+
Blocking is two things: the comment from Step 3 holds the full question, and the `statusReason` is its one-sentence summary (what is missing or contradictory) that people see as an exclamation-mark icon in the planning view and on the slice header. Set both — the reason is optional, but you should always give it here.
|
|
133
|
+
|
|
132
134
|
Prefer MCP:
|
|
133
135
|
|
|
134
136
|
```
|
|
135
|
-
mcp__eventmodelers__update_slice_status { "boardId": "<BOARD_ID>", "sliceId": "<SLICE_NODE_ID>", "newStatus": "Blocked" }
|
|
137
|
+
mcp__eventmodelers__update_slice_status { "boardId": "<BOARD_ID>", "sliceId": "<SLICE_NODE_ID>", "newStatus": "Blocked", "statusReason": "<one sentence: what is missing>" }
|
|
136
138
|
```
|
|
137
139
|
|
|
138
140
|
Also mark the slice 'blocked' locally in the index.json if possible.
|
|
@@ -149,10 +151,11 @@ curl -s -X POST "<BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/events" \
|
|
|
149
151
|
"id": "<new-random-uuid>",
|
|
150
152
|
"eventType": "node:changed",
|
|
151
153
|
"nodeId": "<SLICE_NODE_ID>",
|
|
152
|
-
"changedAttributes": ["sliceStatus"],
|
|
154
|
+
"changedAttributes": ["sliceStatus", "statusReason"],
|
|
153
155
|
"meta": {
|
|
154
156
|
"type": "SLICE_BORDER",
|
|
155
|
-
"sliceStatus": "Blocked"
|
|
157
|
+
"sliceStatus": "Blocked",
|
|
158
|
+
"statusReason": "<one sentence: what is missing>"
|
|
156
159
|
}
|
|
157
160
|
}]'
|
|
158
161
|
```
|
|
@@ -17,6 +17,7 @@ From `$ARGUMENTS`, extract:
|
|
|
17
17
|
|-------|---------------|---------|
|
|
18
18
|
| `sliceName` | the slice title to update (case-insensitive match) | **required** |
|
|
19
19
|
| `newStatus` | the target status value | **required** |
|
|
20
|
+
| `statusReason` | ONE sentence saying why the status changes | optional, but you **should** set it |
|
|
20
21
|
|
|
21
22
|
Valid status values (case-sensitive):
|
|
22
23
|
|
|
@@ -35,6 +36,13 @@ Valid status values (case-sensitive):
|
|
|
35
36
|
|
|
36
37
|
If `newStatus` is not one of these exact values, stop and tell the user the valid options.
|
|
37
38
|
|
|
39
|
+
### Give a reason (optional, but you should)
|
|
40
|
+
|
|
41
|
+
`statusReason` is optional — a status change works without it — but whenever you change a status you **should** send one: **one sentence**, in plain words, saying *why* the status changes
|
|
42
|
+
("Backend built and tested, UI contract published.", "Blocked: the order total rule is unclear.", "Reviewed and approved by Anna.").
|
|
43
|
+
It is stored next to `sliceStatus` in the SLICE_BORDER's meta and shown to people as an exclamation-mark icon in the planning view and on the slice header,
|
|
44
|
+
so write it for a person who was not watching. Say what happened, not the status name again. For `Blocked`, also post a comment with the details (see `request-feedback`) and let `statusReason` be its short summary. Don't leave an old reason in place when the status changes — send a new one each time.
|
|
45
|
+
|
|
38
46
|
---
|
|
39
47
|
|
|
40
48
|
## Step 2 — List all slices
|
|
@@ -69,13 +77,13 @@ Save the matched slice as:
|
|
|
69
77
|
Prefer the MCP tool — it does the same `node:changed`/`sliceStatus` update in one call, no event envelope to hand-assemble:
|
|
70
78
|
|
|
71
79
|
```
|
|
72
|
-
mcp__eventmodelers__update_slice_status { "boardId": "<BOARD_ID>", "sliceId": "<SLICE_NODE_ID>", "newStatus": "<newStatus>" }
|
|
80
|
+
mcp__eventmodelers__update_slice_status { "boardId": "<BOARD_ID>", "sliceId": "<SLICE_NODE_ID>", "newStatus": "<newStatus>", "statusReason": "<one sentence: why>" }
|
|
73
81
|
```
|
|
74
82
|
|
|
75
83
|
The tool also resolves the slice itself — pass `sliceTitle` (or `columnId`) instead of `sliceId` and the listing step above can be skipped entirely; an ambiguous title comes back with its candidates instead of a guess:
|
|
76
84
|
|
|
77
85
|
```
|
|
78
|
-
mcp__eventmodelers__update_slice_status { "boardId": "<BOARD_ID>", "sliceTitle": "Place Order", "newStatus": "<newStatus>" }
|
|
86
|
+
mcp__eventmodelers__update_slice_status { "boardId": "<BOARD_ID>", "sliceTitle": "Place Order", "newStatus": "<newStatus>", "statusReason": "<one sentence: why>" }
|
|
79
87
|
```
|
|
80
88
|
|
|
81
89
|
A slice that is being *created* takes its status straight from `create_slice`/`create_slice_definition` (`status`) — don't create it and then call this.
|
|
@@ -91,10 +99,11 @@ curl -s -X POST "<BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/events" \
|
|
|
91
99
|
"id": "<new-random-uuid>",
|
|
92
100
|
"eventType": "node:changed",
|
|
93
101
|
"nodeId": "<SLICE_NODE_ID>",
|
|
94
|
-
"changedAttributes": ["sliceStatus"],
|
|
102
|
+
"changedAttributes": ["sliceStatus", "statusReason"],
|
|
95
103
|
"meta": {
|
|
96
104
|
"type": "SLICE_BORDER",
|
|
97
|
-
"sliceStatus": "<newStatus>"
|
|
105
|
+
"sliceStatus": "<newStatus>",
|
|
106
|
+
"statusReason": "<one sentence: why>"
|
|
98
107
|
}
|
|
99
108
|
}]'
|
|
100
109
|
```
|
|
@@ -122,6 +131,7 @@ Tell the user:
|
|
|
122
131
|
- **Slice**: the title that was updated
|
|
123
132
|
- **Previous status**: `CURRENT_STATUS`
|
|
124
133
|
- **New status**: `newStatus`
|
|
134
|
+
- **Reason**: `statusReason` (if set)
|
|
125
135
|
- **Node ID**: `SLICE_NODE_ID`
|
|
126
136
|
- **Outcome**: `SUCCESS`, `ALREADY_IN_STATUS` (another agent got there first — see above), or `ERROR`
|
|
127
137
|
- **Any errors**: raw API message if something failed for a reason other than `ALREADY_IN_STATUS`
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: analyze-code-base
|
|
3
|
-
description: Uncover the business process behind an existing code base and build it on the board as an interview, iteratively — all chapters at high level first, then one chapter per pass, the person choosing which. Reads the code for hypotheses, asks one question at a time, draws as answers land. Use for "analyze this code base", "analyze this existing system", "reverse-engineer the model from the code", "model the legacy app".
|
|
3
|
+
description: Uncover the business process behind an existing code base and build it on the board as an interview, iteratively — all chapters at high level first, then one chapter per pass, the person choosing which. Reads the code and its documentation (README, docs, ADRs, API specs, diagrams, feature files) for hypotheses, asks one question at a time, draws as answers land. Use for "analyze this code base", "analyze this existing system", "reverse-engineer the model from the code", "model the legacy app".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Analyze a Code Base
|
|
7
7
|
|
|
8
|
-
You are the **orchestrator** of an interview. The code
|
|
8
|
+
You are the **orchestrator** of an interview. The code and its documentation give you hypotheses; the person gives you the truth. **The board is the deliverable** — never hand over a JSON model, `config.json` or `high-level-analysis.json`.
|
|
9
9
|
|
|
10
|
-
This skill owns only what is specific to legacy code: reading the sources, mapping
|
|
10
|
+
This skill owns only what is specific to legacy code: reading the sources (code **and** documentation), mapping them to elements, the layering of passes, and recording decisions with code references. Every modeling rule (naming, element types, chaptering, ordering, screens, scenarios, interviewing) lives in the skill named at each step — **read and follow that skill, don't restate or re-implement it here**.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## Step 0 — Is there a code base?
|
|
15
15
|
|
|
16
|
-
Resolve the directory to analyse: `$EVENTMODELERS_CODE_DIR` if set (treat it as the repository root for every step below), otherwise the current directory. It must contain source code (`src/`, `pom.xml`, `build.gradle*`, `package.json`, `*.csproj`, …).
|
|
16
|
+
Resolve the directory to analyse: `$EVENTMODELERS_CODE_DIR` if set (treat it as the repository root for every step below), otherwise the current directory. It must contain source code (`src/`, `pom.xml`, `build.gradle*`, `package.json`, `*.csproj`, …). Documentation alongside it (`README*`, `docs/`, ADRs, specs) is read too, but documentation alone is not a code base — without source code, stop as below.
|
|
17
17
|
|
|
18
18
|
If it does not (an empty folder, a modeling-only workspace holding just `.claude/`, `.eventmodelers/` or `.agent-modeling-kit/`), **stop and answer in one or two plain sentences** — "There is no legacy code here to analyse; run this in the code base" — and do nothing else.
|
|
19
19
|
|
|
@@ -66,9 +66,9 @@ Naming, what to model and the anti-patterns are in `eventmodeling-core-rules` (r
|
|
|
66
66
|
|
|
67
67
|
---
|
|
68
68
|
|
|
69
|
-
## Reading the sources —
|
|
69
|
+
## Reading the sources — five lenses
|
|
70
70
|
|
|
71
|
-
Every pass reads the code through the same
|
|
71
|
+
Every pass reads the code and its documentation through the same five lenses; each produces *hypotheses* to put to the person, never elements on its own. Read only as deep as the current layer needs.
|
|
72
72
|
|
|
73
73
|
1. **API** (look hardest here) — REST controllers, routes, handlers, message listeners, scheduled jobs, outbound clients. Each entry point is a candidate **screen + command** (a person writes), **screen + read model** (a person reads) or **automation** (jobs, listeners, calls to other systems). Request/response payloads hint at fields; the caller hints at who triggers it.
|
|
74
74
|
2. **Tests** — test names, fixtures, assertions. Names reveal the business vocabulary; arrange/act/assert is a *hint* for Given/When/Then, not its shape — which element goes into Given, When and Then is decided by `eventmodeling-elaborating-scenarios`, never by the test's structure (see *Scenarios* below); error cases reveal the rules that matter. Fixtures are the source of realistic example values.
|
|
@@ -81,13 +81,22 @@ Every pass reads the code through the same four lenses; each produces *hypothese
|
|
|
81
81
|
|
|
82
82
|
If the code is a generic engine (templates, schemas, configurable entities), model one real case it handles, not the engine (see *Concrete Over Generic* in `eventmodeling-core-rules`).
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
5. **Documentation & other artifacts** — everything that explains the system without being executable. Look for it in the code root and its parents' obvious places: `README*`, `docs/`, `doc/`, `wiki/`, `adr/` / `docs/decisions/` (architecture decision records), `CHANGELOG*` / release notes, `CONTRIBUTING*`, API specs (OpenAPI/Swagger, AsyncAPI, GraphQL schemas, Postman collections, `.http` files), diagrams (PlantUML, Mermaid, draw.io, C4, images in `docs/`), BDD/acceptance material (`*.feature` Gherkin files, acceptance criteria), requirements, user stories and specs (Markdown, `.docx`/PDF exports), runbooks, DB documentation, and in-repo ticket or issue exports. Also read what configures behaviour: CI/CD pipelines, infra (Docker, Helm, Terraform), feature-flag and environment config — they show integrations and jobs the code alone hides.
|
|
85
|
+
- **No fixed list of file types.** Anything that could plausibly carry business meaning is a candidate: Markdown, text, PDFs, Word/Excel/PowerPoint, CSV and spreadsheets (reference data, rate tables, code lists), JSON/YAML/XML samples and fixtures, HTML pages, images and diagrams, email or chat exports, notebooks. The lists above are examples, not a filter. Judge by what the file may tell you, and treat the unclear ones through the relevance question below.
|
|
86
|
+
- **Find it by what is committed, not only by name.** List the tracked documents (`git ls-files` filtered to everything that is not source code, lock files or build output; without git, find them) and skim titles and file names. Any committed Markdown, text or PDF file can hold requirements, specs, notes or a glossary — but also changelogs of dependencies, licences, generated output or stale scratch notes.
|
|
87
|
+
- **In doubt, ask whether a document is relevant** — one question, listing the candidates: *"I found `docs/visits.md`, `NOTES.txt` and `design/old-flow.md`. Which of these describe the business and should I use? Anything to ignore?"* Like the Step 1 question this is **not a gate**: post it, carry on with the code, and use only the unambiguous documents (README, `docs/`, ADRs, API specs) until the answer arrives. Record the answer (relevant / ignored) in the chapter's `Legacy Sources` note and reuse it on later passes. Never read a document as authoritative just because it is committed.
|
|
88
|
+
- **What it gives you**: the **vocabulary** and the *intent* — glossary terms, personas and roles, the stated purpose of a flow, the rules in prose, the order in user stories and sequence diagrams, the systems around this one, and the *why* behind decisions (ADRs). Often the quickest source for the order and for the business term behind a code name.
|
|
89
|
+
- **Trust it least on "what the system does today".** Documentation goes stale; code and tests show behaviour, docs show intent. Where a document and the code disagree, that is a question for the person (see below) — and the date, version or commit of the document is part of the evidence. A document is also a *summary*: a flow it describes still has to be found in the code, or marked as documented-only.
|
|
90
|
+
- **PDFs** (specs, requirement documents, manuals, exported wiki pages) are read like any other document: with the Read tool page by page (`pages`, max 20 per request), starting with the table of contents and the pages relevant to the current chapter. They are subject to the same relevance question as `.md`/`.txt` files.
|
|
91
|
+
- Documents too large or too binary to read fully (very long PDFs, Word files, a diagram image): skim headings and the parts for the current chapter, and for a whole document to be modelled use `summarize` instead of re-implementing it here.
|
|
92
|
+
|
|
93
|
+
Where the lenses disagree (a route nobody calls, a table never written, a test for removed behaviour, a screen with no backend, a document describing a flow the code no longer has, or code doing something the documentation never mentions), that is a question for the person — not something to model.
|
|
85
94
|
|
|
86
95
|
---
|
|
87
96
|
|
|
88
97
|
## From code to elements — the mapping rules
|
|
89
98
|
|
|
90
|
-
Start with the **API** and **persistence** lenses; they carry the most signal. Tests and
|
|
99
|
+
Start with the **API** and **persistence** lenses; they carry the most signal. Tests, UI and documentation then confirm, name and order what they found — documentation is the first place to look for the business word and the sequence.
|
|
91
100
|
|
|
92
101
|
| In the code | On the board |
|
|
93
102
|
|-------------|--------------|
|
|
@@ -96,6 +105,7 @@ Start with the **API** and **persistence** lenses; they carry the most signal. T
|
|
|
96
105
|
| **Inbound API call nobody types in** — a webhook, a message/queue listener, a scheduled job, a call from another system | an **AUTOMATION** (+ its COMMAND). A webhook or message from another system goes through the translation chain: external EVENT → todo-list READMODEL → translation AUTOMATION → internal EVENT. |
|
|
97
106
|
| **Outbound call to another system** — HTTP client, SDK, mail/SMS/payment/queue publish | an **AUTOMATION**: it reacts to an event (via its todo-list READMODEL), makes the call, and its COMMAND records the outcome as an EVENT (`Confirmation Mail Sent`, `Payment Failed`). |
|
|
98
107
|
| **Read endpoint / query / join** | a **READMODEL**, fed by the events behind the tables it reads. |
|
|
108
|
+
| **Documentation** — a user story, sequence diagram, ADR, glossary entry, API spec, `.feature` file | no element on its own: it **names** (glossary → titles), **orders** (stories, sequence diagrams → column order), **explains** (ADRs, rules in prose → decision rows, scenario candidates) and **corroborates** the elements derived from code. An API spec lists entry points and payloads like the *API* lens; a documented step with no counterpart in the code is documented-only — ask. |
|
|
99
109
|
|
|
100
110
|
Rules of thumb: every API call is either a screen-driven command/read or an automation that does something; reaching out to other systems is typically an automation; a row that is only ever read, never written by this system, is reference data from outside — ask where it comes from instead of inventing an event. Class, table and endpoint names go in `description`, not titles.
|
|
101
111
|
|
|
@@ -104,7 +114,7 @@ Rules of thumb: every API call is either a screen-driven command/read or an auto
|
|
|
104
114
|
## Progressive elaboration — all chapters first, then one chapter per pass
|
|
105
115
|
|
|
106
116
|
### Pass 0 — all chapters, high level
|
|
107
|
-
1. Read the sources broadly through the
|
|
117
|
+
1. Read the sources broadly through the five lenses — start with the README and `docs/` for the overview and vocabulary — to spot the business workflows — don't wait for the Step 1 answer; walk the running UI via `discover-storyboard` once a URL has been given (also when it arrives after Pass 0).
|
|
108
118
|
2. Group them into chapters and create them as `eventmodeling-brainstorming-events` (§ *Group events by workflow* / *Create one chapter per group*) does — a chapter is a user journey, never one endpoint, controller or CRUD operation. Code is split by operation (`OwnerController#initCreationForm`, `#processFindForm`, `#showOwner`, `#processUpdateOwnerForm`); the story is not — registering, finding, viewing and updating an owner are **one** chapter. Order the chapters per `eventmodeling-plotting-events`; ask where it is unclear. Add the **Decisions** lane, put the `Legacy Sources` note into **column 0** (see *The analysis log*), then sketch only the milestones (titles only) **from column 1 on**.
|
|
109
119
|
3. Report the chapters and **ask which chapter to start with**. Never pick for them.
|
|
110
120
|
|
|
@@ -116,6 +126,7 @@ Rules of thumb: every API call is either a screen-driven command/read or an auto
|
|
|
116
126
|
- `eventmodeling-designing-automation-chains` / `eventmodeling-translating-external-events` — jobs, listeners, webhooks, outbound calls;
|
|
117
127
|
- `eventmodeling-elaborating-scenarios` — rules from the tests (layer 1+ only), built exactly as that skill says (see *Scenarios* below).
|
|
118
128
|
Feed each skill what the lenses and the mapping table give you; ask only where the code stops (see *Step 1* when the order is unclear).
|
|
129
|
+
**Screens and scenarios are part of the pass — never skip them.** A chapter with only events, commands and read models is not detailed yet. Every command and read model a person uses gets its `HTML_SCREEN` (storyboarding step), and every command gets at least its happy-path scenario from `eventmodeling-elaborating-scenarios`. Never report "not done: screens, scenarios, tests, UI" and ask for the next chapter; run those steps first. If a step truly can't be done (e.g. no tests to mine for a rule), say why in the chapter's decision rows, but still place the screens and the happy-path scenario.
|
|
119
130
|
2. Stay within the layer's detail budget (below). Every placement batch carries its decision rows (see *Recording decisions*).
|
|
120
131
|
3. Re-space the chapters (see *Keeping chapters apart*) after every batch.
|
|
121
132
|
4. Append this pass's row to the chapter's *Analysis history*.
|
|
@@ -150,7 +161,8 @@ Every decision you make while turning code into the model is recorded **on the t
|
|
|
150
161
|
| Decision | Example |
|
|
151
162
|
|----------|---------|
|
|
152
163
|
| Code construct → element | `VisitController#processNewVisitForm` + `visits` insert → *Book Visit* / *Visit Booked* |
|
|
153
|
-
| Order | *Owner Registered* before *Pet Added* — from the UI click path
|
|
164
|
+
| Order | *Owner Registered* before *Pet Added* — from the UI click path or `docs/user-stories.md`, confirmed by the person |
|
|
165
|
+
| Code vs. documentation conflict | `docs/visits.md` says visits can be cancelled, the code has no cancel path → asked; recorded as the person answered |
|
|
154
166
|
| Code term → business term | `PetType` → *Species*, the person's word |
|
|
155
167
|
| Person overrides the code | Code allows cancelling a visit; the person says it never happens → not modeled |
|
|
156
168
|
| Merged / split | Two writes in `OwnerService#save` → one event; one endpoint → two commands |
|
|
@@ -205,6 +217,7 @@ Code root `petclinic/` · running UI: http://localhost:8080 (test account `georg
|
|
|
205
217
|
| API | `src/main/java/org/acme/visit/` | `VisitController` |
|
|
206
218
|
| Persistence | `src/main/resources/db/schema.sql` | `visits` table, `VisitRepository` |
|
|
207
219
|
| Tests | `src/test/java/org/acme/visit/` | `VisitControllerTests` |
|
|
220
|
+
| Docs | `docs/visits.md`, `docs/adr/0007-visit-scheduling.md` | user story *Book a Visit*, ADR 7 |
|
|
208
221
|
| UI | `src/main/resources/templates/pets/` | `createOrUpdateVisitForm.html` |
|
|
209
222
|
|
|
210
223
|
## Chapter decisions
|
|
@@ -232,7 +245,7 @@ Code root `petclinic/` · running UI: http://localhost:8080 (test account `georg
|
|
|
232
245
|
| `description` (Visit) | *Reason for Visit* |
|
|
233
246
|
```
|
|
234
247
|
|
|
235
|
-
The `Confirmed by` column shows how far to trust a decision: `code` (derived from the sources), `person` (they said so) or `assumed` (neither, still open). An `assumed` row whose question can't be settled from the model also gets a QUESTION comment on the node (see *Principles*); the row records the assumption, the comment asks the question.
|
|
248
|
+
The `Confirmed by` column shows how far to trust a decision: `code` (derived from the sources), `docs` (taken from documentation only, not seen in the code — say which document), `person` (they said so) or `assumed` (neither, still open). An `assumed` row whose question can't be settled from the model also gets a QUESTION comment on the node (see *Principles*); the row records the assumption, the comment asks the question.
|
|
236
249
|
|
|
237
250
|
Element `description`s still carry their own short code reference. The feedback notes add the *why* and the decisions that span several elements.
|
|
238
251
|
|