@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.
Files changed (123) hide show
  1. package/README.md +5 -2
  2. package/cli.js +53 -1
  3. package/package.json +2 -2
  4. package/shared/build-kit/lib/checks/README.md +59 -0
  5. package/shared/build-kit/lib/ralph.js +110 -28
  6. package/shared/build-kit/lib/util/find-slice.cjs +59 -0
  7. package/shared/build-kit/ralph-claude.js +6 -2
  8. package/shared/skills/learn-eventmodelers-api/SKILL.md +52 -46
  9. package/shared/skills/request-feedback/SKILL.md +7 -5
  10. package/stacks/axon/templates/build-kit/CLAUDE.md +1 -1
  11. package/stacks/blank/templates/build-kit/CLAUDE.md +1 -1
  12. package/stacks/blank/templates/build-kit/lib/backend-prompt.md +106 -102
  13. package/stacks/blank/templates/build-kit/lib/prompt.md +102 -106
  14. package/stacks/cratis-csharp/templates/build-kit/CLAUDE.md +9 -0
  15. package/stacks/kurrent/templates/.claude/skills/build-automation/SKILL.md +422 -0
  16. package/stacks/kurrent/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +19 -0
  17. package/stacks/kurrent/templates/.claude/skills/build-automation/references/idempotent-dispatch-patterns.md +65 -0
  18. package/stacks/kurrent/templates/.claude/skills/build-state-change/SKILL.md +418 -0
  19. package/stacks/kurrent/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +41 -0
  20. package/stacks/kurrent/templates/.claude/skills/build-state-change/references/integration-test-patterns.md +64 -0
  21. package/stacks/kurrent/templates/.claude/skills/build-state-view/SKILL.md +391 -0
  22. package/stacks/kurrent/templates/build-kit/CLAUDE.md +124 -0
  23. package/stacks/kurrent/templates/build-kit/lib/AGENT.md +73 -0
  24. package/stacks/kurrent/templates/build-kit/lib/backend-prompt.md +169 -0
  25. package/stacks/kurrent/templates/build-kit/lib/prompt.md +128 -0
  26. package/stacks/kurrent/templates/root/README.md +46 -0
  27. package/stacks/kurrent/templates/root/docker-compose.yml +45 -0
  28. package/stacks/kurrent/templates/root/mvnw +259 -0
  29. package/stacks/kurrent/templates/root/mvnw.cmd +149 -0
  30. package/stacks/kurrent/templates/root/pom.xml +152 -0
  31. package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/QuickstartApplication.java +12 -0
  32. package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/common/EventStore.java +91 -0
  33. package/stacks/kurrent/templates/root/src/main/java/com/example/quickstart/config/KurrentConfiguration.java +42 -0
  34. package/stacks/kurrent/templates/root/src/main/resources/application.properties +14 -0
  35. package/stacks/kurrent/templates/root/src/main/resources/static/index.html +11 -0
  36. package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/SKILL.md +2 -2
  37. package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +0 -1
  38. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +1 -1
  39. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/references/examples.md +2 -2
  40. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-core-rules/SKILL.md +2 -2
  41. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +1 -1
  42. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-interview-protocol/SKILL.md +1 -1
  43. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +4 -4
  44. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +1 -1
  45. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +1 -1
  46. package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +1 -1
  47. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +13 -4
  48. package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +2 -2
  49. package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +5 -5
  50. package/stacks/modeling-kit/templates/kit/AGENTS.md +1 -1
  51. package/stacks/modeling-kit/templates/kit/CLAUDE.md +2 -2
  52. package/stacks/node/templates/build-kit/CLAUDE.md +23 -1
  53. package/stacks/node/templates/build-kit/lib/check-commit-scope.cjs +123 -0
  54. package/stacks/node/templates/build-kit/lib/checks/00-blocked-paths.cjs +28 -0
  55. package/stacks/node/templates/build-kit/lib/checks/10-slice-scope.cjs +29 -0
  56. package/stacks/node/templates/build-kit/lib/checks/20-append-only-migrations.cjs +20 -0
  57. package/stacks/node/templates/build-kit/lib/checks/30-test-file-present.cjs +44 -0
  58. package/stacks/node/templates/build-kit/lib/checks/40-no-invented-fields.cjs +92 -0
  59. package/stacks/node/templates/build-kit/lib/checks/50-spec-coverage.cjs +50 -0
  60. package/stacks/node/templates/build-kit/lib/checks/90-tsc-build.cjs +22 -0
  61. package/stacks/node/templates/root/.githooks/pre-commit +11 -0
  62. package/stacks/node/templates/root/package.json +2 -1
  63. package/stacks/node/templates/root/setup-env.sh +7 -1
  64. package/stacks/opencqrs/templates/.claude/skills/build-automation/SKILL.md +434 -0
  65. package/stacks/opencqrs/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +19 -0
  66. package/stacks/opencqrs/templates/.claude/skills/build-automation/references/idempotent-dispatch-patterns.md +62 -0
  67. package/stacks/opencqrs/templates/.claude/skills/build-state-change/SKILL.md +413 -0
  68. package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +46 -0
  69. package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/rest-api-patterns.md +145 -0
  70. package/stacks/opencqrs/templates/.claude/skills/build-state-change/references/test-fixture-patterns.md +85 -0
  71. package/stacks/opencqrs/templates/.claude/skills/build-state-view/SKILL.md +354 -0
  72. package/stacks/opencqrs/templates/build-kit/CLAUDE.md +103 -0
  73. package/stacks/opencqrs/templates/build-kit/lib/AGENT.md +58 -0
  74. package/stacks/opencqrs/templates/build-kit/lib/backend-prompt.md +169 -0
  75. package/stacks/opencqrs/templates/build-kit/lib/prompt.md +128 -0
  76. package/stacks/opencqrs/templates/root/README.md +42 -0
  77. package/stacks/opencqrs/templates/root/docker-compose.yml +37 -0
  78. package/stacks/opencqrs/templates/root/mvnw +259 -0
  79. package/stacks/opencqrs/templates/root/mvnw.cmd +149 -0
  80. package/stacks/opencqrs/templates/root/pom.xml +139 -0
  81. package/stacks/opencqrs/templates/root/src/main/java/com/example/quickstart/QuickstartApplication.java +12 -0
  82. package/stacks/opencqrs/templates/root/src/main/java/com/example/quickstart/config/CqrsConfiguration.java +74 -0
  83. package/stacks/opencqrs/templates/root/src/main/resources/application.properties +23 -0
  84. package/stacks/opencqrs/templates/root/src/main/resources/schema.sql +19 -0
  85. package/stacks/opencqrs/templates/root/src/main/resources/static/index.html +11 -0
  86. package/stacks/supabase/templates/build-kit/CLAUDE.md +26 -1
  87. package/stacks/supabase/templates/build-kit/lib/check-commit-scope.cjs +126 -0
  88. package/stacks/supabase/templates/build-kit/lib/checks/00-blocked-paths.cjs +28 -0
  89. package/stacks/supabase/templates/build-kit/lib/checks/10-slice-scope.cjs +34 -0
  90. package/stacks/supabase/templates/build-kit/lib/checks/20-append-only-migrations.cjs +21 -0
  91. package/stacks/supabase/templates/build-kit/lib/checks/30-test-file-present.cjs +44 -0
  92. package/stacks/supabase/templates/build-kit/lib/checks/40-no-invented-fields.cjs +92 -0
  93. package/stacks/supabase/templates/build-kit/lib/checks/50-spec-coverage.cjs +50 -0
  94. package/stacks/supabase/templates/build-kit/lib/checks/90-tsc-build.cjs +22 -0
  95. package/stacks/supabase/templates/root/.githooks/pre-commit +11 -0
  96. package/stacks/supabase/templates/root/package.json +2 -1
  97. package/stacks/supabase/templates/root/setup-env.sh +7 -1
  98. package/stacks/umadb/templates/.claude/skills/build-automation/SKILL.md +313 -0
  99. package/stacks/umadb/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +42 -0
  100. package/stacks/umadb/templates/.claude/skills/build-state-change/SKILL.md +376 -0
  101. package/stacks/umadb/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +42 -0
  102. package/stacks/umadb/templates/.claude/skills/build-state-change/references/umadb-query-patterns.md +78 -0
  103. package/stacks/umadb/templates/.claude/skills/build-state-view/SKILL.md +338 -0
  104. package/stacks/umadb/templates/build-kit/CLAUDE.md +94 -0
  105. package/stacks/umadb/templates/build-kit/lib/AGENT.md +47 -0
  106. package/stacks/umadb/templates/build-kit/lib/backend-prompt.md +169 -0
  107. package/stacks/umadb/templates/build-kit/lib/prompt.md +128 -0
  108. package/stacks/umadb/templates/root/.mvn/wrapper/maven-wrapper.properties +19 -0
  109. package/stacks/umadb/templates/root/README.md +48 -0
  110. package/stacks/umadb/templates/root/docker-compose.yml +29 -0
  111. package/stacks/umadb/templates/root/mvnw +259 -0
  112. package/stacks/umadb/templates/root/mvnw.cmd +149 -0
  113. package/stacks/umadb/templates/root/pom.xml +151 -0
  114. package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/QuickstartApplication.java +12 -0
  115. package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/config/UmaDbConfig.java +39 -0
  116. package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/DecisionModelLoader.java +76 -0
  117. package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/EventCodec.java +40 -0
  118. package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/EventDispatcher.java +100 -0
  119. package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/OptimisticConcurrencyException.java +14 -0
  120. package/stacks/umadb/templates/root/src/main/java/io/umadb/quickstart/eventstore/SliceEventListener.java +23 -0
  121. package/stacks/umadb/templates/root/src/main/resources/application.properties +17 -0
  122. package/stacks/umadb/templates/root/src/test/java/io/umadb/quickstart/testsupport/InMemoryUmaDbClient.java +135 -0
  123. 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
+ }
@@ -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 `QUESTION`/`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.
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 `QUESTION` 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.
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
 
@@ -100,7 +100,6 @@ For each node:
100
100
  "name": "<attributeName>",
101
101
  "type": "String",
102
102
  "query": false,
103
- "edited": false,
104
103
  "optional": false,
105
104
  "generated": false,
106
105
  "subfields": [],
@@ -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, `QUESTION` for gaps that need clarification.
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`/`QUESTION` comments via `handle-comment`), not in writing a document like this.
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`/`QUESTION` 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.
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 `QUESTION`-type comment (`handle-comment`) on the relevant node. It stays open until someone actually answers it resolving means answering, not deleting the comment.
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 `QUESTION` comment looks unresolved when it isn't. When counting completeness (`eventmodeling-checking-completeness`), only a genuinely unanswered `QUESTION` counts as a gap — a decided failure path needs its `expectError` scenario, not a comment standing in for one.
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
 
@@ -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 (`.trogonai/interviews/.../EVENTMODELING.md`), not the actual field data. It will not reliably carry the per-field mappings forward. Go back to the board itself:
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
 
@@ -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: `.trogonai/interviews/[project-name]/EVENTMODELING.md`, under a section for this step:
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 `.trogonai/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`):
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 `.trogonai/interviews/[project-name]/EVENTMODELING.md`:
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/QUESTION comment was also posted on the affected node.
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 `.trogonai/` updated with status of each completed step
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
@@ -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 QUESTION comment on any screen node where data fields are unclear or missing sources are identified.
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
 
@@ -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, `QUESTION` for warnings and recommendations. (That skill already handles the `add_comment` MCP-vs-curl choice internally — no separate rewrite needed here.)
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. Set `edited: true` on any field you modify.
82
+ Build the updated `fields` array: same structure as the original, only the `example` property changed where needed.
83
83
 
84
84
  ---
85
85