@eventmodelers/cli 0.0.7 → 0.0.8

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.
Files changed (48) hide show
  1. package/README.md +42 -9
  2. package/cli.js +612 -149
  3. package/package.json +1 -1
  4. package/{stacks/node/templates → shared}/build-kit/README.md +3 -3
  5. package/{stacks/axon/templates → shared}/build-kit/lib/ralph.js +10 -3
  6. package/shared/build-kit/ralph-ollama.js +2 -2
  7. package/{stacks/node/templates → shared}/build-kit/ralph.sh +1 -1
  8. package/shared/build-kit/realtime-agent.js +1 -1
  9. package/{stacks/supabase/templates/.claude → shared}/skills/connect/SKILL.md +10 -5
  10. package/stacks/cratis-csharp/templates/build-kit/lib/AGENT.md +1 -0
  11. package/stacks/modeling-kit/templates/kit/README.md +79 -0
  12. package/stacks/modeling-kit/templates/kit/lib/ralph.js +9 -2
  13. package/stacks/modeling-kit/templates/kit/ralph.sh +1 -1
  14. package/stacks/node/templates/build-kit/lib/backend-prompt.md +1 -1
  15. package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +1 -1
  16. package/stacks/axon/templates/.claude/skills/connect/SKILL.md +0 -178
  17. package/stacks/axon/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +0 -611
  18. package/stacks/axon/templates/.claude/skills/update-slice-status/SKILL.md +0 -105
  19. package/stacks/axon/templates/build-kit/ralph.sh +0 -98
  20. package/stacks/cratis-csharp/templates/.claude/skills/connect/SKILL.md +0 -178
  21. package/stacks/cratis-csharp/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +0 -609
  22. package/stacks/cratis-csharp/templates/.claude/skills/update-slice-status/SKILL.md +0 -105
  23. package/stacks/cratis-csharp/templates/build-kit/lib/agent.sh +0 -20
  24. package/stacks/cratis-csharp/templates/build-kit/lib/ralph.js +0 -302
  25. package/stacks/cratis-csharp/templates/build-kit/ralph-claude.js +0 -37
  26. package/stacks/cratis-csharp/templates/build-kit/ralph.sh +0 -98
  27. package/stacks/modeling-kit/templates/.claude/skills/connect/SKILL.md +0 -178
  28. package/stacks/modeling-kit/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +0 -441
  29. package/stacks/modeling-kit/templates/.claude/skills/update-slice-status/SKILL.md +0 -110
  30. package/stacks/modeling-kit/templates/kit/lib/agent.sh +0 -20
  31. package/stacks/modeling-kit/templates/kit/lib/ollama-agent.js +0 -147
  32. package/stacks/modeling-kit/templates/kit/ralph-ollama.js +0 -38
  33. package/stacks/modeling-kit/templates/kit/realtime-agent.js +0 -18
  34. package/stacks/node/templates/.claude/skills/connect/SKILL.md +0 -178
  35. package/stacks/node/templates/build-kit/lib/agent.sh +0 -20
  36. package/stacks/node/templates/build-kit/lib/ralph.js +0 -369
  37. package/stacks/node/templates/build-kit/ralph-claude.js +0 -44
  38. package/stacks/supabase/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +0 -628
  39. package/stacks/supabase/templates/.claude/skills/update-slice-status/SKILL.md +0 -110
  40. package/stacks/supabase/templates/build-kit/README.md +0 -86
  41. package/stacks/supabase/templates/build-kit/lib/agent.sh +0 -20
  42. package/stacks/supabase/templates/build-kit/lib/ralph.js +0 -369
  43. package/stacks/supabase/templates/build-kit/ralph-claude.js +0 -44
  44. package/stacks/supabase/templates/build-kit/ralph.sh +0 -98
  45. /package/{stacks/axon/templates → shared}/build-kit/lib/agent.sh +0 -0
  46. /package/{stacks/axon/templates → shared}/build-kit/ralph-claude.js +0 -0
  47. /package/{stacks/node/templates/.claude → shared}/skills/learn-eventmodelers-api/SKILL.md +0 -0
  48. /package/{stacks/node/templates/.claude → shared}/skills/update-slice-status/SKILL.md +0 -0
@@ -1,441 +0,0 @@
1
- ---
2
- name: learn-eventmodelers-api
3
- description: Teaches an agent everything about the eventmodelers platform API — all endpoints, their purpose, request payloads, response shapes, authentication, and element types.
4
- ---
5
-
6
- # Eventmodelers Platform API
7
-
8
- **Before making any API calls, invoke the `connect` skill** to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`.
9
-
10
- ```bash
11
- # Variables produced by the connect skill:
12
- TOKEN=<api-token> BASE_URL=https://api.eventmodelers.ai
13
- ORG_ID=<orgId> BOARD_ID=<boardId> NODE=<nodeId>
14
- ```
15
-
16
- **Auth headers** (required on every request):
17
- ```
18
- x-token: $TOKEN
19
- x-board-id: $BOARD_ID
20
- x-user-id: <skill-name>
21
- ```
22
-
23
- All board-scoped URLs: `$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/...`
24
-
25
- ---
26
-
27
- ## Boards
28
-
29
- ```bash
30
- curl $BASE_URL/api/boards -H "x-token: $TOKEN"
31
- curl -X DELETE $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID -H "x-token: $TOKEN"
32
- curl $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/events -H "x-token: $TOKEN"
33
- curl "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/events/search?name=OrderPlaced" -H "x-token: $TOKEN"
34
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/bucket -H "x-token: $TOKEN"
35
-
36
- # Post board events (nodes / comments / edges)
37
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/events \
38
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
39
- -d '[{"eventType":"node:created","nodeId":"<uuid>","boardId":"'$BOARD_ID'","timestamp":1234567890}]'
40
- ```
41
-
42
- ---
43
-
44
- ## Comments
45
-
46
- ```bash
47
- curl $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$NODE/comments -H "x-token: $TOKEN"
48
-
49
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$NODE/comments \
50
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
51
- -d '{"text":"Needs clarification","type":"TASK","author":"alice"}'
52
- # type: COMMENT | TASK | QUESTION — returns 201 {"id":"<commentId>"}
53
-
54
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$NODE/comments/$CID/resolve \
55
- -H "x-token: $TOKEN"
56
-
57
- curl -X DELETE $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$NODE/comments/$CID \
58
- -H "x-token: $TOKEN"
59
- ```
60
-
61
- ---
62
-
63
- ## Chapters & Timelines
64
-
65
- > **Cell ID convention**: Cell IDs are always implicit — computed as `<rowId>-<columnId>` (the row UUID, a hyphen, then the column UUID). Never search `timelineData.cells` to find a cell ID; just concatenate: `cellId = rowId + "-" + columnId`. The `cells` array in `timelineData` is still useful for checking whether a cell is occupied (`nodeId` present), but never for deriving the cell's own ID.
66
-
67
- ```bash
68
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/chapters \
69
- -H "x-token: $TOKEN" -H "Content-Type: application/json" -d '{}'
70
-
71
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/columns \
72
- -H "x-token: $TOKEN" -H "Content-Type: application/json" -d '{"index":2}'
73
-
74
- curl -X DELETE $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/columns/$COL \
75
- -H "x-token: $TOKEN"
76
-
77
- # Move a column to a new 0-based index within the timeline
78
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/columns/$COL/move \
79
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
80
- -d '{"toIndex":2}'
81
- # → 200 on success · 400 same index or out of range · 404 timeline/column not found
82
-
83
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/lanes \
84
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
85
- -d '{"type":"swimlane","label":"Domain Events"}'
86
- # type: actor | interaction | swimlane | spec | feedback
87
-
88
- # Move a lane (row) to a new 0-based index within the timeline
89
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/lanes/$ROW/move \
90
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
91
- -d '{"toIndex":1}'
92
- # → 200 on success · 400 same index or out of range · 404 timeline/row not found
93
-
94
- # $CELL = <rowId>-<columnId> (computed, not looked up)
95
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/cells/$CELL/drop \
96
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
97
- -d '{"nodeId":"<uuid>","nodeType":"EVENT"}'
98
- # swimlane→EVENT interaction→COMMAND/READMODEL actor→SCREEN/AUTOMATION
99
-
100
- # Update canvas position of a timeline node
101
- curl -X PUT $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/position \
102
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
103
- -d '{"x":100,"y":200}'
104
- # → { timelineId, x, y }
105
- # timeline:position-changed event is emitted
106
- ```
107
-
108
- ---
109
-
110
- ## Connections (Edges)
111
-
112
- **Edge style** — always include this style when creating edges via `edge:added` events:
113
- ```json
114
- {
115
- "style": {
116
- "stroke": "#000000",
117
- "strokeColor": "#000000",
118
- "strokeStyle": "normal",
119
- "strokeWidth": 4,
120
- "endStrokeCap": "arrow",
121
- "startStrokeCap": "none",
122
- "opacity": 1
123
- }
124
- }
125
- ```
126
- > The high-level `/connections` endpoint and MCP `connect_nodes` tool do not accept style — use `edge:added` events (via `/nodes/events` or MCP `post_board_events`) when style is needed.
127
-
128
- ```bash
129
- # Connect two nodes — direction is auto-corrected to the valid orientation
130
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/connections \
131
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
132
- -d '{"source":"<nodeUuid>","target":"<nodeUuid>"}'
133
- # → 201 { edgeId, source, target, created: true } (new edge)
134
- # → 200 { edgeId, source, target, created: false } (already existed)
135
- # → 400 { error, hint } if the connection type is not allowed
136
- # Allowed: COMMAND→EVENT · SCREEN→COMMAND · EVENT→READMODEL · READMODEL→SCREEN · READMODEL→AUTOMATION · AUTOMATION→COMMAND
137
- # Both nodes must belong to the same timeline.
138
-
139
- # Remove an edge — direction is checked both ways
140
- curl -X DELETE $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/connections \
141
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
142
- -d '{"source":"<nodeUuid>","target":"<nodeUuid>"}'
143
- # → 200 { removed: true } or { removed: false } (no edge existed — not an error)
144
- ```
145
-
146
- ---
147
-
148
- ## Nodes
149
-
150
- ```bash
151
- curl "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=EVENT" -H "x-token: $TOKEN"
152
- curl $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$NODE -H "x-token: $TOKEN"
153
-
154
- # Create/update node
155
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events \
156
- -H "x-token: $TOKEN" -H "x-user-id: $USER_ID" -H "Content-Type: application/json" \
157
- -d '[{"id":"<uuid>","eventType":"node:created","nodeId":"<uuid>","boardId":"'$BOARD_ID'","timestamp":1234567890,"meta":{"type":"EVENT","title":"OrderPlaced"},"chapterId":"<id>","cellName":"B2"}]'
158
- # eventType: node:created | node:changed | node:deleted
159
-
160
- # Valid meta.type values (required on node:created, validated on node:changed):
161
- # MODEL_CONTEXT | CHAPTER | ACTOR | AUTOMATION | API | SCREEN
162
- # COMMAND | EVENT | SPEC_ERROR | TABLE | READMODEL | SCENARIO | LANE | SLICE_BORDER
163
- # Omitting or supplying an unknown type returns 400.
164
- ```
165
-
166
- #### Field object format (`meta.fields`)
167
-
168
- Each entry in `meta.fields` on a COMMAND/EVENT/READMODEL/SCREEN node:
169
- ```json
170
- {
171
- "name": "customerId",
172
- "type": "String",
173
- "cardinality": "Single",
174
- "example": "cust-42",
175
- "mapping": "session:customerId",
176
- "generated": false,
177
- "optional": false,
178
- "query": false,
179
- "edited": false,
180
- "subfields": [],
181
- "idAttribute": false,
182
- "showAttributes": false,
183
- "technicalAttribute": false
184
- }
185
- ```
186
- `cardinality` is one of `"Single"` (default) or `"List"` — use `"List"` only when the field genuinely holds multiple values (an array, a repeated line item). When in doubt, use `"Single"`.
187
-
188
- Only add the fields an element actually needs at creation time — its identity key plus the facts the business/consumer cares about right now. Do not front-load every conceivable field; add more later with the `/attributes` skill as the model matures.
189
-
190
- #### Linked copies
191
-
192
- A node's `data.linkedTo` (mirrored at the top level as `linkedTo`) marks it as a **linked copy**, not an independent node. Users intentionally repeat the same EVENT/READMODEL/SCREEN at multiple points on a timeline for readability — to avoid crossing connections — rather than draw long edges across the board. The platform's UI keeps these copies in sync with the original.
193
-
194
- ```json
195
- "data": {
196
- "linkedTo": "/app/board/<originBoardId>/?moveToWidget=<originNodeId>",
197
- ...
198
- }
199
- ```
200
-
201
- - Presence of `linkedTo` (non-empty) → this node is a copy; the `moveToWidget` query param is the **original** node's ID (on `originBoardId`, which may or may not be the current board).
202
- - A node with no `linkedTo` is either a true standalone node or the original that other copies point to.
203
- - **Never treat two same-titled/same-type nodes as duplicates without first checking `linkedTo` on both.** If either carries `linkedTo`, they are an intentional linked pair, not a modeling defect — do not report it as a gap, and never propose deleting/merging either side. See `eventmodeling-checking-completeness` for how this applies during a completeness check.
204
-
205
- ---
206
-
207
- ## Slices
208
-
209
- ```bash
210
- # type: state-change (SCREEN+COMMAND+EVENT) | state-view (SCREEN+READMODEL+EVENT) | automation (AUTOMATION+COMMAND+EVENT)
211
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/slices \
212
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
213
- -d '{"type":"state-change","nodes":{"swimlane":{"title":"OrderPlaced"}}}'
214
- # MCP: create_slice
215
-
216
- # Mark an *existing* column as a slice (SLICE_BORDER node) — does not add a column
217
- # or any actor/interaction/swimlane content nodes. columnId must already exist
218
- # (e.g. created via POST .../slices above, or the column API).
219
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/slice-definitions \
220
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
221
- -d '{"columnId":"<colId>","title":"OrderPlaced"}'
222
- # → 200 { nodeId, timelineId, columnId, title }
223
- # → 400 missing columnId/title or column not found · 404 timeline not found
224
- # title is always taken from the "title" field, never derived from a command/read model
225
- # MCP: create_slice_definition
226
- ```
227
-
228
- ---
229
-
230
- ## Specifications (GWT)
231
-
232
- Specs are scoped to a **timeline** and placed in a column's `spec` row — no context or slice name needed.
233
-
234
- ```bash
235
- # List valid given/when/then elements for a timeline (EVENT, COMMAND, READMODEL)
236
- curl "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/spec-info" \
237
- -H "x-token: $TOKEN"
238
- # → { timelineId, elements: [{ id, title, type }] }
239
-
240
- # Append one or more GWT scenarios to a column's spec cell.
241
- # The SCENARIO spec node is created automatically — no pre-creation step needed.
242
- # Body: a single scenario object OR an array of scenario objects.
243
- curl -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$TL/columns/$COL/scenarios" \
244
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
245
- -d '[
246
- {
247
- "id": "<uuid>",
248
- "title": "Happy path",
249
- "given": [{"id":"<eventNodeId>","title":"OrderPlaced","type":"EVENT"}],
250
- "when": [{"id":"<commandNodeId>","title":"PlaceOrder","type":"COMMAND"}],
251
- "then": [{"id":"<eventNodeId2>","title":"OrderConfirmed","type":"EVENT"}]
252
- },
253
- {
254
- "id": "<uuid>",
255
- "title": "Insufficient stock",
256
- "given": [{"id":"<eventNodeId>","title":"OrderPlaced","type":"EVENT"}],
257
- "when": [{"id":"<commandNodeId>","title":"PlaceOrder","type":"COMMAND"}],
258
- "then": [],
259
- "expectError": true,
260
- "errorDescription": "Stock below requested quantity"
261
- }
262
- ]'
263
- # → 201 { specNodeId, scenarios (all), added (count), isNewNode }
264
- ```
265
-
266
- **Step item format** — each item in `given`, `when`, `then`:
267
- ```json
268
- { "id": "<board-node-uuid>", "title": "OrderPlaced", "type": "EVENT", "fields": [], "specRow": 0 }
269
- ```
270
- `id` is required (board node UUID). `title` and `type` are informational only.
271
-
272
- **Rules enforced by the server:**
273
- - `given`: EVENT nodes only, all from the same timeline as `$TL`
274
- - `when`: at most one COMMAND; must be empty when `then` contains a READMODEL
275
- - `then`: EVENTs only **or** exactly one READMODEL — never mixed
276
- - Error-case scenarios: set `expectError: true` and leave `then: []`
277
- - Scenario `title` must be unique within the spec node (checked across all new + existing)
278
- - All referenced node IDs must exist on the board and belong to timeline `$TL`
279
-
280
- **Errors:** `400` validation · `404` timeline, column, or referenced node not found · `409` duplicate scenario title
281
-
282
- > **Multiple spec rows:** The `/scenarios` endpoint always targets the **first** spec row in a column. If the chapter has multiple spec rows and you need to target a different one, use `node:changed` directly on that spec node's `meta.givenWhenThenScenario` via `/nodes/events`.
283
-
284
- #### Scenario object format
285
-
286
- **Happy path:**
287
- ```json
288
- {
289
- "id": "<uuid>", "title": "...", "vertical": false,
290
- "given": [...], "when": [...], "then": [...],
291
- "comments": []
292
- }
293
- ```
294
-
295
- **Error case** (business rule violation):
296
- ```json
297
- {
298
- "id": "<uuid>", "title": "...", "vertical": false,
299
- "given": [...], "when": [...], "then": [],
300
- "expectError": true, "errorDescription": "<human-readable message>",
301
- "examples": [], "expectEmptyList": false, "comments": []
302
- }
303
- ```
304
-
305
- #### Step item format
306
-
307
- Each item in `given`, `when`, `then` must use the **board node UUID**:
308
- ```json
309
- { "id": "<board-node-uuid>", "title": "OrderPlaced", "type": "EVENT", "fields": [{"name":"locale","type":"String","example":"nl_NL"}], "specRow": 0 }
310
- ```
311
- `id` is required. `title`, `type`, `fields`, and `specRow` are informational.
312
-
313
- | Step | Allowed `type` |
314
- |------|----------------|
315
- | `given` | `EVENT` |
316
- | `when` | `COMMAND` |
317
- | `then` (happy path) | `EVENT` or `READMODEL` |
318
- | `then` (error case) | leave empty — use `expectError: true` on the scenario |
319
- | `then` (spec error item) | `SPEC_ERROR` with `title`, `description`, `fields: []` |
320
-
321
- #### Mapping config IDs to board node IDs
322
-
323
- If working from a slice config file where items use config-internal IDs, build a lookup first:
324
- ```
325
- config_command_id → board COMMAND node ID (from chapter cells for that column)
326
- config_event_id → board EVENT node ID (from chapter cells for that column)
327
- config_rm_id → board READMODEL node ID
328
- ```
329
- Type name mapping from config → board: `WHEN` → `COMMAND`, `GIVEN` → `EVENT`, `THEN` → `EVENT`.
330
-
331
- ---
332
-
333
- ## Images / Sketches
334
-
335
- ```bash
336
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/images/$IMG \
337
- -H "x-token: $TOKEN" -F "file=@image.png"
338
-
339
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/images/$IMG/sketch \
340
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
341
- -d '{"description":"Login form","elements":[{"type":"rectangle","x":1,"y":1,"w":10,"h":5}]}'
342
-
343
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/image-nodes/$NODE/sketch \
344
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
345
- -d '{"chapterId":"<id>","cellName":"A1","description":{"elements":[]}}'
346
- ```
347
-
348
- ---
349
-
350
- ## Slice Data
351
-
352
- ```bash
353
- curl "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/slicedata?contextName=Ordering" -H "x-token: $TOKEN"
354
- curl $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/slicedata/slices -H "x-token: $TOKEN"
355
- ```
356
-
357
- ---
358
-
359
- ## Snapshots (max 3 · 30d · 50MB)
360
-
361
- ```bash
362
- curl $BASE_URL/api/snapshots -H "x-token: $TOKEN"
363
- curl -X POST $BASE_URL/api/snapshots -H "x-token: $TOKEN" \
364
- -F "payloadFile=@board.json" -F "name=my-snapshot" -F "retention=7"
365
- curl -X PATCH $BASE_URL/api/snapshots/$SID/share -H "x-token: $TOKEN"
366
- curl -X DELETE $BASE_URL/api/snapshots/$SID -H "x-token: $TOKEN"
367
- ```
368
-
369
- ---
370
-
371
- ## Prompts & Agent
372
-
373
- ```bash
374
- # Submit prompt
375
- curl -X POST $BASE_URL/api/org/$ORG_ID/prompts \
376
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
377
- -d '{"prompt":"Add OrderShipped event","board_id":"'$BOARD_ID'","timeline_id":"<id>","node_id":"<id>","comment_id":"<id>"}'
378
-
379
- # Dequeue next prompt (agent)
380
- curl $BASE_URL/api/org/$ORG_ID/prompts/next -H "x-token: $TOKEN"
381
-
382
- # Delete processed prompt (agent)
383
- curl -X DELETE $BASE_URL/api/org/$ORG_ID/prompts/$PID -H "x-token: $TOKEN"
384
-
385
- # Cancel own prompt
386
- curl -X DELETE $BASE_URL/api/org/$ORG_ID/prompts/$PID/user -H "x-token: $TOKEN"
387
-
388
- # Realtime token (agent)
389
- curl $BASE_URL/api/org/$ORG_ID/prompts/realtime-token -H "x-token: $TOKEN"
390
-
391
- # Heartbeat
392
- curl -X POST $BASE_URL/api/agent-alive \
393
- -H "x-token: $TOKEN" -H "Content-Type: application/json" \
394
- -d '{"token":"'$TOKEN'"}'
395
-
396
- # Check agent alive
397
- curl $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/agent-alive -H "x-token: $TOKEN"
398
- ```
399
-
400
- ---
401
-
402
- ## Extensions
403
-
404
- ```bash
405
- curl $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/extensions -H "x-token: $TOKEN"
406
- curl -X PUT $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/extensions/git \
407
- -H "x-token: $TOKEN" -H "Content-Type: application/json" -d '{"enabled":true}'
408
- ```
409
-
410
- ---
411
-
412
- ## User Management
413
-
414
- ```bash
415
- # Commands → {ok, next_expected_stream_version, last_event_global_position}
416
- curl -X POST $BASE_URL/api/creategroup -H "x-token: $TOKEN" -H "Content-Type: application/json" \
417
- -d '{"groupId":"<uuid>","name":"My Team"}'
418
- curl -X POST $BASE_URL/api/inviteuser -H "x-token: $TOKEN" -H "Content-Type: application/json" \
419
- -d '{"groupId":"<uuid>","email":"user@example.com","invitationId":"<uuid>"}'
420
- curl -X POST $BASE_URL/api/acceptinvite -H "x-token: $TOKEN" -H "Content-Type: application/json" \
421
- -d '{"userId":"<uuid>","groupId":"<uuid>","invitationId":"<uuid>"}'
422
- curl -X POST $BASE_URL/api/assignrole -H "x-token: $TOKEN" -H "Content-Type: application/json" \
423
- -d '{"userId":"<uuid>","groupId":"<uuid>","role":"admin"}'
424
-
425
- # Read models (add ?_id= to filter)
426
- curl $BASE_URL/api/query/group-details-lookup -H "x-token: $TOKEN"
427
- curl $BASE_URL/api/query/open-invites -H "x-token: $TOKEN"
428
- curl $BASE_URL/api/query/user-group-assignments -H "x-token: $TOKEN"
429
- curl $BASE_URL/api/query/users-to-assign-to-groups -H "x-token: $TOKEN"
430
- ```
431
-
432
- ---
433
-
434
- ## Utility
435
-
436
- ```bash
437
- curl $BASE_URL/api/user -H "x-token: $TOKEN" # current user
438
- curl $BASE_URL/swagger.json # OpenAPI spec
439
- curl -X POST $BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/import-config \
440
- -H "x-token: $TOKEN" -F "file=@config.json"
441
- ```
@@ -1,110 +0,0 @@
1
- ---
2
- name: update-slice-status
3
- description: Update the status of a single slice on an eventmodelers board by changing the SLICE_BORDER node's sliceStatus field
4
- ---
5
-
6
- # Update Slice Status
7
-
8
- > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until the connect skill has completed.
9
-
10
- ---
11
-
12
- ## Step 1 — Parse arguments
13
-
14
- From `$ARGUMENTS`, extract:
15
-
16
- | Field | How to find it | Default |
17
- |-------|---------------|---------|
18
- | `sliceName` | the slice title to update (case-insensitive match) | **required** |
19
- | `newStatus` | the target status value | **required** |
20
-
21
- Valid status values (case-sensitive):
22
-
23
- | Value | Meaning |
24
- |-------|---------|
25
- | `Created` | Default — slice has been created but not started |
26
- | `Planned` | Work is planned |
27
- | `InProgress` | Work is actively in progress |
28
- | `Review` | Ready for review |
29
- | `Done` | Completed |
30
- | `Blocked` | Blocked by something |
31
- | `Assigned` | Assigned to someone |
32
- | `Informational` | Informational / reference slice |
33
-
34
- If `newStatus` is not one of these exact values, stop and tell the user the valid options.
35
-
36
- ---
37
-
38
- ## Step 2 — List all slices
39
-
40
- Fetch all slices on the board:
41
-
42
- ```bash
43
- curl -s \
44
- -H "x-token: <TOKEN>" \
45
- -H "x-board-id: <BOARD_ID>" \
46
- -H "x-user-id: update-slice-status-skill" \
47
- "<BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/slicedata/slices"
48
- ```
49
-
50
- Response: `{ "slices": [{ "id": "<nodeId>", "title": "<title>", "status": "<status>" }] }`
51
-
52
- The `id` here is the `SLICE_BORDER` node ID — use it directly in Step 3.
53
-
54
- Find the slice whose `title` matches `sliceName` (case-insensitive). If no match is found, stop and list the available slice titles so the user can pick one.
55
-
56
- Save the matched slice as:
57
- - `SLICE_NODE_ID` — the node ID of the SLICE_BORDER
58
- - `CURRENT_STATUS` — the current status value
59
-
60
- ---
61
-
62
- ## Step 3 — Update the slice status
63
-
64
- Send a `node:changed` event to update the `sliceStatus` field in the SLICE_BORDER node's meta:
65
-
66
- ```bash
67
- curl -s -X POST "<BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/events" \
68
- -H "Content-Type: application/json" \
69
- -H "x-token: <TOKEN>" \
70
- -H "x-board-id: <BOARD_ID>" \
71
- -H "x-user-id: update-slice-status-skill" \
72
- -d '[{
73
- "id": "<new-random-uuid>",
74
- "eventType": "node:changed",
75
- "nodeId": "<SLICE_NODE_ID>",
76
- "boardId": "<BOARD_ID>",
77
- "timestamp": <Date.now()>,
78
- "changedAttributes": ["sliceStatus"],
79
- "meta": {
80
- "sliceStatus": "<newStatus>"
81
- }
82
- }]'
83
- ```
84
-
85
- Response: `{ "hashes": { "<eventId>": "<hash>" } }`
86
-
87
- ### If the API rejects the update because the slice is already in `newStatus`
88
-
89
- The API refuses to move a slice into a status it is already in — this is a deliberate concurrency guard so two agents racing to claim the same slice can't both succeed. If Step 3 fails with an error indicating the slice is already at `<newStatus>` (e.g. a `409`, or an error body mentioning "already"), this is **not a failure to surface as broken** — it means another agent already claimed or moved the slice first. Report this as a distinct `ALREADY_IN_STATUS` outcome (see Step 4) rather than a generic error, and do not retry the same update.
90
-
91
- ---
92
-
93
- ## Step 4 — Report back
94
-
95
- Tell the user:
96
-
97
- - **Slice**: the title that was updated
98
- - **Previous status**: `CURRENT_STATUS`
99
- - **New status**: `newStatus`
100
- - **Node ID**: `SLICE_NODE_ID`
101
- - **Outcome**: `SUCCESS`, `ALREADY_IN_STATUS` (another agent got there first — see above), or `ERROR`
102
- - **Any errors**: raw API message if something failed for a reason other than `ALREADY_IN_STATUS`
103
-
104
- Example success output:
105
- ```
106
- Updated: "Order Placed" slice
107
- Before: InProgress
108
- After: Done
109
- Node ID: a1b2c3d4-…
110
- ```
@@ -1,20 +0,0 @@
1
- #!/bin/bash
2
- # Runs the AI agent with the given prompt in the project directory.
3
- # Called by ralph.sh with cwd already set to the project root.
4
- # Usage: ./agent.sh "<prompt>"
5
-
6
- set -euo pipefail
7
-
8
- PROMPT="${1:-}"
9
- if [[ -z "$PROMPT" ]]; then
10
- echo "ERROR: No prompt provided"
11
- exit 1
12
- fi
13
-
14
- claude --dangerously-skip-permissions -p "$PROMPT"
15
-
16
- # --- To use a local Ollama model instead, comment out the line above
17
- # and uncomment the block below. Run `ollama serve` first.
18
- #
19
- # MODEL="${OLLAMA_MODEL:-qwen3:8b}"
20
- # node "$(dirname "$0")/ollama-agent.js" "$MODEL"