@eventmodelers/cli 1.0.110 → 1.0.112
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/cli.js +9 -2
- package/package.json +1 -1
- package/shared/skills/learn-eventmodelers-api/SKILL.md +3 -2
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +3 -1
- package/stacks/modeling-kit/templates/.claude/skills/analyze-legacy-system/SKILL.md +198 -0
- package/stacks/modeling-kit/templates/.claude/skills/detect-architecture-drift/SKILL.md +2 -2
- package/stacks/modeling-kit/templates/kit/CLAUDE.md +2 -1
package/cli.js
CHANGED
|
@@ -1949,7 +1949,7 @@ async function ensureGlobalKit(baseUrl) {
|
|
|
1949
1949
|
// untargeted is handed straight back to the queue for another agent to take. It says
|
|
1950
1950
|
// nothing about the standalone lane — a self-directed turn is nobody's task, so an
|
|
1951
1951
|
// exclusive standalone agent still works the board on its own initiative.
|
|
1952
|
-
async function runModeling(kitDir, projectDir, { verbose = false, standalone = false, exclusive = false, worker = false, overrides = null, maxAgents = DEFAULT_MAX_AGENTS, identity = {}, localAi = null, exec = null, model = null } = {}) {
|
|
1952
|
+
async function runModeling(kitDir, projectDir, { codeDir = null, verbose = false, standalone = false, exclusive = false, worker = false, overrides = null, maxAgents = DEFAULT_MAX_AGENTS, identity = {}, localAi = null, exec = null, model = null } = {}) {
|
|
1953
1953
|
// --worker: only prompts — no chat, and no board-change turns (it has nowhere to propose).
|
|
1954
1954
|
const chat = !worker;
|
|
1955
1955
|
const configLibPath = join(kitDir, 'lib', 'config.js');
|
|
@@ -2104,8 +2104,13 @@ async function runModeling(kitDir, projectDir, { verbose = false, standalone = f
|
|
|
2104
2104
|
|
|
2105
2105
|
const claudeArgs = ['--dangerously-skip-permissions', '-p', '--input-format', 'stream-json', '--output-format', 'stream-json', '--verbose'];
|
|
2106
2106
|
if (cfg.model) claudeArgs.push('--model', cfg.model);
|
|
2107
|
+
// The global install runs in ~/.eventmodelers/kit, away from the code base the person started
|
|
2108
|
+
// the agent in — hand that directory over so code-reading skills (detect-architecture-drift)
|
|
2109
|
+
// can still see it.
|
|
2110
|
+
if (codeDir) claudeArgs.push('--add-dir', codeDir);
|
|
2107
2111
|
const claudeEnv = {
|
|
2108
2112
|
...process.env,
|
|
2113
|
+
...(codeDir ? { EVENTMODELERS_CODE_DIR: codeDir } : {}),
|
|
2109
2114
|
...(cfg.anthropicBaseUrl ? { ANTHROPIC_BASE_URL: cfg.anthropicBaseUrl } : {}),
|
|
2110
2115
|
EVENTMODELERS_TOKEN: cfg.token,
|
|
2111
2116
|
// What the connect skill puts in `.mcp.json`'s x-agent-id header and every curl-fallback
|
|
@@ -3762,7 +3767,9 @@ credentialFlags(program
|
|
|
3762
3767
|
}
|
|
3763
3768
|
let projectDir = kitDir ? resolve(kitDir, '..') : null;
|
|
3764
3769
|
let overrides = null;
|
|
3770
|
+
let codeDir = null;
|
|
3765
3771
|
if (!kitDir) {
|
|
3772
|
+
codeDir = cwd;
|
|
3766
3773
|
// The blob and the individual flags are both "explicit", so they share a
|
|
3767
3774
|
// precedence tier — with a single --token/--board-id winning, since overriding one
|
|
3768
3775
|
// field of a pasted blob is the only reason to pass both.
|
|
@@ -3785,7 +3792,7 @@ credentialFlags(program
|
|
|
3785
3792
|
const runnerLabel = modelingLocalAi ? 'local model' : opts.exec ? 'one agent process per turn' : 'warm Claude process';
|
|
3786
3793
|
await new Promise((res) => process.stdout.write(`▶ Starting modeling loop (${runnerLabel}) for ${shown && !shown.startsWith('..') ? shown : kitDir}...\n\n`, res));
|
|
3787
3794
|
try {
|
|
3788
|
-
await runModeling(kitDir, projectDir, { verbose: !!opts.verbose, standalone: !!opts.standalone, exclusive: !!opts.exclusive, worker: !!opts.worker, overrides, maxAgents, identity, localAi: modelingLocalAi, exec: opts.exec ?? null, model: !opts.exec && modelingLocalAi === null ? model : null });
|
|
3795
|
+
await runModeling(kitDir, projectDir, { codeDir, verbose: !!opts.verbose, standalone: !!opts.standalone, exclusive: !!opts.exclusive, worker: !!opts.worker, overrides, maxAgents, identity, localAi: modelingLocalAi, exec: opts.exec ?? null, model: !opts.exec && modelingLocalAi === null ? model : null });
|
|
3789
3796
|
} catch (err) {
|
|
3790
3797
|
console.error('[modeling] Fatal:', err);
|
|
3791
3798
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eventmodelers/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.112",
|
|
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": {
|
|
@@ -1121,7 +1121,8 @@ Rule of thumb: if you are about to write "Shall I…?", "Want me to…?", "A or
|
|
|
1121
1121
|
{ kind: 'code', code: string, language?: string, title?: string } // monospaced, with a copy button
|
|
1122
1122
|
{ kind: 'report', chart: 'bar' | 'line' | 'pie', title?: string, unit?: string,
|
|
1123
1123
|
labels: string[], // 1–50 points: x axis, or the pie slices
|
|
1124
|
-
series: Array<{ name: string, values: number[] }
|
|
1124
|
+
series: Array<{ name: string, values: number[] }>, // one number per label; bar/line up to 6 series, pie uses only the first (no negatives)
|
|
1125
|
+
confirm?: { headline: string, yesLabel?: string, noLabel?: string } } // optional yes/no question under the diagram, like a confirm snippet
|
|
1125
1126
|
```
|
|
1126
1127
|
|
|
1127
1128
|
### How to use them
|
|
@@ -1131,7 +1132,7 @@ Rule of thumb: if you are about to write "Shall I…?", "Want me to…?", "A or
|
|
|
1131
1132
|
- **Name elements** with `nodeId` wherever you can (`tasks`, `changes`, `link`), so the person can click through to them — in a `tasks` list, put the element's name in `description` and its id in `nodeId`.
|
|
1132
1133
|
- **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.
|
|
1133
1134
|
- `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.
|
|
1134
|
-
- **`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.
|
|
1135
|
+
- **`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.
|
|
1135
1136
|
- A snippet is shown exactly as you send it — keep secrets and tokens out of `code` and `image`.
|
|
1136
1137
|
|
|
1137
1138
|
---
|
|
@@ -215,10 +215,12 @@ mcp__eventmodelers__post_chat_message {
|
|
|
215
215
|
"snippet": {
|
|
216
216
|
"kind": "report", "chart": "pie", "title": "Slices by status", "unit": "slices",
|
|
217
217
|
"labels": ["Done", "InProgress", "Planned", "Blocked"],
|
|
218
|
-
"series": [{ "name": "Slices", "values": [12, 6, 4, 2] }]
|
|
218
|
+
"series": [{ "name": "Slices", "values": [12, 6, 4, 2] }],
|
|
219
|
+
"confirm": { "headline": "Want the full list of slices without scenarios?" }
|
|
219
220
|
}
|
|
220
221
|
}
|
|
221
222
|
```
|
|
223
|
+
- `confirm` is optional: use it when you end on a follow-up question, instead of asking it in the text; the answer arrives as the person's next chat message.
|
|
222
224
|
- Only statuses with at least one slice, one number per label — the chart draws exactly what you send, so count first.
|
|
223
225
|
- One snippet per message: if the person asks for more diagrams (spec coverage, element inventory per type as a `bar`),
|
|
224
226
|
answer each in its own reply.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: analyze-legacy-system
|
|
3
|
+
description: Uncover the business process behind a legacy 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 existing system", "reverse-engineer the model from the code", "model the legacy app".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Analyze a Legacy System
|
|
7
|
+
|
|
8
|
+
You are a facilitator running an interview, not a batch analyser. The code gives you a hypothesis; the person gives you the truth. **The board is the deliverable** — never hand over a JSON model, `config.json` or `high-level-analysis.json`. Everything you derive is created on the board as you go.
|
|
9
|
+
|
|
10
|
+
This skill owns the *conversation and the layering*. Everything that touches the board is **delegated** to the skill named in the table at the bottom — do not re-implement placement, scenarios or attributes by hand.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Step 0 — Is there a code base?
|
|
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`, …).
|
|
17
|
+
|
|
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
|
+
|
|
20
|
+
Then invoke `connect` (if not already connected). Prefer `mcp__eventmodelers__*` tools; if the MCP server is not connected, say so and continue over REST (see `learn-eventmodelers-api`) — never silently fall back to writing files.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## The goal — a model business people *and* AI can both read
|
|
25
|
+
|
|
26
|
+
The finished board has two readers, and every element has to serve both:
|
|
27
|
+
|
|
28
|
+
- **Business people** read titles, order, screens and scenarios. Titles are the words the business uses (*Visit Booked*), in the right sequence, with no technical terms — the "say it out loud" test.
|
|
29
|
+
- **AI** (a later agent generating code, tests or docs from the board) reads fields, descriptions, edges and scenarios, and cannot ask what you meant. So it needs what a person would take for granted: identifying fields with types and realistic examples, edges that show where data comes from (every field has an origin), Given/When/Then rules for the decisions that matter, and a `description` that says in a sentence what the element means and links back to the legacy source (class, endpoint, table).
|
|
30
|
+
|
|
31
|
+
Therefore: never trade one reader for the other. No cryptic titles to save space, no business prose without fields once the layer calls for them, no implicit order, no unexplained abbreviations. When the person uses a term the code doesn't (or the reverse), the board carries the business term and the `description` records the code term — so both readers can find each other. Where something is still unclear, a QUESTION comment makes the gap visible to both instead of hiding it.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Principles
|
|
36
|
+
|
|
37
|
+
- **What to model:** business processes, state transitions, business rules hidden in code and tests, domain flows.
|
|
38
|
+
- **What not to model:** databases, frameworks, caching/logging/monitoring, class structure, UI styling.
|
|
39
|
+
- **Evidence, not elements.** Controllers, repositories, entities and `@Transactional` services tell you a business step exists — they are not the step. Model the *decision* it represents.
|
|
40
|
+
- **Say it out loud test.** If you cannot say an element's name to a domain expert and be understood, you are modeling the implementation — rename it. Class names, packages and endpoints go in the element's `description` (the link back to the legacy source), never in its title.
|
|
41
|
+
- **The user outranks the code.** On a conflict model what the person says and leave a QUESTION comment (`/wdyt`, `handle-comment`) on the node recording what the code does instead.
|
|
42
|
+
- **Never invent to fill a gap.** Not in the sources and not said by the person → ask; if it stays open, leave a QUESTION comment, not a guess.
|
|
43
|
+
- **Stop when they say stop**, at any depth. A shallow, correct model beats a deep, invented one.
|
|
44
|
+
|
|
45
|
+
## How to interview
|
|
46
|
+
|
|
47
|
+
- **Propose, then ask.** "From `VisitController` I see the owner picks a pet and then books a visit — does that match, and what happens after?" — never an empty question.
|
|
48
|
+
- **One question at a time**, answerable in a sentence or two. Never a wall of questions.
|
|
49
|
+
- The recurring question is **"what happens next?"** — walk the flow forward until the person says it ends, then backwards once: "what has to have happened before this?"
|
|
50
|
+
- **Order before placement.** Confirm the order, then place; the timeline is only as right as its sequence.
|
|
51
|
+
- **Draw as you go.** Every confirmed answer goes onto the board immediately (in a chat: every *ticked* answer — see Chat mode) — the person watches the model grow. Never disappear for ten tool calls.
|
|
52
|
+
- **Ask before every descent.** Which flow next and how much deeper — never decide alone.
|
|
53
|
+
|
|
54
|
+
### Be proactive — and ask about order above all
|
|
55
|
+
|
|
56
|
+
The code almost never says in which order the business does things: persistence writes have no sequence, controllers are independent, tests run in isolation. **Order is the person's knowledge, so ask for it — every round, unprompted.** Don't settle for the sequence the code happens to suggest.
|
|
57
|
+
|
|
58
|
+
**Order is what the timeline is made of.** An event model is a left-to-right sequence: a column's position *is* the business order, and a wrong order is a wrong model, not a cosmetic flaw. So never place an element at a position you guessed — place it where the person confirmed it goes, and if the order is still open, hold the element back (or leave a QUESTION comment) rather than put it somewhere plausible. Chapters get their order the same way.
|
|
59
|
+
|
|
60
|
+
- Whenever you have two or more elements (events, chapters, milestones), propose an order *and* ask: "I'd put *Owner Registered* before *Pet Added* — does the clinic ever add a pet first, or can it happen in either order?"
|
|
61
|
+
- Ask what must have happened **before** each step (preconditions) and what **can run in parallel** or in any order.
|
|
62
|
+
- Ask where the **ordering of chapters** comes from: which flow starts the story, which depends on another, which repeat.
|
|
63
|
+
- Ask when a step can happen **again** (a second visit, a re-booking) and what it means then.
|
|
64
|
+
- Put an order question into every snippet round (in chat: a `poll` with the candidate orders, or a `confirm` on your proposal).
|
|
65
|
+
- Don't wait for gaps to surface: whenever the code leaves you guessing — what triggers an automation, who is allowed to act, what happens on failure, whether a step is optional — ask, with your best hypothesis attached. Still one question at a time: pick the one that unblocks the most.
|
|
66
|
+
|
|
67
|
+
Questions to keep in rotation: *What happens next? · Which comes first — and can it be the other way round? · What must be true before this can happen? · Who triggers this? · What do they see before they decide? · Can this fail — and what does the business do then? · Is that the word the business uses? · Which flow now? · Deeper, or enough?*
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Reading the sources — four lenses
|
|
72
|
+
|
|
73
|
+
Every pass reads the code through the same four lenses; each produces *hypotheses* to put to the person, never elements on its own. Read only as deep as the current layer needs.
|
|
74
|
+
|
|
75
|
+
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.
|
|
76
|
+
2. **Tests** — test names, fixtures, assertions. Names reveal the business vocabulary; arrange/act/assert becomes Given/When/Then; error cases reveal the rules that matter. Fixtures are the source of realistic example values.
|
|
77
|
+
3. **Persistence** (look hardest here, too — *what gets saved*) — entities, tables, migrations, repositories. Every write is a candidate **event**. Writes show which state changes exist (→ events); relations show aggregate boundaries; status/enum columns show lifecycles; derived or joined queries show read models. Tables are evidence, never elements.
|
|
78
|
+
4. **UI** — templates, views, components, forms, navigation. Forms and buttons are where a person triggers a command; list and detail pages are read models; the page order is the flow; visible labels are the business words. **Ask the person once, early (Pass 0), whether a running UI exists** — URL, and login or test account if needed — and point the analysis at it. If there is none, say so and rely on the other three lenses.
|
|
79
|
+
|
|
80
|
+
**With a URL, play with it using Playwright.** Prefer the Playwright MCP tools (`browser_navigate`, `browser_snapshot`, `browser_click`, `browser_type`, …) when they are available; otherwise drive it with a small Playwright script (`npx playwright`) kept in the scratchpad, not in the repository.
|
|
81
|
+
- Walk it like a user: start at the entry page, follow the navigation, and note each page, form, button and list. Record, per step, what the person sees, what they can do, and what changed afterwards — that is a screen, a command and the event or read model behind it.
|
|
82
|
+
- Take snapshots/screenshots as evidence for what you propose ("the *Add Visit* form asks for date and description") and, where a person decides, as input for `/html-screen`.
|
|
83
|
+
- Trigger a write (submit a form) only against a test or local system, or after the person agrees — it changes real data. Never on anything that looks like production without asking first. Create test data with a clear marker so it can be found again.
|
|
84
|
+
- Confirm what you observed against the code: the UI shows the flow, the API/persistence lenses show what really happens behind it.
|
|
85
|
+
- Not reachable, login missing or the page needs something you don't have: tell the person and carry on with the other lenses; never invent screens.
|
|
86
|
+
|
|
87
|
+
Where the lenses disagree (a route nobody calls, a table never written, a test for removed behaviour, a screen with no backend), that is a question for the person — not something to model.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## From code to elements — the mapping rules
|
|
92
|
+
|
|
93
|
+
Start with the **API** and **persistence** lenses; they carry the most signal. Tests and UI then confirm and name what they found.
|
|
94
|
+
|
|
95
|
+
| In the code | On the board |
|
|
96
|
+
|-------------|--------------|
|
|
97
|
+
| **Persistence write** — an insert/update/delete, a `save()`, a status change: *what gets saved* | an **EVENT**, past tense, in business words (`Visit Booked`, not `visits row inserted`). Every persisted change is a candidate event; the saved fields are the event's fields. Several writes in one call = one decision with possibly several events — ask. |
|
|
98
|
+
| **Inbound API call a person triggers** — a REST controller behind a form, button or page | a **SCREEN** that fires a **COMMAND** (write) or shows a **READMODEL** (read). The controller is evidence; the person's decision is the command. |
|
|
99
|
+
| **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. |
|
|
100
|
+
| **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`). |
|
|
101
|
+
| **Read endpoint / query / join** | a **READMODEL**, fed by the events behind the tables it reads. |
|
|
102
|
+
|
|
103
|
+
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.
|
|
104
|
+
|
|
105
|
+
### Use the kit's modeling knowledge, not just this file
|
|
106
|
+
|
|
107
|
+
Before proposing elements for a chapter, apply the rules of the skills that own them — read `eventmodeling-core-rules` once per session, and consult as the flow demands:
|
|
108
|
+
|
|
109
|
+
- `eventmodeling-core-rules` — what each element is, lanes, naming, causality, the translation chain, anti-patterns to reject (CRUD names, events as commands, read models without a source).
|
|
110
|
+
- `eventmodeling-brainstorming-events` / `eventmodeling-plotting-events` — are the persistence writes complete and in business order?
|
|
111
|
+
- `eventmodeling-identifying-inputs` / `eventmodeling-identifying-outputs` — who issues each command, what each read model must show.
|
|
112
|
+
- `eventmodeling-designing-automation-chains` — every automation needs a todo-list read model; outbound calls and webhooks get their chain.
|
|
113
|
+
- `eventmodeling-translating-external-events` — external systems and their payloads.
|
|
114
|
+
- `eventmodeling-elaborating-scenarios`, `eventmodeling-checking-completeness`, `eventmodeling-validating-event-models-checklist` — deeper layers and the end-of-pass check.
|
|
115
|
+
- `eventmodeling-interview-protocol` — when to ask and how to record what was decided.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Progressive elaboration — all chapters first, then one chapter per pass
|
|
120
|
+
|
|
121
|
+
### Pass 0 — all chapters, high level
|
|
122
|
+
1. Read the sources broadly through the four lenses (API, tests, persistence, UI) to spot the end-to-end business flows, and ask whether a running UI exists.
|
|
123
|
+
2. Interview the person to confirm the list: which flows does the business actually run, what starts each, where does each end? Name them in business words (*Register an Owner*, *Book a Visit*).
|
|
124
|
+
3. Create **one chapter per high-level flow** (`/timeline`), in business order. Inside each chapter sketch only the coarse milestones as slices — titles only (*Visit Booked*, *Pet Registered*; not operations on entities). Connect the chapters' order, not their internals.
|
|
125
|
+
4. Report the chapters back and **ask which chapter to start with**. Never pick for them.
|
|
126
|
+
|
|
127
|
+
### Pass N — detail the chosen chapter
|
|
128
|
+
1. The person picks one existing chapter. Work **in that chapter** — do not create a new one. Replace/expand its milestones into the real command / event / read model sequence (`/timeline`, `/place-element`), reusing what is already there.
|
|
129
|
+
2. Interview forward — what happens next, who does it, what do they see, what can go wrong — while reading the code that backs each step (all four lenses).
|
|
130
|
+
3. Add this layer's detail (budget below) as answers land.
|
|
131
|
+
4. Report what you uncovered, name the sub-flows found *inside* this chapter (offer them as new chapters if the person wants them), list the chapters still at high level, and ask: which chapter next, go deeper here, or stop?
|
|
132
|
+
|
|
133
|
+
Repeat until the person says stop. Each pass leaves the chapters not yet chosen untouched at high level.
|
|
134
|
+
|
|
135
|
+
### Detail budget per layer
|
|
136
|
+
|
|
137
|
+
| Layer | Elements | Fields | Examples | Scenarios | Screens |
|
|
138
|
+
|-------|----------|--------|----------|-----------|---------|
|
|
139
|
+
| **0 — High level** | one chapter per flow, business milestones as slices | none | none | none | none |
|
|
140
|
+
| **1 — Flow** | real command / event / read model sequence of one flow | only identifying and business-critical | one per key element | happy path + the one or two rules that matter | only where a person decides |
|
|
141
|
+
| **2+ — Deeper** | sub-flows, alternate paths, automations | full business field set incl. optional/list | realistic values from tests and fixtures | error cases and edge rules from the tests | sketches where a decision needs them |
|
|
142
|
+
|
|
143
|
+
Never add detail that belongs to a deeper layer. Every element must trace to sources you read or an answer the person gave. **Deeper never means more technical** — it means more business: decisions, rules, failure modes.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Chat mode — snippets instead of prose
|
|
148
|
+
|
|
149
|
+
**When this run has a chat** (`CHAT_SESSION_ID` is set — the request came from the board's chat), questions the person answers with a pick are **snippets** (`post_chat_message` with `snippet`; shapes in `/learn-eventmodelers-api` § 16 *Chat snippets*), and nothing goes on the board until they tick it. Open questions ("what happens after the visit is booked?") stay text. Without a chat (terminal) everything works as written — ask in prose, draw immediately.
|
|
150
|
+
|
|
151
|
+
1. **Pass 0 — the chapters.** Post **one** `tasks` snippet with every candidate chapter you found, one tickable line each (`title` = business name of the flow, `description` = the milestones you saw and the code it came from). End the turn. The ticked ones become chapters, in the order listed.
|
|
152
|
+
2. **Which chapter next** (end of every pass): a **`poll` snippet** — one option per chapter still at high level, plus *"Stop here"*. End the turn. The pick arrives as the next chat message.
|
|
153
|
+
3. **Pass N — the detail.** Offer the elements, edges, fields and scenarios you found for the chosen chapter as **one** `tasks` snippet per round (one line per slice or rule, `description` = where it goes and the code reference), then one follow-up question in the same message — a pick (*"Can this fail?"* → `confirm`, *"Which comes first?"* → `poll`) is a snippet, an open question stays text. Put **every** finding of the round in the one snippet (it pages itself at 5). Nothing found: one line of text, no snippet.
|
|
154
|
+
4. **A code-vs-user conflict** is not worth a snippet on its own — fold it into the tasks snippet as a line *"Comment: code does X instead"* the person can tick.
|
|
155
|
+
5. **Applying the answer.** It arrives as a `CHAT` turn (`Please do these:` + the ticked titles, or ids when the list was long). Read your snippet back (`get_chat_session`), match the ticked tasks, and create **one prompt**: *"Apply these /analyze-legacy-system changes in chapter `<CHAPTER_ID>`: `<id> | <title>` per line"*. Unticked ones were declined — drop them. A prompt starting with **"Apply these /analyze-legacy-system changes"** is the applying run: skip the code reading and the offering, create what is listed through the delegated skills, then post one short chat message — what went on the board and the next question (item 2 or 3). This is how the model grows: *a snippet to tick → applied → the next snippet.*
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Slice types (what to map the code to)
|
|
160
|
+
|
|
161
|
+
- **Write operation → STATE_CHANGE** — 1 Command + 1 Event (optional Screen, only after a STATE_VIEW).
|
|
162
|
+
- **Read operation → STATE_VIEW** — 1 Read Model (optional Screen, only after a STATE_CHANGE).
|
|
163
|
+
- **Background work → AUTOMATION** — 1 Processor + 1 Command + 1+ Events; never connects directly to an Event, always via an intermediate STATE_VIEW.
|
|
164
|
+
|
|
165
|
+
Naming, element types and edge rules: `eventmodeling-core-rules`. Fields can be single values or lists (cardinality "List"). Reuse before creating — query what is already on the board; never duplicate nodes.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Delegate — which skill does what
|
|
170
|
+
|
|
171
|
+
| Intent | Skill |
|
|
172
|
+
|--------|-------|
|
|
173
|
+
| Build / adjust the timeline (chapters, milestones, flow sequence) live | `/timeline` |
|
|
174
|
+
| Place a single COMMAND / READMODEL / EVENT / SCREEN / AUTOMATION | `/place-element` |
|
|
175
|
+
| Make a timeline element's slice explicit | `/eventmodeling-slicing-event-models` |
|
|
176
|
+
| Command / read-model / automation design rules | `/eventmodeling-identifying-inputs`, `/eventmodeling-identifying-outputs`, `/eventmodeling-designing-automation-chains` |
|
|
177
|
+
| Given/When/Then scenarios from the tests | `/eventmodeling-elaborating-scenarios` |
|
|
178
|
+
| Add or rename attributes along a chain | `/attributes` |
|
|
179
|
+
| Realistic example data from tests and fixtures | `/examples` |
|
|
180
|
+
| A screen where a person decides | `/html-screen` (wireframe sketch only on explicit request: `/storyboard-screen`) |
|
|
181
|
+
| Set a slice's status | `/update-slice-status` |
|
|
182
|
+
| Questions, gaps, code-vs-user conflicts | `/wdyt`, `/handle-comment` |
|
|
183
|
+
| Inspect what is already modelled | `/analyze-existing-model` |
|
|
184
|
+
| Validate before reporting completion | `/eventmodeling-validating-event-models-checklist` |
|
|
185
|
+
| Any endpoint or element type not covered above | `/learn-eventmodelers-api` |
|
|
186
|
+
|
|
187
|
+
Scenarios: only business rules found in tests and comments — not simple validations ("must be a number"). Only create a storyline when the person explicitly asks.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## End every pass the same way
|
|
192
|
+
|
|
193
|
+
Re-read the board (do not trust your memory) and check: layer discipline held, no duplicates, every element has an edge, descriptions carry the code reference, slice statuses set. Then report:
|
|
194
|
+
|
|
195
|
+
1. what you put on the board — titles, node IDs, chapter;
|
|
196
|
+
2. what is still open or unanswered;
|
|
197
|
+
3. the sub-flows you found;
|
|
198
|
+
4. the question — **which one next, or stop?**
|
|
@@ -7,7 +7,7 @@ description: Compare the event model on the board with the code in this reposito
|
|
|
7
7
|
|
|
8
8
|
## Step 0 — Is there a code base?
|
|
9
9
|
|
|
10
|
-
Drift is the gap between the board and the code, so it can only be detected where code exists. **Before anything else — before `connect`, before reading the board — check that the current directory is a code base
|
|
10
|
+
Drift is the gap between the board and the code, so it can only be detected where code exists. **Before anything else — before `connect`, before reading the board — resolve the directory to check**: `$EVENTMODELERS_CODE_DIR` if it is set (the agent runs from the global install and was started inside that directory — treat it as the repository root for every step below, not the current directory), otherwise the current directory. Check that it is a code base: it contains source code (e.g. `src/`, `.build-kit/`, a `package.json`, `pom.xml`, `*.csproj`, `build.gradle`, or similar project files with slice/command/event/projection code).
|
|
11
11
|
|
|
12
12
|
If it is 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**, e.g.:
|
|
13
13
|
|
|
@@ -58,7 +58,7 @@ Index the result in memory: per slice → commands, events, read models, screens
|
|
|
58
58
|
|
|
59
59
|
## Step 3 — Understand the code
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
The code base is the directory resolved in Step 0 (`$EVENTMODELERS_CODE_DIR`, else the current directory) — every path below is relative to it, and it may hold any stack. Find out which, don't assume.
|
|
62
62
|
|
|
63
63
|
1. Read `.build-kit/CLAUDE.md` (and `.build-kit/AGENTS.md` if present) — its *Structure* section says where slices live and how they're named (e.g. `src/slices/{slice}/` for Node, `src/main/java/.../slices/{context}/{slice}/` for Axon).
|
|
64
64
|
2. If `.build-kit/.slices/<context>/<slice>/slice.json` exists, it is the snapshot the code was **last built from** — useful for telling "the code changed" apart from "the model changed since the build" (see Step 5).
|
|
@@ -203,7 +203,7 @@ for it. Instead:
|
|
|
203
203
|
and posts nothing to the board until they answer (`/wdyt` Step 4.0). Your reply here is one line —
|
|
204
204
|
*"On it — looking at Registration."*
|
|
205
205
|
- **a skill by name** — the message starts with `/<name>` of one of your skills (the chat panel's menu
|
|
206
|
-
writes these: `/analyze-existing-model`, `/detect-architecture-drift`, `/add-next-slice`, `/examples`, `/timeline …`,
|
|
206
|
+
writes these: `/analyze-existing-model`, `/analyze-legacy-system`, `/detect-architecture-drift`, `/add-next-slice`, `/examples`, `/timeline …`,
|
|
207
207
|
`/html-screen …`, `/storyboard …`): the person chose that skill, so it **is** the work — create one prompt,
|
|
208
208
|
*"Run /<name> <the rest of the message>"*, with the target resolved from `context=` like any other
|
|
209
209
|
(selected elements, chapter), and say so in one line. Don't re-interpret it as a question. A skill that
|
|
@@ -356,6 +356,7 @@ nothing to sanitize either, since a board change is not user text.
|
|
|
356
356
|
| Design or update a single wireframe/sketch screen (explicit request only) | `/storyboard-screen` |
|
|
357
357
|
| Business analysis, gap spotting, posting questions | `/wdyt` |
|
|
358
358
|
| Analyse the existing model structure, slice coverage, element counts | `/analyze-existing-model` |
|
|
359
|
+
| Reverse-engineer the business process of a legacy code base into the model, as an interview, one layer at a time | `/analyze-legacy-system` |
|
|
359
360
|
| Find where the model and the code have drifted apart (fields, specs, screens, edges, missing/extra slices) and propose fixes | `/detect-architecture-drift` |
|
|
360
361
|
| Turn a document or image (e.g. a tender/RFP) into a chaptered event model with screens, scenarios and a written blueprint summary | `/summarize` |
|
|
361
362
|
| Look up any API endpoint or element type not already covered by the skill you're executing | `/learn-eventmodelers-api` |
|