update skills

This commit is contained in:
nessar committed 2026-09-25 10:00:00 +02:00
1 parent 9fb18f57ec
commit ff86cf48b4
82 files changed
+2156 -650

No files matched your search

@@ -0,0 +1,35 @@
---
name: domain-driven-design
description: Model business rules and consistency boundaries using domain-driven design. Use when choosing aggregates or bounded contexts, mapping domain relationships, or correcting a mismatch between business language and code.
license: MIT
metadata:
author: wondelai
version: "1.4.0"
---
# Domain-Driven Design
Model the requested business behavior, not an idealized architecture. Start with the user's scenarios, existing code, root `CONTEXT.md`, and relevant accepted ADRs.
## Shared constraints
- Preserve the repository's language and existing architectural decisions. Surface conflicts with evidence rather than silently replacing them.
- Follow [the development data lifecycle](../../../AGENTS.md#development-data-lifecycle): replace obsolete development schemas/contracts and update callers and tests together. Compatibility patterns apply only to genuine external constraints or a later explicit production-data decision.
- Choose aggregate boundaries from invariants and ownership. Preserve [the accepted rental transaction design](../../../docs/adr/0011-rental-aggregate-boundaries.md), including atomic operations across aggregate documents.
- Add events, factories, translation layers, or separate contexts only for a current business or integration need. Simple CRUD is valid; a score or wider architecture audit is optional, not a completion gate.
- Honor the requested deliverable: a design or review does not itself authorize implementation, migrations, or external changes.
## Use the relevant reference
Read only the branch needed by the task:
- Resolving ambiguous terms or maintaining a glossary: [ubiquitous language](references/ubiquitous-language.md).
- Choosing context boundaries or mapping integrations: [bounded contexts](references/bounded-contexts.md).
- Deciding identity, value semantics, aggregate ownership, or atomicity: [building blocks](references/building-blocks.md).
- Designing a real event flow or evaluating event sourcing: [domain events](references/domain-events.md).
- Defining persistence contracts, reconstruction, or complex creation: [repositories and factories](references/repositories-factories.md).
- Prioritizing modeling effort or comparing build/buy choices: [strategic design](references/strategic-design.md).
## Outcome
Explain the proposed concepts, invariant owners, important transitions, and how the design handles failure and concurrency. Show only the alternatives that matter, identify unresolved domain questions, and propose checks that would falsify the design. When implementation is requested, update affected callers, tests, and domain documentation together.
@@ -0,0 +1,32 @@
# Bounded Contexts and Context Mapping
A bounded context defines where a domain model and its language apply. It is not automatically a microservice, package, or team-sized deployment.
## Find a real boundary
Look for differing business meanings, rules, ownership, or change lifecycles. Check concrete scenarios and existing ADRs. A single context may be correct; excessive translation between closely related concepts can signal an unnecessary split.
For a requested context map, show the relevant contexts, ownership, upstream/downstream relationships, shared contracts, and any translation. Avoid mapping unrelated systems just to complete a catalog.
## Choose the relationship
| Pattern | Useful when | Cost to make explicit |
| -------------------------------------- | ------------------------------------------------------------------ | -------------------------------------------------- |
| Shared kernel | Closely collaborating owners genuinely share a small model | Coordinated changes and tests |
| Customer–supplier | The upstream team can accommodate downstream needs | Planning and contract dependency |
| Conformist | Accepting the upstream model is cheaper and safe for this use case | Coupling to upstream semantics |
| Anti-corruption layer | Foreign semantics would distort local business rules | Translation and its tests |
| Open host service / published language | Several consumers need a documented shared contract | Contract ownership and actual external obligations |
| Separate ways | Integration costs more than limited duplication | Separate implementations and knowledge |
| Partnership | Models must evolve together | Ongoing coordination |
| Big ball of mud | Existing entanglement needs to be named during an assessment | A diagnosis, not a target design |
Translation can live in an existing adapter or mapper; it does not require a facade/adapter/translator class hierarchy. Validate untrusted external data even when adopting the upstream model directly.
## Changes and external constraints
Preserve actual external contracts that the task cannot replace. Legacy coexistence patterns apply to a genuinely external system that must remain available, not to this application's disposable development model.
For internal model changes, follow [the development lifecycle](../../../../AGENTS.md#development-data-lifecycle): replace obsolete schemas/contracts, update callers and tests together, and reseed rather than introducing compatibility paths.
Explain a proposed split or merge through its effect on language, invariant ownership, coupling, and coordination. Do not reorganize teams, deploy services, or modify contracts merely because a map was requested.
@@ -0,0 +1,35 @@
# Entities, Value Objects, and Aggregates
Start from identity and business invariants rather than database tables or a target class count.
## Identity and value
An entity retains identity through changes; a value object is interchangeable with another value having the same attributes. Choose equality and mutability accordingly. Use existing identifier conventions rather than adding a new ID scheme by default.
Value objects should enforce their actual invariants and support immutable transformations. Do not infer business rules from examples: negative money may be valid for one concept and invalid for another.
## Aggregate ownership
An aggregate owns a cohesive set of state and invariants, with a root controlling its changes. Keep it small enough to load and update for its real use cases; use references by ID for independent aggregates where the project's model calls for them.
Ask:
- Which rules must hold after every successful operation?
- Who owns each lifecycle and may change its state?
- Which state must be read and written together?
- What prevents two concurrent commands from both accepting incompatible outcomes?
- Can a partial result or delayed update be valid?
Do not embed a growing independent lifecycle merely to make all relationships reachable through one object.
## Atomicity and concurrency
Aggregate boundaries and transaction boundaries are related, not identical. When an operation must commit or roll back across multiple aggregate documents, use the supported service-layer transaction required by the domain.
In this repository, [ADR-0011](../../../../docs/adr/0011-rental-aggregate-boundaries.md) explicitly requires Mongo transactions for relevant rental operations. Preserve optimistic version checks, occupancy contention, and uniqueness constraints; replacing them with asynchronous events or a query-only overlap check would weaken the invariant.
Use eventual consistency only when delayed or partial progress is acceptable, with explicit failure and recovery handling. Keep remote calls and long-running work outside database transactions.
## Verify the boundary
Exercise the actual operation, including invalid transitions, stale versions, duplicate commands, and competing callers where relevant. Prove the invariant at the storage/integration boundary when an in-memory test cannot establish it. Preserve distinct existing test coverage when moving behavior behind a new interface.
@@ -0,0 +1,29 @@
# Domain Events
Use events for a real notification or asynchronous coordination need. Crossing an aggregate boundary alone is not a reason to introduce an event bus.
## Define the fact and consumers
Name a domain event as a completed business fact, distinct from a command or pending operation. Identify its actual consumers and the minimum non-sensitive data they need. Avoid serializing the entire aggregate or inventing metadata fields without a purpose.
Distinguish internal events from externally consumed contracts. Translate when semantics differ; do not introduce a separate layer merely to change the name.
## Persistence and delivery
An event must not claim a state change that rolled back. If delivery after commit must be durable, use the project's existing transactional publication mechanism or justify an outbox that records the state change and pending event atomically.
For retried delivery, make handlers idempotent using an appropriate key, conditional write, or naturally idempotent operation. Coordinate deduplication and the effect atomically where required; recording a key before a failed effect can lose work.
Define ordering requirements, retry limits, and observable failure handling. Test duplicate, delayed, out-of-order, and failing delivery where those modes affect the invariant. Do not claim exactly-once behavior merely because duplicate messages are filtered.
## Do not weaken atomic business operations
Preserve the cross-aggregate transactions accepted in [ADR-0011](../../../../docs/adr/0011-rental-aggregate-boundaries.md). Asynchronous coordination is suitable only when partial progress and delay are valid. A saga or process manager is justified only by an actual long-running workflow, with explicit recovery semantics.
## Event sourcing is a separate choice
Event sourcing makes stored events the source of truth; publishing an event does not require it. Consider it only for a demonstrated need for historical reconstruction or temporal queries that the existing model cannot reasonably serve.
If chosen, define replay behavior without repeating external side effects, concurrency protection, and the actual retention obligations. Snapshots are an optimization, not initial scaffolding.
Follow [the development lifecycle](../../../../AGENTS.md#development-data-lifecycle): replace and reseed disposable development events. Retained-history upcasters or compatibility versions require an explicit later production-data decision; genuine external event contracts remain external constraints.
@@ -0,0 +1,25 @@
# Repositories and Factories
Use this branch when the task concerns persistence contracts or complex object creation, not as a checklist of layers to add.
## Repository contracts
Keep domain decisions separate from storage mechanics. Define methods in terms of actual domain operations and queries, following the repository's existing architecture. Avoid generic query escape hatches that leak SQL or document details into domain behavior.
Aggregate-loading methods return enough valid state for the operation to enforce its invariants. Query-only methods may return explicit read projections; this does not require a new CQRS subsystem. Fetch only needed data and test relevant storage, transaction, and concurrency behavior.
Follow the persistence technology's actual save/change-tracking semantics. Make absence, failed writes, and stale versions explicit in the contract.
## Reconstruction versus creation
Creating a new aggregate validates command inputs and invariants and may record creation events. Loading an existing aggregate preserves its identity and must not replay creation events or other external effects.
Validate the persisted shape and invariants needed for safe use rather than assuming stored data is trustworthy. Report corrupt or incompatible records; apply the project's disposable-data policy instead of adding legacy readers.
## Factories and query specifications
Use a constructor or existing mapper for straightforward creation. A factory earns its place when assembly or selection logic is sufficiently complex, duplicated, or independently testable; it must not produce an invalid aggregate.
Use query specifications only when actual reusable composition warrants them. A focused repository method is often enough.
Keep dependencies aligned with existing domain/application/infrastructure ownership. An in-memory test adapter can isolate domain logic, but does not replace integration checks for database behavior.
@@ -0,0 +1,23 @@
# Strategic Design
Use this branch when the user asks where to invest modeling effort or whether to build, reuse, or buy a capability.
## Classify by the actual business
- **Core:** the behavior that provides the product's distinctive value.
- **Supporting:** business-specific functionality needed to deliver that value.
- **Generic:** a broadly shared problem where existing solutions may fit.
These are decision aids, not fixed quality tiers or staffing rules. Security, accessibility, and data integrity remain required in every category. A domain's classification can change as the product changes.
## Compare concrete options
Start with the existing implementation and stack. Compare options against needed behavior, integration cost, operational burden, lock-in, privacy/security constraints, and available expertise.
Do not prescribe a vendor, dependency, outsourcing arrangement, or percentage allocation from a generic example. Verify current primary sources before making a real product recommendation and preserve the user's selected product unless changing it is in scope.
## Distill the decision
Identify the concepts and invariants that deserve the most attention, the surrounding functionality that can stay simple, and the evidence supporting that choice. Update existing domain documents only when requested; propose an ADR for a consequential, non-obvious trade-off rather than creating a parallel architecture handbook.
End with a focused recommendation and its limitations. A strategy discussion does not authorize purchasing services, provisioning infrastructure, or reorganizing the codebase.
@@ -0,0 +1,22 @@
# Ubiquitous Language
Use this branch to resolve a terminology problem, not to rename every technical class. Read [the configured domain layout](../../../../docs/agents/domain.md) and the existing glossary before proposing terms.
## Resolve the meaning
Take a concrete business scenario and identify its actors, nouns, actions, and state transitions. Compare the user's explanation with the code and accepted decisions.
- One term with different meanings: identify the actual distinction and its context.
- Several terms for the same concept: propose one canonical term and record relevant aliases.
- A lifecycle difference: decide whether it represents a state of one identity or a distinct concept.
- An unfamiliar name: check domain usage before assuming the model is wrong.
Ask for domain clarification only where the evidence does not settle a consequential choice. Do not invent an expert's agreement.
## Record and apply
Update root `CONTEXT.md` in its existing format when glossary maintenance is requested. Keep definitions concise, show important relationships, and distinguish agreed language from proposals. Technical names such as service or DTO may remain appropriate outside the domain glossary.
A terminology discussion does not automatically authorize a code-wide rename. For an authorized rename, find all affected code, tests, schemas, contracts, and documents; replace them together under the development lifecycle policy. Do not introduce migration or API-version compatibility for disposable development data.
Different contexts may legitimately use different meanings. Do not split a coherent context merely because a word is ambiguous; first determine whether the underlying rules or ownership actually differ.