@eventmodelers/cli 1.0.162 → 2.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 (104) hide show
  1. package/README.md +22 -27
  2. package/RELEASE_NOTES.md +20 -2
  3. package/cli.js +461 -225
  4. package/lib/adapters/spec-kitty-adapter.js +3 -7
  5. package/lib/global-agent-id.js +45 -0
  6. package/lib/modeling-local-ai.js +4 -2
  7. package/package.json +1 -1
  8. package/shared/build-kit/README.md +4 -19
  9. package/shared/build-kit/lib/agent-lock.js +75 -0
  10. package/shared/build-kit/lib/agent-name.js +27 -0
  11. package/shared/build-kit/lib/event-prune.js +58 -0
  12. package/shared/build-kit/lib/events-view.js +121 -0
  13. package/shared/build-kit/lib/local-ai-agent.js +14 -26
  14. package/shared/build-kit/lib/mcp-register.js +17 -1
  15. package/shared/build-kit/lib/prompt-journal.js +191 -0
  16. package/shared/build-kit/lib/prompt-replay.js +35 -0
  17. package/shared/build-kit/lib/ralph.js +250 -163
  18. package/shared/build-kit/lib/slice-curation.js +40 -0
  19. package/shared/build-kit/lib/slice-events.js +93 -0
  20. package/shared/build-kit/lib/slice-git.js +86 -0
  21. package/shared/build-kit/lib/slice-learnings.js +197 -0
  22. package/shared/build-kit/lib/slice-projection.js +101 -0
  23. package/shared/build-kit/lib/slice-run.js +181 -0
  24. package/shared/build-kit/lib/slice-state.js +182 -0
  25. package/shared/build-kit/lib/slice-tasks.js +35 -0
  26. package/shared/build-kit/ralph-claude.js +4 -2
  27. package/shared/build-kit/ralph-exec.js +4 -2
  28. package/shared/build-kit/ralph-local-ai.js +5 -3
  29. package/shared/skills/connect/SKILL.md +1 -5
  30. package/shared/skills/learn-eventmodelers-api/SKILL.md +13 -0
  31. package/shared/skills/request-feedback/SKILL.md +1 -2
  32. package/shared/skills/ui-contract/SKILL.md +5 -3
  33. package/stacks/axon/templates/build-kit/CLAUDE.md +3 -3
  34. package/stacks/axon/templates/build-kit/lib/AGENT.md +6 -7
  35. package/stacks/axon/templates/build-kit/lib/backend-prompt.md +20 -42
  36. package/stacks/axon/templates/build-kit/lib/prompt.md +18 -41
  37. package/stacks/blank/templates/build-kit/CLAUDE.md +3 -3
  38. package/stacks/blank/templates/build-kit/lib/AGENT.md +6 -7
  39. package/stacks/blank/templates/build-kit/lib/backend-prompt.md +20 -37
  40. package/stacks/blank/templates/build-kit/lib/prompt.md +19 -42
  41. package/stacks/classic/templates/.claude/skills/build-automation/SKILL.md +1 -1
  42. package/stacks/classic/templates/.claude/skills/build-state-change/SKILL.md +1 -1
  43. package/stacks/classic/templates/.claude/skills/build-state-view/SKILL.md +2 -2
  44. package/stacks/classic/templates/.claude/skills/record-evidence/SKILL.md +2 -2
  45. package/stacks/classic/templates/build-kit/CLAUDE.md +3 -3
  46. package/stacks/classic/templates/build-kit/lib/AGENT.md +6 -7
  47. package/stacks/classic/templates/build-kit/lib/backend-prompt.md +20 -38
  48. package/stacks/classic/templates/build-kit/lib/prompt.md +19 -42
  49. package/stacks/kurrent/templates/build-kit/CLAUDE.md +3 -4
  50. package/stacks/kurrent/templates/build-kit/lib/AGENT.md +6 -7
  51. package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +20 -42
  52. package/stacks/kurrent/templates/build-kit/lib/prompt.md +18 -41
  53. package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +1 -17
  54. package/stacks/modeling-kit/templates/.claude/skills/detect-model-drift/SKILL.md +1 -1
  55. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-core-rules/SKILL.md +2 -0
  56. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +7 -3
  57. package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +0 -8
  58. package/stacks/modeling-kit/templates/.claude/skills/stressor-analysis/SKILL.md +0 -2
  59. package/stacks/modeling-kit/templates/.claude/skills/walkthrough/SKILL.md +1 -1
  60. package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +1 -1
  61. package/stacks/modeling-kit/templates/kit/AGENTS.md +0 -1
  62. package/stacks/modeling-kit/templates/kit/CLAUDE-STANDALONE.md +3 -4
  63. package/stacks/modeling-kit/templates/kit/CLAUDE.md +11 -72
  64. package/stacks/modeling-kit/templates/kit/README.md +1 -1
  65. package/stacks/modeling-kit/templates/kit/lib/config.js +1 -1
  66. package/stacks/node/templates/build-kit/CLAUDE.md +3 -3
  67. package/stacks/node/templates/build-kit/lib/AGENT.md +6 -7
  68. package/stacks/node/templates/build-kit/lib/backend-prompt.md +20 -42
  69. package/stacks/node/templates/build-kit/lib/prompt.md +18 -41
  70. package/stacks/opencqrs/templates/build-kit/CLAUDE.md +3 -4
  71. package/stacks/opencqrs/templates/build-kit/lib/AGENT.md +6 -7
  72. package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +20 -42
  73. package/stacks/opencqrs/templates/build-kit/lib/prompt.md +18 -41
  74. package/stacks/react/templates/.claude/skills/build-state-change/SKILL.md +1 -1
  75. package/stacks/react/templates/.claude/skills/build-state-view/SKILL.md +1 -1
  76. package/stacks/react/templates/build-kit/CLAUDE.md +3 -3
  77. package/stacks/react/templates/build-kit/lib/AGENT.md +6 -7
  78. package/stacks/react/templates/build-kit/lib/backend-prompt.md +20 -37
  79. package/stacks/react/templates/build-kit/lib/prompt.md +19 -42
  80. package/stacks/supabase/templates/build-kit/CLAUDE.md +3 -3
  81. package/stacks/supabase/templates/build-kit/lib/AGENT.md +6 -7
  82. package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +20 -42
  83. package/stacks/supabase/templates/build-kit/lib/prompt.md +18 -41
  84. package/stacks/supabase-react/templates/.claude/skills/build-state-change/SKILL.md +2 -2
  85. package/stacks/supabase-react/templates/.claude/skills/build-state-view/SKILL.md +2 -2
  86. package/stacks/supabase-react/templates/build-kit/CLAUDE.md +3 -3
  87. package/stacks/supabase-react/templates/build-kit/lib/AGENT.md +6 -7
  88. package/stacks/supabase-react/templates/build-kit/lib/backend-prompt.md +20 -37
  89. package/stacks/supabase-react/templates/build-kit/lib/prompt.md +19 -42
  90. package/stacks/umadb/templates/build-kit/CLAUDE.md +3 -3
  91. package/stacks/umadb/templates/build-kit/lib/AGENT.md +6 -7
  92. package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +20 -42
  93. package/stacks/umadb/templates/build-kit/lib/prompt.md +18 -41
  94. package/shared/bridge/spec-kitty/bridge-spec-kitty-specify/SKILL.md +0 -125
  95. package/shared/bridge/spec-kitty/bridge-spec-kitty-tasks/SKILL.md +0 -95
  96. package/shared/build-kit/lib/agent.sh +0 -20
  97. package/shared/build-kit/ralph.sh +0 -111
  98. package/shared/build-kit/realtime-agent.js +0 -20
  99. package/stacks/bridge/templates/bridge/lib/AGENT.md +0 -47
  100. package/stacks/bridge/templates/bridge/lib/prompt.md +0 -111
  101. package/stacks/bridge/templates/bridge/ralph-claude.js +0 -50
  102. package/stacks/bridge/templates/bridge/ralph-hook.js +0 -103
  103. package/stacks/bridge/templates/bridge/ralph-local-ai.js +0 -43
  104. package/stacks/bridge/templates/bridge/ralph-static.js +0 -90
@@ -20,16 +20,15 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
20
20
 
21
21
  0. Do not read the entire code base. `.build-kit/ARCHITECTURE.md` tells you where to look; read the code of the precedent slices its Slice map names and the files the slice actually touches. If a `Done` slice has no row in the Slice map, run `/learn-architecture slices` first.
22
22
  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.
23
- 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
23
+ 2. Read `.build-kit/AGENTS.md` **if it exists** — the project's accumulated learnings, generated from what earlier builds recorded. If the slice's `slice.json` has a `lastAttempt`, an earlier attempt at it failed: read its `reason`, `lastReply`, `branch` and `changed`, and do not repeat what failed.
24
24
  3. Make sure you are on the right branch "feature/<slicename>", if unsure, start from main.
25
- 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).
26
- **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:**
25
+ 5. Your slice is the one the task request names (the run loop picked the highest priority slice with status "Planned"); it becomes your PRD. The run loop has already claimed it — its status is "InProgress" in index.json and on the board. Build that slice and do not call `update-slice-status`: the run loop owns the slice's status on the board.
26
+ **IMPORTANT: Only work on the slice named in the task request. Never switch to another slice, whatever its status. If the task request names no slice and no slice has status "Planned" in the current context, reply with:**
27
27
  <promise>NO_TASKS</promise> and stop immediately. Do not work on other slices and do not switch to another context.
28
- **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>`.
29
28
  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.
30
- 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
29
+ 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.
31
30
  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.
32
- 8. Write a short progress one liner after each step to progress.txt
31
+ 8. Record each learning the moment you have it (see **Recording Learnings**), not at the end.
33
32
  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.
34
33
  10. The slice in the json is always true, the code follows what is defined in the json
35
34
  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.
@@ -37,44 +36,27 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
37
36
  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).
38
37
  14. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge (update first)
39
38
  15. Invoke `/record-evidence` to write the implementation evidence (element → code mapping, files, specification → test mapping, seams, assumptions, commit) as a note into the slice's column, in the chapter's `Implementation` feedback lane.
40
- 16. 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). For STATE_VIEW/STATE_CHANGE slices when `handover` is enabled the status to set is `Handover`, not `Done` — see the `ui-contract` skill, Step 4.
41
- 17. Append your progress to `progress.txt` after each step in the iteration.
42
- 18. 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
+ 16. Record the outcome with `npx @eventmodelers/cli slice-status Done` — not by editing index.json, and do not call `update-slice-status`: the run loop pushes the status to the board when your turn ends. For STATE_VIEW/STATE_CHANGE slices when `handover` is enabled the status to record is `Handover`, not `Done` — see the `ui-contract` skill, Step 4. A slice you could not finish needs no status: leave it as it is and the run loop discards the attempt.
40
+ 17. Record any reusable learning you have not recorded yet (see **Recording Learnings**).
41
+ 18. If an entry in `.build-kit/AGENTS.md` turned out wrong or obsolete, retract it (see **Recording Learnings**).
43
42
  19. Finish the iteration.
44
43
 
45
44
  ## Escalating Ambiguity
46
45
 
47
- **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".
46
+ **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 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".
48
47
 
49
- ## Progress Report Format
48
+ ## Recording Learnings
50
49
 
51
- APPEND to progress.txt (never replace, always append):
50
+ `.build-kit/AGENTS.md` is generated from the learnings recorded so far — read it at the start of every session, never edit it by hand. Record a learning the moment you have it:
52
51
 
53
52
  ```
54
- ## [Date/Time] - [Slice]
55
-
56
- - What was implemented
57
- - Files changed
58
- - **Learnings for future iterations:**
59
- - Patterns discovered (e.g., "this codebase uses X for Y")
60
- - Gotchas encountered (e.g., "don't forget to update Z when changing W")
61
- - Useful context (e.g., "the evaluation panel is in component X")
62
- ---
53
+ npx @eventmodelers/cli learn "<one terse line>" --topic "<topic>"
63
54
  ```
64
55
 
65
- The learnings section is critical - it helps future iterations avoid repeating mistakes and understand the codebase better.
66
-
67
- ## Consolidate Patterns
68
-
69
- 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).
70
-
71
- ```
72
- ## Codebase Patterns
73
- - Example: "Services are transactional at the class level — never open a transaction in the controller"
74
- - Example: "New tables need a Flyway migration in db/migration, never edit an existing one"
75
- ```
76
-
77
- Only add patterns that are **general and reusable**, not story-specific details.
56
+ - Only what is genuinely reusable: codebase patterns, gotchas, commands that work or don't, conventions — and, after a failed approach, what was tried and why it failed. Not slice-specific details, and nothing the code or git log already says.
57
+ - One learning per call, one line each. A learning that is already in `.build-kit/AGENTS.md` is skipped for you.
58
+ - `--scope system` for what is true of the modeled domain (a business rule, a naming convention of the model); `repo` (the default) for the codebase and its tooling. `--tag <tag>` labels it (repeatable).
59
+ - One in `.build-kit/AGENTS.md` that turned out wrong or obsolete: `npx @eventmodelers/cli learnings --ids` lists each with its id, `npx @eventmodelers/cli learn --retract <id>` removes it.
78
60
 
79
61
  ## Update AGENTS.md Files
80
62
 
@@ -85,7 +67,7 @@ Before committing, check if any edited files have learnings worth preserving in
85
67
  - Slice specific implementation details
86
68
  - Story-specific implementation details
87
69
  - Temporary debugging notes
88
- - Information already in progress.txt
70
+ - Information already recorded as a learning in `.build-kit/AGENTS.md`
89
71
  - Task-specific learnings
90
72
 
91
73
  Only update AGENTS.md if you have **genuinely reusable knowledge** that would help future work
@@ -130,9 +112,9 @@ If ALL slices in the current context are Done, reply with:
130
112
  - If no `.eventmodelers/config.json` exists anywhere (project root or an ancestor directory, or `~/.eventmodelers/config.json` — the one inside `.build-kit/` is only an optional override, so its absence means nothing), skip all platform communication (MCP calls, `update-slice-status`, board sync) and continue working locally.
131
113
  - Work on ONE slice per iteration
132
114
  - Commit frequently
133
- - update progress.txt frequently
134
- - Read the Codebase Patterns section in progress.txt before starting
115
+ - Record learnings as you go with `learn`
116
+ - Read `.build-kit/AGENTS.md` before starting
135
117
 
136
118
  ## When an iteration completes
137
119
 
138
- Use all the key learnings from the progress.txt and update the `.build-kit/AGENTS.md` file with those learnings.
120
+ Make sure every reusable learning is recorded with `learn`; `.build-kit/AGENTS.md` is generated from them — never edit it by hand.
@@ -4,17 +4,11 @@ You are an autonomous agent reacting to slice status change events on an Eventmo
4
4
 
5
5
  ## Your Loop
6
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.
7
+ 1. Read `AGENT.md` and, if it exists, `.build-kit/AGENTS.md` to load accumulated knowledge before doing anything else.
8
+ 2. The task request at the end of this prompt names your task: its id and the slice change that queued it (`sliceId`, `sliceTitle`, `sliceStatus`, …). It is the oldest one waiting — the run loop picked it for you.
9
+ 3. Execute the task — see the Execution section below.
10
+ 4. Record any reusable learning with `npx @eventmodelers/cli learn "<one terse line>" --topic <topic>` (see **Recording Learnings**).
11
+ 5. Reply normally. The run loop completes the task when your turn ends and hands you the next one in a fresh turn — you never read or write a queue file.
18
12
 
19
13
  ## Execution
20
14
 
@@ -50,7 +44,7 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
50
44
 
51
45
  1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
52
46
 
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.
47
+ **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. Say so in your reply, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
54
48
 
55
49
  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
50
 
@@ -78,52 +72,35 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
78
72
  Another agent is already building this slice. Log it and skip — do not build.
79
73
 
80
74
  #### `Done`
81
- Summarize what was completed and update `progress.txt`.
75
+ Summarize what was completed in your reply.
82
76
 
83
77
  #### `Blocked`
84
- Log the blocker in `progress.txt`.
78
+ State the blocker in your reply.
85
79
 
86
80
  #### `Review`
87
- Fetch slice details and prepare a review summary in `progress.txt`.
81
+ Fetch slice details and prepare a review summary in your reply.
88
82
 
89
83
  #### Any other status (`Created`, etc.)
90
- Load the slice and log the state transition in `progress.txt`. No build action.
84
+ Load the slice and note the state transition in your reply. No build action.
91
85
 
92
86
  Use the skills available in `.claude/skills/` to interact with the board.
93
87
 
94
- ## Updating tasks.json
95
-
96
- 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 `[]`.
97
-
98
88
  ## Escalating Ambiguity
99
89
 
100
- **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".
101
-
102
- ## Progress Report Format
103
-
104
- APPEND to `progress.txt` (never replace):
105
- ```
106
- ## [ISO timestamp] — Task [task.id]
90
+ **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 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".
107
91
 
108
- Slice: [sliceTitle] ([sliceId])
109
- Status change: [sliceStatus]
92
+ ## Recording Learnings
110
93
 
111
- Action taken:
112
- - [what was done in response to the slice change]
94
+ `.build-kit/AGENTS.md` is generated from the learnings recorded so far — read it at the start of every session, never edit it by hand. Record a learning the moment you have it:
113
95
 
114
- Learnings:
115
- - [any patterns, gotchas, or reusable knowledge discovered]
116
- ---
96
+ ```
97
+ npx @eventmodelers/cli learn "<one terse line>" --topic "<topic>"
117
98
  ```
118
99
 
119
- ## Stop Condition
120
-
121
- If `.build-kit/tasks.json` is empty (`[]`) or does not exist, reply with:
122
- <promise>IDLE</promise>
123
-
124
- ## Updating AGENT.md
125
-
126
- 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.
100
+ - Only what is genuinely reusable: codebase patterns, gotchas, commands that work or don't, conventions — and, after a failed approach, what was tried and why it failed. Not slice-specific details, and nothing the code or git log already says.
101
+ - One learning per call, one line each. A learning that is already in `.build-kit/AGENTS.md` is skipped for you.
102
+ - `--scope system` for what is true of the modeled domain (a business rule, a naming convention of the model); `repo` (the default) for the codebase and its tooling. `--tag <tag>` labels it (repeatable).
103
+ - One in `.build-kit/AGENTS.md` that turned out wrong or obsolete: `npx @eventmodelers/cli learnings --ids` lists each with its id, `npx @eventmodelers/cli learn --retract <id>` removes it.
127
104
 
128
105
  ## Important
129
106
 
@@ -65,10 +65,9 @@ Ignore case for files and slices in prompts. "CartItems" slice is the same as "c
65
65
  Do not change test files unless explicitly instructed, or the change brings the test in line with slice.json (e.g. step 4's field/spec diff): `src/test/java/**/*Test.java`.
66
66
 
67
67
  At the start of every session, read `.build-kit/AGENTS.md` if it exists to load accumulated project
68
- learnings.
68
+ learnings. It is generated from the learnings recorded so far — record a new one with `npx @eventmodelers/cli learn "<one terse line>" --topic <topic>`, never by editing the file.
69
69
 
70
- When starting to work on a slice, invoke the `update-slice-status` skill with `InProgress` status before
71
- doing anything else.
70
+ When working from a queued task, invoke the `update-slice-status` skill with `InProgress` status before doing anything else. When the task request names the slice to build (a run-loop build), the run loop has already set it to `InProgress` and pushes the final status itself — do not call `update-slice-status`; record the outcome with `npx @eventmodelers/cli slice-status <status>`.
72
71
 
73
72
  ## Building a Slice
74
73
 
@@ -76,7 +75,7 @@ doing anything else.
76
75
  **ALL fields, event names, command names, and business rules MUST come exclusively from slice.json. Do NOT
77
76
  invent, assume, or guess any field or logic not present in the slice definition.**
78
77
 
79
- **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".
78
+ **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 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".
80
79
 
81
80
  When asked to build a slice, always follow this flow:
82
81
 
@@ -1,12 +1,11 @@
1
- # Agent Learnings
1
+ # Agent Reference
2
2
 
3
- Patterns and gotchas discovered during task processing. Update this file whenever you encounter something reusable.
3
+ What task processing relies on: the shape of a task and the API facts the skills use. A reusable learning is recorded with `npx @eventmodelers/cli learn "<one terse line>"`, not added here.
4
4
 
5
- ## tasks.json
5
+ ## Tasks
6
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.
7
+ - A task is a slice change the run loop queued: an `id` and a `payload` (a `SliceChangedPayload`). The task request names it.
8
+ - You never read or write a queue file: the run loop completes the task when your turn ends.
10
9
 
11
10
  ## SliceChangedPayload fields
12
11
 
@@ -44,7 +43,7 @@ These files are always up to date — read them directly before invoking any ski
44
43
  - The `boardId` and `organizationId` from each payload provide full context — pass them to skills.
45
44
  - Node events use `node:created`, `node:changed`, `node:deleted` — always POST to `/api/org/:orgId/boards/:boardId/nodes/events`.
46
45
  - 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.
46
+ - `/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. This applies to queued tasks only: when the task request names the slice to build, the run loop owns its status — never call `/update-slice-status` there.
48
47
 
49
48
  ## KurrentDB-specific
50
49
 
@@ -17,20 +17,19 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
17
17
 
18
18
  0. Do not read the entire code base. Focus on the tasks in this description.
19
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
20
+ 2. Read `.build-kit/AGENTS.md` **if it exists** — the project's accumulated learnings, generated from what earlier builds recorded. If the slice's `slice.json` has a `lastAttempt`, an earlier attempt at it failed: read its `reason`, `lastReply`, `branch` and `changed`, and do not repeat what failed.
21
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:**
22
+ 5. Your slice is the one the task request names (the run loop picked the highest priority slice with status "Planned"); it becomes your PRD. The run loop has already claimed it — its status is "InProgress" in index.json and on the board. Build that slice and do not call `update-slice-status`: the run loop owns the slice's status on the board.
23
+ **IMPORTANT: Only work on the slice named in the task request. Never switch to another slice, whatever its status. If the task request names no slice and no slice has status "Planned" in the current context, reply with:**
24
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
25
  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
26
+ 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.
28
27
  7. Define the slice type and load the matching skill:
29
28
  - Write slice (has commands, no processors) → `build-state-change`
30
29
  - Read slice (has readModel / information flow) → `build-state-view`
31
30
  - Translation slice (`sliceType === "TRANSLATION"`) → read `description` and `notes` from slice.json for hints; default to `build-automation` if nothing else is specified
32
31
  - Automation slice (processors-array is not empty) → `build-automation`
33
- 8. Write a short progress one liner after each step to progress.txt
32
+ 8. Record each learning the moment you have it (see **Recording Learnings**), not at the end.
34
33
  9. Analyze and Implement that single slice, make use of the skills in the skills directory, but also your previsously collected
35
34
  knowledge. Make a list TODO list for what needs to be done. Also make sure to 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.
36
35
  10. The slice in the json is always true, the code follows what is defined in the json
@@ -43,48 +42,27 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
43
42
  If the tests for the slice are not yet named predictably, run `./mvnw test -q` and check for failures.
44
43
  15. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge ( update
45
44
  first )
46
- 16. 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). For STATE_VIEW/STATE_CHANGE slices when `handover` is enabled the status to set is `Handover`, not `Done` — see the `ui-contract` skill, Step 4.
47
- 17. Append your progress to `progress.txt` after each step in the iteration.
48
- 18. 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.
45
+ 16. Record the outcome with `npx @eventmodelers/cli slice-status Done` — not by editing index.json, and do not call `update-slice-status`: the run loop pushes the status to the board when your turn ends. For STATE_VIEW/STATE_CHANGE slices when `handover` is enabled the status to record is `Handover`, not `Done` — see the `ui-contract` skill, Step 4. A slice you could not finish needs no status: leave it as it is and the run loop discards the attempt.
46
+ 17. Record any reusable learning you have not recorded yet (see **Recording Learnings**).
47
+ 18. If an entry in `.build-kit/AGENTS.md` turned out wrong or obsolete, retract it (see **Recording Learnings**).
49
48
  19. Finish the iteration.
50
49
 
51
50
  ## Escalating Ambiguity
52
51
 
53
- **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".
52
+ **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 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".
54
53
 
55
- ## Progress Report Format
54
+ ## Recording Learnings
56
55
 
57
- APPEND to progress.txt (never replace, always append):
56
+ `.build-kit/AGENTS.md` is generated from the learnings recorded so far — read it at the start of every session, never edit it by hand. Record a learning the moment you have it:
58
57
 
59
58
  ```
60
- ## [Date/Time] - [Slice]
61
-
62
- - What was implemented
63
- - Files changed
64
- - **Learnings for future iterations:**
65
- - Patterns discovered (e.g., "this codebase uses X for Y")
66
- - Gotchas encountered (e.g., "don't forget to update Z when changing W")
67
- - Useful context (e.g., "the evaluation panel is in component X")
68
- ---
59
+ npx @eventmodelers/cli learn "<one terse line>" --topic "<topic>"
69
60
  ```
70
61
 
71
- The learnings section is critical - it helps future iterations avoid repeating mistakes and understand the codebase
72
- better.
73
-
74
- ## Consolidate Patterns
75
-
76
- If you discover a **reusable pattern** that future iterations should know, add it to the `## Codebase Patterns`
77
- section at the TOP of progress.txt (create it if it doesn't exist). This section should consolidate the most
78
- important learnings:
79
-
80
- ```
81
- ## Codebase Patterns
82
- - Example: Register every new event's type string in CqrsConfiguration.eventTypeResolver() as part of the slice
83
- - Example: Automations must catch CommandSubjectAlreadyExistsException/CommandSubjectDoesNotExistException locally
84
- - Example: Export write-model records as package-private unless another slice legitimately needs them
85
- ```
86
-
87
- Only add patterns that are **general and reusable**, not story-specific details.
62
+ - Only what is genuinely reusable: codebase patterns, gotchas, commands that work or don't, conventions — and, after a failed approach, what was tried and why it failed. Not slice-specific details, and nothing the code or git log already says.
63
+ - One learning per call, one line each. A learning that is already in `.build-kit/AGENTS.md` is skipped for you.
64
+ - `--scope system` for what is true of the modeled domain (a business rule, a naming convention of the model); `repo` (the default) for the codebase and its tooling. `--tag <tag>` labels it (repeatable).
65
+ - One in `.build-kit/AGENTS.md` that turned out wrong or obsolete: `npx @eventmodelers/cli learnings --ids` lists each with its id, `npx @eventmodelers/cli learn --retract <id>` removes it.
88
66
 
89
67
  ## Update AGENTS.md Files
90
68
 
@@ -110,7 +88,7 @@ Before committing, check if any edited files have learnings worth preserving in
110
88
  - Slice specific implementation details
111
89
  - Story-specific implementation details
112
90
  - Temporary debugging notes
113
- - Information already in progress.txt
91
+ - Information already recorded as a learning in `.build-kit/AGENTS.md`
114
92
  - Task specific learnings
115
93
 
116
94
  Only update AGENTS.md if you have **genuinely reusable knowledge** that would help future work
@@ -154,9 +132,9 @@ If ALL slices in the current context are Done, reply with:
154
132
  - If no `.eventmodelers/config.json` exists anywhere (project root or an ancestor directory, or `~/.eventmodelers/config.json` — the one inside `.build-kit/` is only an optional override, so its absence means nothing), skip all platform communication (MCP calls, `update-slice-status`, board sync) and continue working locally.
155
133
  - Work on ONE slice per iteration
156
134
  - Commit frequently
157
- - update progress.txt frequently
158
- - Read the Codebase Patterns section in progress.txt before starting
135
+ - Record learnings as you go with `learn`
136
+ - Read `.build-kit/AGENTS.md` before starting
159
137
 
160
138
  ## When an iteration completes
161
139
 
162
- Use all the key learnings from the progress.txt and update the `.build-kit/AGENTS.md` file with those learnings.
140
+ Make sure every reusable learning is recorded with `learn`; `.build-kit/AGENTS.md` is generated from them — never edit it by hand.
@@ -4,17 +4,11 @@ You are an autonomous agent reacting to slice status change events on an Eventmo
4
4
 
5
5
  ## Your Loop
6
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.
7
+ 1. Read `AGENT.md` and, if it exists, `.build-kit/AGENTS.md` to load accumulated knowledge before doing anything else.
8
+ 2. The task request at the end of this prompt names your task: its id and the slice change that queued it (`sliceId`, `sliceTitle`, `sliceStatus`, …). It is the oldest one waiting — the run loop picked it for you.
9
+ 3. Execute the task — see the Execution section below.
10
+ 4. Record any reusable learning with `npx @eventmodelers/cli learn "<one terse line>" --topic <topic>` (see **Recording Learnings**).
11
+ 5. Reply normally. The run loop completes the task when your turn ends and hands you the next one in a fresh turn — you never read or write a queue file.
18
12
 
19
13
  ## Execution
20
14
 
@@ -48,11 +42,11 @@ Inspect the `sliceStatus` in the payload:
48
42
 
49
43
  This is the build trigger. Setting `InProgress` and building are one atomic step:
50
44
 
51
- **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".
45
+ **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 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".
52
46
 
53
47
  1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
54
48
 
55
- **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.
49
+ **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. Say so in your reply, drop this task without building, and continue the loop (the next task will naturally cover the next slice). Do not retry.
56
50
 
57
51
  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.
58
52
 
@@ -78,48 +72,31 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
78
72
  Another agent is already building this slice. Log it and skip — do not build.
79
73
 
80
74
  #### `Done`
81
- Summarize what was completed and update `progress.txt`.
75
+ Summarize what was completed in your reply.
82
76
 
83
77
  #### `Blocked`
84
- Log the blocker in `progress.txt`.
78
+ State the blocker in your reply.
85
79
 
86
80
  #### `Review`
87
- Fetch slice details and prepare a review summary in `progress.txt`.
81
+ Fetch slice details and prepare a review summary in your reply.
88
82
 
89
83
  #### Any other status (`Created`, etc.)
90
- Load the slice and log the state transition in `progress.txt`. No build action.
84
+ Load the slice and note the state transition in your reply. No build action.
91
85
 
92
86
  Use the skills available in `.claude/skills/` to interact with the board.
93
87
 
94
- ## Updating tasks.json
88
+ ## Recording Learnings
95
89
 
96
- 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 `[]`.
90
+ `.build-kit/AGENTS.md` is generated from the learnings recorded so far — read it at the start of every session, never edit it by hand. Record a learning the moment you have it:
97
91
 
98
- ## Progress Report Format
99
-
100
- APPEND to `progress.txt` (never replace):
101
92
  ```
102
- ## [ISO timestamp] — Task [task.id]
103
-
104
- Slice: [sliceTitle] ([sliceId])
105
- Status change: [sliceStatus]
106
-
107
- Action taken:
108
- - [what was done in response to the slice change]
109
-
110
- Learnings:
111
- - [any patterns, gotchas, or reusable knowledge discovered]
112
- ---
93
+ npx @eventmodelers/cli learn "<one terse line>" --topic "<topic>"
113
94
  ```
114
95
 
115
- ## Stop Condition
116
-
117
- If `.build-kit/tasks.json` is empty (`[]`) or does not exist, reply with:
118
- <promise>IDLE</promise>
119
-
120
- ## Updating AGENT.md
121
-
122
- 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.
96
+ - Only what is genuinely reusable: codebase patterns, gotchas, commands that work or don't, conventions — and, after a failed approach, what was tried and why it failed. Not slice-specific details, and nothing the code or git log already says.
97
+ - One learning per call, one line each. A learning that is already in `.build-kit/AGENTS.md` is skipped for you.
98
+ - `--scope system` for what is true of the modeled domain (a business rule, a naming convention of the model); `repo` (the default) for the codebase and its tooling. `--tag <tag>` labels it (repeatable).
99
+ - One in `.build-kit/AGENTS.md` that turned out wrong or obsolete: `npx @eventmodelers/cli learnings --ids` lists each with its id, `npx @eventmodelers/cli learn --retract <id>` removes it.
123
100
 
124
101
  ## Important
125
102
 
@@ -114,22 +114,6 @@ Stop traversal when:
114
114
 
115
115
  ---
116
116
 
117
- ## Step 3e — Check the slices first (before any write)
118
-
119
- Only elements in a slice with status `Created` may be changed — and an element in no slice at all is
120
- not locked. The chain you resolved does not carry that: `get_attribute_chain` and `get_node` do not
121
- report `sliceStatus`. Read it now, once: `mcp__eventmodelers__get_board_outline { "boardId": "$BOARD_ID", "chapterId": "$CHAPTER_ID" }`
122
- gives every column a `sliceStatus` when a slice spans it. Look up each chain node's column.
123
-
124
- - **Every node writable** (`Created`, or no `sliceStatus`) → continue with Step 4.
125
- - **Any node in a column with another status** (`Done`, `Review`, `Handover`, `InProgress`, `Blocked`, `Ready`, `Planned`, `Assigned`,
126
- `Informational`) → **do not write that node.** If the task text says the person already confirmed changing
127
- that locked slice (*"The person confirmed changing the locked slice '…'"*, with an `origin_message_id`), you may
128
- change those elements and only those. Otherwise write **nothing** — not even the nodes that are writable, the
129
- chain is one logical edit — and follow `CLAUDE.md` § *Locked slices in a chat*: ask in the chat with a
130
- `confirm` snippet (or a `changes` snippet listing the elements) naming the slice and its status, post no
131
- `COMMENT` on the slice, and end the turn. (No chat to ask in? Change nothing and post a `COMMENT` on the slice.)
132
-
133
117
  ## Step 4 — Apply the change to the whole chain in one write
134
118
 
135
119
  Compute the updated `fields` array for **every** node in the chain first, in order (TARGET_NODE first, then backwards to SOURCE_NODE), then submit them all in a **single** `submit_node_events` call. Do not write one node, check it, and move to the next — the chain is one logical edit and `events[]` takes the whole batch.
@@ -196,7 +180,7 @@ Tell the user:
196
180
  - **Operation**: add `"<name>"` / rename `"<old>"` → `"<new>"`
197
181
  - **Chain**: list each element in order (type + title + cell)
198
182
  - **Updated**: which nodes were changed
199
- - **Skipped**: which nodes were skipped and why (field already exists / field not found / slice not `Created` — asked to confirm)
183
+ - **Skipped**: which nodes were skipped and why (field already exists / field not found)
200
184
  - **Lineage**: where the attribute starts (`generated` on which element) and any `mapping` you set for a renamed hop
201
185
 
202
186
  Example output:
@@ -84,7 +84,7 @@ Why per commit: when the range contains the commit that **created** a file (e.g.
84
84
  | Group | Examples | Handling |
85
85
  |-------|----------|----------|
86
86
  | **Behavior** | controllers/handlers, services, entities/aggregates, events, projections/queries, schema & migrations, validation, templates/UI, tests | compared in Step 5 |
87
- | **Noise** | dependency bumps, build/CI config, gradle/maven wrappers, formatting-only diffs, docs, `.build-kit/`, `.claude/`, `.agent-modeling-kit/`, `.eventmodelers/`, `.mcp.json`, `CLAUDE.md`, `progress.txt`, generated files | listed in the report footer as *not relevant*, never a finding |
87
+ | **Noise** | dependency bumps, build/CI config, gradle/maven wrappers, formatting-only diffs, docs, `.build-kit/`, `.claude/`, `.agent-modeling-kit/`, `.eventmodelers/`, `.mcp.json`, `CLAUDE.md`, generated files | listed in the report footer as *not relevant*, never a finding |
88
88
 
89
89
  **Build-kit commits vs. hand-made commits.** A commit is the build kit's only if an `Implementation — <Slice>` evidence note names its sha, or — without evidence notes — its subject is `feat: <Slice Name>` for a slice on the board. It implemented the board, so its files are the **as-built state**: compare it cheaply against that slice only. Every other commit — including any commit after it that touches the same files — is a **hand-made change** and the main subject of this skill: for each file the build kit wrote, the drift candidates are `git diff <buildSha>..<REF> -- <file>`, attributed to the later commits.
90
90
 
@@ -127,6 +127,8 @@ To make one: place a normal new node of the same type (COMMAND/EVENT/READMODEL o
127
127
 
128
128
  A linked copy is allowed to diverge from its origin afterward in the specific field(s) a newly-connected event actually drives — e.g. the "Updating a Read Model That Already Feeds a Screen" copy above, where `status` is updated post-link to the event's new value. The link establishes "this is the same underlying fact, not a duplicate" at creation time; it doesn't freeze the copy's fields identical to the origin's forever.
129
129
 
130
+ **Scenarios (and storylines) are always added to the original, never to a copy.** A copy is the same fact reused, so its GWT spec lives once, in the origin's column. Before calling `add_scenario`/`add_storyline`, check `meta.linkedTo` on the target node and follow it to the origin. `eventmodeling-elaborating-scenarios` carries the step-by-step.
131
+
130
132
  Never delete the original (the node with no `linkedTo`) once copies of it exist — copies reference it, and removing it breaks every copy. `eventmodeling-checking-completeness` already treats any `linkedTo`-marked node as an intentional copy, never a duplicate or missing-slice gap to flag.
131
133
 
132
134
  See `place-element` Step 6a for the mechanical linking steps.
@@ -138,8 +138,10 @@ timestamp no event carries), add that field to the element — don't move the va
138
138
  - `isError` marks a beat as an alternate/error branch off the previous beat.
139
139
  - A note beat (`type: "STORYLINE_NOTE"`, `refId: ""`, markdown in `note`) may sit anywhere and is
140
140
  skipped by the order rules — see "Notes — Last Resort Only" above before adding one.
141
- - `fields`, `expectEmptyList`, `exampleMode`, `examples` mirror the same fields GWT scenario steps
142
- use, letting a beat show concrete example data the same way a "then" readmodel step does.
141
+ - `fields`, `expectEmptyList`, `exampleMode`, `examples` are set **per beat** — a list READMODEL beat
142
+ carries its own expected rows (or `expectEmptyList: true`), so every intermediate state is
143
+ asserted, not just "not empty". This is storyline-only: in a GWT scenario the same data goes on
144
+ the scenario, never on the `then` step (see Step 4b).
143
145
 
144
146
  Post storylines via `POST .../timelines/:tl/columns/:col/storylines` (see `learn-eventmodelers-api`
145
147
  for the full endpoint contract) — the same auto-create-if-missing SCENARIO spec node scenarios use,
@@ -406,6 +408,8 @@ mcp__eventmodelers__get_nodes { "boardId": "<BOARD_ID>", "type": "CHAPTER", "pro
406
408
 
407
409
  If there is more than one chapter, ask the user which timeline to target.
408
410
 
411
+ **Scenarios go on the original node, never on a linked copy.** If the COMMAND/READMODEL you are specifying has `meta.linkedTo` (it is a copy), resolve to the origin node (the one without `linkedTo`), and use the origin's timeline and column for `add_scenario`/`POST .../scenarios`. A copy's column gets no spec node of its own; the origin's column holds the one spec for that fact. If the origin sits on another timeline, post there. The same applies to storylines.
412
+
409
413
  For each command or view being specified, find its column: `mcp__eventmodelers__get_board_outline { "boardId": "<BOARD_ID>", "chapterId": "<TL>" }` lists every column (`columnId`, index) with the nodes in it — take the column whose node list holds that COMMAND or READMODEL. If the user named the slice, find the SLICE_BORDER node with that title (`get_nodes { "type": "SLICE_BORDER", "name": "<slice title>", "projection": "line" }` gives its id) or its column in the outline to get the `colId`. (REST fallback: `GET .../nodes/$TL?projection=cells` → `{rows, columns, cells}`; find the cell whose `nodeId` is the COMMAND/READMODEL and take its `colId`.)
410
414
 
411
415
  ### Step 2 — Load valid step elements
@@ -454,7 +458,7 @@ Pass `compact: true` — you already hold every scenario object you sent, so the
454
458
 
455
459
  ### Step 4b — List-type readmodel scenario fields
456
460
 
457
- When `then` contains a READMODEL whose `listElement` property is `true` — set on the node when it was created, per `eventmodeling-core-rules`'s READMODEL section and `eventmodeling-identifying-outputs`/`eventmodeling-designing-automation-chains` — add two fields **at the scenario level** (not inside `then`):
461
+ When `then` contains a READMODEL whose `listElement` property is `true` — set on the node when it was created, per `eventmodeling-core-rules`'s READMODEL section and `eventmodeling-identifying-outputs`/`eventmodeling-designing-automation-chains` — add two fields **at the scenario level** (not inside `then`). Setting `examples`, `exampleMode` or `expectEmptyList` on the `then` step is not supported — the board never reads it, and the API rejects it with `SCENARIO_STEP_LIST_EXPECTATION_UNSUPPORTED`:
458
462
 
459
463
  **`examples`** — one object per expected row, keyed by the readmodel's snake_case field names. Without this the spec node renders with no expected output and the scenario is unverifiable.
460
464
 
@@ -25,14 +25,6 @@ From `$ARGUMENTS`, extract:
25
25
 
26
26
  ---
27
27
 
28
- ## Step 1a — Locked slices
29
-
30
- Only elements in a slice with status `Created` may be changed (no slice at all = not locked).
31
- `get_board_outline` reports `sliceStatus` per column; read it for the chapter before writing, and for
32
- any target in a column with another status (`Done`, `Review`, `InProgress`, …) **write nothing to it**
33
- unless the task says the person already confirmed changing that locked slice. Otherwise ask in the chat
34
- with a `confirm` snippet — `CLAUDE.md` § *Locked slices in a chat* — and post no `COMMENT` on the slice.
35
-
36
28
  ## Step 1b — Many targets at once
37
29
 
38
30
  `target` is singular, but the common real request is "fill in the examples across this chapter". When you have more than one target, **do not run this skill once per element and do not fetch context a node at a time.**