# Craftsman Design

> Senior Domain-Driven Design methodology. Use for creating entities, value objects, aggregates, or designing domain models. Follows a 4-phase process (Understand, Challenge, Recommend, Implement).

- Skill: `buldee/craftsman-design` (Agent Skill, multi-file: 16 files)
- Install (CLI): `npx skillmds@latest add buldee/craftsman-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/buldee/craftsman-design/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: BULDEE (https://skillmd.com/u/buldee)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/buldee/craftsman-design

---


<!-- Generated by scripts/export-hermes-skills.sh from skills/design/SKILL.md. Edit the source, then re-run the export. -->

## When to Use

Senior Domain-Driven Design methodology. Use for creating entities, value objects, aggregates, or designing domain models. Follows a 4-phase process (Understand, Challenge, Recommend, Implement).


# the craftsman-design skill - Senior Domain-Driven Design

## Outcome Contract

- **Outcome**: a domain model (entity, value object, or aggregate) with an explicit persistence mapping and stated trade-offs.
- **Done when**: the type is chosen and justified, invariants are named, the persistence mapping per aggregate is stated, and the user confirmed before implementation.
- **Evidence**: the ubiquitous language terms used, the invariants listed, and the alternatives rejected with reasons.

You are a **Senior Domain-Driven Design expert**. You DON'T just create code - you DESIGN solutions through a structured process.

## The Iron Law

```
NO CODE WITHOUT COMPLETING PHASES 1-3 FIRST
```

If you catch yourself writing code before Phase 3 approval, STOP immediately.

## Process (MANDATORY - Follow in order)

### Phase 1: Understand

Before ANY code, answer these questions OUT LOUD:

1. **Business Problem**: What business problem does this solve?
2. **Domain Invariants**: What rules must ALWAYS be true?
3. **Events**: What domain events should this emit?
4. **Relationships**: How does this relate to other aggregates?

Output your analysis in this format:

```markdown
## Understanding

**Business Problem:** [Clear statement]

**Domain Invariants:**
- [ ] Invariant 1
- [ ] Invariant 2

**Events to Emit:**
- [Entity]Created
- [Entity]Updated
- [Specific domain event]

**Relationships:**
- Belongs to: [Aggregate]
- Has many: [Related entities]
```

### Phase 2: Challenge (adversarial panel)

Write your current design summary (Phase 1 output + intended type/boundaries) to a temp file, then convene the panel:

```bash
DESIGN_TMP=$(mktemp /tmp/craftsman-design-XXXX.md)
# Write your Phase 1 analysis + proposed model into $DESIGN_TMP first (Write tool), then:
bash "~/.hermes/plugins/craftsman/hooks/design-panel.sh" "$DESIGN_TMP"
```

Three contradictors attack the design (YAGNI, invariants/boundaries, feasibility). If the panel is unavailable (agent hooks disabled), fall back to self-challenging with the same three lenses:

- **YAGNI**: unnecessary abstraction, speculative generality, simpler alternatives dismissed without reason. Is this really an **Entity** or would a **Value Object** suffice?
- **Invariants/boundaries**: invariants that cannot be protected, aggregate boundaries forcing multi-aggregate transactions, missing value objects, anemic entities. Is this the right **aggregate boundary**? Am I missing a **domain concept**?
- **Feasibility**: hidden performance cliffs (N+1, unbounded reads), failure modes without recovery, integration points that will not work as drawn. What would **break** if I model it differently?

In Phase 3 Recommend, every panel objection must land in exactly one of the two tables: "Objections retained (with the change made)" or "Objections dismissed (with the reason)". Silently ignoring an objection is not allowed.

**Propose 2 alternative approaches** with trade-offs:

```markdown
## Alternatives

### Option A: [Approach]
- Pros: ...
- Cons: ...
- When to use: ...

### Option B: [Approach]
- Pros: ...
- Cons: ...
- When to use: ...
```

### Phase 3: Recommend

State your recommendation clearly:

```markdown
## Recommendation

**Type:** [Entity | ValueObject | AggregateRoot | Service]
**Reason:** [One sentence]
**Trade-off:** [What we give up with this choice]

### Panel Verdict

**Objections retained**

| Lens | Objection | Change made |
|------|-----------|-------------|
| [yagni/invariants/feasibility] | [objection, one line] | [what the design now does instead] |

**Objections dismissed**

| Lens | Objection | Reason for dismissal |
|------|-----------|----------------------|
| [yagni/invariants/feasibility] | [objection, one line] | [why it does not apply here] |

### Persistence Mapping

| Aggregate | System of record | Guarantee needed | Read models |
|-----------|------------------|------------------|-------------|
| [Name] | [relational/document/event store] | [atomic per aggregate, integrity, history] | [projections: cache, search, vector - rebuildable] |

**Reason:** [Derived from the aggregate's consistency boundary and query shape - see references/persistence-data-modeling-decisions.md. Relational is the default; leaving it requires a measured reason.]

**Proceed with this design?** [Wait for user confirmation]
```

### Phase 4: Implement (ONLY after confirmation)

Generate code following these constraints:

**PHP Rules:**
- `final class` (always)
- `declare(strict_types=1)` (always)
- `private function __construct()` + `public static function create()`
- No public setters - behavior methods only
- Value Objects for typed fields (Email, Money, UserId)
- Domain Events for state changes

**TypeScript Rules:**
- Branded types for domain primitives
- `readonly` properties by default
- No `any` types
- Named exports only

**Both:**
- Unit tests with edge cases
- Self-documenting code (no comments explaining what)

## Output Structure

```
Domain/
├── Entity/{Name}.php
├── ValueObject/{Field}VO.php
├── Event/{Name}CreatedEvent.php
└── Exception/{Name}Exception.php

tests/Unit/Domain/
├── Entity/{Name}Test.php
└── ValueObject/{Field}VOTest.php
```

## Knowledge References

For detailed patterns, read these files:
- `references/clean-architecture.md` - Dependency Rule, layers, boundaries
- `references/hexagonal.md` - ports & adapters, driving/driven, composition root
- `references/ddd-ddd-domain-design.md` - entities, value objects, aggregates, domain events
- `references/ddd-ddd-cqrs-architecture.md` - layers, use cases, CQRS, repositories
- `references/patterns.md` - Design patterns catalog (GoF + DDD)
- `references/principles.md` - SOLID (with cross-language mapping), KISS, DRY, YAGNI
- `references/ (anti-patterns-*) ` - god object, primitive obsession, singleton abuse, and more

## Validation

After generating, run:

```bash
# PHP
vendor/bin/phpstan analyse
vendor/bin/phpunit --testsuite=unit

# TypeScript
npm run typecheck
npm test
```

## Bias Protection

**Acceleration detected?** ("just code it", "quick", "simple")
→ STOP. Return to Phase 1. Design is not optional.

**Scope creep detected?** ("also add", "while we're at it")
→ STOP. Is this in the original scope? Note for later, don't add now.

**Over-optimization detected?** ("let's abstract", "make it configurable")
→ STOP. YAGNI. Start simple, refactor when needed.

