@eventmodelers/cli 2.0.1 → 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.
- package/README.md +26 -9
- package/cli.js +320 -29
- package/lib/build-kits.js +23 -0
- package/lib/scaffold-model.js +71 -0
- package/lib/scaffold.js +224 -0
- package/lib/supervise.js +60 -0
- package/lib/ui-baseline.js +123 -0
- package/package.json +1 -1
- package/shared/build-kit/lib/events-view.js +16 -3
- package/shared/build-kit/lib/ralph.js +19 -15
- package/shared/build-kit/lib/slice-run.js +2 -2
- package/shared/build-kit/lib/slice-state.js +5 -3
- package/shared/scaffold/LICENSE-em-scaffold +21 -0
- package/shared/scaffold/supabase/generate.mjs +290 -0
- package/shared/scaffold/supabase/template/scripts/create-user.mjs.tmpl +29 -0
- package/shared/scaffold/supabase/template/scripts/dev.mjs.tmpl +145 -0
- package/shared/scaffold/supabase/template/scripts/write-env.mjs.tmpl +44 -0
- package/shared/scaffold/supabase/template/server.ts.tmpl +168 -0
- package/shared/scaffold/supabase/template/src/common/extraEndpoints.ts.tmpl +5 -0
- package/shared/scaffold/supabase/template/src/common/notImplemented.test.ts.tmpl +58 -0
- package/shared/scaffold/supabase/template/src/common/notImplemented.ts.tmpl +29 -0
- package/shared/scaffold/supabase/template/supabase/migrations/_V0__supabase_stubs.sql.tmpl +34 -0
- package/shared/scaffold/supabase/template/web/src/App.tsx.tmpl +38 -0
- package/shared/scaffold/supabase/template/web/src/app/Layout.tsx.tmpl +48 -0
- package/shared/scaffold/supabase/template/web/src/app/NotFound.tsx.tmpl +12 -0
- package/shared/scaffold/supabase/template/web/src/app/SignIn.tsx.tmpl +42 -0
- package/shared/scaffold/supabase/template/web/src/app/TimelinePage.tsx.tmpl +73 -0
- package/shared/scaffold/supabase/template/web/src/app/pages.ts.tmpl +26 -0
- package/shared/scaffold/supabase/template/web/src/app/skeleton.css.tmpl +25 -0
- package/shared/scaffold/supabase/template/web/src/lib/NotBuilt.tsx.tmpl +12 -0
- package/shared/scaffold/supabase/template/web/src/lib/api.ts.tmpl +226 -0
- package/shared/scaffold/supabase/template/web/src/main.tsx.tmpl +13 -0
- package/shared/skills/learn-eventmodelers-api/SKILL.md +4 -4
- package/shared/skills/ui-contract/SKILL.md +6 -6
- package/shared/skills/update-slice-status/SKILL.md +1 -1
- package/stacks/axon/templates/build-kit/CLAUDE.md +4 -3
- package/stacks/axon/templates/build-kit/lib/backend-prompt.md +1 -1
- package/stacks/axon/templates/build-kit/lib/prompt.md +14 -0
- package/stacks/blank/templates/build-kit/CLAUDE.md +4 -3
- package/stacks/blank/templates/build-kit/lib/backend-prompt.md +1 -1
- package/stacks/blank/templates/build-kit/lib/prompt.md +14 -0
- package/stacks/classic/templates/build-kit/CLAUDE.md +6 -5
- package/stacks/classic/templates/build-kit/lib/backend-prompt.md +1 -1
- package/stacks/classic/templates/build-kit/lib/prompt.md +14 -0
- package/stacks/kurrent/templates/build-kit/CLAUDE.md +4 -3
- package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +1 -1
- package/stacks/kurrent/templates/build-kit/lib/prompt.md +14 -0
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/kit/CLAUDE.md +9 -4
- package/stacks/node/templates/build-kit/CLAUDE.md +4 -3
- package/stacks/node/templates/build-kit/lib/backend-prompt.md +1 -1
- package/stacks/opencqrs/templates/build-kit/CLAUDE.md +4 -3
- package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +1 -1
- package/stacks/opencqrs/templates/build-kit/lib/prompt.md +14 -0
- package/stacks/react/templates/build-kit/CLAUDE.md +4 -3
- package/stacks/react/templates/build-kit/lib/AGENT.md +1 -1
- package/stacks/react/templates/build-kit/lib/backend-prompt.md +7 -7
- package/stacks/react/templates/build-kit/lib/kit.json +1 -1
- package/stacks/react/templates/build-kit/lib/prompt.md +29 -2
- package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +15 -0
- package/stacks/supabase/templates/build-kit/CLAUDE.md +4 -3
- package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +1 -1
- package/stacks/supabase-react/templates/.claude/skills/build-state-change/SKILL.md +78 -6
- package/stacks/supabase-react/templates/.claude/skills/build-state-view/SKILL.md +64 -11
- package/stacks/supabase-react/templates/build-kit/CLAUDE.md +5 -4
- package/stacks/supabase-react/templates/build-kit/lib/AGENT.md +1 -1
- package/stacks/supabase-react/templates/build-kit/lib/backend-prompt.md +7 -7
- package/stacks/supabase-react/templates/build-kit/lib/kit.json +1 -1
- package/stacks/supabase-react/templates/build-kit/lib/prompt.md +30 -3
- package/stacks/umadb/templates/build-kit/CLAUDE.md +4 -3
- package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +1 -1
- package/stacks/umadb/templates/build-kit/lib/prompt.md +14 -0
|
@@ -9,9 +9,9 @@ The structure defined in the Project-Skills is relevant.
|
|
|
9
9
|
You work within **exactly ONE context at a time** — the one named in `.build-kit/.slices/current_context.json` (the runner picks it).
|
|
10
10
|
|
|
11
11
|
- **ONLY** look for and build slices inside `.build-kit/.slices/<currentContext>/`.
|
|
12
|
-
- **NEVER** read, scan, or build slices from any other context directory, even if it has "
|
|
13
|
-
- A "
|
|
14
|
-
- If the current context has no "
|
|
12
|
+
- **NEVER** read, scan, or build slices from any other context directory, even if it has "Waiting" slices, and even if the current context has no work left.
|
|
13
|
+
- A "Waiting" slice in a *different* context is **NOT yours to build**. Ignore it completely.
|
|
14
|
+
- If the current context has no "Waiting" slice, you are **done for this iteration** — reply `<promise>NO_TASKS</promise>` and stop. Do not go looking elsewhere. The runner moves `current_context.json` on to the next context with Waiting work between iterations — never change it yourself.
|
|
15
15
|
|
|
16
16
|
## Your Task
|
|
17
17
|
|
|
@@ -19,8 +19,8 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
|
|
|
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 "handover" is a task.
|
|
20
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. Your slice is the one the task request names (the run loop picked the highest priority slice with status "
|
|
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 "
|
|
22
|
+
5. Your slice is the one the task request names (the run loop picked the highest priority slice with status "Waiting"); 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 "Waiting" 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
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.
|
|
26
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.
|
|
@@ -90,12 +90,12 @@ A Slice is not complete if specifications are missing or can't be executed.
|
|
|
90
90
|
|
|
91
91
|
## Stop Condition
|
|
92
92
|
|
|
93
|
-
**After completing ONE slice, always stop — regardless of whether more slices are in
|
|
93
|
+
**After completing ONE slice, always stop — regardless of whether more slices are in Waiting.** The ralph loop will invoke you again for the next slice. Never chain multiple slices in one iteration.
|
|
94
94
|
|
|
95
95
|
If the slice was completed and committed successfully, reply with:
|
|
96
96
|
<promise>DONE</promise>
|
|
97
97
|
|
|
98
|
-
If no slice has status "
|
|
98
|
+
If no slice has status "Waiting" in the current context, reply with:
|
|
99
99
|
<promise>NO_TASKS</promise>
|
|
100
100
|
(Do NOT switch to another context to find work — stop here.)
|
|
101
101
|
|
|
@@ -38,13 +38,13 @@ Run `/load-slice sliceId=<payload.sliceId>` to fetch full slice details (title,
|
|
|
38
38
|
|
|
39
39
|
Inspect the `sliceStatus` in the payload:
|
|
40
40
|
|
|
41
|
-
#### `
|
|
41
|
+
#### `Waiting` — build the slice
|
|
42
42
|
|
|
43
43
|
This is the build trigger. Setting `InProgress` and building are one atomic step:
|
|
44
44
|
|
|
45
45
|
1. Immediately call `/update-slice-status` to set the slice to `InProgress` on the board.
|
|
46
46
|
|
|
47
|
-
**Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `
|
|
47
|
+
**Claim conflict**: if this call reports the slice is already in `InProgress` (or any status other than `Waiting`), 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.
|
|
48
48
|
|
|
49
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.
|
|
50
50
|
|
|
@@ -56,7 +56,34 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
|
|
|
56
56
|
|
|
57
57
|
4. Invoke the matching skill and follow its instructions **completely**. Do NOT implement the slice manually.
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
**UI baseline gate** — before touching any code, run `npx @eventmodelers/cli ui-baseline check`. It
|
|
60
|
+
compares the board's node hashes (the slice's screen and every element) and `codeGen.uiPrompts` with
|
|
61
|
+
what was recorded after the last UI build, and decides what this build has to do:
|
|
62
|
+
- `UNCHANGED` — nothing on the board changed since the last UI build. Skip all UI work; do not
|
|
63
|
+
re-fetch or diff the screen. Only now is "no code changes needed" a valid outcome.
|
|
64
|
+
- `NO_BASELINE` — no UI build recorded yet (first build, or the slice predates the baseline). Do one
|
|
65
|
+
full screen diff (below), apply every UI prompt.
|
|
66
|
+
- `UNKNOWN` — the board could not be read. Treat it as `NO_BASELINE`; never as `UNCHANGED`.
|
|
67
|
+
- `CHANGED` — it also lists, per element, what changed, was added or was removed since the last recorded
|
|
68
|
+
build (e.g. `changed: Contact Details (screen), Assign Tag (command)`). Work on exactly those nodes
|
|
69
|
+
and leave what matches alone. Act on the parts it flags:
|
|
70
|
+
- `SCREEN_CHANGED`: re-fetch the live screen node (`get_node`, its `meta.pages` / `meta.marks`) —
|
|
71
|
+
never trust the JSX already in the repo — and diff the existing component(s) against the marked
|
|
72
|
+
(or whole, if unmarked) HTML: tags, classes, layout, copy, fields/buttons added, removed or
|
|
73
|
+
reordered, and `cssFrameworks`. Edit the components (and `src/pages/<ScreenTitle>.tsx`, for this
|
|
74
|
+
slice's marked position only) until they match 1:1 and update `samples/`. Keep what already
|
|
75
|
+
matches; do not regenerate the slice from scratch.
|
|
76
|
+
- `ELEMENTS_CHANGED`: diff slice.json against the code field by field (fields,
|
|
77
|
+
`apiEndpoint`/UI contract) and fix every drift.
|
|
78
|
+
- `PROMPTS_CHANGED`: apply the UI prompts it prints — each is an instruction the user typed on the
|
|
79
|
+
board for this slice's UI (e.g. "adjust the UI to the new layout!") — to the component(s) and
|
|
80
|
+
screen markup. Name each prompt and the change you made for it in your final reply.
|
|
81
|
+
|
|
82
|
+
When the UI work is done and the checks in step 6 pass, run `npx @eventmodelers/cli ui-baseline record`
|
|
83
|
+
**before committing**, so `ui-baseline.json` is committed with the slice. Never record without having
|
|
84
|
+
done the work the verdict asked for.
|
|
85
|
+
|
|
86
|
+
5. **Verify against slice.json**: first check where every displayed value comes from — screen examples are samples, so names, selections, options and list rows must be bound to the read model (grep the components for the mockup's example strings; hits outside `samples/` are hardcoded data and must be fixed). Then cross-check the implementation — every command field, event field, and specification in slice.json must appear in the code — specifications are read (Step 3a of the build skill) to understand how the UI should behave and present outcomes; the business logic itself lives in the backend and is not re-implemented here. No invented fields — if it is not in slice.json, it must not be in the code.
|
|
60
87
|
|
|
61
88
|
6. Run `npm run build` and `npm run lint` (both must pass clean) — plus the slice's own tests only, if any exist.
|
|
62
89
|
|
|
@@ -59,9 +59,10 @@ When asked to build a slice, always follow this flow:
|
|
|
59
59
|
- **State-view** — `projections` or `queries` array is non-empty → invoke `/build-state-view`
|
|
60
60
|
- **State-change** — default (has `commands` / `events`) → invoke `/build-state-change`
|
|
61
61
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
62
|
-
4. **
|
|
63
|
-
5.
|
|
64
|
-
6.
|
|
62
|
+
4. **Baseline gate**: run `npx @eventmodelers/cli build-baseline check --scope backend` first and act only on its verdict — `UNCHANGED` means nothing on the board changed since the last recorded build: do not rebuild, just run the slice's tests and finish; `NO_BASELINE`/`UNKNOWN` mean one full field-by-field diff of slice.json against the code; `CHANGED` lists exactly which elements changed, were added or removed — diff and fix only those. After the checks pass and before committing, run `build-baseline record --scope backend`. A screen or UI prompt change never triggers a backend build.
|
|
63
|
+
5. **Verify against slice.json**: After the skill completes, check that every command field, event field, and specification in slice.json appears in the implementation. No invented fields — if it is not in slice.json, it must not be in the code. This applies even when the slice was previously `Done` and reappears as `Planned` — never dismiss a mismatch as "already implemented" or harmless drift; diff slice.json against the code field by field and update the code to match every change.
|
|
64
|
+
6. Run quality checks (`./mvnw compile -q`, then the slice tests only).
|
|
65
|
+
7. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`. For STATE_VIEW/STATE_CHANGE slices when `handover` is enabled the status to set is `Waiting`, not `Done` — see the `ui-contract` skill, Step 4.
|
|
65
66
|
|
|
66
67
|
After you are done, automatically run the tests for the slice that was edited.
|
|
67
68
|
|
|
@@ -42,7 +42,7 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
|
|
|
42
42
|
If the tests for the slice are not yet named predictably, run `./mvnw test -q` and check for failures.
|
|
43
43
|
15. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge ( update
|
|
44
44
|
first )
|
|
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 `
|
|
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
46
|
17. Record any reusable learning you have not recorded yet (see **Recording Learnings**).
|
|
47
47
|
18. If an entry in `.build-kit/AGENTS.md` turned out wrong or obsolete, retract it (see **Recording Learnings**).
|
|
48
48
|
19. Finish the iteration.
|
|
@@ -58,6 +58,20 @@ This is the build trigger. Setting `InProgress` and building are one atomic step
|
|
|
58
58
|
|
|
59
59
|
4. Invoke the matching skill and follow its instructions **completely**. Do NOT implement the slice manually.
|
|
60
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
|
+
|
|
61
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.
|
|
62
76
|
|
|
63
77
|
6. Run quality checks:
|