@eventmodelers/cli 1.0.153 → 1.0.154
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 +35 -1
- package/cli.js +51 -8
- package/package.json +1 -1
- package/shared/build-kit/lib/adapters/pocketbase-realtime-adapter.js +46 -20
- package/shared/build-kit/lib/ralph.js +31 -8
- package/shared/skills/connect/SKILL.md +1 -1
- package/shared/skills/learn-eventmodelers-api/SKILL.md +10 -4
- package/shared/skills/ui-contract/SKILL.md +151 -0
- package/shared/skills/update-slice-status/SKILL.md +3 -1
- package/stacks/axon/templates/.claude/skills/build-state-change/SKILL.md +6 -0
- package/stacks/axon/templates/.claude/skills/build-state-view/SKILL.md +6 -0
- package/stacks/axon/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/axon/templates/build-kit/lib/backend-prompt.md +2 -2
- package/stacks/blank/templates/.claude/skills/build-state-change/SKILL.md +12 -0
- package/stacks/blank/templates/.claude/skills/build-state-view/SKILL.md +12 -0
- package/stacks/blank/templates/build-kit/CLAUDE.md +8 -1
- package/stacks/blank/templates/build-kit/lib/backend-prompt.md +2 -2
- package/stacks/classic/templates/.claude/skills/build-state-change/SKILL.md +6 -0
- package/stacks/classic/templates/.claude/skills/build-state-view/SKILL.md +6 -0
- package/stacks/classic/templates/build-kit/lib/backend-prompt.md +2 -2
- package/stacks/kurrent/templates/.claude/skills/build-state-change/SKILL.md +6 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-view/SKILL.md +6 -0
- package/stacks/kurrent/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +2 -2
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/kit/CLAUDE.md +4 -4
- package/stacks/node/templates/.claude/skills/build-state-change/SKILL.md +8 -0
- package/stacks/node/templates/.claude/skills/build-state-change/references/ui-contract-from-openapi.md +17 -0
- package/stacks/node/templates/.claude/skills/build-state-view/SKILL.md +8 -0
- package/stacks/node/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/node/templates/build-kit/lib/backend-prompt.md +2 -2
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/SKILL.md +6 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-view/SKILL.md +6 -0
- package/stacks/opencqrs/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +2 -2
- package/stacks/react/templates/.claude/skills/build-state-change/SKILL.md +5 -0
- package/stacks/react/templates/.claude/skills/build-state-view/SKILL.md +5 -0
- package/stacks/react/templates/build-kit/lib/AGENT.md +1 -1
- package/stacks/react/templates/build-kit/lib/backend-prompt.md +11 -11
- package/stacks/react/templates/build-kit/lib/kit.json +3 -0
- package/stacks/react/templates/build-kit/lib/prompt.md +2 -2
- package/stacks/supabase/templates/.claude/skills/build-state-change/SKILL.md +8 -0
- package/stacks/supabase/templates/.claude/skills/build-state-change/references/ui-contract-from-openapi.md +17 -0
- package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +8 -0
- package/stacks/supabase/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +2 -2
- package/stacks/supabase-react/templates/.claude/skills/build-state-change/SKILL.md +10 -1
- package/stacks/supabase-react/templates/.claude/skills/build-state-view/SKILL.md +4 -0
- package/stacks/supabase-react/templates/build-kit/lib/AGENT.md +1 -1
- package/stacks/supabase-react/templates/build-kit/lib/backend-prompt.md +11 -11
- package/stacks/supabase-react/templates/build-kit/lib/kit.json +3 -0
- package/stacks/supabase-react/templates/build-kit/lib/prompt.md +2 -2
- package/stacks/umadb/templates/.claude/skills/build-state-change/SKILL.md +6 -0
- package/stacks/umadb/templates/.claude/skills/build-state-view/SKILL.md +6 -0
- package/stacks/umadb/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +2 -2
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ui-contract
|
|
3
|
+
description: Publish the slice's UI contract (read contract = GET, write/state-change contract = POST) as its own `## UI Contract` section in the slice's MARKDOWN node in the feedback lane, which the slice export carries in `slice.json` `notes[]` — so the UI build kit finds the contract in one lookup instead of parsing the whole note. Called by every build-state-view / build-state-change skill after the endpoint is built. A build kit can override it by shipping its own `ui-contract` skill.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# UI Contract
|
|
7
|
+
|
|
8
|
+
The UI build kit builds the frontend against what the backend slice **actually exposes**. This skill
|
|
9
|
+
records that as a contract — one per slice, in a fixed, machine-findable place.
|
|
10
|
+
|
|
11
|
+
> Invoke `connect` first if not already connected (`BOARD_ID`). Prefer `mcp__eventmodelers__*` tools;
|
|
12
|
+
> the REST equivalents are in `learn-eventmodelers-api`.
|
|
13
|
+
>
|
|
14
|
+
> **Override**: a build kit that needs a different contract shape or location ships its own
|
|
15
|
+
> `.claude/skills/ui-contract/SKILL.md`. The kit's copy replaces this one at install time (stack
|
|
16
|
+
> templates are applied after the shared skills). Callers only say "invoke `ui-contract`" — they never
|
|
17
|
+
> restate the format.
|
|
18
|
+
|
|
19
|
+
## When
|
|
20
|
+
|
|
21
|
+
At the end of building a slice, **after** the endpoint exists (so the contract describes the real
|
|
22
|
+
route, not the plan), before the final commit:
|
|
23
|
+
|
|
24
|
+
| Slice type | Contract kind |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `STATE_VIEW` (READMODEL) | **read** — `GET` |
|
|
27
|
+
| `STATE_CHANGE` (COMMAND) | **write** — `POST` (a state change) |
|
|
28
|
+
| `AUTOMATION` | none — no UI counterpart, skip |
|
|
29
|
+
|
|
30
|
+
## Step 1 — Derive the contract from the built endpoint
|
|
31
|
+
|
|
32
|
+
Never copy from the plan — the contract describes what was built.
|
|
33
|
+
|
|
34
|
+
1. **Use the source the stack names.** If the calling `build-state-view` / `build-state-change`
|
|
35
|
+
skill's `## UI Contract` section points to a more authoritative source for this stack (for example a
|
|
36
|
+
machine-readable API description it already maintains), derive from that, mechanically.
|
|
37
|
+
2. **Otherwise read the endpoint's route/handler code**: method, path, parameter and field names,
|
|
38
|
+
success status, and the error codes/statuses the handler really returns.
|
|
39
|
+
3. Field `type` / `optional` / `example` come from the `slice.json` element fields.
|
|
40
|
+
4. **Cross-check against `slice.json`**: the `body` / `response.fields` names must equal the command's /
|
|
41
|
+
read model's `fields[]`. A mismatch is an implementation bug — fix the code, don't publish a
|
|
42
|
+
contract that disagrees with `slice.json`.
|
|
43
|
+
|
|
44
|
+
**Read contract** (`kind: "read"`):
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"kind": "read",
|
|
49
|
+
"slice": "<slice title>",
|
|
50
|
+
"sliceId": "<SLICE_BORDER node id>",
|
|
51
|
+
"readModel": "<READMODEL title>",
|
|
52
|
+
"method": "GET",
|
|
53
|
+
"path": "/api/<...>",
|
|
54
|
+
"pathParams": [{ "name": "customerId", "type": "UUID" }],
|
|
55
|
+
"queryParams": [{ "name": "page", "type": "Int", "optional": true }],
|
|
56
|
+
"response": {
|
|
57
|
+
"cardinality": "Single | List",
|
|
58
|
+
"fields": [{ "name": "status", "type": "String", "optional": false, "example": "active" }]
|
|
59
|
+
},
|
|
60
|
+
"errors": [{ "status": 404, "code": "not_found", "when": "no row for this id" }]
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Write contract** (`kind: "write"`):
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"kind": "write",
|
|
69
|
+
"slice": "<slice title>",
|
|
70
|
+
"sliceId": "<SLICE_BORDER node id>",
|
|
71
|
+
"command": "<COMMAND title>",
|
|
72
|
+
"method": "POST",
|
|
73
|
+
"path": "/api/<...>",
|
|
74
|
+
"pathParams": [],
|
|
75
|
+
"body": [{ "name": "itemId", "type": "UUID", "optional": false, "example": "..." }],
|
|
76
|
+
"response": { "status": 200, "body": [] },
|
|
77
|
+
"errors": [{ "status": 400, "code": "snake_case_code", "when": "business rule violated" }]
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Keep it to what a UI needs — no internal details (no table names, no auth plumbing beyond "requires bearer token" if `security` is set).
|
|
82
|
+
|
|
83
|
+
## Step 2 — Write the `## UI Contract` section into the slice's MARKDOWN node
|
|
84
|
+
|
|
85
|
+
1. **Find the node, creating whatever is missing** — never skip or fail because it doesn't exist yet:
|
|
86
|
+
1. `get_board_outline { boardId, chapterId }` → locate the slice's column and the chapter's
|
|
87
|
+
`feedback` lane. **No feedback lane** → create it: `add_lane { boardId, timelineId, lanes: [{ type: "feedback", label: "Notes" }] }`
|
|
88
|
+
(returns the `laneId`; a feedback lane sorts after the spec lane automatically).
|
|
89
|
+
2. Look for a `markdown` node in the feedback lane in the slice's column. **None** → create it with a
|
|
90
|
+
`node:created` event through `submit_node_events` (not `place_element` / cell-drop):
|
|
91
|
+
`{ "id": "<fresh uuid>", "eventType": "node:created", "nodeId": "<fresh uuid>", "chapterId": "<chapterId>",
|
|
92
|
+
"cellId": "<feedbackRowId>-<columnId>", "meta": { "type": "MARKDOWN", "title": "<slice title>",
|
|
93
|
+
"description": "## UI Contract\n\n…" } }` — the new node's body is just the section in the format of item 3 below.
|
|
94
|
+
2. **Upsert only the section** (skip the read when you just created the node): read the node once (`get_node`), then replace the text from the
|
|
95
|
+
`## UI Contract` heading to the next `## ` heading (or end of file) — or append it when absent.
|
|
96
|
+
Leave every other section untouched. Write back `meta.description` via a `node:changed` event
|
|
97
|
+
(`submit_node_events`; the content lives in `description`, never `content`).
|
|
98
|
+
3. **Section format** — exactly this, so it can be extracted with a single match:
|
|
99
|
+
|
|
100
|
+
````markdown
|
|
101
|
+
## UI Contract
|
|
102
|
+
|
|
103
|
+
**READ** `GET /api/customers/{customerId}/reservation` — <one-line purpose>
|
|
104
|
+
|
|
105
|
+
| Part | Name | Type | Optional | Example |
|
|
106
|
+
|---|---|---|---|---|
|
|
107
|
+
| path | customerId | UUID | no | … |
|
|
108
|
+
| response | status | String | no | active |
|
|
109
|
+
|
|
110
|
+
```json ui-contract
|
|
111
|
+
{ ...the Step 1 JSON, verbatim... }
|
|
112
|
+
```
|
|
113
|
+
````
|
|
114
|
+
|
|
115
|
+
The table is for humans; the fenced block whose info string is `ui-contract` is the single
|
|
116
|
+
machine-readable source. Both must say the same thing.
|
|
117
|
+
|
|
118
|
+
## Step 3 — Nothing else to write
|
|
119
|
+
|
|
120
|
+
The board is the single source. The slice export (`fetch` / `get_slice_data`, full projection) carries
|
|
121
|
+
every MARKDOWN node of the slice's column as a plain string in `slice.json` `notes[]` (the
|
|
122
|
+
`outline` / `fields` / `specs` projections leave `notes` out). The UI build kit therefore needs no
|
|
123
|
+
extra file and no board call.
|
|
124
|
+
|
|
125
|
+
## Step 4 — Completion status: `Handover` instead of `Done`
|
|
126
|
+
|
|
127
|
+
A slice with a UI is only finished once the UI kit has built its half. Whether this build kit hands
|
|
128
|
+
over is decided per run, in this order: the task request's `Handover: on|off` line (authoritative — the
|
|
129
|
+
runner resolves `run --handover` over the project setting), else `"handover": true` in
|
|
130
|
+
`.eventmodelers/config.json` (saved by `init --handover` / `eventmodelers config --handover on|off`).
|
|
131
|
+
|
|
132
|
+
- **On** — the build kit's "set the slice to `Done`" for a STATE_VIEW / STATE_CHANGE slice means
|
|
133
|
+
**`Handover`** instead: after the contract is published and the commit/merge succeeded, via
|
|
134
|
+
`update-slice-status` (mirrored in the local `index.json`). The UI kit claims `Handover` slices and sets
|
|
135
|
+
`Done` when its UI is built.
|
|
136
|
+
- **Off / unset** — nothing changes: `Done`.
|
|
137
|
+
- Automations and translations have no UI → always `Done`.
|
|
138
|
+
|
|
139
|
+
## How the UI build kit looks the contract up
|
|
140
|
+
|
|
141
|
+
1. In the slice's `slice.json`, take the `notes[]` entry that contains a `## UI Contract` heading.
|
|
142
|
+
Ignore every other entry.
|
|
143
|
+
2. In that entry, take the fenced block whose info string is `ui-contract` (```` ```json ui-contract ````)
|
|
144
|
+
and parse just that JSON. Ignore the rest of the note.
|
|
145
|
+
3. No such entry → the backend slice isn't built yet, or the slice wasn't re-fetched since; re-fetch
|
|
146
|
+
once, and if still absent build against `slice.json` and note the assumption.
|
|
147
|
+
|
|
148
|
+
## Re-running
|
|
149
|
+
|
|
150
|
+
Idempotent: a rebuilt slice overwrites its own section; it never duplicates the
|
|
151
|
+
section and never touches other sections of the note.
|
|
@@ -23,8 +23,10 @@ Valid status values (case-sensitive):
|
|
|
23
23
|
| Value | Meaning |
|
|
24
24
|
|-------|---------|
|
|
25
25
|
| `Created` | Default — slice has been created but not started |
|
|
26
|
-
| `
|
|
26
|
+
| `Ready` | Modeling is done — specified and ready to be planned for implementation |
|
|
27
|
+
| `Planned` | Work is planned — queued for the backend build kit |
|
|
27
28
|
| `InProgress` | Work is actively in progress |
|
|
29
|
+
| `Handover` | Backend built and its UI contract published (`## UI Contract` in the slice's markdown note) — queued for the UI build kit |
|
|
28
30
|
| `Review` | Ready for review |
|
|
29
31
|
| `Done` | Completed |
|
|
30
32
|
| `Blocked` | Blocked by something |
|
|
@@ -435,6 +435,12 @@ EVENT→READMODEL beats) belongs to `build-state-view`'s own storyline step, sin
|
|
|
435
435
|
touches a projector. If the beat immediately after the command isn't an EVENT, don't force a test —
|
|
436
436
|
leave it undocumented rather than fabricating an assertion.
|
|
437
437
|
|
|
438
|
+
## UI Contract
|
|
439
|
+
|
|
440
|
+
Once the command endpoint is built, invoke the `ui-contract` skill (write contract, `POST`): it publishes
|
|
441
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
442
|
+
(a build kit may override it).
|
|
443
|
+
|
|
438
444
|
## Final Verification
|
|
439
445
|
|
|
440
446
|
Before considering the slice done:
|
|
@@ -319,6 +319,12 @@ class {SliceName}ProjectorTest {
|
|
|
319
319
|
- **Assert with full objects**: Use `containsExactlyInAnyOrder(new Summary(...))` rather than
|
|
320
320
|
field-by-field assertions — catches serialization mismatches.
|
|
321
321
|
|
|
322
|
+
## UI Contract
|
|
323
|
+
|
|
324
|
+
Once the read endpoint is built, invoke the `ui-contract` skill (read contract, `GET`): it publishes
|
|
325
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
326
|
+
(a build kit may override it).
|
|
327
|
+
|
|
322
328
|
## Final Verification: Does the Implementation Match slice.json?
|
|
323
329
|
|
|
324
330
|
Before marking this slice as `Done`, verify the implementation against slice.json:
|
|
@@ -55,7 +55,7 @@ When asked to build a slice, always follow this flow:
|
|
|
55
55
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
56
56
|
4. **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.
|
|
57
57
|
5. Run quality checks (`./mvnw compile -q`, then the slice tests only).
|
|
58
|
-
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
58
|
+
6. 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 `Handover`, not `Done` — see the `ui-contract` skill, Step 4.
|
|
59
59
|
|
|
60
60
|
After you are done, automatically run the tests for the slice that was edited.
|
|
61
61
|
|
|
@@ -36,14 +36,14 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
|
|
|
36
36
|
10. The slice in the json is always true, the code follows what is defined in the json
|
|
37
37
|
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
|
|
38
38
|
fulfills the slice.json. There must be no specification in json, that has no equivalent in code.
|
|
39
|
-
12.
|
|
39
|
+
12. Invoke the `ui-contract` skill for STATE_VIEW / STATE_CHANGE slices (publishes the UI Contract section to the slice's feedback-lane markdown node)
|
|
40
40
|
13. Run quality checks — it is enough to run the tests for the slice only, not all tests:
|
|
41
41
|
- Compile: `./mvnw compile -q`
|
|
42
42
|
- Test: `./mvnw test -Dtest="<SliceName>*" -q`
|
|
43
43
|
If the tests for the slice are not yet named predictably, run `./mvnw test -q` and check for failures.
|
|
44
44
|
15. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge ( update
|
|
45
45
|
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).
|
|
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
47
|
17. Append your progress to `progress.txt` after each step in the iteration.
|
|
48
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.
|
|
49
49
|
19. Finish the iteration.
|
|
@@ -41,3 +41,15 @@ TODO — file layout, naming conventions, framework idioms, how the handler/proj
|
|
|
41
41
|
## Quality gate
|
|
42
42
|
|
|
43
43
|
TODO — this stack's build command and how to run only this slice's tests (not the full suite).
|
|
44
|
+
|
|
45
|
+
## UI Contract
|
|
46
|
+
|
|
47
|
+
Once the command endpoint is built, invoke the `ui-contract` skill (write contract, `POST`): it publishes the contract
|
|
48
|
+
as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it.
|
|
49
|
+
|
|
50
|
+
TODO — **Source for this stack:** say where the contract is derived from. If your stack maintains a
|
|
51
|
+
machine-readable API description (OpenAPI, GraphQL schema, protobuf, ...), name it here and put the
|
|
52
|
+
mapping to the contract keys in a reference file (see `ui-contract-from-openapi.md` in
|
|
53
|
+
`stacks/node/templates/.claude/skills/build-state-change/references/`). If it has none, delete this
|
|
54
|
+
line — the skill then reads the endpoint's route/handler code. If your UI needs a different contract
|
|
55
|
+
shape or location, ship your own `.claude/skills/ui-contract/SKILL.md`; it replaces the shared one.
|
|
@@ -40,3 +40,15 @@ TODO — file layout, naming conventions, framework idioms, how the handler/proj
|
|
|
40
40
|
## Quality gate
|
|
41
41
|
|
|
42
42
|
TODO — this stack's build command and how to run only this slice's tests (not the full suite).
|
|
43
|
+
|
|
44
|
+
## UI Contract
|
|
45
|
+
|
|
46
|
+
Once the read endpoint is built, invoke the `ui-contract` skill (read contract, `GET`): it publishes the contract
|
|
47
|
+
as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it.
|
|
48
|
+
|
|
49
|
+
TODO — **Source for this stack:** say where the contract is derived from. If your stack maintains a
|
|
50
|
+
machine-readable API description (OpenAPI, GraphQL schema, protobuf, ...), name it here and put the
|
|
51
|
+
mapping to the contract keys in a reference file (see `ui-contract-from-openapi.md` in
|
|
52
|
+
`stacks/node/templates/.claude/skills/build-state-change/references/`). If it has none, delete this
|
|
53
|
+
line — the skill then reads the endpoint's route/handler code. If your UI needs a different contract
|
|
54
|
+
shape or location, ship your own `.claude/skills/ui-contract/SKILL.md`; it replaces the shared one.
|
|
@@ -45,7 +45,7 @@ When asked to build a slice, always follow this flow:
|
|
|
45
45
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
46
46
|
4. **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.
|
|
47
47
|
5. Run quality checks (TODO: this stack's build + test commands), then the slice tests only.
|
|
48
|
-
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
48
|
+
6. 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 `Handover`, not `Done` — see the `ui-contract` skill, Step 4.
|
|
49
49
|
|
|
50
50
|
After you are done, automatically run the tests for the slice that was edited.
|
|
51
51
|
|
|
@@ -55,3 +55,10 @@ TODO — a short tree showing where one slice's files land, e.g.:
|
|
|
55
55
|
```
|
|
56
56
|
TODO
|
|
57
57
|
```
|
|
58
|
+
|
|
59
|
+
## UI Contract
|
|
60
|
+
|
|
61
|
+
`build-state-view` and `build-state-change` end by invoking the shared `ui-contract` skill (publishes the
|
|
62
|
+
slice's read/write contract for the UI build kit). Decide for your stack where it is derived from — see
|
|
63
|
+
the `UI Contract` section of those two skills — or override the skill entirely by shipping
|
|
64
|
+
`.claude/skills/ui-contract/SKILL.md`.
|
|
@@ -30,10 +30,10 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
|
|
|
30
30
|
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.
|
|
31
31
|
10. The slice in the json is always true, the code follows what is defined in the json
|
|
32
32
|
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.
|
|
33
|
-
12.
|
|
33
|
+
12. Invoke the `ui-contract` skill for STATE_VIEW / STATE_CHANGE slices (publishes the UI Contract section to the slice's feedback-lane markdown node)
|
|
34
34
|
13. Run quality checks — TODO: your stack's build command, TODO: your stack's test command (slice-scoped only; do not run all tests).
|
|
35
35
|
14. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge (update first)
|
|
36
|
-
15. 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).
|
|
36
|
+
15. 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.
|
|
37
37
|
16. Append your progress to `progress.txt` after each step in the iteration.
|
|
38
38
|
17. 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
39
|
18. Finish the iteration.
|
|
@@ -101,6 +101,12 @@ After the commit, invoke `/record-evidence`: it writes this slice's element →
|
|
|
101
101
|
|
|
102
102
|
---
|
|
103
103
|
|
|
104
|
+
## UI Contract
|
|
105
|
+
|
|
106
|
+
Once the command endpoint is built, invoke the `ui-contract` skill (write contract, `POST`): it publishes
|
|
107
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
108
|
+
(a build kit may override it).
|
|
109
|
+
|
|
104
110
|
## Final Verification: Does the Implementation Match slice.json?
|
|
105
111
|
|
|
106
112
|
- [ ] Every command field is received and used (validated, persisted or passed on)
|
|
@@ -105,6 +105,12 @@ After the commit, invoke `/record-evidence`: it writes this slice's element →
|
|
|
105
105
|
|
|
106
106
|
---
|
|
107
107
|
|
|
108
|
+
## UI Contract
|
|
109
|
+
|
|
110
|
+
Once the read endpoint is built, invoke the `ui-contract` skill (read contract, `GET`): it publishes
|
|
111
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
112
|
+
(a build kit may override it).
|
|
113
|
+
|
|
108
114
|
## Checklist
|
|
109
115
|
|
|
110
116
|
- [ ] Every read model field is returned, sourced from where its feeding event's data is persisted
|
|
@@ -33,11 +33,11 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
|
|
|
33
33
|
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
34
|
10. The slice in the json is always true, the code follows what is defined in the json
|
|
35
35
|
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.
|
|
36
|
-
12.
|
|
36
|
+
12. Invoke the `ui-contract` skill for STATE_VIEW / STATE_CHANGE slices (publishes the UI Contract section to the slice's feedback-lane markdown node)
|
|
37
37
|
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
38
|
14. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge (update first)
|
|
39
39
|
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).
|
|
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
41
|
17. Append your progress to `progress.txt` after each step in the iteration.
|
|
42
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.
|
|
43
43
|
19. Finish the iteration.
|
|
@@ -404,6 +404,12 @@ EVENT→READMODEL beats) belongs to `build-state-view`'s own storyline step. If
|
|
|
404
404
|
after the command isn't an EVENT, don't force a test — leave it undocumented rather than fabricating an
|
|
405
405
|
assertion.
|
|
406
406
|
|
|
407
|
+
## UI Contract
|
|
408
|
+
|
|
409
|
+
Once the command endpoint is built, invoke the `ui-contract` skill (write contract, `POST`): it publishes
|
|
410
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
411
|
+
(a build kit may override it).
|
|
412
|
+
|
|
407
413
|
## Final Verification
|
|
408
414
|
|
|
409
415
|
Before considering the slice done:
|
|
@@ -379,6 +379,12 @@ If a beat between two read-model states is a `COMMAND` rather than an `EVENT`, t
|
|
|
379
379
|
half. If a storyline segment involves a `SCREEN`/other untraceable beat, don't force a test — leave it
|
|
380
380
|
undocumented rather than fabricating an assertion.
|
|
381
381
|
|
|
382
|
+
## UI Contract
|
|
383
|
+
|
|
384
|
+
Once the read endpoint is built, invoke the `ui-contract` skill (read contract, `GET`): it publishes
|
|
385
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
386
|
+
(a build kit may override it).
|
|
387
|
+
|
|
382
388
|
## Final Verification: Does the Implementation Match slice.json?
|
|
383
389
|
|
|
384
390
|
Before marking this slice as `Done`, verify the implementation against slice.json:
|
|
@@ -94,7 +94,7 @@ When asked to build a slice, always follow this flow:
|
|
|
94
94
|
reappears as `Planned` — never dismiss a mismatch as "already implemented" or harmless drift; diff
|
|
95
95
|
slice.json against the code field by field and update the code to match every change.
|
|
96
96
|
5. Run quality checks (`./mvnw compile -q`, then the slice tests only).
|
|
97
|
-
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
97
|
+
6. 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 `Handover`, not `Done` — see the `ui-contract` skill, Step 4.
|
|
98
98
|
|
|
99
99
|
After you are done, automatically run the tests for the slice that was edited.
|
|
100
100
|
|
|
@@ -36,14 +36,14 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
|
|
|
36
36
|
10. The slice in the json is always true, the code follows what is defined in the json
|
|
37
37
|
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
|
|
38
38
|
fulfills the slice.json. There must be no specification in json, that has no equivalent in code.
|
|
39
|
-
12.
|
|
39
|
+
12. Invoke the `ui-contract` skill for STATE_VIEW / STATE_CHANGE slices (publishes the UI Contract section to the slice's feedback-lane markdown node)
|
|
40
40
|
13. Run quality checks — it is enough to run the tests for the slice only, not all tests:
|
|
41
41
|
- Compile: `./mvnw compile -q`
|
|
42
42
|
- Test: `./mvnw test -Dtest="<SliceName>*" -q`
|
|
43
43
|
If the tests for the slice are not yet named predictably, run `./mvnw test -q` and check for failures.
|
|
44
44
|
15. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge ( update
|
|
45
45
|
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).
|
|
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
47
|
17. Append your progress to `progress.txt` after each step in the iteration.
|
|
48
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.
|
|
49
49
|
19. Finish the iteration.
|
|
@@ -39,7 +39,7 @@ Save the full slice list. Count total slices and group by status:
|
|
|
39
39
|
|
|
40
40
|
| Status values |
|
|
41
41
|
|---------------|
|
|
42
|
-
| `Created`, `Planned`, `InProgress`, `Review`, `Done`, `Blocked`, `Assigned`, `Informational` |
|
|
42
|
+
| `Created`, `Ready`, `Planned`, `InProgress`, `Handover`, `Review`, `Done`, `Blocked`, `Assigned`, `Informational` |
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
@@ -122,7 +122,7 @@ report `sliceStatus`. Read it now, once: `mcp__eventmodelers__get_board_outline
|
|
|
122
122
|
gives every column a `sliceStatus` when a slice spans it. Look up each chain node's column.
|
|
123
123
|
|
|
124
124
|
- **Every node writable** (`Created`, or no `sliceStatus`) → continue with Step 4.
|
|
125
|
-
- **Any node in a column with another status** (`Done`, `Review`, `InProgress`, `Blocked`, `Planned`, `Assigned`,
|
|
125
|
+
- **Any node in a column with another status** (`Done`, `Review`, `Handover`, `InProgress`, `Blocked`, `Ready`, `Planned`, `Assigned`,
|
|
126
126
|
`Informational`) → **do not write that node.** If the task text says the person already confirmed changing
|
|
127
127
|
that locked slice (*"The person confirmed changing the locked slice '…'"*, with an `origin_message_id`), you may
|
|
128
128
|
change those elements and only those. Otherwise write **nothing** — not even the nodes that are writable, the
|
|
@@ -84,8 +84,8 @@ header's `standalone=on|off` tells you which mode they come in.
|
|
|
84
84
|
|
|
85
85
|
At the start of every session, read `.agent-modeling-kit/AGENTS.md` if it exists to load accumulated learnings.
|
|
86
86
|
|
|
87
|
-
**Only touch elements in a slice whose status is `Created` — unless the person explicitly confirmed it.** Every other status — `Planned`,
|
|
88
|
-
`Assigned`, `InProgress`, `Review`, `Blocked`, `Done`, `Informational` — means someone is working
|
|
87
|
+
**Only touch elements in a slice whose status is `Created` — unless the person explicitly confirmed it.** Every other status — `Ready`, `Planned`,
|
|
88
|
+
`Assigned`, `InProgress`, `Handover`, `Review`, `Blocked`, `Done`, `Informational` — means someone is working
|
|
89
89
|
on that slice: read it for context, but never change, move, rename or delete its elements, and
|
|
90
90
|
never add scenarios, fields or examples to them. An element in no slice at all is not locked.
|
|
91
91
|
`get_board_outline` returns `sliceStatus` per column (`get_nodes` does not carry it), so the
|
|
@@ -312,8 +312,8 @@ for it. Instead:
|
|
|
312
312
|
- a **screen idea** in the conversation ("what could that screen look like?") → `screen`, a sandboxed HTML mock-up in the chat; putting a screen on the board is `/html-screen` work;
|
|
313
313
|
- **where one piece of information comes from and where it is used** → `dataJourney` (the `/data-journey` skill);
|
|
314
314
|
- **who does what with which work object, per chapter** → an `svg` domain story (the `/domain-story` skill);
|
|
315
|
-
- **"draw" / "sketch" / "diagram" something** (a UML diagram, a flow, a class model) → a snippet in the chat (`
|
|
316
|
-
`code` block with
|
|
315
|
+
- **"draw" / "sketch" / "diagram" something** (a UML diagram, a flow, a class model) → a snippet in the chat (`mermaid` for a sequence/flow/state/ER/class diagram written as
|
|
316
|
+
Mermaid, `svg` for a picture you draw yourself, or a `code` block with PlantUML/ASCII), **never** drawn on the board with stickies, arrows or `create_drawing`.
|
|
317
317
|
Only an explicit request to put it on the board changes that, and then as an image (`/domain-story` § board), not rebuilt from shapes;
|
|
318
318
|
- **rows and columns** — a comparison, a matrix, a short list with a few attributes per item → `table`.
|
|
319
319
|
- **a prototype you just built** (the `/prototype` skill) → `prototype`, the uploaded page running in the chat with a Full screen button;
|
|
@@ -417,6 +417,14 @@ import {api as {SliceName}Api} from './slices/{context}/{SliceName}/routes';
|
|
|
417
417
|
|
|
418
418
|
---
|
|
419
419
|
|
|
420
|
+
## UI Contract
|
|
421
|
+
|
|
422
|
+
Once the command endpoint is built, invoke the `ui-contract` skill (write contract, `POST`): it publishes
|
|
423
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
424
|
+
(a build kit may override it).
|
|
425
|
+
|
|
426
|
+
**Source for this stack:** derive the contract from the handler's `@openapi` block, using `references/ui-contract-from-openapi.md`.
|
|
427
|
+
|
|
420
428
|
## Files to create
|
|
421
429
|
|
|
422
430
|
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# UI Contract — derive from the `@openapi` block
|
|
2
|
+
|
|
3
|
+
Used by the `ui-contract` skill. This stack's `routes.ts` carries an `@openapi` JSDoc block above every
|
|
4
|
+
handler (guarded by the `openapi-annotation` commit check), so derive the contract from it mechanically
|
|
5
|
+
instead of re-reading handler logic.
|
|
6
|
+
|
|
7
|
+
| Contract key | OpenAPI source |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `method` | the verb key under the path (`get` / `post`) |
|
|
10
|
+
| `path` | the path key, verbatim (`{param}` style) |
|
|
11
|
+
| `pathParams` / `queryParams` | `parameters[]` with `in: path` / `in: query` → `name`, `schema` (`optional` = not `required`) |
|
|
12
|
+
| `body` (write) | `requestBody…schema.properties` |
|
|
13
|
+
| `response.fields` (read) | the `200` response schema `properties` (follow a `$ref` to `components.schemas`); `Single` vs `List` = object vs `type: array` |
|
|
14
|
+
| `response.status` (write) | the success response code |
|
|
15
|
+
| `errors[]` | every non-2xx response: `status` = the key, `code` / `when` = its description / `error` example |
|
|
16
|
+
| `type` | `string`+`uuid` → `UUID`, `integer`/`int32` → `Int`, `int64` → `Long`, `number`/`double` → `Double`, `number` → `Decimal`, `boolean` → `Boolean`, `date` / `date-time` → `Date` / `DateTime`, `object` → `Custom`, else `String` |
|
|
17
|
+
| `example` | the schema's `example`, nothing invented |
|
|
@@ -484,6 +484,14 @@ import {api as {SliceName}Api} from './slices/{context}/{SliceName}/routes';
|
|
|
484
484
|
|
|
485
485
|
---
|
|
486
486
|
|
|
487
|
+
## UI Contract
|
|
488
|
+
|
|
489
|
+
Once the read endpoint is built, invoke the `ui-contract` skill (read contract, `GET`): it publishes
|
|
490
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
491
|
+
(a build kit may override it).
|
|
492
|
+
|
|
493
|
+
**Source for this stack:** derive the contract from the handler's `@openapi` block, using `../build-state-change/references/ui-contract-from-openapi.md`.
|
|
494
|
+
|
|
487
495
|
## Files to create / modify
|
|
488
496
|
|
|
489
497
|
```
|
|
@@ -50,7 +50,7 @@ When asked to build a slice, always follow this flow:
|
|
|
50
50
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
51
51
|
4. **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.
|
|
52
52
|
5. Run quality checks (`npm run build`, then the slice tests only).
|
|
53
|
-
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
53
|
+
6. 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 `Handover`, not `Done` — see the `ui-contract` skill, Step 4.
|
|
54
54
|
|
|
55
55
|
After you are done, automatically run the tests for the slice that was edited.
|
|
56
56
|
|
|
@@ -32,12 +32,12 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
|
|
|
32
32
|
10. The slice in the json is always true, the code follows what is defined in the json
|
|
33
33
|
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
|
|
34
34
|
fulfills the slice.json. There must be no specification in json, that has no equivalent in code.
|
|
35
|
-
12.
|
|
35
|
+
12. Invoke the `ui-contract` skill for STATE_VIEW / STATE_CHANGE slices (publishes the UI Contract section to the slice's feedback-lane markdown node)
|
|
36
36
|
13. Run quality checks ( npm run build, npm run test ) - Attention - it´s enough to run the tests for the slice. Do not run all tests.
|
|
37
37
|
14. even if the slice is fully implemented, run your test-analyzer skill and provide the code-slice.json file as defined in the skill
|
|
38
38
|
15. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge ( update
|
|
39
39
|
first )
|
|
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).
|
|
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
41
|
17. Append your progress to `progress.txt` after each step in the iteration.
|
|
42
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.
|
|
43
43
|
19. Finish the iteration.
|
|
@@ -399,6 +399,12 @@ EVENT→READMODEL beats) belongs to `build-state-view`'s own storyline step, sin
|
|
|
399
399
|
touches a projector. If the beat immediately after the command isn't an EVENT, don't force a test —
|
|
400
400
|
leave it undocumented rather than fabricating an assertion.
|
|
401
401
|
|
|
402
|
+
## UI Contract
|
|
403
|
+
|
|
404
|
+
Once the command endpoint is built, invoke the `ui-contract` skill (write contract, `POST`): it publishes
|
|
405
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
406
|
+
(a build kit may override it).
|
|
407
|
+
|
|
402
408
|
## Final Verification
|
|
403
409
|
|
|
404
410
|
Before considering the slice done:
|
|
@@ -342,6 +342,12 @@ to `build-state-change` (its own command-handler test), not here — only projec
|
|
|
342
342
|
`READMODEL` half. If a storyline segment involves a `SCREEN`/other untraceable beat, don't force a
|
|
343
343
|
test — leave it undocumented in code rather than fabricating an assertion.
|
|
344
344
|
|
|
345
|
+
## UI Contract
|
|
346
|
+
|
|
347
|
+
Once the read endpoint is built, invoke the `ui-contract` skill (read contract, `GET`): it publishes
|
|
348
|
+
the endpoint's contract as the `## UI Contract` section of the slice's feedback-lane markdown node, which the slice export then carries in `slice.json` `notes[]`. Do not restate the format here — the skill owns it
|
|
349
|
+
(a build kit may override it).
|
|
350
|
+
|
|
345
351
|
## Final Verification: Does the Implementation Match slice.json?
|
|
346
352
|
|
|
347
353
|
Before marking this slice as `Done`, verify the implementation against slice.json:
|
|
@@ -80,7 +80,7 @@ When asked to build a slice, always follow this flow:
|
|
|
80
80
|
reappears as `Planned` — never dismiss a mismatch as "already implemented" or harmless drift; diff
|
|
81
81
|
slice.json against the code field by field and update the code to match every change.
|
|
82
82
|
5. Run quality checks (`./mvnw compile -q`, then the slice tests only).
|
|
83
|
-
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
83
|
+
6. 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 `Handover`, not `Done` — see the `ui-contract` skill, Step 4.
|
|
84
84
|
|
|
85
85
|
After you are done, automatically run the tests for the slice that was edited.
|
|
86
86
|
|
|
@@ -36,14 +36,14 @@ You work within **exactly ONE context at a time** — the one named in `.build-k
|
|
|
36
36
|
10. The slice in the json is always true, the code follows what is defined in the json
|
|
37
37
|
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
|
|
38
38
|
fulfills the slice.json. There must be no specification in json, that has no equivalent in code.
|
|
39
|
-
12.
|
|
39
|
+
12. Invoke the `ui-contract` skill for STATE_VIEW / STATE_CHANGE slices (publishes the UI Contract section to the slice's feedback-lane markdown node)
|
|
40
40
|
13. Run quality checks — it is enough to run the tests for the slice only, not all tests:
|
|
41
41
|
- Compile: `./mvnw compile -q`
|
|
42
42
|
- Test: `./mvnw test -Dtest="<SliceName>*" -q`
|
|
43
43
|
If the tests for the slice are not yet named predictably, run `./mvnw test -q` and check for failures.
|
|
44
44
|
15. If checks pass, commit ALL changes with message: `feat: [Slice Name]` and merge back to main as FF merge ( update
|
|
45
45
|
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).
|
|
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
47
|
17. Append your progress to `progress.txt` after each step in the iteration.
|
|
48
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.
|
|
49
49
|
19. Finish the iteration.
|
|
@@ -30,6 +30,11 @@ From the slice definition, extract:
|
|
|
30
30
|
- **events[]** — list of events emitted by each command
|
|
31
31
|
- **specifications[]** — test scenarios (given/when/then)
|
|
32
32
|
|
|
33
|
+
- **UI contract** — the backend slice's published write (`POST`) contract: look it up as described in the
|
|
34
|
+
`ui-contract` skill ("How the UI build kit looks the contract up": the `## UI Contract` entry in
|
|
35
|
+
`slice.json` `notes[]`, parse only its `ui-contract` block). It fixes the request: `path` (+ `pathParams`), the exact `body` fields, the success `response`, and `errors[]` (status + code) — surface each error code as its own user-facing state, not one generic failure. When absent, the backend slice isn't
|
|
36
|
+
built or re-fetched yet: build against `slice.json` and note the assumption in `progress.txt`.
|
|
37
|
+
|
|
33
38
|
> **Comments & description**: each element carries a `comments: string[]` array (board comments) and a `description` field — use them as implementation hints, and resolve consumed comments via `POST <BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/<nodeId>/comments/<commentId>/resolve`.
|
|
34
39
|
|
|
35
40
|
---
|
|
@@ -29,6 +29,11 @@ From the slice definition, extract:
|
|
|
29
29
|
- **projections[]** / **queries[]** — the read model(s) this slice serves
|
|
30
30
|
- **specifications[]** — test scenarios (given/when/then)
|
|
31
31
|
|
|
32
|
+
- **UI contract** — the backend slice's published read (`GET`) contract: look it up as described in the
|
|
33
|
+
`ui-contract` skill ("How the UI build kit looks the contract up": the `## UI Contract` entry in
|
|
34
|
+
`slice.json` `notes[]`, parse only its `ui-contract` block). It fixes the request: `path` (+ `pathParams`/`queryParams`), the exact `response.fields` and `Single` vs `List` cardinality, and `errors[]` — render each error status as a distinct state. When absent, the backend slice isn't
|
|
35
|
+
built or re-fetched yet: build against `slice.json` and note the assumption in `progress.txt`.
|
|
36
|
+
|
|
32
37
|
> **Comments & description**: each element carries a `comments: string[]` array (board comments) and a `description` field — use them as implementation hints, and resolve consumed comments via `POST <BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/<nodeId>/comments/<commentId>/resolve`.
|
|
33
38
|
|
|
34
39
|
---
|