with one click
state-change-slice
Knows how to build state change slices
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Knows how to build state change slices
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
| name | state change slice |
| description | Knows how to build state change slices |
A STATE_CHANGE slice represents a business operation that modifies aggregate state through commands and events. This is the core CQRS/Event Sourcing pattern.
{
"sliceType": "STATE_CHANGE",
"title": "slice: <Name>",
"context": "<BoundedContext>",
"commands": [...],
"events": [...],
"readmodels": [...],
"screens": [...],
"processors": [...],
"specifications": [...]
}
Screen (UI) → Command → Aggregate (@CommandHandler) → Event → ReadModel (via @EventHandler Projector)
↓
Automation (if processors exist)
Location: src/main/kotlin/de/alex/<module>/domain/commands/<commandname>/<CommandName>Command.kt
Template:
package de.alex.<module>.domain.commands.<commandname>
import de.alex.common.Command
import org.axonframework.modelling.command.TargetAggregateIdentifier
import java.util.UUID
data class <CommandName>Command(
@TargetAggregateIdentifier var aggregateId: UUID,
// Add fields from slice command definition
// Map types: UUID, String, Date → LocalDate, Integer → Int, Boolean, Decimal → BigDecimal
// Handle cardinality: Single → regular type, Multiple → List<type>
) : Command
Field Mapping Rules:
| Slice Type | Kotlin Type |
|---|---|
| UUID | UUID |
| String | String |
| Date | LocalDate |
| Integer | Int |
| Boolean | Boolean |
| Decimal | BigDecimal |
| Multiple cardinality | List |
| optional: true | Nullable (T?) |
Location: src/main/kotlin/de/alex/events/<EventName>Event.kt
Template:
package de.alex.events
import de.alex.common.Event
import java.util.UUID
data class <EventName>Event(
var aggregateId: UUID,
// Add fields from slice event definition
// Fields typically mirror command fields
) : Event
Location: src/main/kotlin/de/alex/domain/<Aggregate>Aggregate.kt
Template for existing aggregate:
@CommandHandler
fun handle(command: <CommandName>Command): CommandResult {
// Business validation logic
AggregateLifecycle.apply(
<EventName>Event(
command.aggregateId,
// Map command fields to event fields
)
)
return CommandResult(command.aggregateId.toString(), AggregateLifecycle.getVersion())
}
Template for new aggregate creation (when createsAggregate: true):
@CreationPolicy(AggregateCreationPolicy.ALWAYS)
@CommandHandler
fun handle(command: <CommandName>Command): CommandResult {
AggregateLifecycle.apply(
<EventName>Event(
command.aggregateId,
// Map command fields to event fields
)
)
return CommandResult(command.aggregateId.toString(), AggregateLifecycle.getVersion())
}
@EventSourcingHandler
fun on(event: <EventName>Event) {
// Update aggregate state from event
this.aggregateId = event.aggregateId
// Update other state fields
}
Input:
{
"sliceType": "STATE_CHANGE",
"title": "slice: Assign Clerk to Case",
"commands": [{
"title": "Assign Clerk to Case",
"aggregate": "Case",
"fields": [
{"name": "caseId", "type": "UUID", "idAttribute": true},
{"name": "clerkId", "type": "UUID"},
{"name": "hourlyRate", "type": "Decimal"}
]
}],
"events": [{
"title": "Clerk Assigned to Case",
"fields": [...]
}]
}
Generated Files:
src/main/kotlin/de/alex/cases/domain/commands/assignclerktocase/AssignClerkToCaseCommand.ktsrc/main/kotlin/de/alex/events/ClerkAssignedToCaseEvent.ktsrc/main/kotlin/de/alex/domain/CaseAggregate.kt with handlersEnsure the module has a ProcessingGroups file:
Location: src/main/kotlin/de/alex/<module>/ProcessingGroups.kt
package de.alex.<module>
class ProcessingGroups {
companion object {
const val <MODULE> = "<MODULE>"
}
}