@eventmodelers/cli 1.0.137 → 1.0.138

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,6 +23,7 @@ npx @eventmodelers/cli init --stack umadb # UmaDB (Java)
23
23
  npx @eventmodelers/cli init --stack kurrent # Kurrent (Java, KurrentDB)
24
24
  npx @eventmodelers/cli init --stack react # React (frontend, board-polling sync) — TODO-marked, not yet filled in
25
25
  npx @eventmodelers/cli init --stack supabase-react # React + Supabase (frontend, UI-only, realtime sync)
26
+ npx @eventmodelers/cli init --stack classic # Existing codebase (any language, typically CRUD) — no scaffold
26
27
  ```
27
28
 
28
29
  The installer prompts for your API token, Organization ID, and Board ID from [app.eventmodelers.ai/account](https://app.eventmodelers.ai/account), scaffolds the stack into your project, and writes `.eventmodelers/config.json` with your credentials.
@@ -65,6 +66,15 @@ npx @eventmodelers/cli fetch --context <name>
65
66
 
66
67
  This writes the current slice/event/command detail for that context to disk and prints a summary — no agent loop, no listener, just a one-shot pull.
67
68
 
69
+ **Adding slices to an existing codebase (`classic`):**
70
+
71
+ ```bash
72
+ cd my-existing-app
73
+ npx @eventmodelers/cli init --stack classic
74
+ ```
75
+
76
+ `classic` scaffolds nothing into your project root — it assumes the code is already there, in whatever language and architecture it uses (typically a layered CRUD app, but not necessarily). Before the first slice, the coding agent (Claude, Codex, or any `--agent`) runs `learn-architecture`: it traces one or two existing features end to end and writes `.build-kit/ARCHITECTURE.md` — layout, reference implementations, test style, build/test commands, and how Event Modeling maps onto this code (COMMAND → service method + endpoint, EVENT → the persisted state change, READMODEL → query + DTO, AUTOMATION → the existing listener/consumer/scheduler). The `build-*` skills then implement every slice by copying those reference features, never by introducing a new framework or event store. Review and commit `ARCHITECTURE.md` after the first run — it's the one file that steers every later slice.
77
+
68
78
  **Checking what's installed or which credentials are active:**
69
79
 
70
80
  ```bash
@@ -93,6 +103,8 @@ your-project/
93
103
 
94
104
  The six backend stacks (`node`, `supabase`, `axon`, `opencqrs`, `umadb`, `kurrent`) also scaffold a real project skeleton into your project root (`templates/root/`) — source layout, build files, migrations, etc.
95
105
 
106
+ `classic` ships no `templates/root/` at all — it installs only `.build-kit/` and the skills into an existing codebase (see "Adding slices to an existing codebase" above).
107
+
96
108
  `react` and `supabase-react` are two more registered stacks (installable the same way). `supabase-react` is real, filled-in content — a Vite + React 19 + TypeScript scaffold that authenticates and issues command POSTs via a Supabase session (`src/lib/api.ts`/`src/lib/supabase.ts`), plus `init-style-guide`/`learn-styleguide` skills so generated UI stays on-brand. It's UI-only: `.build-kit/CLAUDE.md` only routes `STATE_CHANGE`/`STATE_VIEW` slices to `build-state-change`/`build-state-view` — an `AUTOMATION` slice has no UI counterpart and gets flagged via `request-feedback` instead, since it belongs to whichever backend stack is installed alongside this one. It needs no overrides at all and uses `shared/build-kit`'s realtime agent as-is.
97
109
 
98
110
  `react` (the plain-REST/board-polling variant, no Supabase) is still in the same state as a fresh `init --build-kit` scaffold — CLAUDE.md, the `build-*` skills, and `templates/root/` are all TODO-marked placeholders, not real content, pending an equivalent reference implementation. It overrides `lib/ralph.js` (+ `ralph-claude.js`/`ralph-local-ai.js`/`package.json`/`README.md`) for board-polling sync. Fill in the TODOs (and add a real `templates/root/` scaffold) against an actual project before relying on it.
package/cli.js CHANGED
@@ -197,6 +197,17 @@ const STACKS = {
197
197
  useShared: true,
198
198
  needsBoardId: true,
199
199
  },
200
+ // Installs into an existing codebase instead of scaffolding one — it ships no
201
+ // templates/root, so nothing is spread into the project root. Its learn-architecture
202
+ // skill analyzes the code once into .build-kit/ARCHITECTURE.md, and the build-* skills
203
+ // implement each slice the way that codebase already works (typically CRUD).
204
+ classic: {
205
+ label: 'Classic — existing codebase (any language, typically CRUD), slices built to match its architecture',
206
+ kitSubdir: 'build-kit',
207
+ kitDirName: '.build-kit',
208
+ useShared: true,
209
+ needsBoardId: true,
210
+ },
200
211
  };
201
212
 
202
213
  // Not a stack — no backend scaffold, just skills + the agent loop. Installed via
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventmodelers/cli",
3
- "version": "1.0.137",
3
+ "version": "1.0.138",
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": {
@@ -710,10 +710,12 @@ Append Given-When-Then scenario(s) to a column's spec node — the node is creat
710
710
  A step given as `{title, type}` is resolved server-side, so the names you already know need **no `get_spec_info`/`get_nodes` call first**. A title matching more than one element is rejected (`SCENARIO_ITEM_AMBIGUOUS`) with the candidates rather than guessed at, and resolution runs before anything is written — a bad name leaves no empty spec node behind.
711
711
 
712
712
  **Validation rules**:
713
+ - `context`: only READMODELs (the state the command decides against)
713
714
  - `given`: only EVENTs from same timeline
714
715
  - `when`: max one COMMAND; must be empty when `then` contains a READMODEL (use an inline QUERY item for a state-view)
715
716
  - `then`: all EVENTs OR exactly one READMODEL — never mixed
716
717
  - All referenced nodes must belong to the same chapter/timeline
718
+ - Each section is checked against the node's real type: a COMMAND lives only in `when`, a READMODEL only in `then`/`context`, an EVENT only in `given`/`then`. A step's `type`, when sent, must match the node (`SCENARIO_ITEM_TYPE_MISMATCH`); when omitted, the node's type is stored on the step
717
719
 
718
720
  **Response**:
719
721
  - `201` — `{ specNodeId, scenarios, added, isNewNode: boolean }`
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: build-automation
3
+ description: Implements an automation slice (react to a state change, issue a command) inside an existing codebase, using whatever reactive mechanism it already has per .build-kit/ARCHITECTURE.md — listener, after-commit hook, message consumer or scheduled job
4
+ ---
5
+
6
+ # Build Automation Slice
7
+
8
+ > Before doing anything else, read the slice definition from `.slices/{Context}/{slicename}/slice.json`. This file is the **source of truth** for which trigger drives the automation and what command it fires — never invent fields not defined there.
9
+
10
+ > Then read `.build-kit/ARCHITECTURE.md` (run `/learn-architecture` if it is missing). Its **AUTOMATION** mapping decides which reactive mechanism this codebase uses.
11
+
12
+ ---
13
+
14
+ ## What an Automation Slice is
15
+
16
+ An automation reacts to something that happened (a trigger event, or entries showing up in a todo-list read model) and issues a command in response — without a user doing it.
17
+
18
+ In a CRUD codebase there is usually no event stream to subscribe to. The automation is built with whatever already reacts to state changes there: an in-process domain/application event listener, an after-commit hook, a message consumer, or a scheduled job that queries for pending work. An automation slice is a **state-change slice with a trigger**: build the command first, then wire the trigger.
19
+
20
+ ---
21
+
22
+ ## Step 1 — Read the slice.json
23
+
24
+ From the slice definition, extract:
25
+ - **sliceName** — the command being fired by the automation
26
+ - **context** — bounded context
27
+ - **processors[]** — the reactions this slice implements: the trigger event (or todo-list read model) and the command each one issues
28
+ - **commands[]** / **events[]** — the command fired and what it records
29
+ - **specifications[]** — test scenarios (given/when/then)
30
+ - **storylines[]** (optional) — present only when the board author built an explicit walkthrough for this flow; most slices have none. See "Storyline-derived tests" under Step 2.
31
+
32
+ > **Comments & description**: each element carries a `comments: string[]` array (board comments) and a `description` field — use them as implementation hints, and resolve consumed comments via `POST <BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/<nodeId>/comments/<commentId>/resolve`.
33
+
34
+ ---
35
+
36
+ ## Step 2 — Build the command
37
+
38
+ Follow `/build-state-change` for this slice's command and events — all of its steps, tests and checks apply. If the command already exists (built by another slice), reuse it; do not duplicate it.
39
+
40
+ ### Storyline-derived tests
41
+
42
+ If `storylines[]` includes a beat sequence running through this automation's trigger → this slice's command, the command test for that segment is already covered by build-state-change's own "Storyline-derived tests" step.
43
+
44
+ ## Step 3 — Find the trigger point
45
+
46
+ Locate where the trigger event's state change happens in the code (the service method / persistence of the event that feeds the processor), and pick the mechanism from `ARCHITECTURE.md`:
47
+
48
+ | Codebase has | Build the automation as |
49
+ |---|---|
50
+ | in-process application/domain events (e.g. Spring `ApplicationEventPublisher`, MediatR notifications, Node `EventEmitter`) | a listener on the existing event for the trigger — or publish a new one from the trigger's service method the same way others are published |
51
+ | transactional outbox / message broker | a consumer on the existing topic/queue, registered like the reference consumer |
52
+ | scheduler / job framework | a scheduled job that queries the todo-list read model (or the trigger's persisted state) for pending items and fires the command per item |
53
+ | none of the above | the least invasive option consistent with the codebase: a direct call from the trigger's service method after it commits, or a scheduled job if the reaction must be decoupled/retried. Record the choice in `progress.txt` and in `ARCHITECTURE.md` so later automations reuse it |
54
+
55
+ Rules:
56
+ - Map trigger fields → command fields exactly as slice.json defines; no extra fields.
57
+ - The reaction must be **idempotent**: reprocessing the same trigger must not issue the command twice (check the resulting state, a processed-marker, or the todo-list query condition — whatever the codebase already uses).
58
+ - Follow the codebase's transaction boundaries: the command must not run inside a transaction that can still roll back the trigger unless the reference does exactly that.
59
+ - Never add a new messaging/scheduling library just for this slice.
60
+
61
+ ## Step 4 — Register it
62
+
63
+ Register the listener/consumer/job the same way the reference one is (annotation, DI registration, scheduler config, worker entry point). Do not touch application bootstrap beyond what that registration requires.
64
+
65
+ ## Step 5 — Write the tests
66
+
67
+ Besides the command tests from Step 2, write one test per `specifications[]` entry that exercises the **trigger**: set up the given state, fire the trigger the way it happens in production (publish the event, run the job once, call the consumer), and assert the command's effect — or that nothing happened when the spec expects no reaction. Follow the reference test style.
68
+
69
+ ## Step 6 — Quality gate
70
+
71
+ Run the build command and the single-test command from `ARCHITECTURE.md` for the tests this slice added or changed. Do not run the full suite.
72
+
73
+ ---
74
+
75
+ ## Checklist
76
+
77
+ - [ ] The command was built (or reused) via build-state-change, with all its specifications tested
78
+ - [ ] The trigger uses the codebase's existing reactive mechanism, registered like the reference
79
+ - [ ] Trigger → command field mapping matches slice.json exactly
80
+ - [ ] Reprocessing the same trigger does not issue the command twice
81
+ - [ ] Every specification has a passing test
82
+ - [ ] If `storylines[]` is present, its command segment is covered via build-state-change's storyline-derived tests
83
+ - [ ] No new framework, library or architectural style was introduced; any first-time mechanism choice is recorded in `ARCHITECTURE.md`
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: build-state-change
3
+ description: Implements a state-change slice (command → validated state transition) inside an existing codebase, following the architecture recorded in .build-kit/ARCHITECTURE.md — typically a CRUD service method + endpoint + persistence, not necessarily event-sourced
4
+ ---
5
+
6
+ # Build State Change Slice
7
+
8
+ > Before doing anything else, read the slice definition from `.slices/{Context}/{slicename}/slice.json`. This file is the **source of truth** for all fields, events, and metadata — never invent fields not defined there.
9
+
10
+ > Then read `.build-kit/ARCHITECTURE.md` (run `/learn-architecture` if it is missing). It decides **how** the slice is built: which layers, which reference feature to copy, how events map onto persistence, how tests look, and which commands to run.
11
+
12
+ ---
13
+
14
+ ## What a State Change Slice is
15
+
16
+ A state-change slice accepts a command, checks it against the current state and the business rules in its specifications, and — if it is allowed — records the resulting state transition (the slice's event(s)).
17
+
18
+ In this codebase that usually means: an entry point (endpoint/handler/action) receives the command's fields, a service method validates them against the current persisted state, and the change is written through the existing persistence layer. Only if `ARCHITECTURE.md` says the codebase is event-based are the events materialized as event objects.
19
+
20
+ ---
21
+
22
+ ## Step 1 — Read the slice.json
23
+
24
+ From the slice definition, extract:
25
+ - **sliceName** — the slice title (names the command/use case)
26
+ - **context** — the bounded context (maps to the module/package/feature area named in `ARCHITECTURE.md`)
27
+ - **commands[]** — list of commands with their data fields
28
+ - **events[]** — list of events emitted by each command — their fields are the state the command must persist
29
+ - **specifications[]** — test scenarios (given/when/then)
30
+ - **storylines[]** (optional) — present only when the board author built an explicit walkthrough for this flow; most slices have none. See "Storyline-derived tests" under Step 5.
31
+
32
+ > **Comments & description**: each element carries a `comments: string[]` array (board comments) and a `description` field — use them as implementation hints, and resolve consumed comments via `POST <BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/<nodeId>/comments/<commentId>/resolve`.
33
+
34
+ ---
35
+
36
+ ## Step 2 — Check what already exists
37
+
38
+ Search the codebase for the command name, event names, the entity they act on, and the key fields. A slice that reappears as `Planned` may be partly or fully implemented already — then this skill is a **diff**: update the existing code to match slice.json field by field, add missing specifications, remove fields slice.json no longer has. Never dismiss a mismatch as harmless drift.
39
+
40
+ Also find the entity/table the events write to. If it exists, extend it; if not, create it the way the reference implementation creates one (entity + migration, schema file, ...).
41
+
42
+ ## Step 3 — Map the slice onto the reference write path
43
+
44
+ Open the **write** reference implementation from `ARCHITECTURE.md` and build the same shape for this slice, file by file, in the same locations and with the same naming:
45
+
46
+ | From slice.json | Becomes (per `ARCHITECTURE.md`) |
47
+ |---|---|
48
+ | command + its fields | input DTO/request type and the entry point that receives it, with the same validation style as the reference |
49
+ | business rules (from specifications whose `then` is an error, plus `description`/`comments`) | checks in the service/use case, failing the way the codebase fails (exception type, result type, error response) |
50
+ | event(s) + their fields | the persisted state change: entity fields/columns set, rows inserted/updated/deleted. In an event-based codebase: the event types, appended/published the existing way |
51
+ | event that represents a status transition (`...Approved`, `...Cancelled`) | the field/status column update the codebase uses for such transitions |
52
+
53
+ Rules:
54
+ - Every command field, every event field ends up somewhere concrete — persisted, validated or returned. A field with no destination is a gap: record your assumption.
55
+ - No fields that are not in slice.json. Technical columns the codebase always adds (ids, timestamps, version, audit) are fine if every comparable entity has them.
56
+ - Schema changes go through the codebase's migration mechanism — add a new migration, never edit an existing one.
57
+ - Follow the codebase's transaction, auth and error-mapping conventions exactly as the reference does.
58
+
59
+ ## Step 4 — Expose it
60
+
61
+ Expose the command the way comparable writes are exposed (REST endpoint, RPC method, message handler, UI/server action, ...), including whatever registration, routing, API documentation or permission config the reference has. If comparable writes are not exposed externally (pure domain service), don't add an entry point.
62
+
63
+ ## Step 5 — Write the tests
64
+
65
+ Write one executable test per entry in `specifications[]`, in the test style and location of the reference test:
66
+
67
+ - **given** — each given event becomes pre-existing state: insert the equivalent rows via the codebase's fixtures/builders/repositories, or execute the earlier commands that produce that state if that is how the reference tests set up data. An empty `given` means a clean state.
68
+ - **when** — invoke the command through the same layer the reference tests use (service call, HTTP request, handler).
69
+ - **then** — for events: assert the persisted state (or the published events, in an event-based codebase) carries exactly the event fields and example values; for an error: assert the codebase's failure (exception, error result, status code).
70
+
71
+ Name each test after the specification title so it can be traced back to the board.
72
+
73
+ ### Storyline-derived tests (optional)
74
+
75
+ `storylines[]` in slice.json (optional — only present when the board author built an explicit walkthrough) can supply additional tests. A storyline embedded in this slice's slice.json already belongs entirely to this slice — no need to match beats against `commands[]` by id/title. Scan each storyline's ordered `elements` for a `type: COMMAND` beat followed by its EVENT beat(s):
76
+
77
+ - `given` — the cumulative ordered events from the start of the storyline up to (not including) the command beat, set up as state as above
78
+ - `when` — the command, built from that beat's `fields`
79
+ - `then` — the following EVENT beat(s)' data, asserted on the resulting state
80
+
81
+ Group these separately (own test class/`describe`/region, named after the storyline), on top of — never instead of — the specification tests.
82
+
83
+ ## Step 6 — Quality gate
84
+
85
+ Run the build command and the single-test command from `ARCHITECTURE.md` for the tests this slice added or changed. Do not run the full suite.
86
+
87
+ ---
88
+
89
+ ## Final Verification: Does the Implementation Match slice.json?
90
+
91
+ - [ ] Every command field is received and used (validated, persisted or passed on)
92
+ - [ ] Every event field is persisted (or published) with the expected value
93
+ - [ ] Every specification has exactly one corresponding, passing test
94
+ - [ ] If `storylines[]` is present, a storyline-derived test was added for every COMMAND beat
95
+ - [ ] No business rules, defaults, or constraints were added that do not appear in slice.json `description`, `comments` or specifications
96
+ - [ ] No field names were assumed or guessed — if a field is not in slice.json, it is not in the code
97
+ - [ ] The new code mirrors the reference implementation's layout, naming and conventions; no new framework, library or architectural style was introduced
98
+ - [ ] Assumptions are recorded in `progress.txt` and as code comments
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: build-state-view
3
+ description: Implements a state-view slice (read model served from previously recorded state) inside an existing codebase, following the architecture recorded in .build-kit/ARCHITECTURE.md — typically a query + response DTO + read endpoint over existing tables, not necessarily a projection
4
+ ---
5
+
6
+ # Build State View Slice
7
+
8
+ > Before doing anything else, read the slice definition from `.slices/{Context}/{slicename}/slice.json`. This file is the **source of truth** for all fields, events, and metadata — never invent fields not defined there.
9
+
10
+ > Then read `.build-kit/ARCHITECTURE.md` (run `/learn-architecture` if it is missing). It decides **how** the slice is built: which layers, which reference feature to copy, where reads come from, how tests look, and which commands to run.
11
+
12
+ ---
13
+
14
+ ## What a State View Slice is
15
+
16
+ A state-view slice answers a question with data that earlier state changes recorded: the read model's fields are derived from the events that feed it.
17
+
18
+ In a CRUD codebase there is usually no projection to maintain — the events were persisted as rows by their state-change slices, so the read model is a **query** over those tables plus a response DTO and a read entry point. A dedicated table, view or projection is only justified when `ARCHITECTURE.md` says the codebase uses them, or the read genuinely can't be answered from existing data.
19
+
20
+ ---
21
+
22
+ ## Step 1 — Read the slice.json
23
+
24
+ From the slice definition, extract:
25
+ - **sliceName** — the slice title (names the query/read model)
26
+ - **context** — the bounded context (maps to the module/package/feature area named in `ARCHITECTURE.md`)
27
+ - **readmodels[]** / **projections[]** / **queries[]** — the read model(s) this slice serves, with their fields
28
+ - the **events** feeding each read model — they tell you which persisted state the fields come from
29
+ - **specifications[]** — test scenarios (given events → expected read model)
30
+ - **storylines[]** (optional) — present only when the board author built an explicit walkthrough for this flow; most slices have none. See "Storyline-derived tests" under Step 5.
31
+
32
+ > **Comments & description**: each element carries a `comments: string[]` array (board comments) and a `description` field — use them as implementation hints, and resolve consumed comments via `POST <BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/<nodeId>/comments/<commentId>/resolve`.
33
+
34
+ ---
35
+
36
+ ## Step 2 — Locate the source data
37
+
38
+ For every read model field, find where the feeding event's data is persisted (the entity/table/column written by that event's state-change slice). Search by event name, entity and field names.
39
+
40
+ - **Found** → the field is read from there.
41
+ - **Not persisted anywhere** (the state-change slice isn't built yet, or never stored that field) → do not invent a parallel store. Add the missing column/entity the way the reference does (new migration) only if it clearly belongs to this read; otherwise record the gap as an assumption in `progress.txt` and as a code comment.
42
+
43
+ If the slice reappears as `Planned` and a query for it already exists, treat this skill as a **diff** against slice.json: add missing fields, remove fields slice.json no longer has, add missing specifications.
44
+
45
+ ## Step 3 — Map the slice onto the reference read path
46
+
47
+ Open the **read** reference implementation from `ARCHITECTURE.md` and build the same shape, in the same locations and with the same naming:
48
+
49
+ | From slice.json | Becomes (per `ARCHITECTURE.md`) |
50
+ |---|---|
51
+ | read model + its fields | response DTO with exactly these fields |
52
+ | how events shape the read model (list vs. single item, filters, status mapping, latest-wins) | the query: joins, filters, ordering, status derivation — in the codebase's query style (repository method, ORM query, SQL, ...) |
53
+ | key/id fields and how the read is addressed | query parameters / path variables, matching how comparable reads are addressed |
54
+ | list-shaped read models | pagination/sorting the way comparable list endpoints do it — only if they do |
55
+
56
+ In an event-based codebase (per `ARCHITECTURE.md`), build the projection/read-model updater the existing way instead and register it like the reference does.
57
+
58
+ ## Step 4 — Expose it
59
+
60
+ Expose the read the way comparable reads are exposed (REST endpoint, RPC, UI loader, ...), including registration, routing, API documentation and permission config, mirroring the reference. If the read is only consumed internally (e.g. by an automation's todo list), a service/repository method is enough.
61
+
62
+ ## Step 5 — Write the tests
63
+
64
+ Write one executable test per entry in `specifications[]`, in the test style and location of the reference test:
65
+
66
+ - **given** — the given events become pre-existing state: insert the equivalent rows via the codebase's fixtures/builders/repositories, or run the commands that produce them if that's how the reference tests set up data.
67
+ - **when** — run the query through the same layer the reference tests use.
68
+ - **then** — assert the returned read model matches the expected fields and example values exactly (including an empty result where the spec expects one).
69
+
70
+ Name each test after the specification title.
71
+
72
+ ### Storyline-derived tests (optional)
73
+
74
+ `storylines[]` in slice.json is optional — present only when the board author explicitly built a walkthrough for this flow. When present, mine it for **additional** tests, on top of (never instead of) the specification tests.
75
+
76
+ A storyline is `{ id, title, elements: [...] }`, where `elements` is an ordered list of beats — the same element can repeat to show its state at different points in the flow. A storyline embedded in this slice's slice.json already belongs entirely to this slice — no need to match beats against `readmodels[]` by id/title. Scan for a pair of adjacent beats that are both `type: READMODEL`, with only EVENT beat(s) between them and no COMMAND beat in that run. That pair is one self-contained test:
77
+
78
+ - `given` — the cumulative ordered events from the start of the storyline through the intervening event beat(s), set up as state
79
+ - `then` — the second READMODEL beat's fields
80
+
81
+ Group these separately, named after the storyline. Skip a beat pair when a COMMAND beat sits in between (that half belongs to build-state-change) or when the run includes a SCREEN/AUTOMATION beat with no traceable event — a one-line comment noting the storyline segment exists is enough.
82
+
83
+ ## Step 6 — Quality gate
84
+
85
+ Run the build command and the single-test command from `ARCHITECTURE.md` for the tests this slice added or changed. Do not run the full suite.
86
+
87
+ ---
88
+
89
+ ## Checklist
90
+
91
+ - [ ] Every read model field is returned, sourced from where its feeding event's data is persisted
92
+ - [ ] No extra fields in the response that are not in slice.json
93
+ - [ ] No parallel data store was invented for data that already exists
94
+ - [ ] Every specification has exactly one corresponding, passing test
95
+ - [ ] If `storylines[]` is present, a storyline-derived test was added for every isolable read-model transition (adjacent READMODEL beats with only EVENT beats between them)
96
+ - [ ] The new code mirrors the reference implementation's layout, naming and conventions; no new framework, library or architectural style was introduced
97
+ - [ ] Assumptions and data gaps are recorded in `progress.txt` and as code comments
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: learn-architecture
3
+ description: Analyzes the existing codebase once and writes .build-kit/ARCHITECTURE.md — layers, feature layout, persistence, how writes/reads/background work are built, test style, build/test commands, and how Event Modeling slices map onto it. Run before the first slice is built, or when ARCHITECTURE.md is missing or stale.
4
+ ---
5
+
6
+ # Learn Architecture
7
+
8
+ The classic build kit implements slices inside a codebase it did not create. Before any slice is built, the agent has to know how *this* codebase builds a feature — otherwise every slice drifts toward a generic pattern. This skill finds that out once and writes it down in `.build-kit/ARCHITECTURE.md`, which every `build-*` skill reads instead of re-exploring.
9
+
10
+ **Arguments** (optional): `refresh` — re-analyze and rewrite `ARCHITECTURE.md` even if it exists.
11
+
12
+ If `.build-kit/ARCHITECTURE.md` exists and `refresh` was not passed, stop: read it and return.
13
+
14
+ ---
15
+
16
+ ## Step 1 — Identify the stack
17
+
18
+ Read the build/dependency files at the project root and one level down (`package.json`, `pom.xml`, `build.gradle*`, `*.csproj`/`*.sln`, `pyproject.toml`, `go.mod`, `Gemfile`, `composer.json`, `Cargo.toml`, ...), plus `README*`, any existing `CLAUDE.md`/`AGENTS.md`/`CONTRIBUTING.md`, `docker-compose*`, and CI config (`.github/workflows/*`, `.gitlab-ci.yml`, ...).
19
+
20
+ Record: language + version, framework(s), persistence (database, ORM/query layer, migration tool), messaging if any, test framework(s), and the exact commands to build, run all tests, and run a **single** test file/class. Prefer what CI actually runs over what a README claims. Do not guess a command — if one can't be determined, say so in `ARCHITECTURE.md`.
21
+
22
+ ## Step 2 — Find reference features
23
+
24
+ Pick **one or two existing features** that look like the slices the board will produce — something that accepts input and changes state, and something that only reads/lists data. A recently changed, ordinary feature is a better reference than the oldest or the most special one (`git log --stat -20` helps).
25
+
26
+ Trace each one end to end, reading only the files on that path:
27
+
28
+ - **Write path**: entry point (controller/route/handler/form action) → input DTO + validation → service/use case → domain object/entity → repository/DAO → schema/migration → response and error mapping.
29
+ - **Read path**: entry point → query/repository → response DTO → pagination/filtering conventions.
30
+ - **Background/reactive work**: anything that reacts to a state change — event listeners, after-commit hooks, message consumers, schedulers/cron jobs, outbox. Note if there is none.
31
+ - **Tests**: where they live, unit vs. integration, how state is set up (fixtures, builders, factories, test containers, in-memory DB, mocks), how assertions are written.
32
+
33
+ Do not read the whole codebase. Search (`grep`/glob) for a concept, then follow references.
34
+
35
+ ## Step 3 — Decide the Event Modeling mapping
36
+
37
+ Decide how each board element is built **in this codebase**, based on what you found — not on Event Modeling theory:
38
+
39
+ - **Is it event-based?** Only if the code already persists or publishes events (event store, domain events, outbox, audit log of facts). Otherwise it is state-based (typically CRUD) and board EVENTs become the state transitions a command persists, not new event classes.
40
+ - **COMMAND** → which entry point + DTO + service method shape, and where business-rule violations go (exception type, result type, validation error).
41
+ - **EVENT** → the persisted change (tables/columns written), or the existing event mechanism if there is one.
42
+ - **READMODEL** → query + response DTO; when a new table/view/materialized projection is justified versus querying existing tables.
43
+ - **AUTOMATION / processor** → the existing reactive mechanism (or, if none exists, the least invasive option consistent with the codebase — usually a direct call or a scheduled job; note that choice explicitly).
44
+ - **Specification (given/when/then)** → how `given` events become pre-existing state in a test, and what `then` asserts on.
45
+
46
+ ## Step 4 — Write `.build-kit/ARCHITECTURE.md`
47
+
48
+ Keep it short and concrete — paths, class names and commands, not prose. Use this structure:
49
+
50
+ ```markdown
51
+ # Architecture
52
+
53
+ ## Stack
54
+ - Language/framework/persistence/test framework (with versions)
55
+ - Architecture style: e.g. layered CRUD (controller → service → JPA repository), or event-sourced, or ...
56
+
57
+ ## Commands
58
+ - Build: `...`
59
+ - All tests: `...`
60
+ - Single test: `...` (with a concrete example)
61
+ - Other checks CI runs (lint, format, typecheck): `...`
62
+
63
+ ## Where a feature lives
64
+ - Layout of one feature, with the reference feature as a concrete tree
65
+ - Naming conventions (classes, files, endpoints, tables, columns)
66
+
67
+ ## Reference implementations
68
+ - Write: `path/to/Controller` → `path/to/Service` → `path/to/Repository` (+ migration)
69
+ - Read: ...
70
+ - Background: ... (or "none")
71
+ - Tests: `path/to/ReferenceTest` — how state is set up and asserted
72
+
73
+ ## Event Modeling mapping
74
+ | Board element | Built as |
75
+ |---|---|
76
+ | COMMAND | ... |
77
+ | EVENT | ... |
78
+ | READMODEL | ... |
79
+ | AUTOMATION | ... |
80
+ | Specification | ... |
81
+
82
+ ## Rules
83
+ - Conventions a new slice must follow (transactions, validation, error mapping, auth, migrations append-only, ...)
84
+ - Files a slice must not touch (app bootstrap, global config, lockfiles, ...)
85
+ ```
86
+
87
+ ## Step 5 — Verify the commands
88
+
89
+ Run the build command and the single-test command against one existing test. If either fails for reasons unrelated to the code (missing service, missing env var), record the prerequisite under **Commands**. Do not "fix" the project to make it pass.
90
+
91
+ Commit `ARCHITECTURE.md` on its own: `chore: document architecture for build kit`.
@@ -0,0 +1,63 @@
1
+ # Project Configuration
2
+
3
+ This build kit was installed into an **existing codebase** — it ships no scaffold, no framework and no fixed file layout. Slices are implemented the way this codebase already builds features.
4
+
5
+ The codebase is typically a classic application (layered, CRUD, a relational database behind services/repositories) — but not necessarily: it may already use domain events, messaging, or event sourcing. Never assume; look.
6
+
7
+ ## Architecture First
8
+
9
+ `.build-kit/ARCHITECTURE.md` describes how this codebase works: language, layers, where a feature's files go, persistence and migrations, how state changes are exposed (REST, RPC, UI actions), how reads are served, how background/reactive work is wired, the test style, and the exact build/test commands.
10
+
11
+ - If `.build-kit/ARCHITECTURE.md` does not exist, run `/learn-architecture` before building anything.
12
+ - Treat it as the authority for *how* to build. Treat `slice.json` as the authority for *what* to build.
13
+ - If the code contradicts `ARCHITECTURE.md` (a moved folder, a renamed base class, a wrong command), fix `ARCHITECTURE.md` in the same iteration rather than working around it.
14
+
15
+ ## Code Standards
16
+
17
+ - **Match the codebase**: language, module system, naming, layering, error handling, validation, DI, logging and test style all come from the existing code — copy the closest existing feature, not a textbook pattern.
18
+ - **No new architecture**: never introduce a new framework, library, persistence technology or architectural style (event store, CQRS bus, mediator, ...) to build a slice. If the codebase is CRUD, the slice is CRUD.
19
+ - **No dependency changes**: do not add or upgrade dependencies unless slice.json or a slice prompt explicitly asks for it.
20
+ - **Minimal footprint**: touch only the files the slice needs. Do not refactor, reformat or "clean up" unrelated code.
21
+
22
+ Ignore case for files and slices in prompts. "CartItems" slice is the same as "cartitems".
23
+
24
+ Do not change existing tests unless explicitly instructed, or the change brings the test in line with slice.json (e.g. step 4's field/spec diff).
25
+
26
+ At the start of every session, read `.build-kit/AGENTS.md` if it exists to load accumulated project learnings.
27
+
28
+ When starting to work on a slice, invoke the `update-slice-status` skill with `InProgress` status before doing anything else.
29
+
30
+ ## Building a Slice
31
+
32
+ **CRITICAL: You MUST always use the provided skills to build slices. NEVER implement a slice manually.**
33
+ **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT invent, assume, or guess any field or logic not present in the slice definition.**
34
+
35
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, where a file should live, ...), pick the most sensible interpretation from `slice.json`, its specifications, the surrounding model and the existing code, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
36
+
37
+ When asked to build a slice, always follow this flow:
38
+
39
+ 1. Read the slice definition from `.build-kit/.slices/<context>/<slicename>/slice.json`.
40
+ 2. Make sure `.build-kit/ARCHITECTURE.md` exists — run `/learn-architecture` if it does not.
41
+ 3. Determine the slice type:
42
+ - **Translation** — `sliceType === "TRANSLATION"` → read `description` and `notes` from slice.json for hints; default to `/build-automation` if nothing else is specified
43
+ - **Automation** — `processors` array is non-empty → invoke `/build-automation`
44
+ - **State-view** — `projections` or `queries` array is non-empty → invoke `/build-state-view`
45
+ - **State-change** — default (has `commands` / `events`) → invoke `/build-state-change`
46
+ 4. Invoke the matching skill and follow its instructions completely. Do not deviate.
47
+ 5. **Verify against slice.json**: After the skill completes, check that every command field, event field, read model field and specification in slice.json has its counterpart in the implementation. No invented fields — if it is not in slice.json, it must not be in the code. This applies even when the slice was previously `Done` and reappears as `Planned` — never dismiss a mismatch as "already implemented" or harmless drift; diff slice.json against the code field by field and update the code to match every change.
48
+ 6. Run the quality checks from `.build-kit/ARCHITECTURE.md` (build/compile, then only the tests this slice touched).
49
+ 7. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
50
+
51
+ After you are done, automatically run the tests for the slice that was edited.
52
+
53
+ ## How Event Modeling maps onto this codebase
54
+
55
+ The board speaks Event Modeling; the codebase may not. `/learn-architecture` records the concrete mapping in `ARCHITECTURE.md` — the default for a CRUD codebase is:
56
+
57
+ | Board element | Typical CRUD counterpart |
58
+ |---|---|
59
+ | COMMAND | An input DTO/request + the service/use-case method that validates and applies it, exposed the way the codebase exposes writes (endpoint, RPC, form action, ...) |
60
+ | EVENT | The state transition the command persists — the rows/columns written. A real domain/integration event only if the codebase already publishes them |
61
+ | READMODEL | A query + response DTO (and endpoint) answering from the tables those events were persisted to; a dedicated table/view only if the read can't be served from existing data |
62
+ | AUTOMATION / processor | Whatever already reacts to state changes here: an in-process event listener, after-commit hook, message consumer or scheduled job |
63
+ | Specification (given/when/then) | A test in the codebase's own style: `given` events → pre-existing data (fixtures, repositories, or earlier commands), `when` → the command/query, `then` → resulting state, returned data or the expected error |
@@ -0,0 +1,47 @@
1
+ # Agent Learnings
2
+
3
+ Patterns and gotchas discovered during task processing. Update this file whenever you encounter something reusable.
4
+
5
+ ## tasks.json
6
+
7
+ - Tasks are objects with `id`, `createdAt`, and `payload` (a `SliceChangedPayload`).
8
+ - After completing a task, remove it from the array entirely — do not add a status field.
9
+ - Write `[]` to `tasks.json` if the last task is completed.
10
+
11
+ ## SliceChangedPayload fields
12
+
13
+ ```
14
+ event always "slice:changed"
15
+ organizationId org UUID or null
16
+ boardId board UUID
17
+ sliceId SLICE_BORDER node UUID — use this with /load-slice
18
+ sliceTitle human-readable slice name (may be null)
19
+ sliceStatus e.g. "Created", "InProgress", "Done", "Blocked" (may be null)
20
+ timestamp unix ms when the change was emitted
21
+ ```
22
+
23
+ ## Slice files
24
+
25
+ The realtime agent writes one file per slice on startup and after each `slice:changed` event:
26
+
27
+ ```
28
+ .slices/<context>/<sliceName>.json
29
+ ```
30
+
31
+ - `<context>` is the slice's context value, or `default` if none.
32
+ - `<sliceName>` is the slice title lowercased with spaces and the `"slice:"` prefix removed (e.g. `"slice: Enable User"` → `enableuser`).
33
+
34
+ These files are always up to date — read them directly before invoking any skill.
35
+
36
+ ## Skill Usage
37
+
38
+ - Always run `/connect` first to load credentials from `.eventmodelers/config.json` before calling any other skill.
39
+ - `/load-slice sliceId=<uuid>` re-fetches all slices from the API, refreshes the slice files, and returns the requested slice. Use it when you need a guaranteed-fresh view of a specific slice.
40
+ - Read `.slices/<context>/<sliceName>.json` directly when you already know the context and name and the file is recent enough.
41
+
42
+ ## Board API
43
+
44
+ - The `boardId` and `organizationId` from each payload provide full context — pass them to skills.
45
+ - Node events use `node:created`, `node:changed`, `node:deleted` — always POST to `/api/org/:orgId/boards/:boardId/nodes/events`.
46
+ - Slice metadata (title, status) lives on the SLICE_BORDER node under `meta.sliceStatus` and `meta.title`.
47
+ - `/update-slice-status` rejects moving a slice into a status it's already in — this is a concurrency guard, not a bug. It means another agent already claimed the slice. Treat it as `ALREADY_IN_STATUS`, skip that slice, and move on to the next `Planned` one instead of erroring out.
@@ -0,0 +1,133 @@
1
+ # Ralph Agent Instructions
2
+
3
+ You are an autonomous coding agent working on a software project. You apply your skills to build software slices. You only work on one slice at a time.
4
+
5
+ This kit runs inside an **existing codebase** — nothing was scaffolded for you. The code is not necessarily event-sourced; typically it is a classic layered/CRUD application. The slice describes *what* must happen (commands, events, read models, specifications); the existing code decides *how* it is built. `.build-kit/ARCHITECTURE.md` is the record of how this codebase works — if it does not exist yet, run `/learn-architecture` before anything else.
6
+
7
+ ## Context Boundary (READ FIRST — NON-NEGOTIABLE)
8
+
9
+ You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json`.
10
+
11
+ - **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
12
+ - **NEVER** read, scan, or build slices from any other context directory, even if it has "Planned" slices, and even if the current context has no work left.
13
+ - A "Planned" slice in a *different* context is **NOT yours to build**. Ignore it completely.
14
+ - If the current context has no "Planned" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The context is only ever changed on the board, never by you.
15
+
16
+ ## Your Task
17
+
18
+ 0. Do not read the entire code base. `.build-kit/ARCHITECTURE.md` tells you where to look; read the reference implementations it names and the files the slice actually touches.
19
+ 1. Read `.build-kit/.slices/current_context.json` to find the active context name, then read `.build-kit/.slices/<contextName>/index.json`. Every item in status "planned" is a task.
20
+ 2. Read the progress log at `progress.txt` **if it exists** (check Codebase Patterns section first) — it is absent until the first slice is built, which is not an error; create it when you write your first entry
21
+ 3. Make sure you are on the right branch "feature/<slicename>", if unsure, start from main.
22
+ 5. Pick the **highest priority** slice where status is **exactly** "Planned" (case insensitive). This becomes your PRD. Set the status "InProgress" in the index.json **and** update the slice status on the eventmodelers board using the `update-slice-status` skill (or MCP if available).
23
+ **IMPORTANT: Only work on slices with status "Planned" in the CURRENT context. Never pick up a slice that is "InProgress", "Done", "Blocked", "Created", or any other status — even if it looks incomplete. If no slice has status "Planned" in the current context, reply with:**
24
+ <promise>NO_TASKS</promise> and stop immediately. Do not work on other slices and do not switch to another context.
25
+ **Claim conflict**: the board rejects the status update if the slice is already in the target status — this is expected: another agent claimed it first, racing you for the same slice. This is NOT an error. Do not stop, do not retry the same slice. Re-read `index.json` (or re-fetch via `load-slice`), pick the next-highest-priority slice still "Planned", and try claiming that one instead. Repeat until a claim succeeds or no "Planned" slice remains, in which case reply `<promise>NO_TASKS</promise>`.
26
+ 6. Pick the slice definition from `.build-kit/.slices/<contextName>/<folder>/slice.json` as defined in the prd. Never work on more than one slice per iteration.
27
+ 7. A slice can define additional prompts as codegen/backendPrompt. Any additional prompts defined in backend are hints for the implementation of the slice and have to be taken into account. If you use the additional prompt, add a line in progress.txt
28
+ 7. Determine the slice type and invoke the matching skill as defined in the **Building a Slice** section of `.build-kit/CLAUDE.md`. Do NOT implement manually.
29
+ 8. Write a short progress one liner after each step to progress.txt
30
+ 9. Analyze and Implement that single slice, making use of the skills in the skills directory plus your previously collected knowledge. Make a TODO list for what needs to be done, and adjust the implementation according to the JSON definition. Carefully inspect events, fields and compare against the implemented slice. JSON is the desired state. ATTENTION: a "planned" task can also be just added specifications. So always look at the slice itself, but also the specifications. If specifications were added in json which are not on code, you need to add them in code.
31
+ 10. The slice in the json is always true, the code follows what is defined in the json
32
+ 11. Slice is only 'Done' if business logic is implemented as defined in the JSON, APIs are implemented, all scenarios in JSON are implemented in code and it fulfills the slice.json. There must be no specification in json that has no equivalent in code.
33
+ 12. Make sure to write the ui-prompt.md as defined if defined in the skill
34
+ 13. Run the quality checks listed in `.build-kit/ARCHITECTURE.md` — build/compile, then only the tests touched by this slice (do not run all tests).
35
+ 14. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge (update first)
36
+ 15. Update the PRD to set `status: Done` for the completed story in index.json **and** update the slice status on the eventmodelers board using the `update-slice-status` skill (or MCP if available).
37
+ 16. Append your progress to `progress.txt` after each step in the iteration.
38
+ 17. Append your new learnings to `.build-kit/AGENTS.md` in a compressed form, reusable for future iterations. Only add learnings if they are not already there.
39
+ 18. Finish the iteration.
40
+
41
+ ## Escalating Ambiguity
42
+
43
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
44
+
45
+ ## Progress Report Format
46
+
47
+ APPEND to progress.txt (never replace, always append):
48
+
49
+ ```
50
+ ## [Date/Time] - [Slice]
51
+
52
+ - What was implemented
53
+ - Files changed
54
+ - **Learnings for future iterations:**
55
+ - Patterns discovered (e.g., "this codebase uses X for Y")
56
+ - Gotchas encountered (e.g., "don't forget to update Z when changing W")
57
+ - Useful context (e.g., "the evaluation panel is in component X")
58
+ ---
59
+ ```
60
+
61
+ The learnings section is critical - it helps future iterations avoid repeating mistakes and understand the codebase better.
62
+
63
+ ## Consolidate Patterns
64
+
65
+ If you discover a **reusable pattern** that future iterations should know, add it to the `## Codebase Patterns` section at the TOP of progress.txt (create it if it doesn't exist).
66
+
67
+ ```
68
+ ## Codebase Patterns
69
+ - Example: "Services are transactional at the class level — never open a transaction in the controller"
70
+ - Example: "New tables need a Flyway migration in db/migration, never edit an existing one"
71
+ ```
72
+
73
+ Only add patterns that are **general and reusable**, not story-specific details.
74
+
75
+ ## Update AGENTS.md Files
76
+
77
+ Before committing, check if any edited files have learnings worth preserving in nearby AGENTS.md files — API patterns/conventions, gotchas, dependencies between files, testing approaches, configuration/environment requirements.
78
+
79
+ **Do NOT add:**
80
+
81
+ - Slice specific implementation details
82
+ - Story-specific implementation details
83
+ - Temporary debugging notes
84
+ - Information already in progress.txt
85
+ - Task-specific learnings
86
+
87
+ Only update AGENTS.md if you have **genuinely reusable knowledge** that would help future work
88
+
89
+ ## Quality Requirements
90
+
91
+ - ALL commits must pass this project's quality checks (typecheck/compile, lint, test)
92
+ - Use the build and test commands recorded in `.build-kit/ARCHITECTURE.md`
93
+ - If a command there turns out to be wrong, fix it in `ARCHITECTURE.md` in the same iteration
94
+ - Do NOT commit broken code
95
+ - Keep changes focused and minimal
96
+ - Follow existing code patterns — match the architecture, naming and test style already in the codebase; never introduce a new framework, library or architectural style to build a slice
97
+
98
+ ## Skills
99
+
100
+ Use the provided skills in the skills folder as guidance.
101
+ Update skill definitions if you find an improvement you can make.
102
+
103
+ ## Specifications
104
+
105
+ For every specification added to the Slice, you need to implement one executable Specification in Code.
106
+
107
+ A Slice is not complete if specifications are missing or can't be executed.
108
+
109
+ ## Stop Condition
110
+
111
+ **After completing ONE slice, always stop — regardless of whether more slices are Planned.** The ralph loop will invoke you again for the next slice. Never chain multiple slices in one iteration.
112
+
113
+ If the slice was completed and committed successfully, reply with:
114
+ <promise>DONE</promise>
115
+
116
+ If no slice has status "Planned" in the current context, reply with:
117
+ <promise>NO_TASKS</promise>
118
+ (Do NOT switch to another context to find work — stop here.)
119
+
120
+ If ALL slices in the current context are Done, reply with:
121
+ <promise>COMPLETE</promise>
122
+
123
+ ## Important
124
+
125
+ - If `.build-kit/.eventmodelers/config.json` is absent, skip all platform communication (MCP calls, `update-slice-status`, board sync) and continue working locally.
126
+ - Work on ONE slice per iteration
127
+ - Commit frequently
128
+ - update progress.txt frequently
129
+ - Read the Codebase Patterns section in progress.txt before starting
130
+
131
+ ## When an iteration completes
132
+
133
+ Use all the key learnings from the progress.txt and update the `.build-kit/AGENTS.md` file with those learnings.
@@ -0,0 +1,130 @@
1
+ # Agent Task Instructions
2
+
3
+ You are an autonomous agent reacting to slice status change events on an Eventmodelers board.
4
+
5
+ ## Your Loop
6
+
7
+ 1. Read `AGENT.md` to load accumulated learnings before doing anything else.
8
+ 2. Read `.build-kit/tasks.json`.
9
+ 3. If `tasks.json` is empty or missing, reply with:
10
+ <promise>IDLE</promise>
11
+ and stop.
12
+ 4. Pick the **oldest task** (earliest `createdAt`).
13
+ 5. Execute the task — see the Execution section below.
14
+ 6. After execution, remove that task from the array and write `.build-kit/tasks.json` back.
15
+ 7. Append a progress entry to `progress.txt` (create if missing).
16
+ 8. Update `AGENT.md` with any new reusable learnings discovered this iteration.
17
+ 9. Reply normally so the next iteration can pick up the next task.
18
+
19
+ ## Execution
20
+
21
+ Each task has a single `payload` of type `SliceChangedPayload`:
22
+
23
+ ```
24
+ {
25
+ event: "slice:changed"
26
+ organizationId: string | null
27
+ boardId: string
28
+ sliceId: string ← SLICE_BORDER node UUID
29
+ sliceTitle: string | null
30
+ sliceStatus: string | null ← e.g. "InProgress", "Done", "Blocked"
31
+ timestamp: number
32
+ }
33
+ ```
34
+
35
+ ### Step 1 — Load credentials
36
+
37
+ Run `/connect` to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL` from `.eventmodelers/config.json`.
38
+
39
+ ### Step 2 — Load the slice
40
+
41
+ Run `/load-slice sliceId=<payload.sliceId>` to fetch full slice details (title, status, raw node record).
42
+
43
+ ### Step 3 — Act on the change
44
+
45
+ Inspect the `sliceStatus` in the payload:
46
+
47
+ #### `Planned` — build the slice
48
+
49
+ This is the build trigger. Setting `InProgress` and building are one atomic step:
50
+
51
+ 1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
52
+
53
+ **Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Planned`), another agent already claimed it first — this is expected, not an error. Log it in `progress.txt`, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
54
+
55
+ 2. Run `/load-slice sliceId=<payload.sliceId>` to fetch the full slice, then read the slice definition from `.build-kit/.slices/<contextSlug>/<sliceFolder>/slice.json`. The runner keeps a `slice.json` fresh from a summary endpoint, so a file holding only `id`, `title`, `status` and `sliceType` is that stub, not an empty slice — never conclude a slice has no elements from it. Only if the full fetch itself returns no commands/events/read models/fields is the slice actually empty.
56
+
57
+ 3. Make sure `.build-kit/ARCHITECTURE.md` exists — if it is missing, run `/learn-architecture` first. This kit installs into an existing codebase: that file records how *this* project is built (layers, persistence, naming, tests, build/test commands), and every `build-*` skill implements the slice the way the codebase already works.
58
+
59
+ 4. Determine the **slice type** from the slice.json:
60
+ - **Translation** — `sliceType === "TRANSLATION"` → read `description` and `notes` from slice.json for hints; default to `/build-automation` if nothing else is specified
61
+ - **Automation** — `processors` array is non-empty → invoke `/build-automation`
62
+ - **State-view** — `projections` or `queries` array is non-empty → invoke `/build-state-view`
63
+ - **State-change** — default (has `commands` / `events`) → invoke `/build-state-change`
64
+
65
+ 5. Invoke the matching skill and follow its instructions **completely**. Do NOT implement the slice manually.
66
+
67
+ 6. **Verify against slice.json**: cross-check the implementation — every command field, event field, and specification in slice.json must appear in the code. No invented fields — if it is not in slice.json, it must not be in the code.
68
+
69
+ 7. Run the quality checks listed in `.build-kit/ARCHITECTURE.md` (build/compile, then only the tests touched by this slice — not the full suite).
70
+
71
+ 8. If checks pass, commit all changes with message: `feat: [Slice Name]`.
72
+
73
+ 9. Call `/update-slice-status` to set the slice to `Done` on the board.
74
+
75
+ #### `InProgress`
76
+ Another agent is already building this slice. Log it and skip — do not build.
77
+
78
+ #### `Done`
79
+ Summarize what was completed and update `progress.txt`.
80
+
81
+ #### `Blocked`
82
+ Log the blocker in `progress.txt`.
83
+
84
+ #### `Review`
85
+ Fetch slice details and prepare a review summary in `progress.txt`.
86
+
87
+ #### Any other status (`Created`, etc.)
88
+ Load the slice and log the state transition in `progress.txt`. No build action.
89
+
90
+ Use the skills available in `.claude/skills/` to interact with the board.
91
+
92
+ ## Updating tasks.json
93
+
94
+ After completing a task, remove it from the array and write the updated array back to `.build-kit/tasks.json`. If the array is now empty, write `[]`.
95
+
96
+ ## Escalating Ambiguity
97
+
98
+ **Default: make a reasonable assumption and build the slice.** If a detail is unclear or missing (an example value, a field type, a status mapping, a referenced event that isn't modeled yet, ...), pick the most sensible interpretation from `slice.json`, its specifications and the surrounding model, build it, and record each assumption in one line in `progress.txt` and as a code comment. Ambiguity alone is never a reason to stop. **Only if the slice literally cannot be built** — nothing runnable can be produced even with sensible assumptions — invoke `/request-feedback` with the specific question; it posts the question as a comment on the slice and marks it `Blocked`. That must be the absolute exception; a `Blocked` slice should mean "impossible without a human", never "the agent preferred to ask".
99
+
100
+ ## Progress Report Format
101
+
102
+ APPEND to `progress.txt` (never replace):
103
+ ```
104
+ ## [ISO timestamp] — Task [task.id]
105
+
106
+ Slice: [sliceTitle] ([sliceId])
107
+ Status change: [sliceStatus]
108
+
109
+ Action taken:
110
+ - [what was done in response to the slice change]
111
+
112
+ Learnings:
113
+ - [any patterns, gotchas, or reusable knowledge discovered]
114
+ ---
115
+ ```
116
+
117
+ ## Stop Condition
118
+
119
+ If `.build-kit/tasks.json` is empty (`[]`) or does not exist, reply with:
120
+ <promise>IDLE</promise>
121
+
122
+ ## Updating AGENT.md
123
+
124
+ After completing a task, add any **reusable** learnings to `AGENT.md` — patterns, gotchas, API quirks, or skill behaviour that future iterations should know. Only add things that are general and applicable beyond this single task. Do not duplicate what is already there.
125
+
126
+ ## Important
127
+
128
+ - Process **one task per iteration**.
129
+ - Read `AGENT.md` first — it contains patterns from previous iterations.
130
+ - Always start with `/connect` if credentials are not yet loaded.
@@ -198,15 +198,19 @@ As scenarios are written, ensure each role checks:
198
198
  | # | Type | Question to ask |
199
199
  |---|------|----------------|
200
200
  | 1 | **Happy Path** | "What is the normal success case?" |
201
- | 2 | **Validation Failure** | "What invalid or missing inputs should be rejected?" |
201
+ | 2 | **Validation Failure** | "What input does the *business* refuse?" (e.g. a booking date in the past) — not schema checks like missing/malformed fields |
202
202
  | 3 | **State Violation** | "What if the system is in a state that makes this command invalid?" |
203
- | 4 | **Duplicate Action** | "What if this command is issued again after it already succeeded?" |
203
+ | 4 | **Duplicate Action** | "What if someone performs this business action again on something already in that state?" (e.g. resolving an already-resolved todo) — never a re-sent or colliding id |
204
204
  | 5 | **Alternative Path** | "Are there different valid outcomes depending on context?" |
205
205
  | 6 | **External Failure** | "What if an external system or scheduler fails during this command?" |
206
206
  | 7 | **Compensation** | "Can this be undone or reversed? What triggers the cleanup?" |
207
207
 
208
208
  Work through each question with the domain in mind. If the answer is "that situation cannot occur in this business" then no scenario is needed for that type — but that judgment must come from the domain, not from a desire to write fewer scenarios.
209
209
 
210
+ **Scenarios specify business rules, not technical guarantees.** Every rejection must name a rule a domain expert would recognise and could argue about ("a closed day takes no new todos"). Do not write scenarios for: duplicate or colliding ids, retries/idempotency of the same request, missing or malformed required fields, type/format checks, or infrastructure failures — the implementation handles those and they say nothing about the domain. Rules the brief states explicitly (e.g. "adding on a closed day is rejected") are the core of the coverage and must all be present.
211
+
212
+ **`errorDescription` is domain language** — the reason as a user would read it ("Day is already closed"), never an id, a placeholder or a truncated example value.
213
+
210
214
  ## Workflow
211
215
 
212
216
  ### 0. Decide GWT vs. storyline for every READMODEL — before drafting any scenario payload
@@ -426,21 +430,21 @@ When a scenario represents a command being **rejected** (validation failure, sta
426
430
 
427
431
  **`expectError: true`** — signals that the command should be rejected and no event is produced. Set this for every failure/rejection scenario.
428
432
 
429
- **`errorDescription`** — a short human-readable description of the expected error or rejection reason (e.g. `"missing required field: date"`, `"reservation already confirmed"`). Do not leave this empty when `expectError` is `true`.
433
+ **`errorDescription`** — a short human-readable description of the expected error or rejection reason (e.g. `"reservation date is in the past"`, `"reservation already confirmed"`). Do not leave this empty when `expectError` is `true`.
430
434
 
431
435
  When `expectError` is `true`:
432
436
  - `then` must be `[]` — no events are produced on rejection
433
437
  - `when` contains the COMMAND being rejected
434
- - `given` contains any prerequisite EVENTs needed to establish the wrong state (may be empty for pure input-validation rejections)
438
+ - `given` contains any prerequisite EVENTs needed to establish the wrong state (may be empty for an input the business refuses)
435
439
  - Do **not** set `expectEmptyList` — that flag is only for list READMODELs
436
440
 
437
441
  Rejection scenario example:
438
442
  ```json
439
443
  {
440
444
  "id": "<uuid>",
441
- "title": "Reject reservation with missing required date field",
445
+ "title": "Reject a reservation for a date in the past",
442
446
  "expectError": true,
443
- "errorDescription": "missing required field: date",
447
+ "errorDescription": "reservation date is in the past",
444
448
  "given": [],
445
449
  "when": [{"id": "<commandNodeId>", "title": "Reservation Command", "type": "COMMAND"}],
446
450
  "then": [],
@@ -344,7 +344,7 @@ if Conway's Law boundaries are not relevant to the project.
344
344
 
345
345
  ### Step 7: Elaborate Scenarios
346
346
 
347
- Invoke `eventmodeling-elaborating-scenarios`.
347
+ Invoke `eventmodeling-elaborating-scenarios` with the Skill tool **before the first `add_scenario` call** — its scenario types, business-rules-only rule and payload shape are not repeated here, so scenarios written from this file alone come out wrong.
348
348
 
349
349
  **Input**: Commands and read models.
350
350
  **Output to carry forward**: Given-When-Then specifications (or storylines, for
@@ -356,7 +356,7 @@ the elaborating-scenarios workflow — not just happy path + one error case —
356
356
  gate checklist below. A command-only pass is an incomplete Step 7, even if
357
357
  every command's coverage looks exhaustive.
358
358
 
359
- > **Do not reduce scenarios to a simple good-case / bad-case pair.** The `eventmodeling-elaborating-scenarios` skill defines a structured scenario workshop covering seven scenario types per command (Happy Path, Validation Failure, State Violation, Duplicate Action, Alternative Path, External Failure, Compensation — see that skill's own table for the question-form definition of each) — which apply is determined by the domain, not by a fixed rule. All applicable types must be written before this step is complete; do not decide based on brevity.
359
+ > **Do not reduce scenarios to a simple good-case / bad-case pair** — but do not pad them with technical cases either. Which scenario types apply is defined in `eventmodeling-elaborating-scenarios` and decided by the domain.
360
360
 
361
361
  > **Read models need scenarios too — easy to forget since the seven types above are command-shaped.** Every READMODEL needs at least one view scenario (GWT or storyline); a read model with zero scenarios is as incomplete as a command with zero. `eventmodeling-elaborating-scenarios`'s own checklist covers the details — connectivity rules, GWT-vs-storyline judgment per read model, and avoiding redundancy between a storyline and its GWTs — don't re-derive those here, just enforce the gate.
362
362
 
@@ -138,7 +138,7 @@ mcp__eventmodelers__add_scenario {
138
138
  }
139
139
  ```
140
140
 
141
- Same rules apply (given=EVENTs only, when=at most one COMMAND or QUERY, then=EVENTs only or exactly one READMODEL, `expectError`+`errorDescription` for error cases). This auto-creates the spec node if the cell is empty, same as the curl endpoint.
141
+ Same rules apply (context=READMODELs only, given=EVENTs only, when=at most one COMMAND or QUERY, then=EVENTs only or exactly one READMODEL, `expectError`+`errorDescription` for error cases). This auto-creates the spec node if the cell is empty, same as the curl endpoint.
142
142
 
143
143
  **Fallback (no MCP):** see `references/api-fallback.md` — "Step 4a — SCENARIO: append scenarios via the spec endpoint" for the full curl call and example payload.
144
144