From harness-claude
Runs event storming workshops to discover domain events, commands, and bounded contexts for system design, migration, or microservices decomposition.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:events-event-stormingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Run event storming workshops to discover domain events, commands, and bounded contexts.
Run event storming workshops to discover domain events, commands, and bounded contexts.
Event storming process — Big Picture format:
Phase 1: Chaotic exploration (30-60 min)
Phase 2: Enforce timeline (20-30 min)
Phase 3: Identify pain points (10-15 min)
Phase 4: Commands (blue stickies)
Phase 5: Aggregates (yellow stickies)
Phase 6: Bounded contexts (pink/purple lines)
Event map template:
[Command] → [Aggregate] → [Domain Event] → [Read Model]
↓ ↓
[Policy/Rule] [External System]
Translating storming output to code:
// From event storming: "Order" aggregate with events
// Commands discovered: PlaceOrder, CancelOrder, ShipOrder
// Aggregate root
class Order {
private events: DomainEvent[] = [];
static place(data: PlaceOrderInput): Order {
const order = new Order(data);
order.record(new OrderPlaced({ orderId: order.id, ...data }));
return order;
}
cancel(reason: string): void {
if (this.status === 'SHIPPED') throw new Error('Cannot cancel shipped order');
this.status = 'CANCELLED';
this.record(new OrderCancelled({ orderId: this.id, reason }));
}
ship(trackingNumber: string): void {
if (this.status !== 'PAID') throw new Error('Order must be paid before shipping');
this.status = 'SHIPPED';
this.record(new OrderShipped({ orderId: this.id, trackingNumber }));
}
pullEvents(): DomainEvent[] {
const events = [...this.events];
this.events = [];
return events;
}
private record(event: DomainEvent): void {
this.events.push(event);
}
}
// Domain events discovered in storming
class OrderPlaced implements DomainEvent {
readonly type = 'order.placed';
constructor(public readonly payload: { orderId: string; userId: string; items: Item[] }) {}
}
class OrderCancelled implements DomainEvent {
readonly type = 'order.cancelled';
constructor(public readonly payload: { orderId: string; reason: string }) {}
}
class OrderShipped implements DomainEvent {
readonly type = 'order.shipped';
constructor(public readonly payload: { orderId: string; trackingNumber: string }) {}
}
Bounded context communication:
// Events that cross bounded context boundaries become integration events
// Integration event from Order context → Inventory context
interface OrderPlacedIntegrationEvent {
eventId: string;
type: 'order.placed';
occurredAt: string;
// Only include data the consuming context needs
orderId: string;
items: { productId: string; quantity: number }[];
}
// Inventory context maps this to its own domain language
class InventoryContext {
handleOrderPlaced(event: OrderPlacedIntegrationEvent): void {
// Translate to Inventory language: "stock reservation request"
const reservationRequest: StockReservationRequest = {
referenceId: event.orderId,
items: event.items.map((i) => ({
sku: this.mapProductToSKU(i.productId),
quantity: i.quantity,
})),
};
this.reserveStock(reservationRequest);
}
}
Sticky note color convention:
Bounded context warning signs:
Remote workshop tools: Miro, Mural, FigJam. Use virtual stickies with the same color coding. Allow async contribution before live sessions.
Transition to code: Each bounded context maps to:
Anti-patterns:
eventstorming.com/
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeGuides advanced Event Storming for process, design, and software levels using color-coded sticky notes, facilitation steps, and Brandolini's methodology. For deep domain modeling.
Simulates event storming workshops with multi-persona agents to discover domain events, commands, actors, and bounded contexts. Use full-simulation, quick, or guided modes for domain modeling.