@eventmodelers/cli 0.0.1

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 (220) hide show
  1. package/README.md +175 -0
  2. package/cli.js +676 -0
  3. package/package.json +35 -0
  4. package/shared/build-kit/code-export.mjs +560 -0
  5. package/shared/build-kit/lib/ollama-agent.js +147 -0
  6. package/shared/build-kit/package.json +11 -0
  7. package/shared/build-kit/ralph-ollama.js +39 -0
  8. package/shared/build-kit/realtime-agent.js +18 -0
  9. package/stacks/axon/templates/.claude/skills/build-automation/SKILL.md +407 -0
  10. package/stacks/axon/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +114 -0
  11. package/stacks/axon/templates/.claude/skills/build-automation-workflow/SKILL.md +496 -0
  12. package/stacks/axon/templates/.claude/skills/build-automation-workflow/references/axon-workflow-api.md +279 -0
  13. package/stacks/axon/templates/.claude/skills/build-automation-workflow/references/feature-flag-patterns.md +114 -0
  14. package/stacks/axon/templates/.claude/skills/build-state-change/SKILL.md +396 -0
  15. package/stacks/axon/templates/.claude/skills/build-state-change/references/axon-test-fixture-patterns.md +162 -0
  16. package/stacks/axon/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +56 -0
  17. package/stacks/axon/templates/.claude/skills/build-state-change/references/rest-api-patterns.md +115 -0
  18. package/stacks/axon/templates/.claude/skills/build-state-view/SKILL.md +282 -0
  19. package/stacks/axon/templates/.claude/skills/connect/SKILL.md +178 -0
  20. package/stacks/axon/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +611 -0
  21. package/stacks/axon/templates/.claude/skills/load-slice/SKILL.md +141 -0
  22. package/stacks/axon/templates/.claude/skills/update-slice-status/SKILL.md +105 -0
  23. package/stacks/axon/templates/build-kit/lib/AGENT.md +47 -0
  24. package/stacks/axon/templates/build-kit/lib/agent.sh +20 -0
  25. package/stacks/axon/templates/build-kit/lib/backend-prompt.md +158 -0
  26. package/stacks/axon/templates/build-kit/lib/prompt.md +126 -0
  27. package/stacks/axon/templates/build-kit/lib/ralph.js +369 -0
  28. package/stacks/axon/templates/build-kit/ralph-claude.js +44 -0
  29. package/stacks/axon/templates/build-kit/ralph.sh +98 -0
  30. package/stacks/axon/templates/root/.env.example +5 -0
  31. package/stacks/axon/templates/root/CLAUDE.md +60 -0
  32. package/stacks/axon/templates/root/README.md +44 -0
  33. package/stacks/axon/templates/root/docker-compose.yml +64 -0
  34. package/stacks/axon/templates/root/mvnw +259 -0
  35. package/stacks/axon/templates/root/mvnw.cmd +149 -0
  36. package/stacks/axon/templates/root/pom.xml +125 -0
  37. package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/QuickstartApplication.java +128 -0
  38. package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/config/WebConfig.java +155 -0
  39. package/stacks/axon/templates/root/src/main/resources/application.properties +2 -0
  40. package/stacks/axon/templates/root/src/main/resources/static/bg-body.png +0 -0
  41. package/stacks/axon/templates/root/src/main/resources/static/bg-header.png +0 -0
  42. package/stacks/axon/templates/root/src/main/resources/static/index.html +596 -0
  43. package/stacks/cratis-csharp/templates/.claude/skills/_shared/cratis-conventions.md +251 -0
  44. package/stacks/cratis-csharp/templates/.claude/skills/build-automation/SKILL.md +99 -0
  45. package/stacks/cratis-csharp/templates/.claude/skills/build-automation/references/patterns.md +115 -0
  46. package/stacks/cratis-csharp/templates/.claude/skills/build-state-change/SKILL.md +163 -0
  47. package/stacks/cratis-csharp/templates/.claude/skills/build-state-change/references/patterns.md +234 -0
  48. package/stacks/cratis-csharp/templates/.claude/skills/build-state-view/SKILL.md +120 -0
  49. package/stacks/cratis-csharp/templates/.claude/skills/build-state-view/references/patterns.md +166 -0
  50. package/stacks/cratis-csharp/templates/.claude/skills/connect/SKILL.md +169 -0
  51. package/stacks/cratis-csharp/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +609 -0
  52. package/stacks/cratis-csharp/templates/.claude/skills/load-slice/SKILL.md +141 -0
  53. package/stacks/cratis-csharp/templates/.claude/skills/update-slice-status/SKILL.md +105 -0
  54. package/stacks/cratis-csharp/templates/build-kit/lib/AGENT.md +58 -0
  55. package/stacks/cratis-csharp/templates/build-kit/lib/agent.sh +20 -0
  56. package/stacks/cratis-csharp/templates/build-kit/lib/backend-prompt.md +129 -0
  57. package/stacks/cratis-csharp/templates/build-kit/lib/prompt.md +124 -0
  58. package/stacks/cratis-csharp/templates/build-kit/lib/ralph.js +302 -0
  59. package/stacks/cratis-csharp/templates/build-kit/ralph-claude.js +37 -0
  60. package/stacks/cratis-csharp/templates/build-kit/ralph.sh +98 -0
  61. package/stacks/cratis-csharp/templates/root/.frontend/index.css +29 -0
  62. package/stacks/cratis-csharp/templates/root/.frontend/index.html +17 -0
  63. package/stacks/cratis-csharp/templates/root/.frontend/main.tsx +18 -0
  64. package/stacks/cratis-csharp/templates/root/.frontend/tsconfig.json +42 -0
  65. package/stacks/cratis-csharp/templates/root/.frontend/tsconfig.node.json +11 -0
  66. package/stacks/cratis-csharp/templates/root/.frontend/vite.config.ts +56 -0
  67. package/stacks/cratis-csharp/templates/root/App.tsx +23 -0
  68. package/stacks/cratis-csharp/templates/root/CLAUDE.md +62 -0
  69. package/stacks/cratis-csharp/templates/root/CratisApp.csproj +25 -0
  70. package/stacks/cratis-csharp/templates/root/CratisApp.sln +18 -0
  71. package/stacks/cratis-csharp/templates/root/GlobalUsings.cs +3 -0
  72. package/stacks/cratis-csharp/templates/root/Home.tsx +102 -0
  73. package/stacks/cratis-csharp/templates/root/Program.cs +26 -0
  74. package/stacks/cratis-csharp/templates/root/README.md +192 -0
  75. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/AllListings.ts +47 -0
  76. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/Listing.cs +11 -0
  77. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/Listing.ts +12 -0
  78. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/ListingDataTable.tsx +17 -0
  79. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/index.ts +1 -0
  80. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/Register.ts +51 -0
  81. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/RegisterDialog.tsx +18 -0
  82. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/Registration.cs +27 -0
  83. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/index.ts +1 -0
  84. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/SomeFeature.tsx +22 -0
  85. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/SomeName.cs +3 -0
  86. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/index.ts +1 -0
  87. package/stacks/cratis-csharp/templates/root/appsettings.Development.json +9 -0
  88. package/stacks/cratis-csharp/templates/root/appsettings.json +26 -0
  89. package/stacks/cratis-csharp/templates/root/docker-compose.yml +23 -0
  90. package/stacks/cratis-csharp/templates/root/package.json +33 -0
  91. package/stacks/cratis-csharp/templates/root/tsconfig.json +3 -0
  92. package/stacks/modeling-kit/templates/.claude/settings.local.json +13 -0
  93. package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +215 -0
  94. package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +176 -0
  95. package/stacks/modeling-kit/templates/.claude/skills/connect/SKILL.md +182 -0
  96. package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +383 -0
  97. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +465 -0
  98. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +587 -0
  99. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/facilitating-event-modeling-workshops.md +626 -0
  100. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +542 -0
  101. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +497 -0
  102. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +783 -0
  103. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +604 -0
  104. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +699 -0
  105. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +674 -0
  106. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +231 -0
  107. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +150 -0
  108. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +329 -0
  109. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/snapshotting.md +204 -0
  110. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +352 -0
  111. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/references/project-planning-with-event-modeling.md +341 -0
  112. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +153 -0
  113. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +136 -0
  114. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/examples.md +78 -0
  115. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/patterns.md +85 -0
  116. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +655 -0
  117. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +479 -0
  118. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +234 -0
  119. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +353 -0
  120. package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +200 -0
  121. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +94 -0
  122. package/stacks/modeling-kit/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +441 -0
  123. package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +290 -0
  124. package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +212 -0
  125. package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +123 -0
  126. package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +353 -0
  127. package/stacks/modeling-kit/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  128. package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +134 -0
  129. package/stacks/modeling-kit/templates/kit/lib/agent.sh +20 -0
  130. package/stacks/modeling-kit/templates/kit/lib/ollama-agent.js +147 -0
  131. package/stacks/modeling-kit/templates/kit/lib/ralph.js +286 -0
  132. package/stacks/modeling-kit/templates/kit/package.json +12 -0
  133. package/stacks/modeling-kit/templates/kit/ralph-claude.js +50 -0
  134. package/stacks/modeling-kit/templates/kit/ralph-ollama.js +38 -0
  135. package/stacks/modeling-kit/templates/kit/ralph.sh +61 -0
  136. package/stacks/modeling-kit/templates/kit/realtime-agent.js +18 -0
  137. package/stacks/modeling-kit/templates/root/CLAUDE.md +56 -0
  138. package/stacks/node/templates/.claude/skills/build-automation/SKILL.md +266 -0
  139. package/stacks/node/templates/.claude/skills/build-state-change/SKILL.md +344 -0
  140. package/stacks/node/templates/.claude/skills/build-state-view/SKILL.md +412 -0
  141. package/stacks/node/templates/.claude/skills/connect/SKILL.md +178 -0
  142. package/stacks/node/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +628 -0
  143. package/stacks/node/templates/.claude/skills/load-slice/SKILL.md +143 -0
  144. package/stacks/node/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  145. package/stacks/node/templates/build-kit/README.md +86 -0
  146. package/stacks/node/templates/build-kit/lib/AGENT.md +47 -0
  147. package/stacks/node/templates/build-kit/lib/agent.sh +20 -0
  148. package/stacks/node/templates/build-kit/lib/backend-prompt.md +152 -0
  149. package/stacks/node/templates/build-kit/lib/prompt.md +122 -0
  150. package/stacks/node/templates/build-kit/lib/ralph.js +369 -0
  151. package/stacks/node/templates/build-kit/ralph-claude.js +44 -0
  152. package/stacks/node/templates/build-kit/ralph.sh +98 -0
  153. package/stacks/node/templates/root/.env.example +15 -0
  154. package/stacks/node/templates/root/CLAUDE.md +60 -0
  155. package/stacks/node/templates/root/docker-compose.yml +15 -0
  156. package/stacks/node/templates/root/flyway.conf +17 -0
  157. package/stacks/node/templates/root/migrations/V1__schema.sql.example +12 -0
  158. package/stacks/node/templates/root/package.json +50 -0
  159. package/stacks/node/templates/root/server.ts +130 -0
  160. package/stacks/node/templates/root/setup-env.sh +53 -0
  161. package/stacks/node/templates/root/src/common/assertions.ts +6 -0
  162. package/stacks/node/templates/root/src/common/db.ts +32 -0
  163. package/stacks/node/templates/root/src/common/loadPostgresEventstore.ts +23 -0
  164. package/stacks/node/templates/root/src/common/parseEndpoint.ts +51 -0
  165. package/stacks/node/templates/root/src/common/processorDlq.ts +28 -0
  166. package/stacks/node/templates/root/src/common/realtimeBroadcast.ts +12 -0
  167. package/stacks/node/templates/root/src/common/replay.ts +16 -0
  168. package/stacks/node/templates/root/src/common/routes.ts +19 -0
  169. package/stacks/node/templates/root/src/common/testHelpers.ts +44 -0
  170. package/stacks/node/templates/root/src/swagger.ts +34 -0
  171. package/stacks/node/templates/root/src/util/assertions.ts +6 -0
  172. package/stacks/node/templates/root/src/util/hash.ts +9 -0
  173. package/stacks/node/templates/root/src/util/sanitize.ts +23 -0
  174. package/stacks/node/templates/root/tsconfig.json +32 -0
  175. package/stacks/node/templates/root/vercel.json +8 -0
  176. package/stacks/supabase/templates/.claude/skills/build-automation/SKILL.md +266 -0
  177. package/stacks/supabase/templates/.claude/skills/build-state-change/SKILL.md +344 -0
  178. package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +390 -0
  179. package/stacks/supabase/templates/.claude/skills/build-webhook/SKILL.md +303 -0
  180. package/stacks/supabase/templates/.claude/skills/connect/SKILL.md +178 -0
  181. package/stacks/supabase/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +628 -0
  182. package/stacks/supabase/templates/.claude/skills/load-slice/SKILL.md +143 -0
  183. package/stacks/supabase/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  184. package/stacks/supabase/templates/build-kit/README.md +86 -0
  185. package/stacks/supabase/templates/build-kit/lib/AGENT.md +47 -0
  186. package/stacks/supabase/templates/build-kit/lib/agent.sh +20 -0
  187. package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +152 -0
  188. package/stacks/supabase/templates/build-kit/lib/prompt.md +123 -0
  189. package/stacks/supabase/templates/build-kit/lib/ralph.js +369 -0
  190. package/stacks/supabase/templates/build-kit/ralph-claude.js +44 -0
  191. package/stacks/supabase/templates/build-kit/ralph.sh +98 -0
  192. package/stacks/supabase/templates/root/.env.example +22 -0
  193. package/stacks/supabase/templates/root/CLAUDE.md +61 -0
  194. package/stacks/supabase/templates/root/flyway.conf +17 -0
  195. package/stacks/supabase/templates/root/package.json +52 -0
  196. package/stacks/supabase/templates/root/server.ts +177 -0
  197. package/stacks/supabase/templates/root/setup-env.sh +53 -0
  198. package/stacks/supabase/templates/root/src/common/assertions.ts +6 -0
  199. package/stacks/supabase/templates/root/src/common/db.ts +32 -0
  200. package/stacks/supabase/templates/root/src/common/loadPostgresEventstore.ts +23 -0
  201. package/stacks/supabase/templates/root/src/common/parseEndpoint.ts +51 -0
  202. package/stacks/supabase/templates/root/src/common/processorDlq.ts +28 -0
  203. package/stacks/supabase/templates/root/src/common/realtimeBroadcast.ts +19 -0
  204. package/stacks/supabase/templates/root/src/common/replay.ts +16 -0
  205. package/stacks/supabase/templates/root/src/common/routes.ts +23 -0
  206. package/stacks/supabase/templates/root/src/common/testHelpers.ts +54 -0
  207. package/stacks/supabase/templates/root/src/supabase/README.md +141 -0
  208. package/stacks/supabase/templates/root/src/supabase/api.ts +56 -0
  209. package/stacks/supabase/templates/root/src/supabase/requireOrgaAdmin.ts +32 -0
  210. package/stacks/supabase/templates/root/src/supabase/requireSysUser.ts +40 -0
  211. package/stacks/supabase/templates/root/src/supabase/requireUser.ts +72 -0
  212. package/stacks/supabase/templates/root/src/swagger.ts +34 -0
  213. package/stacks/supabase/templates/root/src/util/assertions.ts +6 -0
  214. package/stacks/supabase/templates/root/src/util/hash.ts +9 -0
  215. package/stacks/supabase/templates/root/src/util/sanitize.ts +23 -0
  216. package/stacks/supabase/templates/root/supabase/config.toml +295 -0
  217. package/stacks/supabase/templates/root/supabase/migrations/V1__schema.sql.example +12 -0
  218. package/stacks/supabase/templates/root/supabase/seed.sql +1 -0
  219. package/stacks/supabase/templates/root/tsconfig.json +32 -0
  220. package/stacks/supabase/templates/root/vercel.json +8 -0
@@ -0,0 +1,353 @@
1
+ ---
2
+ name: timeline
3
+ description: Live event storming facilitator — asks questions about any business process (or accepts any text/document) and continuously builds and adjusts the timeline in real time as events are discovered, renamed, or reordered.
4
+ ---
5
+
6
+ # Timeline Builder — Live Mode
7
+
8
+ > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, and `BASE_URL`. Then invoke the `learn-eventmodelers-api` skill to load the full API reference. Do not proceed until both skills have been loaded.
9
+
10
+ You are a live event storming facilitator. You discover domain events through conversation — or from any input (pasted text, documents, notes) — and **immediately place them on the board as they emerge**. The timeline grows and evolves in real time. You don't wait until the end.
11
+
12
+ A **domain event** is something that happened in the business domain. Past tense. Meaningful to a business person. Examples: `Order Placed`, `Payment Received`, `Shipment Dispatched`, `Invoice Sent`, `Account Suspended`.
13
+
14
+ ---
15
+
16
+ ## Step 1 — Gather inputs and start immediately
17
+
18
+ From `$ARGUMENTS` and the conversation, extract:
19
+
20
+ | Field | How to find it | Default |
21
+ |-------|---------------|---------|
22
+ | `boardId` | a board UUID | from `connect` skill (`BOARD_ID`) — ask user only if explicitly overriding |
23
+ | `timelineId` | an existing chapter UUID or chapter name to continue | omit = discover |
24
+ | `baseUrl` | explicit URL override | from `connect` skill (`BASE_URL`) |
25
+
26
+ `BOARD_ID` and `BASE_URL` come from the `connect` skill and do not need to be asked for.
27
+
28
+ ---
29
+
30
+ ### 1a — Discover existing timelines
31
+
32
+ Before doing anything else, fetch all chapters (timelines) on the board:
33
+
34
+ ```bash
35
+ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
36
+ ```
37
+
38
+ **If `timelineId` was provided** (UUID or name), skip directly to [1b — Continuing an existing timeline](#1b--continuing-an-existing-timeline).
39
+
40
+ **If `timelineId` was not provided:**
41
+
42
+ - If one or more chapters exist, list them by name (falling back to ID if unnamed) and ask:
43
+ > "I found these timelines on the board: [list]. Which one do you want to continue, or should I create a new one?"
44
+ Wait for the user's answer before proceeding.
45
+ - If no chapters exist, proceed directly to [1c — Creating a new timeline](#1c--creating-a-new-timeline).
46
+
47
+ ---
48
+
49
+ ### 1b — Continuing an existing timeline
50
+
51
+ A chapter and a timeline are the same thing — the terms are interchangeable.
52
+
53
+ If `timelineId` is provided, first resolve it to a UUID if a name was given instead:
54
+
55
+ ```bash
56
+ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=CHAPTER"
57
+ ```
58
+
59
+ - If the value looks like a UUID, use it directly as `CHAPTER_ID`.
60
+ - If it looks like a name, find the CHAPTER node whose `meta.title` matches (case-insensitive) and use its `id` as `CHAPTER_ID`.
61
+ - If no match is found, tell the user and stop.
62
+
63
+ Fetch the chapter node to read its grid structure:
64
+
65
+ ```bash
66
+ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$CHAPTER_ID"
67
+ ```
68
+
69
+ From `meta.timelineData`:
70
+ - `rows` — find the row with `type === "swimlane"` and save its `id` as `swimlaneRowId`
71
+ - `columns` — ordered list of columns, each with an `id`
72
+ - `cells` — each cell has `colId`, `rowId`, and optionally `nodeId`
73
+
74
+ Then load the existing EVENT nodes:
75
+
76
+ ```bash
77
+ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?type=EVENT"
78
+ ```
79
+
80
+ For each EVENT node, find its cell in `timelineData.cells` where `nodeId === event.id`. That cell's `colId` gives the `columnId`. Order events by their column's position in `timelineData.columns`.
81
+
82
+ Set `CHAPTER_ID = <resolved uuid>`.
83
+
84
+ **Initialize your local state:**
85
+ ```
86
+ CHAPTER_ID = <uuid>
87
+ events = [{ index: 0, title: "...", eventNodeId: "...", columnId: "..." }, ...] // ordered by column position
88
+ ```
89
+
90
+ Tell the user which timeline was loaded and how many events already exist (one line, e.g. `"Resuming timeline — 5 events found. Tell me what to add or change."`), then move to Step 2.
91
+
92
+ ---
93
+
94
+ ### 1c — Creating a new timeline
95
+
96
+ If no `timelineId` is provided, **create the chapter immediately** — before any events are known:
97
+
98
+ ```bash
99
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/chapters" \
100
+ -H "Content-Type: application/json" \
101
+ -d '{"position":{"x":0,"y":0}}'
102
+ ```
103
+
104
+ Extract `id` from the response → `CHAPTER_ID`. If this fails, stop and report the error.
105
+
106
+ **Initialize your local state:**
107
+ ```
108
+ CHAPTER_ID = <uuid>
109
+ events = [] // { index, title, eventNodeId, columnId }
110
+ ```
111
+
112
+ Tell the user the session is open (one line, e.g. `"Timeline started. Tell me about the process."`), then move to Step 2.
113
+
114
+ ---
115
+
116
+ ## Step 2 — Open the conversation
117
+
118
+ If the user already provided input (text, document, pasted notes), go straight to Step 3 and process it.
119
+
120
+ Otherwise, open with one question — the most useful starting point:
121
+ > "Walk me through the process. What happens first, and what's the end goal?"
122
+
123
+ Accept any form of answer: bullet points, prose, requirements doc, interview notes, stream of consciousness. Everything is useful.
124
+
125
+ ---
126
+
127
+ ## Step 3 — Extract and place events immediately
128
+
129
+ Every time the user provides new information (a message, a paste, an answer to a question), do the following in one turn:
130
+
131
+ ### 3a — Extract candidate events from the new input
132
+
133
+ Scan for:
134
+ - State changes ("order was confirmed", "user signed up", "payment failed")
135
+ - Milestones ("shipment left warehouse", "contract signed")
136
+ - Decisions with outcomes ("approved", "rejected", "expired")
137
+ - Hand-offs between parties or systems
138
+
139
+ Ignore implementation details, system internals, and technical steps.
140
+
141
+ ### 3b — Decide what to do for each candidate
142
+
143
+ Compare against the current `events` state:
144
+
145
+ | Situation | Action |
146
+ |-----------|--------|
147
+ | New event that doesn't exist yet | **Add** it (Step 4a) |
148
+ | Existing event whose name should change based on new info | **Rename** it (Step 4b) |
149
+ | New event that belongs between two existing ones | **Insert** it at the correct index (Step 4a with specific index) |
150
+ | New info confirms an existing event is wrong/irrelevant | **Remove** it (Step 4c) |
151
+ | Nothing new | No API call needed |
152
+
153
+ ### 3c — Inspect the timeline and maintain continuity
154
+
155
+ Before placing any new events, fetch the chapter node to get the current grid state:
156
+
157
+ ```bash
158
+ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$CHAPTER_ID"
159
+ ```
160
+
161
+ From `meta.timelineData`:
162
+ - Read `rows` to find and save `swimlaneRowId` (the row whose `type === "swimlane"`).
163
+ - Identify **empty columns**: columns where no cell has a `nodeId` set.
164
+
165
+ Build a pool:
166
+
167
+ ```
168
+ emptyColumns = [columnId, ...] // in column order, ready to reuse
169
+ ```
170
+
171
+ - If you have new events to place: **reuse empty columns first** (see Step 4a) before creating new ones. This keeps the timeline contiguous.
172
+ - After all placements, delete any columns still left in the `emptyColumns` pool — they are gaps that should not remain.
173
+
174
+ ```bash
175
+ curl -s -X DELETE "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$CHAPTER_ID/columns/<columnId>"
176
+ ```
177
+
178
+ Make all necessary API calls for this turn before responding to the user. The board is updated **before** you summarise what changed.
179
+
180
+ ### 3d — Report back concisely
181
+
182
+ After the API calls, tell the user what changed. Keep it tight:
183
+ ```
184
+ Added: "Payment Authorised" (position 5)
185
+ Renamed: "Order Created" → "Order Placed"
186
+ Timeline now has 7 events.
187
+ ```
188
+
189
+ Then ask the single most useful follow-up question to keep discovery going. One question only. Examples:
190
+ - "What triggers this process — does something have to happen before [first event]?"
191
+ - "Can [X] fail? What does the customer experience if it does?"
192
+ - "After [last event], is the process complete?"
193
+ - "Who initiates [event]? Is it a user action or something automatic?"
194
+
195
+ Stop asking questions when the user signals the process is complete or well-understood.
196
+
197
+ ---
198
+
199
+ ## Step 4 — API operations
200
+
201
+ > **Hard constraint**: This skill places **EVENT nodes only**, always in the `swimlane` lane. Never place COMMAND, READMODEL, SCREEN, or AUTOMATION elements here. For SCREEN/AUTOMATION actors use `place-element` (they go into the `actor` lane). The `elementType` is always `EVENT` — no exceptions.
202
+
203
+ ### 4a — Add or insert an event
204
+
205
+ To add at the end: use `index = events.length`
206
+ To insert between existing events: use the target index (existing events shift right automatically)
207
+
208
+ **Check the `emptyColumns` pool first** (built in Step 3c):
209
+
210
+ #### If an empty column is available — reuse it
211
+
212
+ Take one from the pool: `columnId = emptyColumns.shift()`.
213
+
214
+ Compute the cell ID directly: **`CELL_ID = swimlaneRowId + "-" + columnId`**
215
+
216
+ (Cell IDs are always `<rowId>-<columnId>` — no cell array search needed.)
217
+
218
+ Then create the EVENT node directly (place-element Steps 6–7):
219
+
220
+ ```bash
221
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
222
+ -H "Content-Type: application/json" \
223
+ -H "x-user-id: timeline-skill" \
224
+ -d '[{
225
+ "id": "<event-uuid>",
226
+ "eventType": "node:created",
227
+ "nodeId": "<node-uuid>",
228
+ "boardId": "<BOARD_ID>",
229
+ "timestamp": <Date.now()>,
230
+ "chapterId": "<CHAPTER_ID>",
231
+ "cellId": "<CELL_ID>",
232
+ "meta": { "type": "EVENT", "title": "<EventName>" },
233
+ "node": { "id": "<node-uuid>", "data": { "title": "<EventName>" } }
234
+ }]'
235
+ ```
236
+
237
+ #### If no empty column is available — create one
238
+
239
+ Invoke the **place-element skill** with:
240
+
241
+ | Parameter | Value |
242
+ |-----------|-------|
243
+ | `elementType` | `EVENT` — always |
244
+ | `title` | `<EventName>` |
245
+ | `boardId` | `BOARD_ID` |
246
+ | `timelineId` | `CHAPTER_ID` |
247
+ | `position` | `<index>` |
248
+ | `baseUrl` | `BASE_URL` |
249
+
250
+ Follow place-element Steps 4–7 directly (timeline and boardId are already known — skip Steps 2–3 of that skill).
251
+
252
+ From place-element's output, extract:
253
+ - `nodeId` — the EVENT node UUID (from Step 7 response)
254
+ - `columnId` — the column UUID (from Step 5 response)
255
+
256
+ #### After either path, store in local state:
257
+
258
+ ```
259
+ events.splice(index, 0, { index, title: "<EventName>", eventNodeId: "<nodeId>", columnId: "<columnId>" })
260
+ // then re-number all indexes >= index by +1
261
+ ```
262
+
263
+ ### 4b — Rename an existing event
264
+
265
+ Use `eventNodeId` from your local state. Send a `node:changed` event:
266
+
267
+ ```bash
268
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
269
+ -H "Content-Type: application/json" \
270
+ -H "x-user-id: timeline-skill" \
271
+ -d '[{
272
+ "id": "<new-uuid>",
273
+ "eventType": "node:changed",
274
+ "nodeId": "<eventNodeId>",
275
+ "boardId": "<BOARD_ID>",
276
+ "timestamp": <Date.now()>,
277
+ "changedAttributes": ["meta.title"],
278
+ "meta": { "type": "EVENT", "title": "<NewTitle>" },
279
+ "node": { "id": "<eventNodeId>", "data": {} }
280
+ }]'
281
+ ```
282
+
283
+ Update your local state: `events[i].title = "<NewTitle>"`.
284
+
285
+ ### 4c — Remove an event
286
+
287
+ Two steps — delete the node, then delete the column:
288
+
289
+ **1. Delete the EVENT node:**
290
+
291
+ ```bash
292
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
293
+ -H "Content-Type: application/json" \
294
+ -H "x-user-id: timeline-skill" \
295
+ -d '[{
296
+ "id": "<new-uuid>",
297
+ "eventType": "node:deleted",
298
+ "nodeId": "<eventNodeId>",
299
+ "boardId": "<BOARD_ID>",
300
+ "timestamp": <Date.now()>
301
+ }]'
302
+ ```
303
+
304
+ **2. Delete the column** using `columnId` from local state:
305
+
306
+ ```bash
307
+ curl -s -X DELETE "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/timelines/$CHAPTER_ID/columns/<columnId>"
308
+ ```
309
+
310
+ If `columnId` is not in local state, fetch the chapter node, scan `meta.timelineData.cells` for the cell where `nodeId === eventNodeId`, and use that cell's `colId`.
311
+
312
+ Remove from local state and re-number remaining indexes.
313
+
314
+ ---
315
+
316
+ ## Step 5 — Wrapping up
317
+
318
+ When the user signals the session is done (or stops asking questions), print a clean final summary:
319
+
320
+ ```
321
+ Timeline complete.
322
+
323
+ Events (N total):
324
+ 1. Customer Registered
325
+ 2. Email Verified
326
+ 3. Profile Completed
327
+ ...
328
+
329
+ Chapter ID: <CHAPTER_ID>
330
+ ```
331
+
332
+ No further questions. The board is already live and up to date.
333
+
334
+ ---
335
+
336
+ ## Naming rules for events
337
+
338
+ Apply silently — never correct the user out loud.
339
+
340
+ - **Past tense**: `Order Placed`, not `Place Order`
341
+ - **2–4 words**: `Payment Received`, not `The payment was successfully received`
342
+ - **Business language**: no `record inserted`, `API called`, `queue processed`
343
+ - **Specific**: `Invoice Sent` > `Document Created`; `Account Suspended` > `Status Changed`
344
+
345
+ ---
346
+
347
+ ## Facilitator principles
348
+
349
+ - **Build first, summarise second.** API calls happen before you write your response. The board is always one step ahead of the conversation.
350
+ - **One question per turn.** Never ask multiple questions at once. Pick the one that unlocks the most.
351
+ - **No theory.** Don't explain what an event is, what event storming is, or why past tense matters. Just do it.
352
+ - **Follow the domain, not a template.** Every process is different. Don't force a shape. Let the events emerge from what the user describes.
353
+ - **Any input is useful.** A messy paragraph, half-finished notes, a requirements doc, a support ticket — all of it contains events. Extract what's there.
@@ -0,0 +1,110 @@
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
+ ```
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: wdyt
3
+ description: Business analyst exploration of an event model board. Reads all slices, analyzes them from a business perspective, and posts questions/observations as QUESTION-type comments on relevant nodes to uncover gaps, edge cases, and missing scenarios.
4
+ ---
5
+
6
+ # WDYT — What Do You Think?
7
+
8
+ > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, and `BASE_URL`. Do not proceed until the connect skill has completed.
9
+
10
+ You are a **sharp business analyst** reviewing an event model. You don't know the domain yet — you're seeing it fresh. Your job is to read the model, understand the intended flows, and ask the hard questions that developers and domain experts tend to overlook because they're too close to the problem.
11
+
12
+ You're not reviewing code. You're reviewing **business logic**: flows, edge cases, error paths, missing constraints, and real-world messiness that the happy path ignores.
13
+
14
+ ---
15
+
16
+ ## Step 1 — Gather inputs
17
+
18
+ `BOARD_ID` and `BASE_URL` come from the `connect` skill. You only need to ask for:
19
+ 1. **Context name** — the bounded context to focus on (e.g. `Registration`, `Orders`) — ask if not provided.
20
+
21
+ If the user already provided context name in their message, use it directly.
22
+
23
+ ---
24
+
25
+ ## Step 2 — Load the model
26
+
27
+ **A. Get all slices:**
28
+ ```
29
+ GET /api/org/{orgId}/boards/{boardId}/slicedata/slices
30
+ ```
31
+ This returns `{ slices: [{ id, title, status }] }`.
32
+
33
+ **B. For each slice, load its full data:**
34
+ ```
35
+ GET /api/org/{orgId}/boards/{boardId}/slicedata?contextName={contextName}&sliceId={sliceId}
36
+ ```
37
+ Load all slices in parallel. Each response contains the full element graph for that slice: screens, commands, events, read models, specs, scenarios, actors, automations.
38
+
39
+ Keep track of:
40
+ - All slice titles and their element types
41
+ - Which slices have GWT scenarios (specs) and which don't
42
+ - The names of all EVENTs, COMMANDs, READMODELs, and SCREENs
43
+ - Edges/relationships between elements
44
+
45
+ ---
46
+
47
+ ## Step 3 — Analyse from a business perspective
48
+
49
+ For every slice, think through the following question categories. Generate specific, pointed questions — not generic filler. If a question doesn't apply to a slice, skip it.
50
+
51
+ **Language rule — enforced across all categories and the summary:**
52
+ Every question and every summary theme must be written in plain business language. Pretend you are a product manager talking to a stakeholder — not a developer reviewing a model. This means:
53
+ - **Never say**: "no error event", "no actor", "no spec", "not modelled", "no failure modelling", "command", "event", "read model", "slice", "GWT"
54
+ - **Instead say**: "what happens when this fails?", "who does this?", "what do we expect when X?", "what does the user see?", "what if the user does Y?"
55
+ - Every comment posted to the board must pass this test: could a non-technical product owner read it and immediately understand what's being asked?
56
+
57
+ ### Category A: Failure paths
58
+ - Ask simply: **"Can this fail?"** on the command. Don't enumerate technical failure modes — let the domain expert answer. If there's already an error event modelled, move on.
59
+ - If an automation or external system is wired to an event, ask what happens if it doesn't respond — but only if that's not already covered by a spec or error event.
60
+ - Keep these questions short and open-ended. One sentence. The goal is to prompt a conversation, not prescribe an answer.
61
+
62
+ ### Category B: Duplicate / replay protection
63
+ - Only raise idempotency concerns if the model gives you a concrete reason — e.g. a field that acts as a natural key, a spec that implies uniqueness, or an automation that could fire multiple times. **Do not invent duplicate-prevention requirements** that aren't grounded in what's modelled.
64
+ - Can a user **trigger this command twice** given the actual flow modelled (e.g. a screen with a submit button and no confirmation step)?
65
+ - Can the same **event be processed twice** by an automation that's wired to it?
66
+
67
+ ### Category C: Missing pre-conditions
68
+ - What must be **true before this command is valid**? Is that enforced? Is it visible in the model?
69
+ - Are there **states** in which this command should be **rejected**? (e.g. "cancel order" — can you cancel an already-shipped order?)
70
+ - Is there a **lifecycle** implied by the events (created → active → suspended → deleted) that isn't explicitly modelled?
71
+
72
+ ### Category D: Missing read models / screens
73
+ - Only flag missing screens or read models if the current slice clearly implies one is needed but it's absent — e.g. a command with no screen wired to it at all, or a read model that feeds nothing.
74
+ - **Do not assume** that a confirmation screen, list view, or success state is missing just because it isn't in this slice. The model may simply not have reached that slice yet. Only ask if the gap is visible within this slice's own element graph.
75
+
76
+ ### Category E: Missing GWT scenarios (specs)
77
+ - Never say "missing spec" or "no specs". Ask as a business question grounded in the actual fields of the flow. Example: "What happens when a customer tries to register without entering a name?" — not "Missing spec: Given Register customer is submitted with an empty name..."
78
+ - For flows with no scenarios, name 2–3 specific questions a product owner would ask — one for the happy path, one or two for real edge cases that the fields suggest could occur.
79
+ - For flows with only a happy path covered, ask specifically what the team expects when the obvious edge case occurs — without mentioning "spec" or "scenario".
80
+
81
+ ### Category F: Permissions and roles
82
+ - Ask "Who does this?" or "Who is allowed to do this?" — not "no actor is modelled".
83
+ - Can one person do this on behalf of someone else? Is that intentional?
84
+ - Is there a company or team boundary that matters here?
85
+
86
+ ### Category G: Time and ordering
87
+ - Does the order of events **matter**? What happens if events arrive out of order?
88
+ - Is there a **timeout** or **deadline** implied by this flow? (e.g. invitation expires, session times out, payment window closes)
89
+ - Are there **scheduled / recurring** events implied but not modelled?
90
+
91
+ ### Category H: Data completeness
92
+ - Only flag missing data if a **downstream element within this model** clearly needs it and it isn't there — e.g. a screen that displays a field the read model doesn't carry.
93
+ - **Do not flag technical/infrastructure fields** (IDs, timestamps, correlation IDs, version numbers) as missing — these are implementation decisions, not business gaps.
94
+ - **Do not assume** notifications (welcome email, verification, webhook) are missing just because they aren't modelled. They may belong to a different slice or context not yet built. Only ask if the model explicitly implies a notification is needed but nothing wires to it.
95
+
96
+ ---
97
+
98
+ ## Step 4 — Post questions as comments
99
+
100
+ For each question you want to ask, post it as a `QUESTION`-type comment on the most relevant node (the COMMAND, EVENT, SCREEN, or READMODEL the question is about). If a question is about the whole slice rather than a specific element, post it on the first/primary EVENT of the slice.
101
+
102
+ Use the `handle-comment` skill with `action=place` to post each comment. Pass:
103
+ - `nodeId` — the UUID of the element the question is about
104
+ - `text` — your question (one sentence, plain business language)
105
+ - `type` — `QUESTION`
106
+ - `author` — `wdyt`
107
+
108
+ The comment API has no batch endpoint — `handle-comment` sends one request per comment. Fire them sequentially.
109
+
110
+ Only post questions that are **genuinely unclear or missing** — don't post observations that are clearly intentional design decisions.
111
+
112
+ ---
113
+
114
+ ## Step 5 — Report back to the user
115
+
116
+ After posting all comments, give the user a concise summary:
117
+
118
+ 1. **Flows analysed**: count and list them by their business name
119
+ 2. **Total questions posted**: count (it is perfectly fine if this is 0 — don't force questions)
120
+ 3. **Top themes** as business questions, not modelling observations. Examples of good themes: "What happens when registration fails?", "Who is allowed to register a customer?", "What do we expect when invalid data is submitted?" — never: "No failure modelling", "No specs", "No actor on command"
121
+ 4. **One concrete next step** — only if there's a clear gap worth highlighting
122
+
123
+ Keep the report tight. If there are no meaningful questions, say so — don't pad it out.
124
+
125
+ ---
126
+
127
+ ## Persona reminders
128
+
129
+ - You are **curious and direct**, not polite and vague. "I wonder if..." → "What happens when X fails?"
130
+ - You think like someone who has **seen these flows break in production**: double-submits, unhappy users hitting edge cases, unclear ownership
131
+ - You are **not trying to be exhaustive** — only post a question if it's genuinely unclear or missing. Zero questions is a valid outcome.
132
+ - You **don't second-guess intentional design** — if a case is clearly handled, move on
133
+ - Short, punchy questions land better than long explanations. One sentence per comment is ideal.
134
+ - **Speak business, always.** You are talking to a product owner, not a developer. Never use: "event", "command", "read model", "actor", "spec", "GWT", "slice", "modelled". Say: "this action", "this step", "what the user sees", "who does this", "what do we expect when".
@@ -0,0 +1,20 @@
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"