@eventmodelers/cli 1.0.163 → 2.0.2

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 (128) hide show
  1. package/README.md +48 -36
  2. package/RELEASE_NOTES.md +20 -2
  3. package/cli.js +774 -247
  4. package/lib/adapters/spec-kitty-adapter.js +3 -7
  5. package/lib/build-kits.js +23 -0
  6. package/lib/global-agent-id.js +45 -0
  7. package/lib/modeling-local-ai.js +4 -2
  8. package/lib/scaffold-model.js +71 -0
  9. package/lib/scaffold.js +224 -0
  10. package/lib/supervise.js +60 -0
  11. package/lib/ui-baseline.js +123 -0
  12. package/package.json +1 -1
  13. package/shared/build-kit/README.md +4 -19
  14. package/shared/build-kit/lib/agent-lock.js +75 -0
  15. package/shared/build-kit/lib/agent-name.js +27 -0
  16. package/shared/build-kit/lib/event-prune.js +58 -0
  17. package/shared/build-kit/lib/events-view.js +134 -0
  18. package/shared/build-kit/lib/local-ai-agent.js +14 -26
  19. package/shared/build-kit/lib/mcp-register.js +17 -1
  20. package/shared/build-kit/lib/prompt-journal.js +191 -0
  21. package/shared/build-kit/lib/prompt-replay.js +35 -0
  22. package/shared/build-kit/lib/ralph.js +218 -169
  23. package/shared/build-kit/lib/slice-curation.js +40 -0
  24. package/shared/build-kit/lib/slice-events.js +93 -0
  25. package/shared/build-kit/lib/slice-git.js +86 -0
  26. package/shared/build-kit/lib/slice-learnings.js +197 -0
  27. package/shared/build-kit/lib/slice-projection.js +101 -0
  28. package/shared/build-kit/lib/slice-run.js +181 -0
  29. package/shared/build-kit/lib/slice-state.js +184 -0
  30. package/shared/build-kit/lib/slice-tasks.js +35 -0
  31. package/shared/build-kit/ralph-claude.js +4 -2
  32. package/shared/build-kit/ralph-exec.js +4 -2
  33. package/shared/build-kit/ralph-local-ai.js +5 -3
  34. package/shared/scaffold/LICENSE-em-scaffold +21 -0
  35. package/shared/scaffold/supabase/generate.mjs +290 -0
  36. package/shared/scaffold/supabase/template/scripts/create-user.mjs.tmpl +29 -0
  37. package/shared/scaffold/supabase/template/scripts/dev.mjs.tmpl +145 -0
  38. package/shared/scaffold/supabase/template/scripts/write-env.mjs.tmpl +44 -0
  39. package/shared/scaffold/supabase/template/server.ts.tmpl +168 -0
  40. package/shared/scaffold/supabase/template/src/common/extraEndpoints.ts.tmpl +5 -0
  41. package/shared/scaffold/supabase/template/src/common/notImplemented.test.ts.tmpl +58 -0
  42. package/shared/scaffold/supabase/template/src/common/notImplemented.ts.tmpl +29 -0
  43. package/shared/scaffold/supabase/template/supabase/migrations/_V0__supabase_stubs.sql.tmpl +34 -0
  44. package/shared/scaffold/supabase/template/web/src/App.tsx.tmpl +38 -0
  45. package/shared/scaffold/supabase/template/web/src/app/Layout.tsx.tmpl +48 -0
  46. package/shared/scaffold/supabase/template/web/src/app/NotFound.tsx.tmpl +12 -0
  47. package/shared/scaffold/supabase/template/web/src/app/SignIn.tsx.tmpl +42 -0
  48. package/shared/scaffold/supabase/template/web/src/app/TimelinePage.tsx.tmpl +73 -0
  49. package/shared/scaffold/supabase/template/web/src/app/pages.ts.tmpl +26 -0
  50. package/shared/scaffold/supabase/template/web/src/app/skeleton.css.tmpl +25 -0
  51. package/shared/scaffold/supabase/template/web/src/lib/NotBuilt.tsx.tmpl +12 -0
  52. package/shared/scaffold/supabase/template/web/src/lib/api.ts.tmpl +226 -0
  53. package/shared/scaffold/supabase/template/web/src/main.tsx.tmpl +13 -0
  54. package/shared/skills/learn-eventmodelers-api/SKILL.md +17 -4
  55. package/shared/skills/request-feedback/SKILL.md +1 -2
  56. package/shared/skills/ui-contract/SKILL.md +7 -5
  57. package/shared/skills/update-slice-status/SKILL.md +1 -1
  58. package/stacks/axon/templates/build-kit/CLAUDE.md +7 -6
  59. package/stacks/axon/templates/build-kit/lib/AGENT.md +6 -7
  60. package/stacks/axon/templates/build-kit/lib/backend-prompt.md +20 -42
  61. package/stacks/axon/templates/build-kit/lib/prompt.md +32 -41
  62. package/stacks/blank/templates/build-kit/CLAUDE.md +7 -6
  63. package/stacks/blank/templates/build-kit/lib/AGENT.md +6 -7
  64. package/stacks/blank/templates/build-kit/lib/backend-prompt.md +20 -37
  65. package/stacks/blank/templates/build-kit/lib/prompt.md +33 -42
  66. package/stacks/classic/templates/.claude/skills/build-automation/SKILL.md +1 -1
  67. package/stacks/classic/templates/.claude/skills/build-state-change/SKILL.md +1 -1
  68. package/stacks/classic/templates/.claude/skills/build-state-view/SKILL.md +2 -2
  69. package/stacks/classic/templates/.claude/skills/record-evidence/SKILL.md +2 -2
  70. package/stacks/classic/templates/build-kit/CLAUDE.md +9 -8
  71. package/stacks/classic/templates/build-kit/lib/AGENT.md +6 -7
  72. package/stacks/classic/templates/build-kit/lib/backend-prompt.md +20 -38
  73. package/stacks/classic/templates/build-kit/lib/prompt.md +33 -42
  74. package/stacks/kurrent/templates/build-kit/CLAUDE.md +7 -7
  75. package/stacks/kurrent/templates/build-kit/lib/AGENT.md +6 -7
  76. package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +20 -42
  77. package/stacks/kurrent/templates/build-kit/lib/prompt.md +32 -41
  78. package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +1 -1
  79. package/stacks/modeling-kit/templates/.claude/skills/detect-model-drift/SKILL.md +1 -1
  80. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-core-rules/SKILL.md +2 -0
  81. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +7 -3
  82. package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +1 -1
  83. package/stacks/modeling-kit/templates/kit/CLAUDE-STANDALONE.md +3 -4
  84. package/stacks/modeling-kit/templates/kit/CLAUDE.md +18 -28
  85. package/stacks/modeling-kit/templates/kit/README.md +1 -1
  86. package/stacks/modeling-kit/templates/kit/lib/config.js +1 -1
  87. package/stacks/node/templates/build-kit/CLAUDE.md +7 -6
  88. package/stacks/node/templates/build-kit/lib/AGENT.md +6 -7
  89. package/stacks/node/templates/build-kit/lib/backend-prompt.md +20 -42
  90. package/stacks/node/templates/build-kit/lib/prompt.md +18 -41
  91. package/stacks/opencqrs/templates/build-kit/CLAUDE.md +7 -7
  92. package/stacks/opencqrs/templates/build-kit/lib/AGENT.md +6 -7
  93. package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +20 -42
  94. package/stacks/opencqrs/templates/build-kit/lib/prompt.md +32 -41
  95. package/stacks/react/templates/.claude/skills/build-state-change/SKILL.md +1 -1
  96. package/stacks/react/templates/.claude/skills/build-state-view/SKILL.md +1 -1
  97. package/stacks/react/templates/build-kit/CLAUDE.md +7 -6
  98. package/stacks/react/templates/build-kit/lib/AGENT.md +6 -7
  99. package/stacks/react/templates/build-kit/lib/backend-prompt.md +25 -42
  100. package/stacks/react/templates/build-kit/lib/kit.json +1 -1
  101. package/stacks/react/templates/build-kit/lib/prompt.md +47 -43
  102. package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +15 -0
  103. package/stacks/supabase/templates/build-kit/CLAUDE.md +7 -6
  104. package/stacks/supabase/templates/build-kit/lib/AGENT.md +6 -7
  105. package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +20 -42
  106. package/stacks/supabase/templates/build-kit/lib/prompt.md +18 -41
  107. package/stacks/supabase-react/templates/.claude/skills/build-state-change/SKILL.md +80 -8
  108. package/stacks/supabase-react/templates/.claude/skills/build-state-view/SKILL.md +66 -13
  109. package/stacks/supabase-react/templates/build-kit/CLAUDE.md +8 -7
  110. package/stacks/supabase-react/templates/build-kit/lib/AGENT.md +6 -7
  111. package/stacks/supabase-react/templates/build-kit/lib/backend-prompt.md +25 -42
  112. package/stacks/supabase-react/templates/build-kit/lib/kit.json +1 -1
  113. package/stacks/supabase-react/templates/build-kit/lib/prompt.md +48 -44
  114. package/stacks/umadb/templates/build-kit/CLAUDE.md +7 -6
  115. package/stacks/umadb/templates/build-kit/lib/AGENT.md +6 -7
  116. package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +20 -42
  117. package/stacks/umadb/templates/build-kit/lib/prompt.md +32 -41
  118. package/shared/bridge/spec-kitty/bridge-spec-kitty-specify/SKILL.md +0 -125
  119. package/shared/bridge/spec-kitty/bridge-spec-kitty-tasks/SKILL.md +0 -95
  120. package/shared/build-kit/lib/agent.sh +0 -20
  121. package/shared/build-kit/ralph.sh +0 -111
  122. package/shared/build-kit/realtime-agent.js +0 -20
  123. package/stacks/bridge/templates/bridge/lib/AGENT.md +0 -47
  124. package/stacks/bridge/templates/bridge/lib/prompt.md +0 -111
  125. package/stacks/bridge/templates/bridge/ralph-claude.js +0 -50
  126. package/stacks/bridge/templates/bridge/ralph-hook.js +0 -103
  127. package/stacks/bridge/templates/bridge/ralph-local-ai.js +0 -43
  128. package/stacks/bridge/templates/bridge/ralph-static.js +0 -90
@@ -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 `Waiting`, 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` section
77
- at the TOP of progress.txt (create it if it doesn't exist). This section should consolidate the most important
78
- learnings:
79
-
80
- ```
81
- ## Codebase Patterns
82
- - Example: Use event sourcing aggregate patterns for all state changes
83
- - Example: Always use @CommandHandler on the aggregate for write slices
84
- - Example: Export query result types from the slice package
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
 
@@ -64,6 +58,20 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
64
58
 
65
59
  4. Invoke the matching skill and follow its instructions **completely**. Do NOT implement the slice manually.
66
60
 
61
+ **Baseline gate** — before touching any code, run `npx @eventmodelers/cli build-baseline check --scope backend`.
62
+ It compares the board's node hashes of every element of the slice (commands, events, read models,
63
+ processors, specifications, ...) with what was recorded after the last successful build:
64
+ - `UNCHANGED` — nothing on the board changed. Do not rebuild or re-diff; run the slice's tests and
65
+ finish. Only now is "no code changes needed" a valid outcome.
66
+ - `NO_BASELINE` / `UNKNOWN` — no recorded build, or the board could not be read: do one full
67
+ field-by-field diff of slice.json against the code (never treat `UNKNOWN` as `UNCHANGED`).
68
+ - `CHANGED` — it lists the elements that changed, were added or were removed. Diff slice.json
69
+ against the code for exactly those and fix every drift; leave what matches alone.
70
+
71
+ When the checks pass, run `npx @eventmodelers/cli build-baseline record --scope backend` **before
72
+ committing**, so `ui-baseline.json` is committed with the slice. Never record without having done the
73
+ work the verdict asked for. Screens and UI prompts are not this kit's business and never trigger a build.
74
+
67
75
  5. **Verify against slice.json**: Cross-check the implementation — every command field, event field, and specification in slice.json must appear in the code. No invented fields — if it is not in slice.json, it must not be in the code.
68
76
 
69
77
  6. Run quality checks:
@@ -78,48 +86,31 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
78
86
  Another agent is already building this slice. Log it and skip — do not build.
79
87
 
80
88
  #### `Done`
81
- Summarize what was completed and update `progress.txt`.
89
+ Summarize what was completed in your reply.
82
90
 
83
91
  #### `Blocked`
84
- Log the blocker in `progress.txt`.
92
+ State the blocker in your reply.
85
93
 
86
94
  #### `Review`
87
- Fetch slice details and prepare a review summary in `progress.txt`.
95
+ Fetch slice details and prepare a review summary in your reply.
88
96
 
89
97
  #### Any other status (`Created`, etc.)
90
- Load the slice and log the state transition in `progress.txt`. No build action.
98
+ Load the slice and note the state transition in your reply. No build action.
91
99
 
92
100
  Use the skills available in `.claude/skills/` to interact with the board.
93
101
 
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 `[]`.
102
+ ## Recording Learnings
97
103
 
98
- ## Progress Report Format
104
+ `.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:
99
105
 
100
- APPEND to `progress.txt` (never replace):
101
106
  ```
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
- ---
107
+ npx @eventmodelers/cli learn "<one terse line>" --topic "<topic>"
113
108
  ```
114
109
 
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.
110
+ - 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.
111
+ - One learning per call, one line each. A learning that is already in `.build-kit/AGENTS.md` is skipped for you.
112
+ - `--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).
113
+ - 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
114
 
124
115
  ## Important
125
116
 
@@ -1,125 +0,0 @@
1
- ---
2
- name: bridge-spec-kitty-specify
3
- description: "Adapter: generate a Spec Kitty mission spec.md (and auto-evaluate its quality checklist) from an Eventmodelers board's exported event model, instead of running the /spec-kitty.specify interview. Use when the user says \"use the event model as the spec\", \"sync the board to spec-kitty\", \"generate the spec from the event model\", or when a .slices/ export exists and a Spec Kitty mission needs to start or refresh from it."
4
- ---
5
-
6
- # bridge-spec-kitty-specify
7
-
8
- Replaces the human interview in `/spec-kitty.specify` with a direct read of an
9
- Eventmodelers board export. The event model is the source of truth; `spec.md`
10
- becomes a **generated, read-only artifact** derived from it. Everything
11
- downstream of specify (`/spec-kitty.plan`, `/spec-kitty.tasks`,
12
- implement/review/merge) is untouched — this skill only produces the two
13
- artifacts that phase gate expects: `spec.md` and `checklists/requirements.md`.
14
-
15
- Do not use this to hand-author or hand-edit `spec.md` — if the event model is
16
- wrong, fix it on the board and re-run this skill. A `spec.md` produced here
17
- that gets manually edited afterward will be silently overwritten on the next
18
- sync; there is no merge/diff in this version (see Limitations).
19
-
20
- ## Inputs
21
-
22
- The Eventmodelers `listen` server (`npx @eventmodelers/cli listen`) writes the
23
- board export locally. Read it directly — do not call the board API:
24
-
25
- - `.slices/current_context.json` → `{ "name": "<context>" }` — which context
26
- to ingest if the user didn't name one.
27
- - `.slices/<context>/index.json` → `{ "slices": [{ id, slice, index, context,
28
- folder, status, group }] }` — the ordered slice list.
29
- - `.slices/<context>/context.json` → context-level name/package info.
30
- - `.slices/<context>/<folder>/slice.json` → full slice detail per the
31
- [event-modeling-spec](https://github.com/dilgerma/event-modeling-spec)
32
- contract: `commands[]`, `events[]`, `readModels[]` (projections/queries),
33
- `screens[]`, `automations[]`/`processors[]`, `specifications[]` (given/when/
34
- then), plus free-text `description`/`notes`.
35
-
36
- If `.slices/` doesn't exist yet, stop and tell the user to run
37
- `npx @eventmodelers/cli listen` (or `init-modeling` first if the kit isn't
38
- installed) and push the board export before retrying.
39
-
40
- ## Flow
41
-
42
- 1. **Resolve the mission.** If an existing `kitty-specs/<slug>/meta.json`
43
- already points at this context (check `purpose_tldr`/a stored context
44
- reference), re-sync into it. Otherwise create a new mission dir the same
45
- way `/spec-kitty.specify` does: kebab-case name + 8-char ULID suffix,
46
- `mission_type: software-dev` (this adapter does not introduce a new
47
- mission type — see project memory on why). Write `meta.json` matching the
48
- shape in an existing mission (`mission_id`, `mission_slug`, `purpose_tldr`,
49
- `purpose_context`, `target_branch`, etc.).
50
- 2. **Load every slice** referenced in `index.json` by reading each
51
- `<folder>/slice.json`. Do not skip slices with empty `specifications` —
52
- surface them as gaps in the checklist instead (step 4).
53
- 3. **Compose `spec.md`** using the standard Spec Kitty template sections,
54
- sourced only from what the model actually states — never invent detail
55
- the board doesn't have:
56
- - **Purpose** ← `context.json` name/description, or ask the user for a
57
- one-paragraph purpose if the board has none.
58
- - **Primary User Story** ← walk the slices in `index.json` order (this is
59
- already the chronological/timeline order from the board) and narrate
60
- the SCREEN → COMMAND → EVENT → READMODEL flow across them.
61
- - **Acceptance Scenarios** ← one bullet per `specifications[]` entry,
62
- copied straight from its given/when/then — do not paraphrase away
63
- precision the model already captured.
64
- - **Edge Cases** ← `specifications[]` entries that describe rejection/
65
- negative/boundary behavior (reject, invalid, already-exists, etc.).
66
- - **Domain Language** ← distinct nouns from event/command/read-model field
67
- names and titles, deduped.
68
- - **Functional Requirements (FR-###)** ← one row per COMMAND (state-change
69
- slice) and per AUTOMATION slice; wording from the command/automation
70
- name + `description`.
71
- - **Non-Functional Requirements / Constraints** ← only from explicit
72
- `notes`/`description` content tagged as timing/authorization/volume
73
- constraints. If the model states none, leave the table empty — do not
74
- fabricate NFRs to fill it.
75
- - **Key Entities** ← distinct read-model/event payload shapes.
76
- - **Interfaces to Other Teams** ← any `TRANSLATION`-type slice or external
77
- system mentioned in a slice's `description`.
78
- 4. **Evaluate `checklists/requirements.md`** against the ingested model
79
- instead of a human review pass. Check an item only if the model
80
- demonstrably satisfies it:
81
- - "No [NEEDS CLARIFICATION] markers remain" → fails if any slice has an
82
- empty `specifications[]` or a `description` containing `TODO`/`TBD`.
83
- - "Requirements are testable and unambiguous" → fails if an FR/NFR row has
84
- no backing `specifications[]` entry.
85
- - "Non-functional requirements include measurable thresholds" → fails
86
- (leave unchecked, don't skip the row) if the NFR table is empty but the
87
- model contains AUTOMATION slices implying a timing constraint the board
88
- never made explicit.
89
- - Leave any check unchecked with a `## Notes` explanation when the event
90
- model genuinely doesn't provide enough to verify it — this checklist
91
- gates `/spec-kitty.plan`, so a false pass defeats the point of the gate.
92
- 5. **Hand off.** Once `spec.md` + `checklists/requirements.md` are written,
93
- tell the user the mission is ready for `/spec-kitty.plan` as normal — do
94
- not run plan/tasks yourself from this skill.
95
-
96
- ## Re-sync behavior
97
-
98
- Re-running this skill against the same mission regenerates `spec.md` and
99
- `checklists/requirements.md` wholesale from the current `.slices/` state.
100
- There is no field-level diff against the previous generation — if the spec
101
- needs to reflect board changes, re-run this skill rather than hand-patching
102
- `spec.md`.
103
-
104
- ## Guardrail
105
-
106
- If a required section can't be populated from the event model (e.g. no
107
- Purpose anywhere on the board), ask the user rather than inventing one — an
108
- invented Purpose defeats the reason this adapter exists (the event model,
109
- not the LLM, is the source of truth for product intent).
110
-
111
- ## Limitations (by design, v1)
112
-
113
- - Does not itself generate `tasks/WP##-*.md` from slices — see the companion
114
- `bridge-spec-kitty-tasks` skill, which enforces a 1:1
115
- slice-to-WP mapping when `wps.yaml` is written during
116
- `/spec-kitty.tasks-outline`.
117
- - Does not introduce a new Spec Kitty mission type. Spec Kitty 3.2.5's
118
- built-in mission types are loaded from a flat directory inside the
119
- installed package (`doctrine/missions/mission_types/*.yaml`) via
120
- `MissionTypeRepository.default()`, and org-pack extension for the
121
- `mission_types` kind is unwired in this version (fragments only add
122
- governance-graph metadata, not an executable type). A real native mission
123
- type would require patching the installed `spec-kitty-cli` package itself.
124
- This adapter avoids that entirely — it stays inside `mission_type:
125
- software-dev` and only replaces the specify phase's *inputs*.
@@ -1,95 +0,0 @@
1
- ---
2
- name: bridge-spec-kitty-tasks
3
- description: "Adapter: enforce a 1:1 mapping between Eventmodelers board slices and Spec Kitty work packages when writing wps.yaml. Use when the user says \"one slice should become one task/WP\", \"generate tasks from the event model\", or right after bridge-spec-kitty-specify, in place of freeform subtask-grouping judgment in /spec-kitty.tasks-outline."
4
- ---
5
-
6
- # bridge-spec-kitty-tasks
7
-
8
- Companion to `bridge-spec-kitty-specify`. That skill turns the event model into
9
- `spec.md`; this one enforces that each **slice** on the board becomes exactly
10
- **one work package** — never split across WPs, never merged with another
11
- slice — when Spec Kitty's task-planning pipeline builds `wps.yaml`.
12
-
13
- This replaces only step 3–6 of `/spec-kitty.tasks-outline` (deriving
14
- subtasks and rolling them into WPs). `/spec-kitty.tasks-packages` and
15
- `/spec-kitty.tasks-finalize` run completely unmodified afterward — they only
16
- ever consume `wps.yaml`, and don't care where its groupings came from.
17
-
18
- ## Why a hard 1:1 boundary
19
-
20
- Spec Kitty's default `tasks-outline` groups subtasks into WPs by
21
- judgment (target 3–7 subtasks, merge small ones, split large ones). That's
22
- the right default when subtask boundaries come from an LLM reading prose. It
23
- is the *wrong* default here: the event model already drew the real
24
- boundaries (each SLICE_BORDER is a reviewable, independently buildable unit
25
- the board's `Planned → InProgress → Done` slice lifecycle already governs).
26
- Re-grouping at the WP layer would create a second, competing notion of "unit
27
- of work" that drifts from the board over time. So this skill trades away
28
- `tasks-outline`'s sizing flexibility on purpose: WP boundary = slice
29
- boundary, full stop.
30
-
31
- ## Inputs
32
-
33
- Same event-model export as `bridge-spec-kitty-specify`:
34
- `.slices/<context>/index.json` (slice list, board/timeline order) and each
35
- `.slices/<context>/<folder>/slice.json` (commands, events, readModels,
36
- automations, `specifications`). Also read, from `feature_dir`:
37
- `spec.md` (for FR/NFR ids — already generated by `bridge-spec-kitty-specify`) and
38
- `plan.md` (for the tech-stack/file-layout context needed to fill
39
- `owned_files`, since the event model doesn't know the codebase's directory
40
- structure).
41
-
42
- ## Flow
43
-
44
- 1. **One WP per slice, in board order.** Assign `WP01`, `WP02`, ... following
45
- `index.json`'s order (already the board's chronological/timeline order).
46
- Do not reorder for "phase grouping" the way default `tasks-outline` does —
47
- the board order already encodes the intended build sequence.
48
- 2. **Subtasks come from inside the slice, not across slices.** For each
49
- slice, break its own commands/read-models/screens/automations into T-ids
50
- (one per command handler, one per read-model endpoint, one per
51
- screen/automation, one for its tests) — all nested under that slice's one
52
- WP. Every subtask must trace to exactly one slice; never let a subtask
53
- span two slices.
54
- 3. **Dependencies from event flow, not guesswork.** WP *B* depends on WP *A*
55
- iff slice B's commands/queries/automations consume an event that slice
56
- A's commands/automations produce. Derive this by diffing each slice's
57
- emitted event names against every other slice's consumed event names —
58
- this is mechanical, not judgment-based, so don't also apply
59
- `tasks-outline`'s "Phase 2 typically depends on Phase 1" heuristic on top
60
- of it.
61
- 4. **`requirement_refs` from the spec's own FR/NFR table.** Match each
62
- slice's command/read-model/automation names against `spec.md`'s FR/NFR
63
- rows (written by `bridge-spec-kitty-specify` from these same slices) and cite
64
- whichever ids trace to this slice. A slice with no matching row means
65
- `bridge-spec-kitty-specify` needs a re-run, not a fabricated ref here.
66
- 5. **Write `wps.yaml`** using the exact schema `/spec-kitty.tasks-outline`
67
- expects (`id`, `title`, `dependencies`, `owned_files`, `requirement_refs`,
68
- `plan_concern_refs` or `cross_cutting: true`, `subtasks`, `prompt_file:
69
- null`) — so `tasks-packages`/`finalize-tasks` need no awareness that this
70
- skill (rather than default `tasks-outline`) produced it.
71
- 6. **Hand off.** Tell the user to continue with `/spec-kitty.tasks-packages`
72
- then `/spec-kitty.tasks-finalize` (or `spec-kitty next`) exactly as normal.
73
-
74
- ## Guardrail: don't fix boundary problems here
75
-
76
- If a slice's own scope would blow past Spec Kitty's WP sizing ceiling (>10
77
- subtasks / >700 lines), **do not silently split it into two WPs** — that
78
- breaks the 1:1 invariant this skill exists to enforce, and produces the
79
- exact spec/code drift it's meant to prevent. Instead, flag it to the user:
80
- the slice is too coarse on the board itself, so split the SLICE_BORDER
81
- there and re-run both `bridge-spec-kitty-specify` and this skill. The event model
82
- stays the single place slice boundaries get decided.
83
-
84
- The same holds in the other direction: never merge two small slices into
85
- one WP for tidiness, even if `tasks-outline`'s default guidance would.
86
-
87
- ## Limitations (v1)
88
-
89
- - `owned_files`/file-layout ownership still comes from `plan.md`, which is
90
- still produced by the normal, LLM-authored `/spec-kitty.plan` — the event
91
- model has no notion of source-file structure, so this isn't something to
92
- push onto it.
93
- - Re-running this skill after the board changes regenerates `wps.yaml`
94
- wholesale from the current slice set, same as `bridge-spec-kitty-specify`'s
95
- re-sync behavior — no field-level diff against a prior run.
@@ -1,20 +0,0 @@
1
- #!/bin/bash
2
- # Runs the AI agent with the given prompt in the project directory.
3
- # Called by ralph.sh with cwd already set to the project root.
4
- # Usage: ./agent.sh "<prompt>"
5
-
6
- set -euo pipefail
7
-
8
- PROMPT="${1:-}"
9
- if [[ -z "$PROMPT" ]]; then
10
- echo "ERROR: No prompt provided"
11
- exit 1
12
- fi
13
-
14
- claude --dangerously-skip-permissions -p "$PROMPT"
15
-
16
- # --- To use a local Ollama model instead, comment out the line above
17
- # and uncomment the block below. Run `ollama serve` first.
18
- #
19
- # MODEL="${OLLAMA_MODEL:-qwen3.5:9b}"
20
- # node "$(dirname "$0")/ollama-agent.js" "$MODEL"
@@ -1,111 +0,0 @@
1
- #!/bin/bash
2
- # Ralph agent loop — two independent loops, each triggered by their own condition
3
- #
4
- # onTask: tasks.json has entries → load slice from board, update .build-kit/.slices/
5
- # onPlannedSlice: .build-kit/.slices/ has a "Planned" slice → build it
6
- #
7
- # The loops are NOT causally linked — either can trigger on its own.
8
- #
9
- # Usage: ./ralph.sh [iterations] [project_dir]
10
- # iterations — number of loop cycles to run; 0 or omitted means run forever
11
- # project_dir — path to the project root; defaults to the parent of .build-kit
12
-
13
- set -euo pipefail
14
-
15
- KIT_DIR="$(cd "$(dirname "$0")" && pwd)"
16
- ITERATIONS="${1:-0}"
17
- PROJECT_DIR="${2:-"$KIT_DIR/.."}"
18
- TASKS_FILE="$KIT_DIR/tasks.json"
19
- PROMPT_FILE="$KIT_DIR/lib/prompt.md"
20
- BACKEND_PROMPT_FILE="$KIT_DIR/lib/backend-prompt.md"
21
- AGENT_SCRIPT="$KIT_DIR/lib/agent.sh"
22
-
23
- HAS_CREDENTIALS=true
24
- if [[ "${RALPH_LOCAL:-}" == "1" ]]; then
25
- echo "[ralph] --local — platform sync disabled." >&2
26
- HAS_CREDENTIALS=false
27
- elif [[ ! -f "$KIT_DIR/.eventmodelers/config.json" ]]; then
28
- echo "[ralph] Note: no .eventmodelers/config.json found — platform sync disabled." >&2
29
- echo " To enable board sync, follow: https://app.eventmodelers.ai/documentation#build" >&2
30
- echo " Code generation from local slice definitions will still run." >&2
31
- HAS_CREDENTIALS=false
32
- fi
33
-
34
- echo "Ralph — kit: $KIT_DIR project: $PROJECT_DIR"
35
-
36
- # Returns 0 if tasks.json has at least one task
37
- has_pending_tasks() {
38
- [[ -f "$TASKS_FILE" ]] || return 1
39
- local content
40
- content=$(cat "$TASKS_FILE")
41
- [[ "$content" != "[]" && -n "$content" ]]
42
- }
43
-
44
- # Status this loop picks work up from — `run --status-trigger <status>` (RALPH_STATUS_TRIGGER), default Planned
45
- PICKUP_STATUS="${RALPH_STATUS_TRIGGER:-Planned}"
46
-
47
- # Returns 0 if any JSON under .build-kit/.slices/ contains a slice in the pickup status
48
- has_planned_slices() {
49
- grep -rqi "\"status\"[[:space:]]*:[[:space:]]*\"$PICKUP_STATUS\"" "$KIT_DIR/.slices/" --include='index.json' 2>/dev/null
50
- }
51
-
52
- # Returns the title of the first "Planned" slice, or empty string
53
- get_planned_slice_title() {
54
- for index_file in "$KIT_DIR/.slices/"*/index.json; do
55
- [[ -f "$index_file" ]] || continue
56
- local title
57
- title=$(node -e "
58
- try {
59
- const d = JSON.parse(require('fs').readFileSync(process.argv[1], 'utf-8'));
60
- const s = (d.slices||[]).find(s => (s.status||'').toLowerCase() === process.argv[2].toLowerCase());
61
- if (s) process.stdout.write(s.slice || s.id || '');
62
- } catch(e) {}
63
- " "$index_file" "$PICKUP_STATUS" 2>/dev/null)
64
- if [[ -n "$title" ]]; then
65
- echo "$title"
66
- return
67
- fi
68
- done
69
- }
70
-
71
- # prompt.md and backend-prompt.md are instruction manuals with no request in them — handed one
72
- # alone, the agent may read it as background and ask what to do. Every turn ends with the concrete
73
- # request, the same one lib/ralph.js's taskRequest() appends.
74
- task_request() {
75
- printf '\n\n---\n\nYour task now: %s, following the instructions above. Start immediately.\n' "$1"
76
- }
77
-
78
- # Runs agent.sh with the given prompt; retries on non-zero exit
79
- run_agent() {
80
- local label="$1"
81
- local prompt="$2"
82
- while true; do
83
- echo "[$(date -u +%H:%M:%S)] $label"
84
- (cd "$PROJECT_DIR" && bash "$AGENT_SCRIPT" "$prompt") 2>&1 && return 0
85
- echo "[$(date -u +%H:%M:%S)] Agent error — retrying in 60s..."
86
- sleep 60
87
- done
88
- }
89
-
90
- cycle=0
91
- while [[ "$ITERATIONS" -eq 0 || "$cycle" -lt "$ITERATIONS" ]]; do
92
- ran_something=false
93
-
94
- if [[ "$HAS_CREDENTIALS" == true ]] && has_pending_tasks; then
95
- run_agent "onTask: loading slice from board..." "$(cat "$PROMPT_FILE"; task_request 'process the pending tasks in tasks.json')"
96
- ran_something=true
97
- fi
98
-
99
- if has_planned_slices; then
100
- slice_title=$(get_planned_slice_title)
101
- run_agent "onPlannedSlice: building \"$slice_title\"..." "$(cat "$BACKEND_PROMPT_FILE"; task_request "build the $PICKUP_STATUS slice \"$slice_title\"")"
102
- echo "[$(date -u +%H:%M:%S)] Slice \"$slice_title\" build complete — waiting for next slice"
103
- ran_something=true
104
- fi
105
-
106
- if [[ "$ran_something" == false ]]; then
107
- sleep 3
108
- fi
109
-
110
- (( cycle++ )) || true
111
- done
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env node
2
- // Standalone realtime agent — subscribes to board events and writes tasks.json.
3
- // The same logic runs embedded inside ralph-claude.js / ralph-local-ai.js, so you
4
- // only need this if you want to run the agent independently (e.g. separate terminal).
5
- // Usage: node realtime-agent.js [kit_dir]
6
-
7
- import { loadLocalConfig, fetchPlatformConfig, retryTransient, startRealtimeAgent } from './lib/ralph.js';
8
- import { redactConsole } from './lib/redact.js';
9
- import { dirname, resolve } from 'path';
10
- import { fileURLToPath } from 'url';
11
-
12
- const kitDir = process.argv[2] ? resolve(process.argv[2]) : dirname(fileURLToPath(import.meta.url));
13
-
14
- const local = loadLocalConfig(kitDir);
15
- redactConsole([local.token]);
16
- const cfg = await retryTransient('fetchPlatformConfig', () => fetchPlatformConfig(local));
17
-
18
- console.log(`[agent] Starting — org=${cfg.organizationId}${cfg.boardId ? `, board=${cfg.boardId}` : ''}, base=${cfg.baseUrl}`);
19
-
20
- await startRealtimeAgent(cfg, kitDir);