@eventmodelers/cli 1.0.46 → 1.0.48
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 +1 -1
- package/cli.js +2 -0
- package/package.json +1 -1
- package/shared/skills/learn-eventmodelers-api/SKILL.md +52 -46
- package/shared/skills/request-feedback/SKILL.md +7 -5
- package/stacks/axon/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/blank/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/cratis-csharp/templates/build-kit/CLAUDE.md +9 -0
- package/stacks/kurrent/templates/build-kit/CLAUDE.md +3 -1
- package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/SKILL.md +2 -2
- package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +0 -1
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/references/examples.md +2 -2
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-core-rules/SKILL.md +2 -2
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-interview-protocol/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +4 -4
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +1 -1
- package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +13 -4
- package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +2 -2
- package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +5 -5
- package/stacks/modeling-kit/templates/kit/AGENTS.md +1 -1
- package/stacks/modeling-kit/templates/kit/CLAUDE.md +2 -2
- package/stacks/node/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/opencqrs/templates/build-kit/CLAUDE.md +3 -1
- package/stacks/supabase/templates/build-kit/CLAUDE.md +1 -1
- package/stacks/umadb/templates/build-kit/CLAUDE.md +1 -1
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ Use skills in Claude Code with `/skill-name`:
|
|
|
97
97
|
| `/update-slice-status` | Update slice status on the board |
|
|
98
98
|
| `/load-slice` | Persist board slices to disk (backend stacks) |
|
|
99
99
|
| `/build-state-change`, `/build-state-view`, `/build-automation`, `/build-webhook` | Implement a slice's command/view/automation/webhook (backend stacks) |
|
|
100
|
-
| `/request-feedback` | Post a
|
|
100
|
+
| `/request-feedback` | Post a comment and mark a slice `Blocked` when it's genuinely ambiguous (backend stacks) |
|
|
101
101
|
|
|
102
102
|
Which skills install depends on the chosen stack — see `stacks/<name>/templates/.claude/skills/`. `/connect`, `/learn-eventmodelers-api`, `/update-slice-status`, and `/request-feedback` have no stack-specific content and install into every stack from `shared/skills/` instead.
|
|
103
103
|
|
package/cli.js
CHANGED
|
@@ -1704,6 +1704,7 @@ credentialFlags(program
|
|
|
1704
1704
|
.description('Refresh an already-installed kit from the current CLI version — re-copies skills and the kit dir (.build-kit or .agent-modeling-kit) so you pick up script/skill updates after upgrading. Unlike `init`, never touches the project root scaffold or the root CLAUDE.md router, and leaves existing credentials alone unless --force is passed.')
|
|
1705
1705
|
.option('--modeling', 'Refresh the modeling kit (.agent-modeling-kit) instead of a build kit')
|
|
1706
1706
|
.option('--stack <name>', `Override which stack to refresh from (${Object.keys(REINITIABLE_STACKS).join(', ')}) instead of the one recorded in install-manifest.json — use this when the manifest is missing/stale, or to switch a .build-kit install to a different stack`)
|
|
1707
|
+
.option('--hooks', 'Install the slice commit-scope guard (.githooks/pre-commit) and wire it up via `git config core.hooksPath .githooks` — same as `init --hooks`, for turning it on after the fact without a full re-scaffold. Off by default.')
|
|
1707
1708
|
.option('--global', 'Re-install skills into ~/.claude/skills/ instead of the project — defaults to however they were originally installed')
|
|
1708
1709
|
.option('-f, --force', 'Re-prompt for credentials even if a config already has everything required — overwrites the existing config.json'))
|
|
1709
1710
|
.action(async (opts, command) => {
|
|
@@ -1745,6 +1746,7 @@ credentialFlags(program
|
|
|
1745
1746
|
force: opts.force,
|
|
1746
1747
|
credentialOverrides: credentialOverridesFromOpts(opts),
|
|
1747
1748
|
skipRootScaffold: true,
|
|
1749
|
+
hooks: opts.hooks,
|
|
1748
1750
|
});
|
|
1749
1751
|
});
|
|
1750
1752
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eventmodelers/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.48",
|
|
4
4
|
"description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, Cratis, OpenCQRS, UmaDB, Kurrent, or modeling-only)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -54,7 +54,7 @@ Server name: `eventmodelers`. Every tool takes `boardId` explicitly; none need `
|
|
|
54
54
|
| `set_connection` | `boardId`, `source`, `target`, `action` (`'connect'\|'remove'`) | Add or remove a type-checked directed edge. Batch form `set_connections` takes `connections[]` (applied in order) plus `compact?` — `compact: true` returns a `{connected, existed, removed, notFound, failed, errors}` tally instead of one row per edge | — (via `edges` on §3 events) |
|
|
55
55
|
| `auto_connect_node` | `boardId`, `nodeId` | Re-run auto-connect for a node | §3 `POST .../nodes/:nodeId/auto-connect` |
|
|
56
56
|
| `link_element` | `boardId`, `nodeId`, `targetNodeId` | Link two existing same-type nodes: `targetNodeId` is replaced with a full copy of `nodeId`'s meta plus `meta.linkedTo`. Linking means first create, then link | §3 `POST .../nodes/:nodeId/link` |
|
|
57
|
-
| `add_comment` | `boardId`, `nodeId`, `text`, `type?` (`'COMMENT'\|'TASK'
|
|
57
|
+
| `add_comment` | `boardId`, `nodeId`, `text`, `type?` (`'COMMENT'\|'TASK'`), `author?` | Add a comment — word the `text` as a question to flag gaps/edge cases during review; there is no separate `QUESTION` type | — (via comment events) |
|
|
58
58
|
| `update_comment` | `boardId`, `nodeId`, `commentId`, `action` (`'resolve'\|'delete'`) | Resolve or delete a comment | — (via comment events) |
|
|
59
59
|
| `create_screen` | `boardId`, `contentType` (`'image'\|'sketch'\|'html'`), `nodeId?`, `chapterId`, `cellId?`/`cellName?`, plus content fields (`imageBase64`/`mimeType`, `elements[]`, or `pages[]`/`backgroundColor`), `description?`, `fields?`, `autoConnect?` | Create + place a new screen node (SCREEN or HTML_SCREEN) atomically, in one call. Batch form `create_screens` takes `screens[]` (HTML only) + `autoConnect?`. `autoConnect: false` places without wiring to timeline neighbors | §4 `POST .../images/:id/sketch` + `image-nodes` |
|
|
60
60
|
| `render_screen` | `boardId`, `nodeId`, `elements[]?` (SCREEN) or `pages[]?`+`backgroundColor?` (HTML_SCREEN), `description?` | Update an existing screen's content — exactly one of `elements`/`pages` | §4 `POST .../images/:id/sketch` + `image-nodes` |
|
|
@@ -66,7 +66,7 @@ Server name: `eventmodelers`. Every tool takes `boardId` explicitly; none need `
|
|
|
66
66
|
| `commit_board_to_git` | `boardId` | Force a git-extension commit/push, bypassing the autoCommit gate | — (MCP-only; git extension) |
|
|
67
67
|
| `update_prompt_status` | `promptId`, `newStatus`, `comment?` | Update a prompt's lifecycle status (`ADDED`/`CLAIMED`/`IN_PROGRESS`/`DONE`), optionally with a progress comment. Not board-scoped — no `boardId` arg; the prompt's board is resolved server-side. | §14 `POST .../prompts/:id/status` |
|
|
68
68
|
|
|
69
|
-
**Not exposed via MCP at all** — always use REST/curl for these: §7 Config Import, §10 Snapshots, §11–12
|
|
69
|
+
**Not exposed via MCP at all** — always use REST/curl for these: §7 Config Import, §10 Snapshots, §11–12 Invitations, §13 Utility (`/api/user`, swagger), and the rest of §14 Prompts (submission, claiming, deletion, realtime-token) — only the status-update endpoint has an MCP tool (`update_prompt_status`, used by the `update-prompt-status` skill); everything else in Prompts is an intentionally separate lifecycle the board-content MCP server doesn't otherwise own.
|
|
70
70
|
|
|
71
71
|
**Capabilities with no direct MCP filter** — e.g. REST's `GET .../nodes?cellId=<id>&timelineId=<id>` and `?colId=<id>&timelineId=<id>` (§3) have no equivalent params on `get_nodes`. Either call the REST endpoint directly, or get the same answer by calling `get_node` on the CHAPTER and reading `meta.timelineData.cells` (sparse array; a cell absent from it is empty) instead of asking the server to filter by cell/column.
|
|
72
72
|
|
|
@@ -736,58 +736,48 @@ Delete a snapshot.
|
|
|
736
736
|
|
|
737
737
|
---
|
|
738
738
|
|
|
739
|
-
## 11.
|
|
739
|
+
## 11. Invitations (Organization Membership) — Commands
|
|
740
740
|
|
|
741
|
-
|
|
742
|
-
```typescript
|
|
743
|
-
{
|
|
744
|
-
ok: true
|
|
745
|
-
next_expected_stream_version: number
|
|
746
|
-
last_event_global_position: number
|
|
747
|
-
}
|
|
748
|
-
```
|
|
749
|
-
|
|
750
|
-
Optional headers on all: `correlation_id`, `causation_id`
|
|
741
|
+
**Files**: `src/slices/organization/InviteUser/routes.ts`, `src/slices/organization/ConfirmInvitation/routes.ts`, `src/slices/organization/DeleteInvitation/routes.ts`
|
|
751
742
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
743
|
+
There is no generic "group"/"role-assignment" API — an organization *is* the group, and a
|
|
744
|
+
member's role is set once, at invite time (there is no separate call to change an existing
|
|
745
|
+
member's role afterward). All of these require a Supabase JWT (`Authorization: Bearer`), never
|
|
746
|
+
a bot `x-token`.
|
|
755
747
|
|
|
756
|
-
|
|
748
|
+
### POST `/api/org/:orga_id/invitations`
|
|
749
|
+
Invite a user to join an organization with a given role. Caller must already be an `admin` of `orga_id`.
|
|
757
750
|
|
|
758
|
-
|
|
759
|
-
**
|
|
760
|
-
**
|
|
751
|
+
**Body**: `{ role: string, email: string, description?: string }`
|
|
752
|
+
**Response**: `201` — invitation created
|
|
753
|
+
**Errors**: `400` role/email missing · `403` caller is not an org admin · `409` user already invited or already a member
|
|
761
754
|
|
|
762
755
|
---
|
|
763
756
|
|
|
764
|
-
### POST `/api/
|
|
765
|
-
|
|
766
|
-
**Event emitted**: `InvitationAccepted`
|
|
767
|
-
|
|
768
|
-
---
|
|
757
|
+
### POST `/api/invitations/:token/confirm`
|
|
758
|
+
Accept an invitation — `token` is the invitation's own token (from the invite email link), not an API token. The confirming user's own account email must match the invited email.
|
|
769
759
|
|
|
770
|
-
|
|
771
|
-
**
|
|
772
|
-
**Event emitted**: `RoleAssigned`
|
|
760
|
+
**Response**: `200` — invitation confirmed, membership created
|
|
761
|
+
**Errors**: `404` invitation not found
|
|
773
762
|
|
|
774
763
|
---
|
|
775
764
|
|
|
776
|
-
|
|
765
|
+
### DELETE `/api/org/:orga_id/invitations/:invitation_id`
|
|
766
|
+
Cancel a pending invitation.
|
|
777
767
|
|
|
778
|
-
|
|
768
|
+
**Response**: `200`/`204` on success
|
|
769
|
+
|
|
770
|
+
---
|
|
779
771
|
|
|
780
|
-
|
|
781
|
-
Group details. Filter: `?_id=groupId`
|
|
772
|
+
## 12. Invitations (Organization Membership) — Read Models
|
|
782
773
|
|
|
783
|
-
|
|
784
|
-
Pending invitations. Filter: `?_id=invitationId`
|
|
774
|
+
All require a Supabase JWT (`Authorization: Bearer`).
|
|
785
775
|
|
|
786
|
-
### GET `/api/
|
|
787
|
-
|
|
776
|
+
### GET `/api/user-organizations`
|
|
777
|
+
Organizations (and the caller's role in each) that the authenticated user belongs to.
|
|
788
778
|
|
|
789
|
-
### GET `/api/
|
|
790
|
-
|
|
779
|
+
### GET `/api/client/org/:orgId/invitations`
|
|
780
|
+
Pending invitations for an organization (client-facing list — used by the org settings UI).
|
|
791
781
|
|
|
792
782
|
---
|
|
793
783
|
|
|
@@ -883,6 +873,22 @@ Exchange an `x-token` for a short-lived Supabase-compatible JWT, used to subscri
|
|
|
883
873
|
|
|
884
874
|
---
|
|
885
875
|
|
|
876
|
+
### POST `/api/agent-alive`
|
|
877
|
+
Record a heartbeat ping for a running modeling/build agent. Auth: Supabase JWT (`Authorization: Bearer`) — exchange the `x-token` for one first via `GET /api/org/:orgId/prompts/realtime-token` above; a raw `x-token` alone is not accepted here.
|
|
878
|
+
|
|
879
|
+
**Body**: `{ token: string, board_id?: string, agent_type: 'MODELING' | 'BUILD', agent_id: string }`
|
|
880
|
+
**Response**: `200` — `{ ok: true }`
|
|
881
|
+
**Errors**: `400` `agent_id`/`agent_type` missing · `404` token not found
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
885
|
+
### GET `/api/org/:orgId/boards/:boardId/agent-alive`
|
|
886
|
+
Check whether an agent has pinged for a board within the last 45s. Auth: `x-token` (bot) or a Supabase JWT (`Authorization: Bearer`) — either works.
|
|
887
|
+
|
|
888
|
+
**Response**: `200` — `{ alive: boolean, agentTypes: string[] }`
|
|
889
|
+
|
|
890
|
+
---
|
|
891
|
+
|
|
886
892
|
## Domain Events
|
|
887
893
|
|
|
888
894
|
### Snapshot Events (`src/events/SnapshotsEvents.ts`)
|
|
@@ -896,14 +902,14 @@ SnapshotShared // { id }
|
|
|
896
902
|
SnapshotPublished // { id, payloadId, bucket, path }
|
|
897
903
|
```
|
|
898
904
|
|
|
899
|
-
###
|
|
905
|
+
### Invitation Events (`src/slices/organization/OrganizationEvent.ts`)
|
|
900
906
|
|
|
901
907
|
```typescript
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
908
|
+
UserInvited // { orgaId, userId, role, invitationId, token, description?, boardId?, email? }
|
|
909
|
+
InvitationConfirmed // { orgaId, userId, invitationId, token?, email? }
|
|
910
|
+
InvitationDeleted // { invitationId }
|
|
911
|
+
UserAssignedToOrganization // { id, userId, orgaId, role?, boardId?, email? }
|
|
912
|
+
UserRemovedFromOrganization // { orgaId, userId }
|
|
907
913
|
```
|
|
908
914
|
|
|
909
915
|
All events support optional metadata: `user_id`, `correlation_id`, `causation_id`
|
|
@@ -928,7 +934,7 @@ All events support optional metadata: `user_id`, `correlation_id`, `causation_id
|
|
|
928
934
|
| `src/slices/slicedata/routes.ts` | Slice data read models |
|
|
929
935
|
| `src/slices/extensions/routes.ts` | Extension management |
|
|
930
936
|
| `src/slices/Snapshots/routes.ts` | Snapshot CRUD |
|
|
931
|
-
| `src/slices/
|
|
937
|
+
| `src/slices/organization/InviteUser/routes.ts`, `ConfirmInvitation/routes.ts`, `DeleteInvitation/routes.ts` | Organization invitation commands |
|
|
932
938
|
| `src/events/SnapshotsEvents.ts` | Snapshot domain events |
|
|
933
|
-
| `src/
|
|
939
|
+
| `src/slices/organization/OrganizationEvent.ts` | Organization/invitation domain events |
|
|
934
940
|
| `backend/src/server.ts` | Route wiring, CORS, `/api/user` |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: request-feedback
|
|
3
|
-
description: Post a
|
|
3
|
+
description: Post a comment on a slice and mark it Blocked when the slice's requirements are genuinely ambiguous, contradictory, or missing something a decision depends on. This is an escalation path, not a routine step — reach for it only when you cannot proceed without guessing.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Request Feedback
|
|
@@ -57,7 +57,7 @@ From `$ARGUMENTS` or the calling skill's context, extract:
|
|
|
57
57
|
|-------|---------------|---------|
|
|
58
58
|
| `sliceName` or `sliceId` | the slice being worked on | **required** — one of the two |
|
|
59
59
|
| `question` | the specific ambiguity or missing piece, phrased as a question | **required** |
|
|
60
|
-
| `author` | author identifier string | `agent` |
|
|
60
|
+
| `author` | author identifier string | `agent-$CLAUDE_CODE_SESSION_ID` (falls back to `agent` if that env var is unset) |
|
|
61
61
|
|
|
62
62
|
## Step 2 — Resolve the slice's node id
|
|
63
63
|
|
|
@@ -81,12 +81,14 @@ Find the slice whose `title` matches `sliceName` (case-insensitive), or whose `i
|
|
|
81
81
|
If no match is found, stop and list the available slice titles so the caller can pick one. Save the
|
|
82
82
|
matched slice's `id` as `SLICE_NODE_ID` and its current `status` as `CURRENT_STATUS`.
|
|
83
83
|
|
|
84
|
-
## Step 3 — Post the
|
|
84
|
+
## Step 3 — Post the comment
|
|
85
|
+
|
|
86
|
+
There is no separate `QUESTION` type at the API level — post a normal `COMMENT` worded as a question.
|
|
85
87
|
|
|
86
88
|
Prefer MCP:
|
|
87
89
|
|
|
88
90
|
```
|
|
89
|
-
mcp__eventmodelers__add_comment { "boardId": "<BOARD_ID>", "nodeId": "<SLICE_NODE_ID>", "text": "<question>", "type": "
|
|
91
|
+
mcp__eventmodelers__add_comment { "boardId": "<BOARD_ID>", "nodeId": "<SLICE_NODE_ID>", "text": "<question>", "type": "COMMENT", "author": "<author>" }
|
|
90
92
|
```
|
|
91
93
|
|
|
92
94
|
**Fallback (no MCP):**
|
|
@@ -95,7 +97,7 @@ mcp__eventmodelers__add_comment { "boardId": "<BOARD_ID>", "nodeId": "<SLICE_NOD
|
|
|
95
97
|
curl -s -X POST "<BASE_URL>/api/org/<ORG_ID>/boards/<BOARD_ID>/nodes/<SLICE_NODE_ID>/comments" \
|
|
96
98
|
-H "Authorization: Bearer <TOKEN>" \
|
|
97
99
|
-H "Content-Type: application/json" \
|
|
98
|
-
-d '{"text":"<question>","type":"
|
|
100
|
+
-d '{"text":"<question>","type":"COMMENT","author":"<author>"}'
|
|
99
101
|
```
|
|
100
102
|
|
|
101
103
|
Response: `201 {"id":"<commentId>"}`. Save it as `COMMENT_ID` — the calling skill may want to reference
|
|
@@ -58,7 +58,7 @@ When asked to build a slice, always follow this flow:
|
|
|
58
58
|
- **State-view** — `projections` or `queries` array is non-empty → invoke `/build-state-view`
|
|
59
59
|
- **State-change** — default (has `commands` / `events`) → invoke `/build-state-change`
|
|
60
60
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
61
|
-
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.
|
|
61
|
+
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.
|
|
62
62
|
5. Run quality checks (`./mvnw compile -q`, then the slice tests only).
|
|
63
63
|
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
64
64
|
|
|
@@ -48,7 +48,7 @@ When asked to build a slice, always follow this flow:
|
|
|
48
48
|
- **State-view** — `projections` or `queries` array is non-empty → invoke `/build-state-view`
|
|
49
49
|
- **State-change** — default (has `commands` / `events`) → invoke `/build-state-change`
|
|
50
50
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
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.
|
|
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 (TODO: this stack's build + test commands), then the slice tests only.
|
|
53
53
|
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
54
54
|
|
|
@@ -16,6 +16,15 @@ then stop work on this slice for this run. This is an escalation path, not a rou
|
|
|
16
16
|
`slice.json` and the matching build skill's own instructions fully first; most slices are fully
|
|
17
17
|
specified and need none of this.
|
|
18
18
|
|
|
19
|
+
## No such thing as harmless drift
|
|
20
|
+
|
|
21
|
+
`slice.json` is always the desired state — the code follows what it defines, never the other way
|
|
22
|
+
around. If code for a slice already exists — most often because it was previously `Done` and got moved
|
|
23
|
+
back to `Planned` — never conclude "already implemented" and move on. A slice does not return to
|
|
24
|
+
`Planned` without a reason: diff the current `slice.json` against the existing implementation field by
|
|
25
|
+
field (events, commands, params, specifications, routes) and update the code to match every difference
|
|
26
|
+
you find. Only mark it `Done` once there is no gap left.
|
|
27
|
+
|
|
19
28
|
## Structure (learn from `SomeModule/SomeFeature/`)
|
|
20
29
|
|
|
21
30
|
```
|
|
@@ -95,7 +95,9 @@ When asked to build a slice, always follow this flow:
|
|
|
95
95
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
96
96
|
4. **Verify against slice.json**: After the skill completes, check that every command field, event field,
|
|
97
97
|
and specification in slice.json appears in the implementation. No invented fields — if it is not in
|
|
98
|
-
slice.json, it must not be in the code.
|
|
98
|
+
slice.json, it must not be in the code. This applies even when the slice was previously `Done` and
|
|
99
|
+
reappears as `Planned` — never dismiss a mismatch as "already implemented" or harmless drift; diff
|
|
100
|
+
slice.json against the code field by field and update the code to match every change.
|
|
99
101
|
5. Run quality checks (`./mvnw compile -q`, then the slice tests only).
|
|
100
102
|
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
101
103
|
|
|
@@ -23,7 +23,7 @@ Same rules as `eventmodeling-slicing-event-models`'s own "Core Concept" section
|
|
|
23
23
|
|
|
24
24
|
"I don't know what the next capability is" is not the same as "any guess risks doing the wrong thing." A plausible next slice — the next lifecycle stage, an unaddressed affordance on an existing screen, a natural CRUD/notification gap — always exists for a working domain, and a wrong guess here costs nothing: it's just another slice on the board, easy to rename or discard later.
|
|
25
25
|
|
|
26
|
-
**Posting a comment and closing the prompt with no board mutation is not an acceptable outcome of this skill.** That only defers the same empty decision to the next identical prompt, forever. If you already posted a `
|
|
26
|
+
**Posting a comment and closing the prompt with no board mutation is not an acceptable outcome of this skill.** That only defers the same empty decision to the next identical prompt, forever. If you already posted a `COMMENT`/`TASK` comment about this exact ambiguity on a previous turn, that does not make it acceptable to do so again instead of creating something — the comment already served its purpose (flagging the assumption for a human to correct later); this turn should still create the slice.
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
@@ -37,7 +37,7 @@ Same rules as `eventmodeling-slicing-event-models`'s own "Core Concept" section
|
|
|
37
37
|
|
|
38
38
|
If a specific instruction *is* given (the prompt names a capability, or references a comment/discussion that does), use that instead of inferring one.
|
|
39
39
|
|
|
40
|
-
If, after looking at the existing slices, it's genuinely unclear which of several equally-reasonable next steps to pick, post a
|
|
40
|
+
If, after looking at the existing slices, it's genuinely unclear which of several equally-reasonable next steps to pick, post a comment (via `handle-comment`) noting the assumption you're about to make — then make it and create the slice in the same turn, every time. Never stop at just the comment.
|
|
41
41
|
|
|
42
42
|
## Step 2: Create the slice
|
|
43
43
|
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md
CHANGED
|
@@ -34,7 +34,7 @@ Use these results as the source of truth for the completeness check.
|
|
|
34
34
|
- Never propose deleting, suppressing, or "cleaning up" either node in a linked pair. Specifically, never target the node that has *no* `linkedTo` (the original) for removal — copies reference it via `moveToWidget=<originNodeId>`, so deleting it breaks every copy.
|
|
35
35
|
- Only flag same-titled nodes as an actual duplicate gap when **none** of them has `linkedTo` — i.e., they are genuinely two independent, unlinked nodes describing the same concept.
|
|
36
36
|
|
|
37
|
-
After the analysis, use the `handle-comment` skill to post findings on relevant nodes — `TASK` for required fixes, `
|
|
37
|
+
After the analysis, use the `handle-comment` skill to post findings on relevant nodes — `TASK` for required fixes, `COMMENT` for gaps that need clarification.
|
|
38
38
|
|
|
39
39
|
## Workflow
|
|
40
40
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Checking Completeness — Worked Examples
|
|
2
2
|
|
|
3
|
-
These are conceptual worked examples (Order/Payment domain) illustrating the completeness-check reasoning this skill applies — useful for understanding the reasoning, but the actual mechanics live in the numbered Workflow sections of the main SKILL.md (reading board state and posting `TASK`/`
|
|
3
|
+
These are conceptual worked examples (Order/Payment domain) illustrating the completeness-check reasoning this skill applies — useful for understanding the reasoning, but the actual mechanics live in the numbered Workflow sections of the main SKILL.md (reading board state and posting `TASK`/`COMMENT` comments via `handle-comment`), not in writing a document like this.
|
|
4
4
|
|
|
5
5
|
## 1. Field Origin & Destination Matrix
|
|
6
6
|
|
|
@@ -265,7 +265,7 @@ Actions taken:
|
|
|
265
265
|
|
|
266
266
|
## Legacy markdown-document format (superseded — kept for reference only)
|
|
267
267
|
|
|
268
|
-
Older versions of this skill wrote the completeness check as a markdown report. The actual mechanism today is reading board state and posting `TASK`/`
|
|
268
|
+
Older versions of this skill wrote the completeness check as a markdown report. The actual mechanism today is reading board state and posting `TASK`/`COMMENT` comments via `handle-comment` (see "Board Context" in the main SKILL.md) — this template is kept only so the shape of the information (what a complete completeness report covers) stays documented somewhere.
|
|
269
269
|
|
|
270
270
|
```markdown
|
|
271
271
|
# Completeness Check: [Domain Name]
|
|
@@ -150,10 +150,10 @@ Every AUTOMATION, translation or worker, needs its own todo-list READMODEL (open
|
|
|
150
150
|
|
|
151
151
|
Two different things are easy to conflate, and conflating them corrupts completeness checking:
|
|
152
152
|
|
|
153
|
-
- **Open question** — something genuinely undecided. Post it as a `
|
|
153
|
+
- **Open question** — something genuinely undecided. Post it as a `COMMENT` (`handle-comment`) on the relevant node, worded as a question. There is no separate question type at the API level — it stays open (unresolved) until someone actually answers it, resolving means answering, not deleting the comment.
|
|
154
154
|
- **Decided failure** — a rejection or error case whose behavior is already decided (e.g. "payment fails → reject, no event"). Model it as a SCENARIO with `expectError: true` and an `errorDescription` (see `eventmodeling-elaborating-scenarios`), never as a comment. It's permanent, specified behavior, not something waiting on an answer.
|
|
155
155
|
|
|
156
|
-
A decided failure left as a lingering
|
|
156
|
+
A decided failure left as a lingering, unresolved question comment looks unresolved when it isn't. When counting completeness (`eventmodeling-checking-completeness`), only a genuinely unanswered question comment counts as a gap — a decided failure path needs its `expectError` scenario, not a comment standing in for one.
|
|
157
157
|
|
|
158
158
|
## Offline-First Thinking
|
|
159
159
|
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md
CHANGED
|
@@ -193,7 +193,7 @@ Before finalizing any read model, ask: "does this screen contain more than one c
|
|
|
193
193
|
|
|
194
194
|
### Step 5d — Pull field mappings from Step 3 — they are the spec, not a guess
|
|
195
195
|
|
|
196
|
-
**Do not re-derive read model needs from a screen's title or description alone, and do not rely on the orchestrator's phase-summary handoff for this** — if you arrived here via `eventmodeling-orchestrating-event-modeling`, the handoff after Step 3 is a short hand-written prose summary (`.
|
|
196
|
+
**Do not re-derive read model needs from a screen's title or description alone, and do not rely on the orchestrator's phase-summary handoff for this** — if you arrived here via `eventmodeling-orchestrating-event-modeling`, the handoff after Step 3 is a short hand-written prose summary (`.eventmodelers/interviews/.../EVENTMODELING.md`), not the actual field data. It will not reliably carry the per-field mappings forward. Go back to the board itself:
|
|
197
197
|
|
|
198
198
|
For every SCREEN node, fetch it directly (`get_node`/`get_nodes`, never from memory) and read its `meta.fields`. Step 3 already required every field to carry a `mapping`, and for view fields that mapping is already in the exact form `"<ReadModelTitle>.<fieldName>"` — recorded specifically so this step doesn't have to re-guess it.
|
|
199
199
|
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-interview-protocol/SKILL.md
CHANGED
|
@@ -17,7 +17,7 @@ Already have everything the step needs? Skip straight to the step's own workflow
|
|
|
17
17
|
|
|
18
18
|
## Recording the outcome
|
|
19
19
|
|
|
20
|
-
Append to the project's event modeling file: `.
|
|
20
|
+
Append to the project's event modeling file: `.eventmodelers/interviews/[project-name]/EVENTMODELING.md`, under a section for this step:
|
|
21
21
|
|
|
22
22
|
```markdown
|
|
23
23
|
## <Step Number>. <Step Name> (<skill-name>)
|
|
@@ -185,7 +185,7 @@ scope, and stated output goal (code, design, learning, docs).
|
|
|
185
185
|
Confirm understanding before proceeding: "So we're modeling [domain], goal is
|
|
186
186
|
[goal], constraints are [constraints]. Starting from [step]. Does that match?"
|
|
187
187
|
|
|
188
|
-
**Capture findings** — create `.
|
|
188
|
+
**Capture findings** — create `.eventmodelers/interviews/[project-name]/EVENTMODELING.md` with this header (this step is what creates the file; every later step appends to it per `eventmodeling-interview-protocol`):
|
|
189
189
|
|
|
190
190
|
```markdown
|
|
191
191
|
# Event Modeling: [Project Name]
|
|
@@ -209,7 +209,7 @@ Then follow **`eventmodeling-interview-protocol`** to record this step's own fin
|
|
|
209
209
|
|
|
210
210
|
After each step completes, before invoking the next skill, write a phase summary to memory.
|
|
211
211
|
|
|
212
|
-
Append a summary block to `.
|
|
212
|
+
Append a summary block to `.eventmodelers/interviews/[project-name]/EVENTMODELING.md`:
|
|
213
213
|
|
|
214
214
|
```markdown
|
|
215
215
|
### Step N complete — [Skill Name]
|
|
@@ -448,7 +448,7 @@ Not delegated to a separate skill — performed directly by this orchestrating s
|
|
|
448
448
|
- **Business rules deliberately encoded as scenarios, not new events** — so a reader doesn't mistake a missing event for an oversight.
|
|
449
449
|
- **Sequencing or design corrections made mid-workflow** — e.g. a column reorder because an event's original placement implied the wrong causality.
|
|
450
450
|
- **Read model design rationale** — especially where one read model deliberately serves several screens/automations, so it doesn't read as a missing 1:1 mapping.
|
|
451
|
-
- **Any cross-context or integration gaps found** (Step 6 Conway's Law, or discovered incidentally, e.g. a same-timeline connection constraint blocking a needed cross-chapter data dependency) — state the finding and the viable resolutions, matching whatever TASK/
|
|
451
|
+
- **Any cross-context or integration gaps found** (Step 6 Conway's Law, or discovered incidentally, e.g. a same-timeline connection constraint blocking a needed cross-chapter data dependency) — state the finding and the viable resolutions, matching whatever TASK/COMMENT comment was also posted on the affected node.
|
|
452
452
|
- **Closing summary**: element counts and the validation verdict for this chapter's slice of the model.
|
|
453
453
|
|
|
454
454
|
If a chapter's story is genuinely simple, say so briefly rather than padding — but for any chapter with real design decisions behind it, this note is the place those decisions survive past the session that made them.
|
|
@@ -505,5 +505,5 @@ specific needs:
|
|
|
505
505
|
- [ ] At least one view scenario (GWT or storyline) exists per READMODEL — not just per command
|
|
506
506
|
- [ ] Completeness check shows no unresolved field traceability gaps
|
|
507
507
|
- [ ] Validation returns PASS or PASS WITH WARNINGS with all critical issues resolved
|
|
508
|
-
- [ ] Interview trail in `.
|
|
508
|
+
- [ ] Interview trail in `.eventmodelers/` updated with status of each completed step
|
|
509
509
|
- [ ] Phase summary written to memory after every completed step before loading the next skill
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md
CHANGED
|
@@ -100,7 +100,7 @@ mcp__eventmodelers__get_nodes { "boardId": "$BOARD_ID", "type": "SCREEN" }
|
|
|
100
100
|
|
|
101
101
|
**Fallback (no MCP):** see `references/api-fallback.md` — "Board Integration — Check existing screen nodes".
|
|
102
102
|
|
|
103
|
-
After completing the screen analysis, use the `handle-comment` skill to post a
|
|
103
|
+
After completing the screen analysis, use the `handle-comment` skill to post a comment on any screen node where data fields are unclear or missing sources are identified.
|
|
104
104
|
|
|
105
105
|
## Resolve One Actor Lane Per Human Role (do this once, before placing any screens)
|
|
106
106
|
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md
CHANGED
|
@@ -37,7 +37,7 @@ mcp__eventmodelers__get_nodes { "boardId": "$BOARD_ID", "type": "READMODEL" }
|
|
|
37
37
|
|
|
38
38
|
**Fallback (no MCP):** see `references/api-fallback.md` — "Board Context".
|
|
39
39
|
|
|
40
|
-
After validation, use the `handle-comment` skill to post findings on the relevant nodes — `TASK` for critical violations that must be fixed, `
|
|
40
|
+
After validation, use the `handle-comment` skill to post findings on the relevant nodes — `TASK` for critical violations that must be fixed, `COMMENT` for warnings and recommendations. (That skill already handles the `add_comment` MCP-vs-curl choice internally — no separate rewrite needed here.)
|
|
41
41
|
|
|
42
42
|
## Purpose
|
|
43
43
|
|
|
@@ -79,7 +79,7 @@ Rules for generating examples:
|
|
|
79
79
|
- Make examples **domain-specific**: if the element is called "Order Placed", use order-domain values; if it's "User Registered", use registration-domain values.
|
|
80
80
|
- Keep examples **short** — one value per field, no paragraphs.
|
|
81
81
|
|
|
82
|
-
Build the updated `fields` array: same structure as the original, only the `example` property changed where needed.
|
|
82
|
+
Build the updated `fields` array: same structure as the original, only the `example` property changed where needed.
|
|
83
83
|
|
|
84
84
|
---
|
|
85
85
|
|
|
@@ -21,20 +21,29 @@ From `$ARGUMENTS` or the calling skill's context, extract:
|
|
|
21
21
|
| `nodeId` | UUID of the target node | **required** |
|
|
22
22
|
| `text` | Comment text (place) or substring to match (resolve/delete) | required for `place`; used to look up comment when `commentId` is absent |
|
|
23
23
|
| `commentId` | UUID of the comment to resolve/delete | preferred over `text` for resolve/delete |
|
|
24
|
-
| `type` | `COMMENT
|
|
25
|
-
| `author` | Author identifier string | `agent` (place only) |
|
|
24
|
+
| `type` | `COMMENT` or `TASK` | `COMMENT` (place only) |
|
|
25
|
+
| `author` | Author identifier string | `agent-$CLAUDE_CODE_SESSION_ID` (place only) |
|
|
26
26
|
| `boardId` | Board UUID | from `connect` skill (`BOARD_ID`) |
|
|
27
27
|
|
|
28
|
+
Use the session env var, not the literal string `agent` — `CLAUDE_CODE_SESSION_ID` is set by the
|
|
29
|
+
host for every session, so two agents working the same board at once post under distinguishable
|
|
30
|
+
authors instead of an identical one. If the env var is unset (non-Claude-Code host), fall back to
|
|
31
|
+
the literal `agent`.
|
|
32
|
+
|
|
33
|
+
There is no `QUESTION` type at the API level — a question is just a `COMMENT` whose text happens
|
|
34
|
+
to be phrased as a question. Callers that want to flag something as a question should word the
|
|
35
|
+
`text` accordingly, not pass a special `type`.
|
|
36
|
+
|
|
28
37
|
Route to the matching section below based on `action`.
|
|
29
38
|
|
|
30
39
|
---
|
|
31
40
|
|
|
32
41
|
## Action: place
|
|
33
42
|
|
|
34
|
-
**Prefer MCP** — one call, `type` (`COMMENT`/`TASK
|
|
43
|
+
**Prefer MCP** — one call, `type` (`COMMENT`/`TASK`) passed straight through:
|
|
35
44
|
|
|
36
45
|
```
|
|
37
|
-
mcp__eventmodelers__add_comment { "boardId": "$BOARD_ID", "nodeId": "$NODE_ID", "text": "<text>", "type": "<COMMENT|TASK
|
|
46
|
+
mcp__eventmodelers__add_comment { "boardId": "$BOARD_ID", "nodeId": "$NODE_ID", "text": "<text>", "type": "<COMMENT|TASK>", "author": "<author>" }
|
|
38
47
|
```
|
|
39
48
|
|
|
40
49
|
**Fallback (no MCP):** see `references/api-fallback.md` — "Action: place".
|
|
@@ -376,9 +376,9 @@ Count inbound edges where `target === COMMAND_NODE_ID` and the source node is ty
|
|
|
376
376
|
mcp__eventmodelers__set_connection { "boardId": "<BOARD_ID>", "source": "<extra-issuer-node-id>", "target": "<COMMAND_NODE_ID>", "action": "remove" }
|
|
377
377
|
```
|
|
378
378
|
|
|
379
|
-
If it's not clear which edge is the deliberate one (e.g. neither source sits in the COMMAND's own column), do not guess — leave both edges and post a
|
|
379
|
+
If it's not clear which edge is the deliberate one (e.g. neither source sits in the COMMAND's own column), do not guess — leave both edges and post a comment on the COMMAND node via `handle-comment` instead, describing the ambiguity.
|
|
380
380
|
|
|
381
|
-
**Fallback (no MCP)**: there is no documented single-purpose REST endpoint for edge removal outside `/nodes/events`. Connect MCP via the `connect` skill first; if that's genuinely not possible, skip the auto-fix and post a
|
|
381
|
+
**Fallback (no MCP)**: there is no documented single-purpose REST endpoint for edge removal outside `/nodes/events`. Connect MCP via the `connect` skill first; if that's genuinely not possible, skip the auto-fix and post a comment on the COMMAND node flagging the double issuer for manual resolution instead of fabricating a payload.
|
|
382
382
|
|
|
383
383
|
---
|
|
384
384
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wdyt
|
|
3
|
-
description: Business analyst exploration of an event model board. Reads all slices, analyzes them from a business perspective, and posts questions/observations as
|
|
3
|
+
description: Business analyst exploration of an event model board. Reads all slices, analyzes them from a business perspective, and posts questions/observations as comments on relevant nodes. Findings about a relationship between elements or a cluster of elements are always additionally drawn on the canvas (arrows, group loops) — comments carry every textual question, drawings carry every visual/structural hint.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# WDYT — What Do You Think?
|
|
@@ -113,17 +113,17 @@ Each of these four is inherently about a relationship or cluster of elements, so
|
|
|
113
113
|
|
|
114
114
|
The two channels have a strict division of labor, always applied the same way — never swap them:
|
|
115
115
|
|
|
116
|
-
- **Every textual question is a comment.** If the finding is "what happens / who does this / what do we expect" about a single element, it is worded and lives only in a
|
|
116
|
+
- **Every textual question is a comment.** If the finding is "what happens / who does this / what do we expect" about a single element, it is worded and lives only in a comment. Never draw a text callout on the canvas to carry a question — that content belongs in 4.1, full stop.
|
|
117
117
|
- **Every visual/structural hint is a drawing.** If the finding is inherently about *where things are relative to each other* — a relationship between two elements, or a cluster of elements sharing one concern — it is always additionally drawn on the canvas (4.2), not left as text alone. This isn't a selective "top 3" step; it's determined by the shape of the finding itself: relational or clustered → draw it, every time.
|
|
118
118
|
|
|
119
119
|
### 4.1 Comments (every textual question, always)
|
|
120
120
|
|
|
121
|
-
For each question you want to ask, post it as a
|
|
121
|
+
For each question you want to ask, post it as a comment on the most relevant node (the COMMAND, EVENT, SCREEN, or READMODEL the question is about). If a question is about the whole slice rather than a specific element, post it on the first/primary EVENT of the slice.
|
|
122
122
|
|
|
123
123
|
Use the `handle-comment` skill with `action=place` to post each comment. Pass:
|
|
124
124
|
- `nodeId` — the UUID of the element the question is about
|
|
125
125
|
- `text` — your question (one sentence, plain business language)
|
|
126
|
-
- `type` — `
|
|
126
|
+
- `type` — `COMMENT` (there is no separate question type — the text itself carries the question)
|
|
127
127
|
- `author` — `wdyt`
|
|
128
128
|
|
|
129
129
|
The comment API has no batch endpoint — `handle-comment` sends one request per comment. Fire them sequentially.
|
|
@@ -137,7 +137,7 @@ Use `POST /api/org/{orgId}/boards/{boardId}/drawing/draw` (auth headers same as
|
|
|
137
137
|
- **Arrow** (`kind: "path"`, `arrowEnd: true`) — the concern is about a missing or unclear relationship *between two elements* (e.g. "does this event actually reach this automation?"). Draw a straight line from one element's position to the other's. `path` is `M 0 0 L <dx> <dy>` in the box's own local coordinates; `x`/`y`/`width`/`height` describe that box in canvas space (so `width`/`height` = the delta between the two elements' positions). Get element positions from the slice data already loaded in Step 2 (or `GET .../nodes/{nodeId}` if not present).
|
|
138
138
|
- **Group loop** (`kind: "rect"`, drawn around a computed bounding box) — the concern spans a *cluster* of elements together (e.g. "this whole flow assumes nothing ever fails"). There's no dedicated group endpoint — union the elements' own `x`/`y`/`width`/`height` (plus some padding) yourself and draw one `rect` around that box via `.../drawing/draw`. This is a visual grouping only — unrelated to the `MODEL_CONTEXT` node type; never touch a `modelContext` field to satisfy this.
|
|
139
139
|
|
|
140
|
-
Every arrow/group loop is paired with a
|
|
140
|
+
Every arrow/group loop is paired with a comment on the relevant node(s) from 4.1 — the drawing makes the concern visible at a glance on the canvas itself, the comment carries the actual worded question. Post both; neither replaces the other.
|
|
141
141
|
|
|
142
142
|
A finding about a single element with no relational or cluster dimension gets a comment only — don't manufacture an arrow or loop for it just to add a drawing.
|
|
143
143
|
|
|
@@ -4,7 +4,7 @@ Reusable learnings accumulated while processing prompts for this board. Append n
|
|
|
4
4
|
ones in a compressed, reusable form; only add if not already covered here.
|
|
5
5
|
|
|
6
6
|
- `/place-element` requires an existing column — create one via the timeline API if missing.
|
|
7
|
-
- `/wdyt` posts
|
|
7
|
+
- `/wdyt` posts comments onto nodes — use for analysis only, not modifications.
|
|
8
8
|
- The `board_id`, `timeline_id`, and `organization_id` from each prompt provide full context — pass them to skills that need them.
|
|
9
9
|
- If a prompt's `context.timelineId` is present and non-null, it overrules the prompt's own `timeline_id` field — it's the chapter the user was pointing at on the canvas, which can differ from whatever chapter the prompt/voice session was scoped to. Resolve `TIMELINE_ID` from `context.timelineId` first, falling back to `timeline_id` only when it's absent, before passing it to any skill.
|
|
10
10
|
- Same pattern for node references: if a prompt's `context.selectedNodes` array is present and non-empty, its first entry overrules the prompt's own `node_id` field (e.g. for `/handle-comment`'s `nodeId`) — it reflects the actual canvas selection at prompt time, whereas `node_id` is only set when the prompt originated from a specific node/comment.
|
|
@@ -42,9 +42,9 @@ At the start of every session, read `.agent-modeling-kit/AGENTS.md` if it exists
|
|
|
42
42
|
5. **Invoke the matched skill — never substitute direct tool calls for it.** Execute the prompt using the skill matched in the Skill Selection table below, passing the resolved `TIMELINE_ID`, `NODE_ID`, and `CELL_ID` from step 3 as that skill's `timelineId`/node-reference/`cellName` arguments (not the raw `timeline_id`/`node_id` fields, and not a cell reference parsed from the prompt text). For a skill like `/place-element` that accepts a `cellName`, pass the resolved `CELL_ID` as `cellName` whenever it's present — skip parsing the prompt text for a cell reference entirely in that case.
|
|
43
43
|
|
|
44
44
|
`mcp__eventmodelers__*` tools (and the REST fallback) are building blocks a skill calls *internally* once you've invoked it — they are not a substitute for invoking the skill. Being able to see `mcp__eventmodelers__get_node`/`create_slice`/etc. in your tool list does not mean you should reach for them directly to satisfy a prompt that matches a row in the Skill Selection table: e.g. "add the next slice" always goes through `/eventmodeling-slicing-event-models` (falling through to `/add-next-slice` when nothing existing is left to slice) or `/place-element`, even though technically a couple of raw MCP calls could produce something on the board. The skill is what encodes the actual domain reasoning (which node type follows which, naming, field derivation, dependency notes) — a raw tool call skips all of that and produces a shallower result even when it "works." Only call MCP/REST directly when no row in the table matches the prompt's intent at all.
|
|
45
|
-
**Questioning rule**: you are running autonomously — no human is available to answer questions. If you need clarification, do not pause or ask interactively — post a
|
|
45
|
+
**Questioning rule**: you are running autonomously — no human is available to answer questions. If you need clarification, do not pause or ask interactively — post a comment (`/handle-comment` with `action=place`, `type=COMMENT`) on the most relevant node. Then:
|
|
46
46
|
- If a reasonable default interpretation exists, continue with it.
|
|
47
|
-
- If it doesn't — the prompt is ambiguous enough that any guess risks doing the wrong thing — stop instead of guessing. Skip straight to step 6 and mark the prompt `DONE` with a comment explaining what's unclear and pointing to the
|
|
47
|
+
- If it doesn't — the prompt is ambiguous enough that any guess risks doing the wrong thing — stop instead of guessing. Skip straight to step 6 and mark the prompt `DONE` with a comment explaining what's unclear and pointing to the comment you just posted. Never leave a prompt neither progressed nor closed.
|
|
48
48
|
6. **Mark the prompt as finished** — invoke `/update-prompt-status` with this turn's `prompt_id`, `newStatus=DONE`, and a `comment` that summarizes what you actually did (e.g. "Added the OrderPlaced event and wired it to the read model"). Do this once, right after the work is done — not per skill call within the turn.
|
|
49
49
|
7. If this turn has a `comment_id` field, invoke `/handle-comment` with `action=resolve`, `nodeId` from the resolved `NODE_ID` (step 3), `commentId` from `comment_id`.
|
|
50
50
|
8. Append a progress entry to `progress.txt` — see the Progress Entry Format below. Fill in the `Learnings` line with anything reusable noticed this turn (pattern, gotcha, useful context), or "none".
|
|
@@ -51,7 +51,7 @@ When asked to build a slice, always follow this flow:
|
|
|
51
51
|
- **State-view** — `projections` or `queries` array is non-empty → invoke `/build-state-view`
|
|
52
52
|
- **State-change** — default (has `commands` / `events`) → invoke `/build-state-change`
|
|
53
53
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
54
|
-
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.
|
|
54
|
+
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.
|
|
55
55
|
5. Run quality checks (`npm run build`, then the slice tests only).
|
|
56
56
|
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
57
57
|
|
|
@@ -81,7 +81,9 @@ When asked to build a slice, always follow this flow:
|
|
|
81
81
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
82
82
|
4. **Verify against slice.json**: After the skill completes, check that every command field, event field,
|
|
83
83
|
and specification in slice.json appears in the implementation. No invented fields — if it is not in
|
|
84
|
-
slice.json, it must not be in the code.
|
|
84
|
+
slice.json, it must not be in the code. This applies even when the slice was previously `Done` and
|
|
85
|
+
reappears as `Planned` — never dismiss a mismatch as "already implemented" or harmless drift; diff
|
|
86
|
+
slice.json against the code field by field and update the code to match every change.
|
|
85
87
|
5. Run quality checks (`./mvnw compile -q`, then the slice tests only).
|
|
86
88
|
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
87
89
|
|
|
@@ -52,7 +52,7 @@ When asked to build a slice, always follow this flow:
|
|
|
52
52
|
- **State-view** — `projections` or `queries` array is non-empty → invoke `/build-state-view`
|
|
53
53
|
- **State-change** — default (has `commands` / `events`) → invoke `/build-state-change`
|
|
54
54
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
55
|
-
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.
|
|
55
|
+
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.
|
|
56
56
|
5. Run quality checks (`npm run build`, then the slice tests only).
|
|
57
57
|
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
58
58
|
|
|
@@ -64,7 +64,7 @@ When asked to build a slice, always follow this flow:
|
|
|
64
64
|
- **State-view** — `projections` or `queries` array is non-empty → invoke `/build-state-view`
|
|
65
65
|
- **State-change** — default (has `commands` / `events`) → invoke `/build-state-change`
|
|
66
66
|
3. Invoke the matching skill and follow its instructions completely. Do not deviate.
|
|
67
|
-
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.
|
|
67
|
+
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.
|
|
68
68
|
5. Run quality checks (`./mvnw compile -q`, then the slice tests only).
|
|
69
69
|
6. If checks pass, commit with `feat: [Slice Name]` and set slice status to `Done`.
|
|
70
70
|
|