feat: add DDD capability for vision-to-issues workflow
Add complete DDD capability set for breaking down product vision into implementation issues using Domain-Driven Design principles. Components: - issue-writing skill: Enhanced with user story format and vertical slices - ddd skill: Strategic and tactical DDD patterns (bounded contexts, aggregates, commands, events) - ddd-breakdown skill: User-invocable workflow (/ddd-breakdown) - ddd-analyst agent: Analyzes manifesto/vision/code, generates DDD-structured user stories Workflow: Read manifesto + vision → analyze codebase → identify bounded contexts → map features to DDD patterns → generate user stories → create Gitea issues Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
255
agents/ddd-analyst/AGENT.md
Normal file
255
agents/ddd-analyst/AGENT.md
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
---
|
||||||
|
name: ddd-analyst
|
||||||
|
description: >
|
||||||
|
Analyzes manifesto, vision, and codebase to identify bounded contexts and
|
||||||
|
generate DDD-based implementation issues as user stories. Use when breaking
|
||||||
|
down product vision into DDD-structured vertical slices.
|
||||||
|
model: sonnet
|
||||||
|
skills: ddd, issue-writing
|
||||||
|
---
|
||||||
|
|
||||||
|
You are a Domain-Driven Design analyst that bridges product vision and software implementation.
|
||||||
|
|
||||||
|
## Your Role
|
||||||
|
|
||||||
|
Analyze product vision and existing code to:
|
||||||
|
1. Identify bounded contexts (intended vs actual)
|
||||||
|
2. Map features to DDD patterns (aggregates, commands, events)
|
||||||
|
3. Generate vertical slice user stories with DDD implementation guidance
|
||||||
|
4. Identify refactoring needs to align code with domain boundaries
|
||||||
|
|
||||||
|
## When Invoked
|
||||||
|
|
||||||
|
You receive:
|
||||||
|
- Path to manifesto.md (organization vision and personas)
|
||||||
|
- Path to vision.md (product-specific goals and features)
|
||||||
|
- Working directory (product codebase to analyze)
|
||||||
|
|
||||||
|
You produce:
|
||||||
|
- Structured analysis of bounded contexts
|
||||||
|
- List of user stories with DDD implementation guidance
|
||||||
|
- Each story formatted per issue-writing skill
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
### 1. Understand the Domain
|
||||||
|
|
||||||
|
**Read manifesto:**
|
||||||
|
- Identify organizational personas
|
||||||
|
- Understand core beliefs and principles
|
||||||
|
- Note domain language and terminology
|
||||||
|
|
||||||
|
**Read vision:**
|
||||||
|
- Identify product goals and milestones
|
||||||
|
- Extract features and capabilities
|
||||||
|
- Map features to personas
|
||||||
|
|
||||||
|
### 2. Analyze Existing Code
|
||||||
|
|
||||||
|
**Explore codebase structure:**
|
||||||
|
- Identify existing modules/packages/directories
|
||||||
|
- Look for natural clustering of concepts
|
||||||
|
- Identify seams and boundaries
|
||||||
|
- Note shared models or data structures
|
||||||
|
|
||||||
|
**Identify current bounded contexts:**
|
||||||
|
- What contexts already exist (explicit or implicit)?
|
||||||
|
- Are boundaries clear or mixed?
|
||||||
|
- Is language consistent within contexts?
|
||||||
|
- Are there translation layers between contexts?
|
||||||
|
|
||||||
|
### 3. Identify Bounded Contexts
|
||||||
|
|
||||||
|
**From vision and code, identify:**
|
||||||
|
|
||||||
|
For each bounded context:
|
||||||
|
- **Name**: Clear, domain-aligned name
|
||||||
|
- **Purpose**: What problem does this context solve?
|
||||||
|
- **Core concepts**: Key entities and value objects
|
||||||
|
- **Personas**: Which personas interact with this context?
|
||||||
|
- **Boundaries**: What's inside vs outside this context?
|
||||||
|
- **Current state**: Does this exist in code? Is it well-bounded?
|
||||||
|
|
||||||
|
**Identify misalignments:**
|
||||||
|
- Vision implies contexts that don't exist in code
|
||||||
|
- Code has contexts not aligned with vision
|
||||||
|
- Shared models leaking across context boundaries
|
||||||
|
- Missing translation layers
|
||||||
|
|
||||||
|
### 4. Map Features to DDD Patterns
|
||||||
|
|
||||||
|
For each feature from vision:
|
||||||
|
|
||||||
|
**Identify:**
|
||||||
|
- **Bounded context**: Which context owns this feature?
|
||||||
|
- **Aggregate(s)**: What entities/value objects are involved?
|
||||||
|
- **Commands**: What actions can users/systems take?
|
||||||
|
- **Events**: What facts should be recorded?
|
||||||
|
- **Value objects**: What concepts are attribute-defined?
|
||||||
|
|
||||||
|
**Determine implementation type:**
|
||||||
|
- **New feature**: No existing code, implement from scratch
|
||||||
|
- **Enhancement**: Existing code, add to it
|
||||||
|
- **Refactoring**: Existing code misaligned, needs restructuring
|
||||||
|
|
||||||
|
### 5. Generate User Stories
|
||||||
|
|
||||||
|
For each feature, create a user story following issue-writing skill format:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Title: As a [persona], I want to [capability], so that [benefit]
|
||||||
|
|
||||||
|
## User Story
|
||||||
|
As a [persona], I want to [capability], so that [benefit]
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- [ ] Specific, testable, user-focused criteria
|
||||||
|
- [ ] Another criteria
|
||||||
|
- [ ] Verifiable outcome
|
||||||
|
|
||||||
|
## Bounded Context
|
||||||
|
[Context name]
|
||||||
|
|
||||||
|
## DDD Implementation Guidance
|
||||||
|
|
||||||
|
**Type:** [New Feature | Enhancement | Refactoring]
|
||||||
|
|
||||||
|
**Aggregate(s):**
|
||||||
|
- `[AggregateName]` (root)
|
||||||
|
- `[Entity]`
|
||||||
|
- `[ValueObject]`
|
||||||
|
|
||||||
|
**Commands:**
|
||||||
|
- `[CommandName]` - [what it does]
|
||||||
|
|
||||||
|
**Events:**
|
||||||
|
- `[EventName]` - [when it's published]
|
||||||
|
|
||||||
|
**Value Objects:**
|
||||||
|
- `[ValueObjectName]` - [what it represents]
|
||||||
|
|
||||||
|
## Technical Notes
|
||||||
|
[Implementation hints, dependencies, refactoring needs]
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- [Links to related issues or blockers]
|
||||||
|
```
|
||||||
|
|
||||||
|
**For refactoring issues:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Title: Refactor [component] to align with [context] bounded context
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
Current state: [describe misalignment]
|
||||||
|
Desired state: [describe proper DDD structure]
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- [ ] Code moved to [context] module
|
||||||
|
- [ ] Boundaries clearly defined
|
||||||
|
- [ ] Tests updated
|
||||||
|
- [ ] No regression in functionality
|
||||||
|
|
||||||
|
## Bounded Context
|
||||||
|
[Context name]
|
||||||
|
|
||||||
|
## DDD Implementation Guidance
|
||||||
|
|
||||||
|
**Type:** Refactoring
|
||||||
|
|
||||||
|
**Changes needed:**
|
||||||
|
- Extract [Aggregate] from [current location]
|
||||||
|
- Introduce [ValueObject] to replace [primitive]
|
||||||
|
- Add translation layer between [Context1] and [Context2]
|
||||||
|
|
||||||
|
## Technical Notes
|
||||||
|
[Migration strategy, backward compatibility]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Structure Output
|
||||||
|
|
||||||
|
**Present analysis as:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# DDD Analysis: [Product Name]
|
||||||
|
|
||||||
|
## Bounded Contexts Identified
|
||||||
|
|
||||||
|
### [Context Name]
|
||||||
|
- **Purpose:** [what it does]
|
||||||
|
- **Core Concepts:** [list]
|
||||||
|
- **Personas:** [who uses it]
|
||||||
|
- **Current State:** [exists/partial/missing]
|
||||||
|
- **Misalignments:** [if any]
|
||||||
|
|
||||||
|
[Repeat for each context]
|
||||||
|
|
||||||
|
## User Stories Generated
|
||||||
|
|
||||||
|
### Context: [Context Name]
|
||||||
|
|
||||||
|
1. [Story title]
|
||||||
|
2. [Story title]
|
||||||
|
...
|
||||||
|
|
||||||
|
[Repeat for each context]
|
||||||
|
|
||||||
|
## Refactoring Needed
|
||||||
|
|
||||||
|
- [Issue] - [reason]
|
||||||
|
- [Issue] - [reason]
|
||||||
|
|
||||||
|
## Implementation Order
|
||||||
|
|
||||||
|
Suggested sequence (considering dependencies):
|
||||||
|
1. [Story/refactoring]
|
||||||
|
2. [Story/refactoring]
|
||||||
|
...
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Detailed User Stories
|
||||||
|
|
||||||
|
[Full user story format for each issue]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Guidelines
|
||||||
|
|
||||||
|
**Strategic before tactical:**
|
||||||
|
- Identify bounded contexts first
|
||||||
|
- Then map features to contexts
|
||||||
|
- Then identify aggregates/commands/events
|
||||||
|
|
||||||
|
**Vertical slices:**
|
||||||
|
- Each story delivers user value
|
||||||
|
- Can be demoed independently
|
||||||
|
- Includes all layers (UI, logic, data)
|
||||||
|
|
||||||
|
**Keep aggregates small:**
|
||||||
|
- Single entity when possible
|
||||||
|
- 2-3 entities maximum
|
||||||
|
- Each aggregate enforces its own invariants
|
||||||
|
|
||||||
|
**Clear boundaries:**
|
||||||
|
- Each context owns its data
|
||||||
|
- Communication via events or APIs
|
||||||
|
- No shared mutable state
|
||||||
|
|
||||||
|
**Refactor incrementally:**
|
||||||
|
- Refactoring issues should be small
|
||||||
|
- Don't require big-bang rewrites
|
||||||
|
- Maintain backward compatibility when possible
|
||||||
|
|
||||||
|
**Dependencies:**
|
||||||
|
- Identify blocking issues (e.g., aggregate before commands)
|
||||||
|
- Note cross-context dependencies
|
||||||
|
- Suggest implementation order
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Use persona names from manifesto in user stories
|
||||||
|
- Use domain language from vision consistently
|
||||||
|
- When uncertain about boundaries, propose options
|
||||||
|
- Prioritize core domain over supporting/generic subdomains
|
||||||
|
- Identify quick wins (small refactorings with big impact)
|
||||||
|
- Note where existing code is already well-aligned
|
||||||
136
skills/ddd-breakdown/SKILL.md
Normal file
136
skills/ddd-breakdown/SKILL.md
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
---
|
||||||
|
name: ddd-breakdown
|
||||||
|
description: >
|
||||||
|
Analyze product vision using DDD to identify bounded contexts and generate
|
||||||
|
implementation issues. Use when breaking down features into DDD-based vertical
|
||||||
|
slices, or when user says /ddd-breakdown.
|
||||||
|
model: haiku
|
||||||
|
argument-hint: [vision-file]
|
||||||
|
user-invocable: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# DDD Breakdown
|
||||||
|
|
||||||
|
@~/.claude/skills/ddd/SKILL.md
|
||||||
|
@~/.claude/skills/issue-writing/SKILL.md
|
||||||
|
@~/.claude/skills/gitea/SKILL.md
|
||||||
|
|
||||||
|
Analyze product vision through a DDD lens to generate implementation issues.
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
1. **Locate manifesto and vision**:
|
||||||
|
|
||||||
|
**Manifesto** (organization-level):
|
||||||
|
```bash
|
||||||
|
# Always in architecture repo
|
||||||
|
cat ~/.claude/manifesto.md
|
||||||
|
# Or if in architecture repo:
|
||||||
|
cat ./manifesto.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**Vision** (product-level):
|
||||||
|
```bash
|
||||||
|
# If argument provided: use that file
|
||||||
|
# Otherwise: look for vision.md in current repo
|
||||||
|
cat ./vision.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify both files exist before proceeding.
|
||||||
|
|
||||||
|
2. **Spawn DDD analyst agent**:
|
||||||
|
|
||||||
|
Use Task tool to spawn `ddd-analyst` agent:
|
||||||
|
```
|
||||||
|
Analyze this product using DDD principles.
|
||||||
|
|
||||||
|
Manifesto: [path to manifesto.md]
|
||||||
|
Vision: [path to vision.md]
|
||||||
|
Codebase: [current working directory]
|
||||||
|
|
||||||
|
Identify bounded contexts, map features to DDD patterns, and generate
|
||||||
|
user stories with DDD implementation guidance.
|
||||||
|
```
|
||||||
|
|
||||||
|
The agent will:
|
||||||
|
- Analyze manifesto (personas, beliefs, domain language)
|
||||||
|
- Analyze vision (goals, features, milestones)
|
||||||
|
- Explore codebase (existing structure, boundaries, misalignments)
|
||||||
|
- Identify bounded contexts (intended vs actual)
|
||||||
|
- Map features to DDD patterns (aggregates, commands, events)
|
||||||
|
- Generate user stories with acceptance criteria and DDD guidance
|
||||||
|
|
||||||
|
3. **Review agent output**:
|
||||||
|
|
||||||
|
The agent returns structured analysis:
|
||||||
|
- Bounded contexts identified
|
||||||
|
- User stories per context
|
||||||
|
- Refactoring needs
|
||||||
|
- Suggested implementation order
|
||||||
|
|
||||||
|
Present this to the user for review.
|
||||||
|
|
||||||
|
4. **Confirm issue creation**:
|
||||||
|
|
||||||
|
Ask user:
|
||||||
|
- Create all issues?
|
||||||
|
- Select specific issues to create?
|
||||||
|
- Modify any stories before creating?
|
||||||
|
|
||||||
|
5. **Create issues in Gitea**:
|
||||||
|
|
||||||
|
For each approved user story:
|
||||||
|
```bash
|
||||||
|
tea issues create \
|
||||||
|
--title "[story title]" \
|
||||||
|
--description "[full story with DDD guidance]"
|
||||||
|
```
|
||||||
|
|
||||||
|
Apply labels:
|
||||||
|
- `feature` (or `refactor` for refactoring issues)
|
||||||
|
- `bounded-context/[context-name]`
|
||||||
|
- Any other relevant labels from the story
|
||||||
|
|
||||||
|
6. **Link dependencies**:
|
||||||
|
|
||||||
|
For stories with dependencies:
|
||||||
|
```bash
|
||||||
|
tea issues deps add <dependent-issue> <blocker-issue>
|
||||||
|
```
|
||||||
|
|
||||||
|
7. **Report results**:
|
||||||
|
|
||||||
|
Show created issues with links:
|
||||||
|
```
|
||||||
|
## Issues Created
|
||||||
|
|
||||||
|
### Context: [Context Name]
|
||||||
|
- #123: [Issue title]
|
||||||
|
- #124: [Issue title]
|
||||||
|
|
||||||
|
### Context: [Another Context]
|
||||||
|
- #125: [Issue title]
|
||||||
|
|
||||||
|
### Refactoring
|
||||||
|
- #126: [Issue title]
|
||||||
|
|
||||||
|
View all: [link to issues page]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Guidelines
|
||||||
|
|
||||||
|
- **Manifesto is organization-wide**: Always read from architecture repo
|
||||||
|
- **Vision is product-specific**: Read from current repo or provided path
|
||||||
|
- **Let agent do the analysis**: Don't try to identify contexts yourself, spawn the agent
|
||||||
|
- **Review before creating**: Always show user the analysis before creating issues
|
||||||
|
- **Label by context**: Use `bounded-context/[name]` labels for filtering
|
||||||
|
- **Link dependencies**: Use `tea issues deps add` for blockers
|
||||||
|
- **Implementation order matters**: Create foundational issues (refactoring, core aggregates) first
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Run this when starting a new product or major feature area
|
||||||
|
- Re-run periodically to identify drift between vision and code
|
||||||
|
- Use with `/vision` skill to manage product vision
|
||||||
|
- Combine with `/plan-issues` for additional breakdown
|
||||||
|
- Review with team before creating all issues
|
||||||
272
skills/ddd/SKILL.md
Normal file
272
skills/ddd/SKILL.md
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
---
|
||||||
|
name: ddd
|
||||||
|
description: >
|
||||||
|
Domain-Driven Design concepts: bounded contexts, aggregates, commands, events,
|
||||||
|
and tactical patterns. Use when analyzing domain models, identifying bounded
|
||||||
|
contexts, or mapping features to DDD patterns.
|
||||||
|
user-invocable: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# Domain-Driven Design (DDD)
|
||||||
|
|
||||||
|
Strategic and tactical patterns for modeling complex domains.
|
||||||
|
|
||||||
|
## Strategic DDD: Bounded Contexts
|
||||||
|
|
||||||
|
### What is a Bounded Context?
|
||||||
|
|
||||||
|
A **bounded context** is a boundary within which a domain model is consistent. Same terms can mean different things in different contexts.
|
||||||
|
|
||||||
|
**Example:** "Order" means different things in different contexts:
|
||||||
|
- **Sales Context**: Order = customer purchase with payment and shipping
|
||||||
|
- **Fulfillment Context**: Order = pick list for warehouse
|
||||||
|
- **Accounting Context**: Order = revenue transaction
|
||||||
|
|
||||||
|
### Identifying Bounded Contexts
|
||||||
|
|
||||||
|
Look for:
|
||||||
|
1. **Different language**: Same term means different things
|
||||||
|
2. **Different models**: Same concept has different attributes/behavior
|
||||||
|
3. **Different teams**: Natural organizational boundaries
|
||||||
|
4. **Different lifecycles**: Entities created/destroyed at different times
|
||||||
|
5. **Different rate of change**: Some areas evolve faster than others
|
||||||
|
|
||||||
|
**From vision/manifesto:**
|
||||||
|
- Identify personas → each persona likely interacts with different contexts
|
||||||
|
- Identify core domain concepts → group related concepts into contexts
|
||||||
|
- Identify capabilities → capabilities often align with contexts
|
||||||
|
|
||||||
|
**From existing code:**
|
||||||
|
- Look for packages/modules that cluster related concepts
|
||||||
|
- Identify seams where code is loosely coupled
|
||||||
|
- Look for translation layers between subsystems
|
||||||
|
- Identify areas where same terms mean different things
|
||||||
|
|
||||||
|
### Context Boundaries
|
||||||
|
|
||||||
|
**Good boundaries:**
|
||||||
|
- Clear interfaces between contexts
|
||||||
|
- Each context owns its data
|
||||||
|
- Contexts communicate via events or APIs
|
||||||
|
- Minimal coupling between contexts
|
||||||
|
|
||||||
|
**Bad boundaries:**
|
||||||
|
- Shared database tables across contexts
|
||||||
|
- Direct object references across contexts
|
||||||
|
- Mixed concerns within a context
|
||||||
|
|
||||||
|
### Common Context Patterns
|
||||||
|
|
||||||
|
| Pattern | Description | Example |
|
||||||
|
|---------|-------------|---------|
|
||||||
|
| **Core Domain** | Your unique competitive advantage | Custom business logic |
|
||||||
|
| **Supporting Subdomain** | Necessary but not differentiating | User management |
|
||||||
|
| **Generic Subdomain** | Common problems, use off-the-shelf | Email sending, file storage |
|
||||||
|
|
||||||
|
## Tactical DDD: Building Blocks
|
||||||
|
|
||||||
|
### Aggregates
|
||||||
|
|
||||||
|
An **aggregate** is a cluster of entities and value objects treated as a unit for data changes.
|
||||||
|
|
||||||
|
**Rules:**
|
||||||
|
- One entity is the **aggregate root** (only entity referenced from outside)
|
||||||
|
- All changes go through the root
|
||||||
|
- Enforce business invariants within the aggregate
|
||||||
|
- Keep aggregates small (2-3 entities max when possible)
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
Order (root)
|
||||||
|
├── OrderLine
|
||||||
|
├── ShippingAddress
|
||||||
|
└── Payment
|
||||||
|
```
|
||||||
|
|
||||||
|
External code only references `Order`, never `OrderLine` directly.
|
||||||
|
|
||||||
|
**Identifying aggregates:**
|
||||||
|
- What entities always change together?
|
||||||
|
- What invariants must be enforced?
|
||||||
|
- What is the transactional boundary?
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
**Commands** represent intent to change state. Named with imperative verbs.
|
||||||
|
|
||||||
|
**Format:** `[Verb][AggregateRoot]` or `[AggregateRoot][Verb]`
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `PlaceOrder` or `OrderPlace`
|
||||||
|
- `CancelSubscription` or `SubscriptionCancel`
|
||||||
|
- `ApproveInvoice` or `InvoiceApprove`
|
||||||
|
|
||||||
|
**Commands:**
|
||||||
|
- Are handled by the aggregate root
|
||||||
|
- Either succeed completely or fail
|
||||||
|
- Can be rejected (return error)
|
||||||
|
- Represent user intent or system action
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
**Events** represent facts that happened in the past. Named in past tense.
|
||||||
|
|
||||||
|
**Format:** `[AggregateRoot][PastVerb]` or `[Something]Happened`
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `OrderPlaced`
|
||||||
|
- `SubscriptionCancelled`
|
||||||
|
- `InvoiceApproved`
|
||||||
|
- `PaymentFailed`
|
||||||
|
|
||||||
|
**Events:**
|
||||||
|
- Are immutable (already happened)
|
||||||
|
- Can be published to other contexts
|
||||||
|
- Enable eventual consistency
|
||||||
|
- Create audit trail
|
||||||
|
|
||||||
|
### Value Objects
|
||||||
|
|
||||||
|
**Value Objects** are immutable objects defined by their attributes, not identity.
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `Money` (amount + currency)
|
||||||
|
- `EmailAddress`
|
||||||
|
- `DateRange`
|
||||||
|
- `Address`
|
||||||
|
|
||||||
|
**Characteristics:**
|
||||||
|
- No identity (two with same values are equal)
|
||||||
|
- Immutable (cannot change, create new instance)
|
||||||
|
- Can contain validation logic
|
||||||
|
- Can contain behavior
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Concept has no lifecycle (no create/update/delete)
|
||||||
|
- Equality is based on attributes, not identity
|
||||||
|
- Can be shared/reused
|
||||||
|
|
||||||
|
### Entities
|
||||||
|
|
||||||
|
**Entities** have identity that persists over time, even if attributes change.
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
- `User` (ID remains same even if name/email changes)
|
||||||
|
- `Order` (ID remains same through lifecycle)
|
||||||
|
- `Product` (ID remains same even if price changes)
|
||||||
|
|
||||||
|
**Characteristics:**
|
||||||
|
- Has unique identifier
|
||||||
|
- Can change over time
|
||||||
|
- Identity matters more than attributes
|
||||||
|
|
||||||
|
## Mapping Features to DDD Patterns
|
||||||
|
|
||||||
|
### Process
|
||||||
|
|
||||||
|
For each feature from vision:
|
||||||
|
|
||||||
|
1. **Identify the bounded context**: Which context does this belong to?
|
||||||
|
|
||||||
|
2. **Identify the aggregate(s)**: What entities/value objects are involved?
|
||||||
|
|
||||||
|
3. **Identify commands**: What actions can users/systems take?
|
||||||
|
|
||||||
|
4. **Identify events**: What facts should be recorded when commands succeed?
|
||||||
|
|
||||||
|
5. **Identify value objects**: What concepts are attribute-defined, not identity-defined?
|
||||||
|
|
||||||
|
### Example: "User can place an order"
|
||||||
|
|
||||||
|
**Bounded Context:** Sales
|
||||||
|
|
||||||
|
**Aggregate:** `Order` (root)
|
||||||
|
- `OrderLine` (entity)
|
||||||
|
- `ShippingAddress` (value object)
|
||||||
|
- `Money` (value object)
|
||||||
|
|
||||||
|
**Commands:**
|
||||||
|
- `PlaceOrder`
|
||||||
|
- `AddOrderLine`
|
||||||
|
- `RemoveOrderLine`
|
||||||
|
- `UpdateShippingAddress`
|
||||||
|
|
||||||
|
**Events:**
|
||||||
|
- `OrderPlaced`
|
||||||
|
- `OrderLineAdded`
|
||||||
|
- `OrderLineRemoved`
|
||||||
|
- `ShippingAddressUpdated`
|
||||||
|
|
||||||
|
**Value Objects:**
|
||||||
|
- `Money` (amount, currency)
|
||||||
|
- `Address` (street, city, zip, country)
|
||||||
|
- `Quantity`
|
||||||
|
|
||||||
|
## Refactoring to DDD
|
||||||
|
|
||||||
|
When existing code doesn't follow DDD patterns:
|
||||||
|
|
||||||
|
### Identify Misalignments
|
||||||
|
|
||||||
|
**Anemic domain model:**
|
||||||
|
- Entities with only getters/setters
|
||||||
|
- Business logic in services, not entities
|
||||||
|
- **Fix:** Move behavior into aggregates
|
||||||
|
|
||||||
|
**God objects:**
|
||||||
|
- One entity doing too much
|
||||||
|
- **Fix:** Split into multiple aggregates or value objects
|
||||||
|
|
||||||
|
**Context leakage:**
|
||||||
|
- Same model shared across contexts
|
||||||
|
- **Fix:** Create context-specific models with translation layers
|
||||||
|
|
||||||
|
**Missing boundaries:**
|
||||||
|
- Everything in one module/package
|
||||||
|
- **Fix:** Identify bounded contexts, separate into modules
|
||||||
|
|
||||||
|
### Refactoring Strategies
|
||||||
|
|
||||||
|
**Extract bounded context:**
|
||||||
|
```markdown
|
||||||
|
As a developer, I want to extract [Context] into a separate module,
|
||||||
|
so that it has clear boundaries and can evolve independently
|
||||||
|
```
|
||||||
|
|
||||||
|
**Extract aggregate:**
|
||||||
|
```markdown
|
||||||
|
As a developer, I want to extract [Aggregate] from [GodObject],
|
||||||
|
so that it enforces its own invariants
|
||||||
|
```
|
||||||
|
|
||||||
|
**Introduce value object:**
|
||||||
|
```markdown
|
||||||
|
As a developer, I want to replace [primitive] with [ValueObject],
|
||||||
|
so that validation is centralized and the domain model is clearer
|
||||||
|
```
|
||||||
|
|
||||||
|
**Introduce event:**
|
||||||
|
```markdown
|
||||||
|
As a developer, I want to publish [Event] when [Command] succeeds,
|
||||||
|
so that other contexts can react to state changes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
**Avoid:**
|
||||||
|
- Aggregates spanning multiple bounded contexts
|
||||||
|
- Shared mutable state across contexts
|
||||||
|
- Direct database access across contexts
|
||||||
|
- Aggregates with dozens of entities (too large)
|
||||||
|
- Value objects with identity
|
||||||
|
- Commands without clear aggregate ownership
|
||||||
|
- Events that imply future actions (use commands)
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Start with strategic DDD (bounded contexts) before tactical patterns
|
||||||
|
- Bounded contexts align with team/organizational boundaries
|
||||||
|
- Keep aggregates small (single entity when possible)
|
||||||
|
- Use events for cross-context communication
|
||||||
|
- Value objects make impossible states impossible
|
||||||
|
- Refactor incrementally - don't rewrite everything at once
|
||||||
212
skills/issue-writing/SKILL.md
Normal file
212
skills/issue-writing/SKILL.md
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
---
|
||||||
|
name: issue-writing
|
||||||
|
description: >
|
||||||
|
Write clear, actionable issues with user stories, vertical slices, and acceptance
|
||||||
|
criteria. Use when creating issues, writing bug reports, feature requests, or when
|
||||||
|
the user needs help structuring an issue.
|
||||||
|
user-invocable: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# Issue Writing
|
||||||
|
|
||||||
|
How to write clear, actionable issues that deliver user value.
|
||||||
|
|
||||||
|
## Primary Format: User Story
|
||||||
|
|
||||||
|
Frame issues as user capabilities, not technical tasks:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Title: As a [persona], I want to [action], so that [benefit]
|
||||||
|
|
||||||
|
## User Story
|
||||||
|
As a [persona], I want to [action], so that [benefit]
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- [ ] Specific, testable requirement
|
||||||
|
- [ ] Another requirement
|
||||||
|
- [ ] User can verify this works
|
||||||
|
|
||||||
|
## Context
|
||||||
|
Additional background, links, or references.
|
||||||
|
|
||||||
|
## Technical Notes (optional)
|
||||||
|
Implementation hints or constraints.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```markdown
|
||||||
|
Title: As a domain expert, I want to save my diagram, so that I can resume work later
|
||||||
|
|
||||||
|
## User Story
|
||||||
|
As a domain expert, I want to save my diagram to the cloud, so that I can resume
|
||||||
|
work later from any device.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- [ ] User can click "Save" button in toolbar
|
||||||
|
- [ ] Diagram persists to cloud storage
|
||||||
|
- [ ] User sees confirmation message on successful save
|
||||||
|
- [ ] Saved diagram appears in recent files list
|
||||||
|
|
||||||
|
## Context
|
||||||
|
Users currently lose work when closing the browser. This is the #1 requested feature.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vertical Slices
|
||||||
|
|
||||||
|
Issues should be **vertical slices** that deliver user-visible value.
|
||||||
|
|
||||||
|
### The Demo Test
|
||||||
|
|
||||||
|
Before writing an issue, ask: **Can a user demo or test this independently?**
|
||||||
|
|
||||||
|
- **Yes** → Good issue scope
|
||||||
|
- **No** → Rethink the breakdown
|
||||||
|
|
||||||
|
### Good vs Bad Issue Titles
|
||||||
|
|
||||||
|
| Good (Vertical) | Bad (Horizontal) |
|
||||||
|
|-----------------|------------------|
|
||||||
|
| "As a user, I want to save my diagram" | "Add persistence layer" |
|
||||||
|
| "As a user, I want to see errors when login fails" | "Add error handling" |
|
||||||
|
| "As a domain expert, I want to list orders" | "Add query syntax to ADL" |
|
||||||
|
|
||||||
|
The technical work is the same, but vertical slices make success criteria clear and deliver demonstrable value.
|
||||||
|
|
||||||
|
## Writing User Stories
|
||||||
|
|
||||||
|
### Format
|
||||||
|
|
||||||
|
```
|
||||||
|
As a [persona], I want [capability], so that [benefit]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Persona:** From manifesto or product vision (e.g., domain expert, developer, product owner)
|
||||||
|
|
||||||
|
**Capability:** What the user can do (not how it's implemented)
|
||||||
|
|
||||||
|
**Benefit:** Why this matters to the user
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
✓ As a developer, I want to run tests locally, so that I can verify changes before pushing
|
||||||
|
✓ As a product owner, I want to view open issues, so that I can prioritize work
|
||||||
|
✓ As a domain expert, I want to export my model as JSON, so that I can share it with my team
|
||||||
|
|
||||||
|
✗ As a developer, I want a test runner (missing benefit)
|
||||||
|
✗ I want to add authentication (missing persona and benefit)
|
||||||
|
✗ As a user, I want the system to be fast (not specific/testable)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
Good criteria are:
|
||||||
|
- **Specific**: "User sees error message" not "Handle errors"
|
||||||
|
- **Testable**: Can verify pass/fail
|
||||||
|
- **User-focused**: What the user experiences
|
||||||
|
- **Independent**: Each stands alone
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
```markdown
|
||||||
|
- [ ] Login form validates email format before submission
|
||||||
|
- [ ] Invalid credentials show "Invalid email or password" message
|
||||||
|
- [ ] Successful login redirects to dashboard
|
||||||
|
- [ ] Session persists across browser refresh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Alternative Formats
|
||||||
|
|
||||||
|
### Bug Report
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Title: Fix [specific problem] in [area]
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
Description of the bug.
|
||||||
|
|
||||||
|
## Steps to Reproduce
|
||||||
|
1. Go to...
|
||||||
|
2. Click...
|
||||||
|
3. Observe...
|
||||||
|
|
||||||
|
## Expected Behavior
|
||||||
|
What should happen.
|
||||||
|
|
||||||
|
## Actual Behavior
|
||||||
|
What happens instead.
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
- Browser/OS/Version
|
||||||
|
```
|
||||||
|
|
||||||
|
### Technical Task
|
||||||
|
|
||||||
|
Use sparingly - prefer user stories when possible.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Title: [Action] [component/area]
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
What technical work needs to be done and why.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
- Include: ...
|
||||||
|
- Exclude: ...
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- [ ] Measurable technical outcome
|
||||||
|
- [ ] Another measurable outcome
|
||||||
|
```
|
||||||
|
|
||||||
|
## Issue Sizing
|
||||||
|
|
||||||
|
Issues should be **small enough to complete in 1-3 days**.
|
||||||
|
|
||||||
|
**Too large?** Split into smaller vertical slices:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Too large
|
||||||
|
As a user, I want full authentication, so that my data is secure
|
||||||
|
|
||||||
|
# Better: Split into slices
|
||||||
|
1. As a user, I want to register with email/password, so that I can create an account
|
||||||
|
2. As a user, I want to log in with my credentials, so that I can access my data
|
||||||
|
3. As a user, I want to reset my password, so that I can regain access if I forget it
|
||||||
|
```
|
||||||
|
|
||||||
|
## Labels
|
||||||
|
|
||||||
|
Use labels to categorize:
|
||||||
|
- Type: `bug`, `feature`, `enhancement`, `refactor`
|
||||||
|
- Priority: `priority/high`, `priority/medium`, `priority/low`
|
||||||
|
- Component: Project-specific (e.g., `auth`, `api`, `ui`)
|
||||||
|
- DDD: `bounded-context/[name]`, `aggregate`, `command`, `event` (when applicable)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
Identify and link dependencies when creating issues:
|
||||||
|
|
||||||
|
1. **In the description**, document dependencies:
|
||||||
|
```markdown
|
||||||
|
## Dependencies
|
||||||
|
- Depends on #12 (must complete first)
|
||||||
|
- Related to #15 (informational)
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **After creating the issue**, formally link blockers using tea CLI:
|
||||||
|
```bash
|
||||||
|
tea issues deps add <this-issue> <blocker-issue>
|
||||||
|
tea issues deps add 5 3 # Issue #5 is blocked by #3
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a formal dependency graph that tools can query.
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
**Avoid:**
|
||||||
|
- Generic titles: "Fix bugs", "Improve performance"
|
||||||
|
- Technical jargon without context: "Refactor service layer"
|
||||||
|
- Missing acceptance criteria
|
||||||
|
- Horizontal slices: "Build API", "Add database tables"
|
||||||
|
- Vague criteria: "Make it better", "Improve UX"
|
||||||
|
- Issues too large to complete in a sprint
|
||||||
Reference in New Issue
Block a user