@cratis/pi 2.24.1 → 2.26.0

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.
@@ -22,6 +22,13 @@ requested-label, merge, and branch-cleanup effects. Do not pause to ask for sepa
22
22
  each step. Follow the repository's Git commit and pull-request rules, use a true merge commit,
23
23
  and verify required checks before merging.
24
24
 
25
+ **Exception: a `major` label does not carry merge authority.** Prepare the branch, commits, push,
26
+ and PR labeled `major` as usual, then stop before merging. Ask a human to confirm the breaking
27
+ change(s), who is affected, and the resulting version number, and merge only on an explicit
28
+ affirmative answer to that specific question — see
29
+ [`pull-requests.md`](../rules/pull-requests.md#a-major-release-needs-a-humans-explicit-go-ahead).
30
+ Every other label proceeds through merge under this prompt's ordinary authority.
31
+
25
32
  This prompt is for an explicit request to ship or land. If the user asked only to commit, only to
26
33
  push, or only to open a PR, stop after that step: the narrower request does not become authority
27
34
  for the rest of the chain because this prompt happens to be loaded.
@@ -0,0 +1,134 @@
1
+ ---
2
+ applyTo: "**/*.java"
3
+ paths:
4
+ - "**/*.java"
5
+ ---
6
+
7
+ # Java Conventions
8
+
9
+ Java is a supported, first-class Cratis application language alongside Kotlin
10
+ — an Arc.Kotlin-based application can be entirely Java source, with Kotlin and
11
+ KSP present only in the build (Arc generates Kotlin adapters for Java
12
+ declarations under the hood). Write idiomatic modern Java; do not import
13
+ Kotlin idioms into Java source, and do not treat Java as a second-class
14
+ citizen of a Kotlin codebase. Arc/Chronicle-specific shapes (`@Command`,
15
+ `@ReadModel`, `@EventType`, and the rest) live in the matching skill, not
16
+ here.
17
+
18
+ ## Building
19
+
20
+ - Use `./gradlew build` (or the repository's Maven equivalent) from the
21
+ command line; it is the definition of "the build is clean" — zero warnings,
22
+ zero errors.
23
+ - Treat compiler warnings as errors (`-Xlint:all -Werror`); do not suppress a
24
+ warning to get to green.
25
+
26
+ ## Formatting
27
+
28
+ - Four-space indentation, no tabs.
29
+ - One public top-level type per file, named after that type.
30
+ - Sort imports alphabetically; no wildcard imports.
31
+ - Braces on the same line as the declaration (`if (...) {`), closing brace on
32
+ its own line.
33
+
34
+ ## Language — American English Only
35
+
36
+ All identifiers, Javadoc, and string literals use **American English**
37
+ spelling (initialize, serialize, behavior, color, organization, center,
38
+ modeling, dialog, license, judgment, gray). See [general.md](./general.md).
39
+
40
+ ## Naming
41
+
42
+ - PascalCase for class and interface names.
43
+ - camelCase for methods, fields, and local variables.
44
+ - No `I` prefix on interfaces — name the interface for what it does.
45
+ - Never suffix a class with `Impl`, `Manager`, or `Helper` purely to
46
+ disambiguate — name it for its role; reserve `Default<Name>` for the
47
+ concrete counterpart of an interface meant to be overridden.
48
+
49
+ ## Records and Immutable Data
50
+
51
+ - Prefer a `record` for an immutable value holder (DTOs, command payloads,
52
+ query results, read models) over a hand-written class with a constructor,
53
+ getters, `equals`, `hashCode`, and `toString` — the record gives all of that
54
+ for free and keeps the file short.
55
+ - Give a record component a validating compact constructor when the type must
56
+ never hold an invalid value, rather than validating at every call site that
57
+ constructs one.
58
+ - Favor `sealed` interfaces with a closed set of `permits` implementations
59
+ over a discriminator field, when a value can genuinely only be one of a
60
+ known set of shapes — pattern matching over the sealed hierarchy replaces
61
+ the `instanceof` chain.
62
+
63
+ ## Nullability
64
+
65
+ - Prefer `Optional<T>` for a method's **return type** when absence is a normal
66
+ outcome the caller must handle; never use `Optional` as a field type, a
67
+ constructor parameter, or a method parameter — that is not what it is for.
68
+ - Prefer a non-null default and an explicit `Objects.requireNonNull(...)` at a
69
+ constructor boundary over accepting `null` and checking for it throughout a
70
+ class.
71
+ - On a surface consumed from Kotlin (an Arc/Chronicle read model, event, or
72
+ command reached from Kotlin code), be deliberate about which fields are
73
+ genuinely optional — a Java field with no null-safety annotation reads as
74
+ non-null to Kotlin-facing generated code by default.
75
+
76
+ ## Classes
77
+
78
+ - Favor composition over inheritance; an `interface` plus one or more
79
+ implementing classes is the house shape for an overridable collaborator, not
80
+ a base class meant to be extended.
81
+ - Make a class `final` unless it is deliberately designed for extension.
82
+ - Prefer constructor injection over field injection for a Spring-managed
83
+ bean — a `final` field set in the constructor over an `@Autowired` field.
84
+
85
+ ## Asynchronous Code
86
+
87
+ - `CompletionStage<T>` (or its `CompletableFuture` implementation) is the
88
+ house shape for an asynchronous Java API, mirroring how Kotlin exposes
89
+ `suspend` — Arc's generated adapters await a returned `CompletionStage`
90
+ without reflection.
91
+ - Never block on a `CompletionStage` inside a method that itself returns
92
+ one — compose with `.thenApply`/`.thenCompose` or `.thenAccept` instead of
93
+ calling `.get()`/`.join()` inside the async chain.
94
+ - Give a Java caller its own explicit scope (an `ExecutorService`, or the
95
+ scope type the host library provides) rather than reaching for a shared
96
+ global one.
97
+
98
+ ## Javadoc
99
+
100
+ - Every public type and method meant for consumption outside its package gets
101
+ a Javadoc comment (`/** ... */`) — what it does and why, not a restatement
102
+ of its name.
103
+ - Use `@param`, `@return`, and `@throws` for parameters, return values, and
104
+ checked exceptions.
105
+
106
+ ## Exceptions
107
+
108
+ - Use exceptions for genuinely exceptional, unrecoverable conditions — not for
109
+ control flow a caller is expected to handle. A command or query rejection a
110
+ user can act on is a validation result, not a thrown exception; see the Arc
111
+ validation skills.
112
+ - Prefer an unchecked exception with a clear name over a checked exception
113
+ that forces every caller to catch or declare it; reserve checked exceptions
114
+ for conditions a caller genuinely has a recovery path for.
115
+
116
+ ## Dependency Injection
117
+
118
+ - Constructor injection is the default for a Spring-managed bean; avoid field
119
+ injection (`@Autowired` on a field) even though Spring supports it.
120
+
121
+ ## Logging
122
+
123
+ - Log through the host's structured logging facility (SLF4J via Spring Boot),
124
+ not `System.out`/`System.err`.
125
+ - Log at the boundary where a decision is made or an error is handled, not at
126
+ every intermediate call.
127
+
128
+ ## Testing
129
+
130
+ - JUnit 5 is the house test runner.
131
+ - A test for a Java-facing surface belongs beside the Java production code
132
+ (`src/test/java/.../<Thing>Test.java`) and must actually compile and run
133
+ against that surface — a Kotlin-only test does not prove Java call-site
134
+ compatibility for a mixed-language library.
@@ -0,0 +1,172 @@
1
+ ---
2
+ applyTo: "**/*.kt,**/*.kts"
3
+ paths:
4
+ - "**/*.kt"
5
+ - "**/*.kts"
6
+ ---
7
+
8
+ # Kotlin Conventions
9
+
10
+ Kotlin is a JVM-first, coroutine-first language. Use its own idioms — data
11
+ classes, `null`-aware types, coroutines, sealed hierarchies — instead of
12
+ carrying Java or C# patterns across unchanged. A Cratis Arc or Chronicle
13
+ application on Kotlin follows Spring Boot conventions for wiring and this
14
+ file's conventions for everything else; Arc/Chronicle-specific shapes
15
+ (`@Command`, `@ReadModel`, `@EventType`, and the rest) live in the matching
16
+ skill, not here.
17
+
18
+ ## Building
19
+
20
+ - Use `./gradlew build` from the command line; it is the definition of "the
21
+ build is clean" — zero warnings, zero errors.
22
+ - Use `./gradlew test` to run tests.
23
+ - Treat compiler warnings as errors. `allWarningsAsErrors` is the house
24
+ default for Kotlin compilation; do not add a suppression to get to green.
25
+
26
+ ## Formatting
27
+
28
+ - Four-space indentation, no tabs.
29
+ - One top-level public declaration per file, named after that declaration.
30
+ - Sort imports alphabetically; no wildcard imports.
31
+ - Trailing commas in multi-line parameter lists and call sites — they keep
32
+ diffs to one line when a member is added or removed.
33
+ - Insert a blank line before the opening `{` of a multi-line `if`/`when`/`for`
34
+ block; keep single-expression bodies on one line.
35
+
36
+ ## Language — American English Only
37
+
38
+ All identifiers, KDoc, and string literals use **American English** spelling
39
+ (initialize, serialize, behavior, color, organization, center, modeling,
40
+ dialog, license, judgment, gray). See [general.md](./general.md).
41
+
42
+ ## Naming
43
+
44
+ - PascalCase for class, interface, and object names.
45
+ - camelCase for functions, properties, and local variables.
46
+ - No `I` prefix on interfaces — Kotlin does not carry that convention; name
47
+ the interface for what it does (`CommandPipeline`, not `ICommandPipeline`)
48
+ unless a concrete/interface pair genuinely needs `Default<Name>` for the
49
+ implementation.
50
+ - Never suffix a class with `Impl`, `Service`, or `Async` purely to
51
+ disambiguate — name it for its role.
52
+
53
+ ## Visibility
54
+
55
+ - Kotlin's implicit-public default is what most declarations should use;
56
+ spelling `public` is a style choice, not a requirement — decide once per
57
+ file or module and stay consistent within it.
58
+ - Mark a declaration `internal` when it must not cross a module boundary, and
59
+ `private` for anything a class does not need to expose. Do not default
60
+ everything to `public` "to be safe" — a wider surface than necessary is a
61
+ bigger contract to keep stable.
62
+ - Compile-time discovery (KSP, reflection-based scanning) generally requires
63
+ **public** top-level types and members. A declaration silently excluded from
64
+ discovery because it is `internal` or `private` is a visibility bug, not a
65
+ framework limitation — check the matching skill's discovery rules before
66
+ assuming a narrower visibility is safe.
67
+
68
+ ## Nullability
69
+
70
+ Kotlin's type system is the first line of defense against null-related bugs —
71
+ trust it the same way C# nullable reference types are trusted.
72
+
73
+ - Prefer a non-nullable type and a real default over a nullable one with a
74
+ defensive check.
75
+ - Use `?.`, `?:`, and `requireNotNull()`/`checkNotNull()` instead of manual
76
+ `if (x != null)` guards.
77
+ - A nullable outer collection (`List<T>?`) is supported; a nullable *element*
78
+ inside a collection (`List<T?>`) is a narrower, often-unsupported shape in
79
+ generated/serialized contracts — do not reach for it without checking
80
+ whether the surface you are writing actually allows it.
81
+ - Data classes model state, not behavior — keep validation and invariants in
82
+ the type that owns them (a concept, a validator), not scattered across every
83
+ call site that happens to touch a nullable field.
84
+
85
+ ## Classes and Data
86
+
87
+ - Prefer `data class` for immutable value holders (DTOs, events, command
88
+ payloads, read models) — value equality, `copy()`, and `componentN()`
89
+ destructuring come for free.
90
+ - Prefer a primary constructor with `val` properties over a body full of
91
+ assignment statements.
92
+ - Reach for a `sealed class`/`sealed interface` hierarchy instead of an enum
93
+ with a payload bolted on, whenever the variants carry different data.
94
+ - Favor composition over inheritance; an `interface` plus a `Default*`
95
+ implementation is the house shape for an overridable collaborator, not a
96
+ base class meant to be extended.
97
+
98
+ ## Coroutines
99
+
100
+ - An asynchronous API is `suspend`, not a returned `Future`/`CompletableFuture`
101
+ — Kotlin callers compose `suspend` functions directly, and a JVM-facing
102
+ bridge (`CompletionStage`) is layered on top for Java callers, never the
103
+ other way around.
104
+ - Per-call state travels in a `CoroutineContext` element; never a
105
+ `ThreadLocal`. A coroutine can move between threads, and thread-local state
106
+ silently goes stale when it does.
107
+ - Never launch on `GlobalScope`. Use the scope the host (Spring Boot's bounded
108
+ application coroutine scope, a test's `runBlocking`/`runTest`) already
109
+ provides.
110
+ - Cleanup that must run even after cancellation goes in
111
+ `withContext(NonCancellable) { ... }`; everything else should stay
112
+ cancellable rather than swallow the cancellation.
113
+ - Bridge a genuinely thread-bound third-party API with a
114
+ `ThreadContextElement`; do not leak a raw `ThreadLocal` into coroutine-facing
115
+ state as a shortcut.
116
+
117
+ ## Java Interop
118
+
119
+ Kotlin/Java interop is a first-class concern whenever a library or an
120
+ application may be consumed from Java — which every Arc/Chronicle application
121
+ should assume by default:
122
+
123
+ - Add `@JvmStatic` to companion-object factories a Java caller needs to call
124
+ without `Companion.`.
125
+ - Add `@JvmOverloads` to a function with default parameter values so Java
126
+ gets the shorter overloads too.
127
+ - Give a function returning a value class or an inline class a `@JvmName`
128
+ when Java needs to call it — the mangled synthetic name is not meant to be
129
+ called directly.
130
+ - Prefer a `List<T>`/`Map<K, V>` parameter type over a Kotlin-only collection
131
+ interface on any Java-facing surface.
132
+
133
+ ## KDoc
134
+
135
+ - Every public type, function, and property meant for consumption outside its
136
+ module gets a KDoc comment (`/** ... */`) — what it does and why, not a
137
+ restatement of its name.
138
+ - Keep the summary to one or two sentences; use `@param`, `@return`, and
139
+ `@throws` for the rest.
140
+
141
+ ## Exceptions
142
+
143
+ - Use exceptions for genuinely exceptional, unrecoverable conditions — not for
144
+ control flow a caller is expected to handle. A command or query rejection a
145
+ user can act on is a validation result, not a thrown exception; see the
146
+ Arc validation skills.
147
+ - Define a custom exception type when a caller needs to distinguish it from
148
+ other failures; do not throw a bare `RuntimeException`/`IllegalStateException`
149
+ for something callers are expected to catch specifically.
150
+
151
+ ## Dependency Injection
152
+
153
+ - Constructor injection through the primary constructor is the default; avoid
154
+ field/property injection.
155
+ - Give a collaborator an interface and a `Default*` implementation when an
156
+ application might reasonably override it, bound with Spring's
157
+ `@ConditionalOnMissingBean` so a consumer can replace it without forking.
158
+
159
+ ## Logging
160
+
161
+ - Log through the host's structured logging facility (SLF4J via Spring Boot),
162
+ not `println`.
163
+ - Log at the boundary where a decision is made or an error is handled, not at
164
+ every intermediate call.
165
+
166
+ ## Testing
167
+
168
+ - JUnit 5 is the house test runner for Kotlin and Java alike.
169
+ - A Kotlin test lives beside its Kotlin production code
170
+ (`src/test/kotlin/.../<Thing>Test.kt`); a Java-facing surface also gets a
171
+ Java test that compiles and runs against it, because Kotlin-only tests do
172
+ not prove Java call-site compatibility.
@@ -59,14 +59,15 @@ The complete list of available profiles is defined in [profile-catalog.json](../
59
59
  | `cratis/application/arc-only` | Arc without Chronicle | `cratis/arc/core`, `cratis/fundamentals`, `cratis/specifications/dotnet` |
60
60
  | `cratis/application/chronicle-dotnet` | Chronicle .NET client | `cratis/chronicle/client-dotnet`, `cratis/chronicle/core`, `cratis/fundamentals`, `cratis/specifications/dotnet` |
61
61
  | `cratis/application/elixir` | Elixir Chronicle client | `cratis/chronicle/client-elixir`, `cratis/language/elixir` |
62
- | `cratis/application/kotlin` | Kotlin Chronicle client | `cratis/arc/client-kotlin`, `cratis/chronicle/client-kotlin`, `cratis/language/kotlin` |
62
+ | `cratis/application/kotlin` | Kotlin Arc + Chronicle application | `cratis/arc/client-kotlin`, `cratis/chronicle/client-kotlin`, `cratis/language/kotlin` |
63
+ | `cratis/application/java` | Java Arc + Chronicle application | `cratis/arc/client-kotlin`, `cratis/chronicle/client-java`, `cratis/language/java` |
63
64
 
64
65
  ### Framework Profiles
65
66
 
66
67
  | Profile ID | Description | Automatically Includes |
67
68
  |---|---|---|
68
- | `cratis/arc` | Arc CQRS framework | `cratis/arc/csharp`, `cratis/arc/kotlin` |
69
- | `cratis/chronicle` | Chronicle event sourcing engine | `cratis/chronicle/compliance`, `cratis/chronicle/csharp`, `cratis/chronicle/elixir`, `cratis/chronicle/kotlin`, `cratis/chronicle/multi-tenancy`, `cratis/chronicle/typescript`, `cratis/chronicle/web-workbench` |
69
+ | `cratis/arc` | Arc CQRS framework | `cratis/arc/csharp`, `cratis/arc/java`, `cratis/arc/kotlin` |
70
+ | `cratis/chronicle` | Chronicle event sourcing engine | `cratis/chronicle/compliance`, `cratis/chronicle/csharp`, `cratis/chronicle/elixir`, `cratis/chronicle/java`, `cratis/chronicle/kotlin`, `cratis/chronicle/multi-tenancy`, `cratis/chronicle/typescript`, `cratis/chronicle/web-workbench` |
70
71
  | `cratis/components` | React component library | (no child profiles) |
71
72
  | `cratis/fundamentals` | Core primitives (`ConceptAs<T>`, `EventSourceId<T>`) | (no child profiles) |
72
73
  | `cratis/specifications` | Specification framework | (no child profiles) |
@@ -88,6 +89,26 @@ The complete list of available profiles is defined in [profile-catalog.json](../
88
89
  | `cratis/language/typescript` | TypeScript language conventions |
89
90
  | `cratis/language/elixir` | Elixir language conventions |
90
91
  | `cratis/language/kotlin` | Kotlin language conventions |
92
+ | `cratis/language/java` | Java language conventions |
93
+
94
+ ### Arc and Chronicle on the JVM (Kotlin and Java)
95
+
96
+ Arc.Kotlin (`io.cratis:arc`) and its optional Chronicle integration
97
+ (`io.cratis:arc-chronicle-spring-boot-starter`) bring the same command/query
98
+ model-bound shape to the JVM that Arc .NET brings to C#, for both Kotlin and
99
+ Java application code. `cratis/arc/client-kotlin` carries the skills for both
100
+ languages — Java application code still needs Kotlin and KSP on the build,
101
+ since Arc generates Kotlin adapters for Java declarations.
102
+
103
+ | Skill | Covers |
104
+ | --- | --- |
105
+ | `cratis-arc-command-kotlin` | `@Command`, `handle()`/`provide()`, Chronicle event responses, command authorization, TypeScript proxy generation |
106
+ | `cratis-arc-query-kotlin` | `@ReadModel` queries, GET vs RFC QUERY, observable queries (`Flow`, `Flow.Publisher`, RxJava 3) over SSE/WebSocket |
107
+ | `cratis-arc-validation-kotlin` | `FluentModelValidator` shared rules, `CommandValidator`/`QueryValidator`/`ConceptValidator`/`ModelValidator`, Jakarta constraints |
108
+
109
+ Standalone Chronicle client usage (no Arc) for Kotlin and Java is
110
+ `cratis-chronicle-client-kotlin`, reused by `cratis/chronicle/client-java`.
111
+ JVM language conventions are `kotlin.md` and `java.md`.
91
112
 
92
113
  ### Specialized Profiles
93
114
 
@@ -37,6 +37,31 @@ Confirm the current repository workflow contract before selecting release intent
37
37
  - **minor** — new features, new slices, non-breaking additions
38
38
  - **patch** — bug fixes, refactoring with identical behavior
39
39
 
40
+ ### A major release needs a human's explicit go-ahead
41
+
42
+ A `major` label is the one release-intent label a ship request does not, by
43
+ itself, authorize through to merge. Breaking a public API is the most
44
+ consequential and hardest-to-reverse thing a release does — every downstream
45
+ consumer eventually has to act on it — so it gets a checkpoint the other two
46
+ intents do not.
47
+
48
+ - Prepare the branch, commits, push, and PR carrying the `major` label exactly
49
+ as any other ship request would.
50
+ - Before merging, stop and ask a human to confirm the major bump specifically:
51
+ name the exact breaking change(s), who is affected and how, and the
52
+ resulting version number. A generic "ready to ship?" is not this checkpoint —
53
+ say plainly that this release breaks compatibility and needs a yes.
54
+ - Proceed to merge only on an explicit, affirmative answer to that question.
55
+ A prior general instruction to "ship" or "land this" does not answer it,
56
+ even when it named `major` as the intended label.
57
+ - This checkpoint is per release, not per conversation — a human confirming
58
+ one major release does not pre-authorize the next one.
59
+
60
+ This narrows the general ship-changes authorization in
61
+ [`ship-changes.prompt.md`](../prompts/ship-changes.prompt.md) for exactly this
62
+ label; every other step of that workflow proceeds under its existing
63
+ authority.
64
+
40
65
  ### A pull request that changes nothing outward-facing carries `no-release`
41
66
 
42
67
  **If nothing in the PR can change what a consumer compiles against, runs, or observes, propose repository-supported non-release intent, ordinarily `no-release`** — not `patch`. Confirm that the current workflow supports the label, requires exactly one release-intent label, and suppresses publication as intended before applying it with authorization.