@eventmodelers/cli 1.0.45 → 1.0.47
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 +5 -2
- package/cli.js +53 -1
- package/package.json +2 -2
- package/shared/build-kit/lib/checks/README.md +59 -0
- package/shared/build-kit/lib/ralph.js +110 -28
- package/shared/build-kit/lib/util/find-slice.cjs +59 -0
- package/shared/build-kit/ralph-claude.js +6 -2
- 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/blank/templates/build-kit/lib/backend-prompt.md +106 -102
- package/stacks/blank/templates/build-kit/lib/prompt.md +102 -106
- package/stacks/cratis-csharp/templates/build-kit/CLAUDE.md +9 -0
- package/stacks/kurrent/templates/.claude/skills/build-automation/SKILL.md +422 -0
- package/stacks/kurrent/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +19 -0
- package/stacks/kurrent/templates/.claude/skills/build-automation/references/idempotent-dispatch-patterns.md +65 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-change/SKILL.md +418 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +41 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-change/references/integration-test-patterns.md +64 -0
- package/stacks/kurrent/templates/.claude/skills/build-state-view/SKILL.md +391 -0
- package/stacks/kurrent/templates/build-kit/CLAUDE.md +124 -0
- package/stacks/kurrent/templates/build-kit/lib/AGENT.md +73 -0
- package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +169 -0
- package/stacks/kurrent/templates/build-kit/lib/prompt.md +128 -0
- package/stacks/kurrent/templates/root/README.md +46 -0
- package/stacks/kurrent/templates/root/docker-compose.yml +45 -0
- package/stacks/kurrent/templates/root/mvnw +259 -0
- package/stacks/kurrent/templates/root/mvnw.cmd +149 -0
- package/stacks/kurrent/templates/root/pom.xml +152 -0
- package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/QuickstartApplication.java +12 -0
- package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/common/EventStore.java +91 -0
- package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/config/KurrentConfiguration.java +42 -0
- package/stacks/kurrent/templates/root/src/main/resources/application.properties +14 -0
- package/stacks/kurrent/templates/root/src/main/resources/static/index.html +11 -0
- 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 +23 -1
- package/stacks/node/templates/build-kit/lib/check-commit-scope.cjs +123 -0
- package/stacks/node/templates/build-kit/lib/checks/00-blocked-paths.cjs +28 -0
- package/stacks/node/templates/build-kit/lib/checks/10-slice-scope.cjs +29 -0
- package/stacks/node/templates/build-kit/lib/checks/20-append-only-migrations.cjs +20 -0
- package/stacks/node/templates/build-kit/lib/checks/30-test-file-present.cjs +44 -0
- package/stacks/node/templates/build-kit/lib/checks/40-no-invented-fields.cjs +92 -0
- package/stacks/node/templates/build-kit/lib/checks/50-spec-coverage.cjs +50 -0
- package/stacks/node/templates/build-kit/lib/checks/90-tsc-build.cjs +22 -0
- package/stacks/node/templates/root/.githooks/pre-commit +11 -0
- package/stacks/node/templates/root/package.json +2 -1
- package/stacks/node/templates/root/setup-env.sh +7 -1
- package/stacks/opencqrs/templates/.claude/skills/build-automation/SKILL.md +434 -0
- package/stacks/opencqrs/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +19 -0
- package/stacks/opencqrs/templates/.claude/skills/build-automation/references/idempotent-dispatch-patterns.md +62 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/SKILL.md +413 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +46 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/rest-api-patterns.md +145 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/test-fixture-patterns.md +85 -0
- package/stacks/opencqrs/templates/.claude/skills/build-state-view/SKILL.md +354 -0
- package/stacks/opencqrs/templates/build-kit/CLAUDE.md +103 -0
- package/stacks/opencqrs/templates/build-kit/lib/AGENT.md +58 -0
- package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +169 -0
- package/stacks/opencqrs/templates/build-kit/lib/prompt.md +128 -0
- package/stacks/opencqrs/templates/root/README.md +42 -0
- package/stacks/opencqrs/templates/root/docker-compose.yml +37 -0
- package/stacks/opencqrs/templates/root/mvnw +259 -0
- package/stacks/opencqrs/templates/root/mvnw.cmd +149 -0
- package/stacks/opencqrs/templates/root/pom.xml +139 -0
- package/stacks/opencqrs/templates/root/src/main/java/com/example/quickstart/QuickstartApplication.java +12 -0
- package/stacks/opencqrs/templates/root/src/main/java/com/example/quickstart/config/CqrsConfiguration.java +74 -0
- package/stacks/opencqrs/templates/root/src/main/resources/application.properties +23 -0
- package/stacks/opencqrs/templates/root/src/main/resources/schema.sql +19 -0
- package/stacks/opencqrs/templates/root/src/main/resources/static/index.html +11 -0
- package/stacks/supabase/templates/build-kit/CLAUDE.md +26 -1
- package/stacks/supabase/templates/build-kit/lib/check-commit-scope.cjs +126 -0
- package/stacks/supabase/templates/build-kit/lib/checks/00-blocked-paths.cjs +28 -0
- package/stacks/supabase/templates/build-kit/lib/checks/10-slice-scope.cjs +34 -0
- package/stacks/supabase/templates/build-kit/lib/checks/20-append-only-migrations.cjs +21 -0
- package/stacks/supabase/templates/build-kit/lib/checks/30-test-file-present.cjs +44 -0
- package/stacks/supabase/templates/build-kit/lib/checks/40-no-invented-fields.cjs +92 -0
- package/stacks/supabase/templates/build-kit/lib/checks/50-spec-coverage.cjs +50 -0
- package/stacks/supabase/templates/build-kit/lib/checks/90-tsc-build.cjs +22 -0
- package/stacks/supabase/templates/root/.githooks/pre-commit +11 -0
- package/stacks/supabase/templates/root/package.json +2 -1
- package/stacks/supabase/templates/root/setup-env.sh +7 -1
- package/stacks/umadb/templates/.claude/skills/build-automation/SKILL.md +313 -0
- package/stacks/umadb/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +42 -0
- package/stacks/umadb/templates/.claude/skills/build-state-change/SKILL.md +376 -0
- package/stacks/umadb/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +42 -0
- package/stacks/umadb/templates/.claude/skills/build-state-change/references/umadb-query-patterns.md +78 -0
- package/stacks/umadb/templates/.claude/skills/build-state-view/SKILL.md +338 -0
- package/stacks/umadb/templates/build-kit/CLAUDE.md +94 -0
- package/stacks/umadb/templates/build-kit/lib/AGENT.md +47 -0
- package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +169 -0
- package/stacks/umadb/templates/build-kit/lib/prompt.md +128 -0
- package/stacks/umadb/templates/root/.mvn/wrapper/maven-wrapper.properties +19 -0
- package/stacks/umadb/templates/root/README.md +48 -0
- package/stacks/umadb/templates/root/docker-compose.yml +29 -0
- package/stacks/umadb/templates/root/mvnw +259 -0
- package/stacks/umadb/templates/root/mvnw.cmd +149 -0
- package/stacks/umadb/templates/root/pom.xml +151 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/QuickstartApplication.java +12 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/config/UmaDbConfig.java +39 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/DecisionModelLoader.java +76 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/EventCodec.java +40 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/EventDispatcher.java +100 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/OptimisticConcurrencyException.java +14 -0
- package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/SliceEventListener.java +23 -0
- package/stacks/umadb/templates/root/src/main/resources/application.properties +17 -0
- package/stacks/umadb/templates/root/src/test/java/io/umadb/quickstart/testsupport/InMemoryUmaDbClient.java +135 -0
- package/stacks/umadb/templates/root/src/test/resources/application.properties +8 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<# : batch portion
|
|
2
|
+
@REM ----------------------------------------------------------------------------
|
|
3
|
+
@REM Licensed to the Apache Software Foundation (ASF) under one
|
|
4
|
+
@REM or more contributor license agreements. See the NOTICE file
|
|
5
|
+
@REM distributed with this work for additional information
|
|
6
|
+
@REM regarding copyright ownership. The ASF licenses this file
|
|
7
|
+
@REM to you under the Apache License, Version 2.0 (the
|
|
8
|
+
@REM "License"); you may not use this file except in compliance
|
|
9
|
+
@REM with the License. You may obtain a copy of the License at
|
|
10
|
+
@REM
|
|
11
|
+
@REM http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
@REM
|
|
13
|
+
@REM Unless required by applicable law or agreed to in writing,
|
|
14
|
+
@REM software distributed under the License is distributed on an
|
|
15
|
+
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
16
|
+
@REM KIND, either express or implied. See the License for the
|
|
17
|
+
@REM specific language governing permissions and limitations
|
|
18
|
+
@REM under the License.
|
|
19
|
+
@REM ----------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
@REM ----------------------------------------------------------------------------
|
|
22
|
+
@REM Apache Maven Wrapper startup batch script, version 3.3.2
|
|
23
|
+
@REM
|
|
24
|
+
@REM Optional ENV vars
|
|
25
|
+
@REM MVNW_REPOURL - repo url base for downloading maven distribution
|
|
26
|
+
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
|
27
|
+
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
|
|
28
|
+
@REM ----------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
|
|
31
|
+
@SET __MVNW_CMD__=
|
|
32
|
+
@SET __MVNW_ERROR__=
|
|
33
|
+
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
|
|
34
|
+
@SET PSModulePath=
|
|
35
|
+
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
|
|
36
|
+
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
|
|
37
|
+
)
|
|
38
|
+
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
|
|
39
|
+
@SET __MVNW_PSMODULEP_SAVE=
|
|
40
|
+
@SET __MVNW_ARG0_NAME__=
|
|
41
|
+
@SET MVNW_USERNAME=
|
|
42
|
+
@SET MVNW_PASSWORD=
|
|
43
|
+
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
|
|
44
|
+
@echo Cannot start maven from wrapper >&2 && exit /b 1
|
|
45
|
+
@GOTO :EOF
|
|
46
|
+
: end batch / begin powershell #>
|
|
47
|
+
|
|
48
|
+
$ErrorActionPreference = "Stop"
|
|
49
|
+
if ($env:MVNW_VERBOSE -eq "true") {
|
|
50
|
+
$VerbosePreference = "Continue"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
|
|
54
|
+
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
|
|
55
|
+
if (!$distributionUrl) {
|
|
56
|
+
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
|
|
60
|
+
"maven-mvnd-*" {
|
|
61
|
+
$USE_MVND = $true
|
|
62
|
+
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
|
|
63
|
+
$MVN_CMD = "mvnd.cmd"
|
|
64
|
+
break
|
|
65
|
+
}
|
|
66
|
+
default {
|
|
67
|
+
$USE_MVND = $false
|
|
68
|
+
$MVN_CMD = $script -replace '^mvnw','mvn'
|
|
69
|
+
break
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
|
74
|
+
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
|
75
|
+
if ($env:MVNW_REPOURL) {
|
|
76
|
+
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
|
|
77
|
+
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
|
|
78
|
+
}
|
|
79
|
+
$distributionUrlName = $distributionUrl -replace '^.*/',''
|
|
80
|
+
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
|
|
81
|
+
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
|
|
82
|
+
if ($env:MAVEN_USER_HOME) {
|
|
83
|
+
$MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
|
|
84
|
+
}
|
|
85
|
+
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
|
|
86
|
+
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
|
|
87
|
+
|
|
88
|
+
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
|
|
89
|
+
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
|
90
|
+
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
|
91
|
+
exit $?
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
|
|
95
|
+
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# prepare tmp dir
|
|
99
|
+
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
|
|
100
|
+
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
|
|
101
|
+
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
|
|
102
|
+
trap {
|
|
103
|
+
if ($TMP_DOWNLOAD_DIR.Exists) {
|
|
104
|
+
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
|
105
|
+
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
|
|
110
|
+
|
|
111
|
+
# Download and Install Apache Maven
|
|
112
|
+
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
|
113
|
+
Write-Verbose "Downloading from: $distributionUrl"
|
|
114
|
+
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
|
115
|
+
|
|
116
|
+
$webclient = New-Object System.Net.WebClient
|
|
117
|
+
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
|
|
118
|
+
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
|
|
119
|
+
}
|
|
120
|
+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
121
|
+
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
|
|
122
|
+
|
|
123
|
+
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
|
124
|
+
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
|
|
125
|
+
if ($distributionSha256Sum) {
|
|
126
|
+
if ($USE_MVND) {
|
|
127
|
+
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
|
|
128
|
+
}
|
|
129
|
+
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
|
|
130
|
+
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
|
|
131
|
+
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# unzip and move
|
|
136
|
+
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
|
|
137
|
+
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
|
|
138
|
+
try {
|
|
139
|
+
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
|
|
140
|
+
} catch {
|
|
141
|
+
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
|
|
142
|
+
Write-Error "fail to move MAVEN_HOME"
|
|
143
|
+
}
|
|
144
|
+
} finally {
|
|
145
|
+
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
|
146
|
+
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
3
|
+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
4
|
+
<modelVersion>4.0.0</modelVersion>
|
|
5
|
+
<groupId>com.example.quickstart</groupId>
|
|
6
|
+
<artifactId>quickstart</artifactId>
|
|
7
|
+
<name>Kurrent Quickstart</name>
|
|
8
|
+
<version>0.0.1-SNAPSHOT</version>
|
|
9
|
+
|
|
10
|
+
<properties>
|
|
11
|
+
<java.version>21</java.version>
|
|
12
|
+
<kurrentdb.version>1.2.1</kurrentdb.version>
|
|
13
|
+
<spring-boot.version>4.1.0</spring-boot.version>
|
|
14
|
+
<!-- Must track whatever version kurrentdb-client itself pulls in transitively (grpc-api is
|
|
15
|
+
runtime-scope only there) — check `mvn dependency:tree | grep grpc` after bumping
|
|
16
|
+
kurrentdb.version, and bump this to match. -->
|
|
17
|
+
<grpc.version>1.80.0</grpc.version>
|
|
18
|
+
</properties>
|
|
19
|
+
|
|
20
|
+
<dependencies>
|
|
21
|
+
<dependency>
|
|
22
|
+
<groupId>org.springframework.boot</groupId>
|
|
23
|
+
<artifactId>spring-boot-starter-webmvc</artifactId>
|
|
24
|
+
</dependency>
|
|
25
|
+
|
|
26
|
+
<!-- Classic Jackson 2 (com.fasterxml.jackson.core), for hand-serializing event payloads
|
|
27
|
+
(LibraryEventTypes and friends) with the same ObjectMapper the kurrentdb-client's own
|
|
28
|
+
samples use. Spring Boot 4 moved its own internal JSON handling to Jackson 3
|
|
29
|
+
(tools.jackson.core) and only pulls classic Jackson 2 in at *runtime* scope, transitively
|
|
30
|
+
via kurrentdb-client itself — not on the compile classpath by default. Declared explicitly,
|
|
31
|
+
version still resolved from Spring Boot's dependency-management BOM. -->
|
|
32
|
+
<dependency>
|
|
33
|
+
<groupId>com.fasterxml.jackson.core</groupId>
|
|
34
|
+
<artifactId>jackson-databind</artifactId>
|
|
35
|
+
</dependency>
|
|
36
|
+
|
|
37
|
+
<!-- Read model persistence: Spring Data JPA + PostgreSQL, default for all projections -->
|
|
38
|
+
<dependency>
|
|
39
|
+
<groupId>org.springframework.boot</groupId>
|
|
40
|
+
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
|
41
|
+
</dependency>
|
|
42
|
+
<dependency>
|
|
43
|
+
<groupId>org.postgresql</groupId>
|
|
44
|
+
<artifactId>postgresql</artifactId>
|
|
45
|
+
<scope>runtime</scope>
|
|
46
|
+
</dependency>
|
|
47
|
+
|
|
48
|
+
<dependency>
|
|
49
|
+
<groupId>org.springframework.boot</groupId>
|
|
50
|
+
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
51
|
+
</dependency>
|
|
52
|
+
|
|
53
|
+
<!-- KurrentDB Java client (plain SDK — no Spring Boot auto-configuration of its own,
|
|
54
|
+
see config.KurrentConfiguration for the beans this project wires by hand) -->
|
|
55
|
+
<dependency>
|
|
56
|
+
<groupId>io.kurrent</groupId>
|
|
57
|
+
<artifactId>kurrentdb-client</artifactId>
|
|
58
|
+
<version>${kurrentdb.version}</version>
|
|
59
|
+
</dependency>
|
|
60
|
+
|
|
61
|
+
<!-- io.grpc.Status/StatusRuntimeException — needed at compile scope to detect an
|
|
62
|
+
ALREADY_EXISTS conflict when idempotently creating a persistent-subscription group
|
|
63
|
+
(see build-state-view/build-automation). Only pulled in transitively by
|
|
64
|
+
kurrentdb-client at *runtime* scope otherwise. -->
|
|
65
|
+
<dependency>
|
|
66
|
+
<groupId>io.grpc</groupId>
|
|
67
|
+
<artifactId>grpc-api</artifactId>
|
|
68
|
+
<version>${grpc.version}</version>
|
|
69
|
+
</dependency>
|
|
70
|
+
|
|
71
|
+
<!-- Auto-starts docker-compose.yml services (KurrentDB, Postgres) on app run -->
|
|
72
|
+
<dependency>
|
|
73
|
+
<groupId>org.springframework.boot</groupId>
|
|
74
|
+
<artifactId>spring-boot-docker-compose</artifactId>
|
|
75
|
+
<scope>runtime</scope>
|
|
76
|
+
<optional>true</optional>
|
|
77
|
+
</dependency>
|
|
78
|
+
|
|
79
|
+
<!-- Testing -->
|
|
80
|
+
<dependency>
|
|
81
|
+
<groupId>org.springframework.boot</groupId>
|
|
82
|
+
<artifactId>spring-boot-starter-test</artifactId>
|
|
83
|
+
<scope>test</scope>
|
|
84
|
+
</dependency>
|
|
85
|
+
<!-- Spring Boot 4 test slices: @DataJpaTest and @WebMvcTest each moved to their own artifact -->
|
|
86
|
+
<dependency>
|
|
87
|
+
<groupId>org.springframework.boot</groupId>
|
|
88
|
+
<artifactId>spring-boot-data-jpa-test</artifactId>
|
|
89
|
+
<scope>test</scope>
|
|
90
|
+
</dependency>
|
|
91
|
+
<dependency>
|
|
92
|
+
<groupId>org.springframework.boot</groupId>
|
|
93
|
+
<artifactId>spring-boot-webmvc-test</artifactId>
|
|
94
|
+
<scope>test</scope>
|
|
95
|
+
</dependency>
|
|
96
|
+
<dependency>
|
|
97
|
+
<groupId>org.junit.jupiter</groupId>
|
|
98
|
+
<artifactId>junit-jupiter</artifactId>
|
|
99
|
+
<scope>test</scope>
|
|
100
|
+
</dependency>
|
|
101
|
+
<dependency>
|
|
102
|
+
<groupId>org.springframework.boot</groupId>
|
|
103
|
+
<artifactId>spring-boot-testcontainers</artifactId>
|
|
104
|
+
<scope>test</scope>
|
|
105
|
+
</dependency>
|
|
106
|
+
<dependency>
|
|
107
|
+
<groupId>org.testcontainers</groupId>
|
|
108
|
+
<artifactId>testcontainers</artifactId>
|
|
109
|
+
<scope>test</scope>
|
|
110
|
+
</dependency>
|
|
111
|
+
<dependency>
|
|
112
|
+
<groupId>org.testcontainers</groupId>
|
|
113
|
+
<artifactId>testcontainers-postgresql</artifactId>
|
|
114
|
+
<scope>test</scope>
|
|
115
|
+
</dependency>
|
|
116
|
+
<dependency>
|
|
117
|
+
<groupId>org.testcontainers</groupId>
|
|
118
|
+
<artifactId>testcontainers-junit-jupiter</artifactId>
|
|
119
|
+
<scope>test</scope>
|
|
120
|
+
</dependency>
|
|
121
|
+
</dependencies>
|
|
122
|
+
|
|
123
|
+
<build>
|
|
124
|
+
<plugins>
|
|
125
|
+
<plugin>
|
|
126
|
+
<groupId>org.apache.maven.plugins</groupId>
|
|
127
|
+
<artifactId>maven-compiler-plugin</artifactId>
|
|
128
|
+
<configuration>
|
|
129
|
+
<source>${java.version}</source>
|
|
130
|
+
<target>${java.version}</target>
|
|
131
|
+
<parameters>true</parameters>
|
|
132
|
+
</configuration>
|
|
133
|
+
</plugin>
|
|
134
|
+
<plugin>
|
|
135
|
+
<groupId>org.springframework.boot</groupId>
|
|
136
|
+
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
137
|
+
</plugin>
|
|
138
|
+
</plugins>
|
|
139
|
+
</build>
|
|
140
|
+
|
|
141
|
+
<dependencyManagement>
|
|
142
|
+
<dependencies>
|
|
143
|
+
<dependency>
|
|
144
|
+
<groupId>org.springframework.boot</groupId>
|
|
145
|
+
<artifactId>spring-boot-dependencies</artifactId>
|
|
146
|
+
<version>${spring-boot.version}</version>
|
|
147
|
+
<type>pom</type>
|
|
148
|
+
<scope>import</scope>
|
|
149
|
+
</dependency>
|
|
150
|
+
</dependencies>
|
|
151
|
+
</dependencyManagement>
|
|
152
|
+
</project>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
package com.example.quickstart;
|
|
2
|
+
|
|
3
|
+
import org.springframework.boot.SpringApplication;
|
|
4
|
+
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
5
|
+
|
|
6
|
+
@SpringBootApplication
|
|
7
|
+
public class QuickstartApplication {
|
|
8
|
+
|
|
9
|
+
public static void main(String[] args) {
|
|
10
|
+
SpringApplication.run(QuickstartApplication.class, args);
|
|
11
|
+
}
|
|
12
|
+
}
|
package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/common/EventStore.java
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
package com.example.quickstart.common;
|
|
2
|
+
|
|
3
|
+
import io.kurrent.dbclient.*;
|
|
4
|
+
import org.springframework.stereotype.Component;
|
|
5
|
+
|
|
6
|
+
import java.util.List;
|
|
7
|
+
import java.util.concurrent.ExecutionException;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Thin wrapper around {@link KurrentDBClient} shared by every write slice — reads a stream into a
|
|
11
|
+
* plain list (or empty, if the stream doesn't exist yet) and appends events, translating the client's
|
|
12
|
+
* checked/wrapped exceptions into unchecked ones so slice code doesn't repeat this boilerplate.
|
|
13
|
+
*
|
|
14
|
+
* <p>This project has no CQRS framework layer (unlike the OpenCQRS/Axon kits) — this class, plus each
|
|
15
|
+
* slice's own {@code decide}/{@code evolve} functions, is the entire "framework". See
|
|
16
|
+
* {@code .build-kit/CLAUDE.md} for the full convention.
|
|
17
|
+
*/
|
|
18
|
+
@Component
|
|
19
|
+
public class EventStore {
|
|
20
|
+
|
|
21
|
+
private final KurrentDBClient client;
|
|
22
|
+
|
|
23
|
+
public EventStore(KurrentDBClient client) {
|
|
24
|
+
this.client = client;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Reads every event in {@code streamId}, forwards from the start. Returns
|
|
29
|
+
* {@link StreamEvents#empty()} if the stream doesn't exist yet — this is the normal, expected case
|
|
30
|
+
* for a creation command, not an error.
|
|
31
|
+
*/
|
|
32
|
+
public StreamEvents read(String streamId) {
|
|
33
|
+
try {
|
|
34
|
+
ReadResult result = client.readStream(streamId, ReadStreamOptions.get().forwards().fromStart()).get();
|
|
35
|
+
return new StreamEvents(result.getEvents(), result.getLastStreamPosition());
|
|
36
|
+
} catch (ExecutionException e) {
|
|
37
|
+
if (e.getCause() instanceof StreamNotFoundException) {
|
|
38
|
+
return StreamEvents.empty();
|
|
39
|
+
}
|
|
40
|
+
throw new EventStoreException(e.getCause());
|
|
41
|
+
} catch (InterruptedException e) {
|
|
42
|
+
Thread.currentThread().interrupt();
|
|
43
|
+
throw new EventStoreException(e);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Appends {@code events} to {@code streamId} under the given {@code expectedState} (see
|
|
49
|
+
* {@link StreamState#noStream()}/{@link StreamState#streamRevision(long)}/etc). Throws
|
|
50
|
+
* {@link WrongExpectedVersionException} directly (unwrapped) on an optimistic-concurrency
|
|
51
|
+
* conflict — callers decide for themselves whether that's a real conflict (map it to HTTP 409) or
|
|
52
|
+
* an expected redelivery to swallow (see build-automation's SKILL.md).
|
|
53
|
+
*/
|
|
54
|
+
public WriteResult append(String streamId, StreamState expectedState, List<EventData> events) {
|
|
55
|
+
try {
|
|
56
|
+
AppendToStreamOptions options = AppendToStreamOptions.get().streamState(expectedState);
|
|
57
|
+
return client.appendToStream(streamId, options, events.toArray(new EventData[0])).get();
|
|
58
|
+
} catch (ExecutionException e) {
|
|
59
|
+
if (e.getCause() instanceof WrongExpectedVersionException wrongExpectedVersion) {
|
|
60
|
+
throw wrongExpectedVersion;
|
|
61
|
+
}
|
|
62
|
+
throw new EventStoreException(e.getCause());
|
|
63
|
+
} catch (InterruptedException e) {
|
|
64
|
+
Thread.currentThread().interrupt();
|
|
65
|
+
throw new EventStoreException(e);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public record StreamEvents(List<ResolvedEvent> events, long lastStreamPosition) {
|
|
70
|
+
private static final long NO_STREAM_POSITION = -1;
|
|
71
|
+
|
|
72
|
+
public static StreamEvents empty() {
|
|
73
|
+
return new StreamEvents(List.of(), NO_STREAM_POSITION);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public boolean isEmpty() {
|
|
77
|
+
return events.isEmpty();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The {@link StreamState} to append under, given this stream's current position. */
|
|
81
|
+
public StreamState expectedState() {
|
|
82
|
+
return isEmpty() ? StreamState.noStream() : StreamState.streamRevision(lastStreamPosition);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public static class EventStoreException extends RuntimeException {
|
|
87
|
+
public EventStoreException(Throwable cause) {
|
|
88
|
+
super(cause);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
package com.example.quickstart.config;
|
|
2
|
+
|
|
3
|
+
import io.kurrent.dbclient.ConnectionStringParsingException;
|
|
4
|
+
import io.kurrent.dbclient.KurrentDBClient;
|
|
5
|
+
import io.kurrent.dbclient.KurrentDBClientSettings;
|
|
6
|
+
import io.kurrent.dbclient.KurrentDBConnectionString;
|
|
7
|
+
import io.kurrent.dbclient.KurrentDBPersistentSubscriptionsClient;
|
|
8
|
+
import org.springframework.beans.factory.annotation.Value;
|
|
9
|
+
import org.springframework.context.annotation.Bean;
|
|
10
|
+
import org.springframework.context.annotation.Configuration;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The KurrentDB Java client ({@code kurrentdb-client}) ships no Spring Boot auto-configuration of its
|
|
14
|
+
* own (unlike OpenCQRS's {@code framework-spring-boot-starter}) — it is a plain SDK. These beans are
|
|
15
|
+
* this project's own wiring, not a vendor-provided starter.
|
|
16
|
+
*/
|
|
17
|
+
@Configuration
|
|
18
|
+
public class KurrentConfiguration {
|
|
19
|
+
|
|
20
|
+
@Value("${kurrentdb.connection-string}")
|
|
21
|
+
private String connectionString;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A single client instance is safe to share as a singleton across the whole application — it does
|
|
25
|
+
* not need to be opened/closed per request (see the client's own getting-started guide).
|
|
26
|
+
*/
|
|
27
|
+
@Bean(destroyMethod = "shutdown")
|
|
28
|
+
public KurrentDBClient kurrentDBClient() throws ConnectionStringParsingException {
|
|
29
|
+
KurrentDBClientSettings settings = KurrentDBConnectionString.parseOrThrow(connectionString);
|
|
30
|
+
return KurrentDBClient.create(settings);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Separate client for managing/consuming persistent subscriptions — used by build-state-view and
|
|
35
|
+
* build-automation slices, not by build-state-change (which only appends/reads streams directly).
|
|
36
|
+
*/
|
|
37
|
+
@Bean(destroyMethod = "shutdown")
|
|
38
|
+
public KurrentDBPersistentSubscriptionsClient kurrentDBPersistentSubscriptionsClient() throws ConnectionStringParsingException {
|
|
39
|
+
KurrentDBClientSettings settings = KurrentDBConnectionString.parseOrThrow(connectionString);
|
|
40
|
+
return KurrentDBPersistentSubscriptionsClient.create(settings);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
spring.application.name=quickstart
|
|
2
|
+
server.port=8080
|
|
3
|
+
|
|
4
|
+
kurrentdb.connection-string=${KURRENTDB_CONNECTION_STRING:kurrentdb://localhost:2113?tls=false}
|
|
5
|
+
|
|
6
|
+
spring.datasource.url=jdbc:postgresql://localhost:5432/quickstart
|
|
7
|
+
spring.datasource.username=quickstart
|
|
8
|
+
spring.datasource.password=quickstart
|
|
9
|
+
spring.jpa.hibernate.ddl-auto=update
|
|
10
|
+
|
|
11
|
+
spring.docker.compose.enabled=true
|
|
12
|
+
spring.docker.compose.file=docker-compose.yml
|
|
13
|
+
|
|
14
|
+
management.endpoint.health.show-components=always
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Kurrent Quickstart</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Kurrent Quickstart</h1>
|
|
9
|
+
<p>Backend is running. Slices built from the event model board are wired up under their own REST paths.</p>
|
|
10
|
+
</body>
|
|
11
|
+
</html>
|
|
@@ -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
|
|