dflow-sdd-ddd 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +971 -0
- package/README.en.md +345 -0
- package/README.md +213 -159
- package/docs/evaluating-dflow.en.md +238 -0
- package/docs/evaluating-dflow.md +94 -151
- package/docs/examples-by-stack.md +516 -0
- package/docs/migrating-to-dflow-v1.md +28 -10
- package/docs/release-versioning-policy.md +13 -0
- package/docs/using-with-claude-code.en.md +210 -0
- package/docs/using-with-claude-code.md +108 -124
- package/docs/using-with-codex.en.md +248 -0
- package/docs/using-with-codex.md +137 -157
- package/docs/using-with-gemini-cli.en.md +200 -0
- package/docs/using-with-gemini-cli.md +184 -0
- package/docs/using-with-github-copilot.en.md +136 -0
- package/docs/using-with-github-copilot.md +177 -0
- package/docs/why-ddd-for-ai.en.md +37 -0
- package/docs/why-ddd-for-ai.md +19 -17
- package/lib/init.js +187 -24
- package/package.json +1 -1
- package/templates/brownfield/scaffolding/AI-AGENT-GUIDE.md +2 -1
- package/templates/brownfield/scaffolding/CLAUDE-md-snippet.md +32 -22
- package/templates/brownfield/scaffolding/Git-principles-gitflow.md +1 -1
- package/templates/brownfield/scaffolding/Git-principles-trunk.md +1 -1
- package/templates/brownfield/scaffolding/_conventions.md +1 -1
- package/templates/brownfield/scaffolding/_overview.md +40 -29
- package/templates/brownfield/templates/CLAUDE.md +26 -18
- package/templates/brownfield/templates/context-definition.md +4 -4
- package/templates/brownfield/templates/context-map.md +1 -1
- package/templates/brownfield/templates/lightweight-spec.md +3 -1
- package/templates/brownfield/templates/models.md +1 -1
- package/templates/brownfield/templates/phase-spec.md +33 -28
- package/templates/brownfield/templates/tech-debt.md +2 -2
- package/templates/greenfield/scaffolding/AI-AGENT-GUIDE.md +2 -1
- package/templates/greenfield/scaffolding/CLAUDE-md-snippet.md +14 -13
- package/templates/greenfield/scaffolding/Git-principles-gitflow.md +2 -2
- package/templates/greenfield/scaffolding/Git-principles-trunk.md +2 -2
- package/templates/greenfield/scaffolding/_conventions.md +1 -1
- package/templates/greenfield/scaffolding/_overview.md +29 -11
- package/templates/greenfield/templates/CLAUDE.md +6 -6
- package/templates/greenfield/templates/phase-spec.md +24 -21
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
# Examples by Stack
|
|
2
|
+
|
|
3
|
+
> A per-stack appendix to Dflow templates. Dflow itself is language- and
|
|
4
|
+
> framework-agnostic; this document shows what canonical placeholders
|
|
5
|
+
> (`{Language}` / `{Framework}` / `{Framework version}` / `{ORM / persistence}`
|
|
6
|
+
> / `{ORM version}` / `{Mediator}` / `{Test framework}`) and stack-neutral
|
|
7
|
+
> prose look like once filled in for common stacks.
|
|
8
|
+
>
|
|
9
|
+
> **How to use this**: after running `dflow init`, open
|
|
10
|
+
> `dflow/specs/shared/_overview.md` and your root `CLAUDE.md`. Replace
|
|
11
|
+
> placeholder rows / directory trees / dependency lists with the snippets
|
|
12
|
+
> from your stack's section below. Adapt as needed — these are starting
|
|
13
|
+
> points, not prescriptions.
|
|
14
|
+
|
|
15
|
+
## Index
|
|
16
|
+
|
|
17
|
+
- [.NET / ASP.NET Core (Greenfield)](#net--aspnet-core-greenfield)
|
|
18
|
+
- [.NET / ASP.NET WebForms (Brownfield)](#net--aspnet-webforms-brownfield)
|
|
19
|
+
- [Java / Spring Boot (Greenfield)](#java--spring-boot-greenfield) — Kotlin/Spring same pattern
|
|
20
|
+
- [Node.js / TypeScript / NestJS (Greenfield)](#nodejs--typescript--nestjs-greenfield)
|
|
21
|
+
- [Python / FastAPI (Greenfield)](#python--fastapi-greenfield) — Django/Flask similar
|
|
22
|
+
- [Go / Gin (Greenfield)](#go--gin-greenfield)
|
|
23
|
+
- [PHP / Laravel (Brownfield migration)](#php--laravel-brownfield-migration)
|
|
24
|
+
|
|
25
|
+
Each section provides:
|
|
26
|
+
|
|
27
|
+
1. **`_overview.md` stack table** — substituted canonical placeholders
|
|
28
|
+
2. **Project layout** — idiomatic directory / package convention
|
|
29
|
+
3. **Domain purity check** — the stack's equivalent of "no delivery-framework references" (used in Git-principles checklist)
|
|
30
|
+
4. **Test framework** — what `{Test framework}` resolves to
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## .NET / ASP.NET Core (Greenfield)
|
|
35
|
+
|
|
36
|
+
### `_overview.md` stack table
|
|
37
|
+
|
|
38
|
+
```markdown
|
|
39
|
+
| Item | Choice |
|
|
40
|
+
|------|--------|
|
|
41
|
+
| Language | C# 12 |
|
|
42
|
+
| Framework | ASP.NET Core 9 |
|
|
43
|
+
| ORM / persistence | Entity Framework Core 9 |
|
|
44
|
+
| Mediator | MediatR 12 |
|
|
45
|
+
| Test framework | xUnit |
|
|
46
|
+
| Database | PostgreSQL 16 |
|
|
47
|
+
| Auth | JWT bearer / OIDC via Azure AD |
|
|
48
|
+
| Hosting | Azure App Service |
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Project layout
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
src/
|
|
55
|
+
├── {Project}.Domain/ # Aggregates, Value Objects, Domain Events
|
|
56
|
+
│ ├── Common/ # Entity, AggregateRoot, ValueObject base classes
|
|
57
|
+
│ ├── {BoundedContext}/
|
|
58
|
+
│ │ ├── Entities/
|
|
59
|
+
│ │ ├── ValueObjects/
|
|
60
|
+
│ │ ├── Events/
|
|
61
|
+
│ │ ├── Services/
|
|
62
|
+
│ │ └── Interfaces/ # Repository / external service interfaces
|
|
63
|
+
│ └── SharedKernel/
|
|
64
|
+
├── {Project}.Application/ # CQRS handlers, validators, DTOs
|
|
65
|
+
│ ├── Common/
|
|
66
|
+
│ └── {BoundedContext}/
|
|
67
|
+
│ ├── Commands/
|
|
68
|
+
│ ├── Queries/
|
|
69
|
+
│ ├── DTOs/
|
|
70
|
+
│ └── EventHandlers/
|
|
71
|
+
├── {Project}.Infrastructure/ # EF Core DbContext, repository impls
|
|
72
|
+
│ ├── Persistence/
|
|
73
|
+
│ ├── Repositories/
|
|
74
|
+
│ └── ExternalServices/
|
|
75
|
+
└── {Project}.WebAPI/ # Presentation: HTTP endpoints
|
|
76
|
+
|
|
77
|
+
tests/
|
|
78
|
+
├── {Project}.Domain.UnitTests/
|
|
79
|
+
├── {Project}.Application.UnitTests/
|
|
80
|
+
└── {Project}.Integration.Tests/
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Domain purity check
|
|
84
|
+
|
|
85
|
+
The Domain project's `.csproj` should have **zero** package references
|
|
86
|
+
outside the allow-list (typically just the `SharedKernel`). Specifically
|
|
87
|
+
forbid:
|
|
88
|
+
|
|
89
|
+
- `Microsoft.AspNetCore.*`, `System.Web`
|
|
90
|
+
- `Microsoft.EntityFrameworkCore.*` (Domain declares interfaces; Infrastructure references EF Core)
|
|
91
|
+
- `HttpContext`, `HttpRequest`, `ISession`
|
|
92
|
+
- `Newtonsoft.Json` / `System.Text.Json` attributes on Domain entities
|
|
93
|
+
|
|
94
|
+
CI check example: `dotnet list package` on Domain.csproj — fail if any
|
|
95
|
+
disallowed dependency appears.
|
|
96
|
+
|
|
97
|
+
### Test framework
|
|
98
|
+
|
|
99
|
+
`xUnit` + `FluentAssertions` + `NSubstitute`. Run with `dotnet test`.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## .NET / ASP.NET WebForms (Brownfield)
|
|
104
|
+
|
|
105
|
+
### `_overview.md` stack table
|
|
106
|
+
|
|
107
|
+
```markdown
|
|
108
|
+
| Item | Current |
|
|
109
|
+
|------|---------|
|
|
110
|
+
| Language | C# 7 (.NET Framework 4.8) |
|
|
111
|
+
| Framework | ASP.NET WebForms 4.8 |
|
|
112
|
+
| ORM / persistence | Entity Framework 6 (or ADO.NET / Dapper) |
|
|
113
|
+
| Test framework | xUnit / NUnit |
|
|
114
|
+
| Database | SQL Server 2019 |
|
|
115
|
+
| UI | WebForms .aspx + Code-Behind + Bootstrap |
|
|
116
|
+
| Auth | Forms authentication / Windows auth |
|
|
117
|
+
| Hosting | IIS on-prem |
|
|
118
|
+
| Target architecture | ASP.NET Core 8 + Clean Architecture |
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Project layout
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
src/
|
|
125
|
+
├── Domain/ # Extracted domain logic (framework-pure)
|
|
126
|
+
│ ├── {BoundedContext}/
|
|
127
|
+
│ │ ├── Entities/
|
|
128
|
+
│ │ ├── ValueObjects/
|
|
129
|
+
│ │ └── Services/
|
|
130
|
+
│ └── SharedKernel/
|
|
131
|
+
└── WebForms/ # Existing .aspx + .aspx.cs (Code-Behind)
|
|
132
|
+
└── Pages/
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Domain purity check
|
|
136
|
+
|
|
137
|
+
The Domain assembly must not reference:
|
|
138
|
+
|
|
139
|
+
- `System.Web.*`, `System.Web.UI.*`
|
|
140
|
+
- `HttpContext.Current`, `Session[…]`, `ViewState[…]`
|
|
141
|
+
- Page lifecycle types (`Page`, `Control`)
|
|
142
|
+
- EF6 attributes on Domain entities (use Fluent API in a separate
|
|
143
|
+
configuration class outside Domain)
|
|
144
|
+
|
|
145
|
+
CI check: project reference analyzer on `src/Domain/Domain.csproj`.
|
|
146
|
+
|
|
147
|
+
### Test framework
|
|
148
|
+
|
|
149
|
+
`xUnit` or `NUnit`. Run with `dotnet test` or `nunit3-console`.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Java / Spring Boot (Greenfield)
|
|
154
|
+
|
|
155
|
+
> Same pattern applies to Kotlin/Spring with minor syntax differences.
|
|
156
|
+
|
|
157
|
+
### `_overview.md` stack table
|
|
158
|
+
|
|
159
|
+
```markdown
|
|
160
|
+
| Item | Choice |
|
|
161
|
+
|------|--------|
|
|
162
|
+
| Language | Java 21 |
|
|
163
|
+
| Framework | Spring Boot 3.3 |
|
|
164
|
+
| ORM / persistence | Spring Data JPA / Hibernate 6.5 |
|
|
165
|
+
| Mediator | (none — direct service injection; optional: Spring Modulith) |
|
|
166
|
+
| Test framework | JUnit 5 + AssertJ + Mockito |
|
|
167
|
+
| Database | PostgreSQL 16 |
|
|
168
|
+
| Auth | Spring Security + OAuth2 / OIDC |
|
|
169
|
+
| Hosting | Kubernetes / managed app platform |
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Project layout
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
src/
|
|
176
|
+
├── main/
|
|
177
|
+
│ └── java/com/example/{system}/
|
|
178
|
+
│ ├── domain/ # Aggregates, Value Objects, Domain Events
|
|
179
|
+
│ │ ├── common/ # Base classes (Entity, AggregateRoot, ValueObject)
|
|
180
|
+
│ │ ├── {boundedcontext}/
|
|
181
|
+
│ │ │ ├── entity/
|
|
182
|
+
│ │ │ ├── valueobject/
|
|
183
|
+
│ │ │ ├── event/
|
|
184
|
+
│ │ │ ├── service/
|
|
185
|
+
│ │ │ └── repository/ # Repository interfaces (NOT implementations)
|
|
186
|
+
│ │ └── sharedkernel/
|
|
187
|
+
│ ├── application/ # Command/Query handlers, DTOs
|
|
188
|
+
│ │ ├── command/
|
|
189
|
+
│ │ ├── query/
|
|
190
|
+
│ │ └── dto/
|
|
191
|
+
│ ├── infrastructure/ # JPA repositories, external clients
|
|
192
|
+
│ │ ├── persistence/
|
|
193
|
+
│ │ └── client/
|
|
194
|
+
│ └── web/ # Controllers, REST endpoints
|
|
195
|
+
└── test/
|
|
196
|
+
└── java/com/example/{system}/
|
|
197
|
+
├── domain/ # Unit tests
|
|
198
|
+
├── application/
|
|
199
|
+
└── web/ # @SpringBootTest integration
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Multi-module Maven/Gradle layouts (one module per layer) are also common
|
|
203
|
+
and recommended for stricter dependency enforcement.
|
|
204
|
+
|
|
205
|
+
### Domain purity check
|
|
206
|
+
|
|
207
|
+
The Domain package must not import:
|
|
208
|
+
|
|
209
|
+
- `org.springframework.*` (no Spring annotations on Domain entities)
|
|
210
|
+
- `jakarta.persistence.*` / `javax.persistence.*` (no JPA annotations on
|
|
211
|
+
Domain entities; use a separate JPA mapping class in Infrastructure)
|
|
212
|
+
- `jakarta.servlet.*` (no HTTP types)
|
|
213
|
+
- `com.fasterxml.jackson.*` (no serialization annotations on Domain)
|
|
214
|
+
|
|
215
|
+
CI check: ArchUnit rule `noClasses().that().resideInAPackage("..domain..")
|
|
216
|
+
.should().dependOnClassesThat().resideInAnyPackage("org.springframework..", "jakarta.persistence..")`.
|
|
217
|
+
|
|
218
|
+
### Test framework
|
|
219
|
+
|
|
220
|
+
`JUnit 5` (`org.junit.jupiter`). Run with `./mvnw test` or `./gradlew test`.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Node.js / TypeScript / NestJS (Greenfield)
|
|
225
|
+
|
|
226
|
+
### `_overview.md` stack table
|
|
227
|
+
|
|
228
|
+
```markdown
|
|
229
|
+
| Item | Choice |
|
|
230
|
+
|------|--------|
|
|
231
|
+
| Language | TypeScript 5.4 |
|
|
232
|
+
| Framework | NestJS 10 |
|
|
233
|
+
| ORM / persistence | Prisma 5 (or TypeORM / MikroORM) |
|
|
234
|
+
| Mediator | (none — NestJS providers; optional: nestjs-cqrs module) |
|
|
235
|
+
| Test framework | Vitest (or Jest) + supertest |
|
|
236
|
+
| Database | PostgreSQL 16 |
|
|
237
|
+
| Auth | Passport (JWT, OAuth2) |
|
|
238
|
+
| Hosting | Containerized (Docker / Kubernetes / Fly.io) |
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Project layout
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
src/
|
|
245
|
+
├── domain/ # Aggregates, Value Objects, Domain Events
|
|
246
|
+
│ ├── common/ # Base classes
|
|
247
|
+
│ ├── {bounded-context}/
|
|
248
|
+
│ │ ├── entities/
|
|
249
|
+
│ │ ├── value-objects/
|
|
250
|
+
│ │ ├── events/
|
|
251
|
+
│ │ ├── services/
|
|
252
|
+
│ │ └── repositories/ # Interfaces only
|
|
253
|
+
│ └── shared-kernel/
|
|
254
|
+
├── application/ # Use cases, command/query handlers
|
|
255
|
+
│ ├── commands/
|
|
256
|
+
│ ├── queries/
|
|
257
|
+
│ └── dtos/
|
|
258
|
+
├── infrastructure/ # Prisma client, external API clients
|
|
259
|
+
│ ├── persistence/
|
|
260
|
+
│ └── external/
|
|
261
|
+
└── presentation/ # NestJS controllers, modules
|
|
262
|
+
└── http/
|
|
263
|
+
|
|
264
|
+
test/
|
|
265
|
+
├── domain/
|
|
266
|
+
├── application/
|
|
267
|
+
└── e2e/
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Domain purity check
|
|
271
|
+
|
|
272
|
+
`src/domain/` files must not import:
|
|
273
|
+
|
|
274
|
+
- `@nestjs/*` (no `@Injectable`, `@Module`, decorators on Domain)
|
|
275
|
+
- `@prisma/client` (Prisma generated client lives in Infrastructure only)
|
|
276
|
+
- `express` / `fastify` types
|
|
277
|
+
- `class-transformer` / `class-validator` (use plain TS types; validation
|
|
278
|
+
in Application layer)
|
|
279
|
+
|
|
280
|
+
CI check: ESLint rule `no-restricted-imports` scoped to `src/domain/**` or
|
|
281
|
+
`dependency-cruiser` rule forbidding cross-layer imports.
|
|
282
|
+
|
|
283
|
+
### Test framework
|
|
284
|
+
|
|
285
|
+
`Vitest` (or `Jest`). Run with `npm test` or `pnpm test`.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Python / FastAPI (Greenfield)
|
|
290
|
+
|
|
291
|
+
> Django and Flask follow the same layered pattern with framework-specific
|
|
292
|
+
> presentation conventions. Django: views/templates as presentation;
|
|
293
|
+
> Flask: blueprints; FastAPI: routers.
|
|
294
|
+
|
|
295
|
+
### `_overview.md` stack table
|
|
296
|
+
|
|
297
|
+
```markdown
|
|
298
|
+
| Item | Choice |
|
|
299
|
+
|------|--------|
|
|
300
|
+
| Language | Python 3.12 |
|
|
301
|
+
| Framework | FastAPI 0.115 |
|
|
302
|
+
| ORM / persistence | SQLAlchemy 2.0 + Alembic (or SQLModel) |
|
|
303
|
+
| Mediator | (none — typed dependency injection via FastAPI Depends) |
|
|
304
|
+
| Test framework | pytest + pytest-asyncio |
|
|
305
|
+
| Database | PostgreSQL 16 |
|
|
306
|
+
| Auth | OAuth2 via fastapi.security (PasswordBearer / JWT) |
|
|
307
|
+
| Hosting | Containerized (Docker / Kubernetes / Fly.io) |
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Project layout
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
src/
|
|
314
|
+
├── domain/ # Aggregates, Value Objects, Domain Events
|
|
315
|
+
│ ├── common/
|
|
316
|
+
│ ├── {bounded_context}/
|
|
317
|
+
│ │ ├── entities.py
|
|
318
|
+
│ │ ├── value_objects.py
|
|
319
|
+
│ │ ├── events.py
|
|
320
|
+
│ │ ├── services.py
|
|
321
|
+
│ │ └── repositories.py # Protocol / abstract base classes
|
|
322
|
+
│ └── shared_kernel/
|
|
323
|
+
├── application/ # Use cases, DTOs
|
|
324
|
+
│ ├── commands/
|
|
325
|
+
│ ├── queries/
|
|
326
|
+
│ └── dtos/
|
|
327
|
+
├── infrastructure/ # SQLAlchemy models, external clients
|
|
328
|
+
│ ├── persistence/
|
|
329
|
+
│ └── external/
|
|
330
|
+
└── presentation/ # FastAPI routers
|
|
331
|
+
└── api/
|
|
332
|
+
|
|
333
|
+
tests/
|
|
334
|
+
├── domain/
|
|
335
|
+
├── application/
|
|
336
|
+
└── integration/
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Domain purity check
|
|
340
|
+
|
|
341
|
+
`src/domain/` modules must not import:
|
|
342
|
+
|
|
343
|
+
- `fastapi` / `starlette`
|
|
344
|
+
- `sqlalchemy.*` (use Protocols / dataclasses in Domain; SQLAlchemy models
|
|
345
|
+
live in Infrastructure as separate mapping classes)
|
|
346
|
+
- `pydantic.BaseModel` for Domain entities (use `dataclass` or plain
|
|
347
|
+
classes; Pydantic models belong in DTO / API layer)
|
|
348
|
+
|
|
349
|
+
CI check: `import-linter` (`importlinter.org`) contract forbidding Domain
|
|
350
|
+
imports of presentation/infrastructure packages.
|
|
351
|
+
|
|
352
|
+
### Test framework
|
|
353
|
+
|
|
354
|
+
`pytest`. Run with `pytest` or `python -m pytest`.
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Go / Gin (Greenfield)
|
|
359
|
+
|
|
360
|
+
### `_overview.md` stack table
|
|
361
|
+
|
|
362
|
+
```markdown
|
|
363
|
+
| Item | Choice |
|
|
364
|
+
|------|--------|
|
|
365
|
+
| Language | Go 1.22 |
|
|
366
|
+
| Framework | Gin 1.10 (or Echo / Chi) |
|
|
367
|
+
| ORM / persistence | GORM v2 (or sqlx / pgx) |
|
|
368
|
+
| Mediator | (none — interface-based dispatch) |
|
|
369
|
+
| Test framework | go test + testify |
|
|
370
|
+
| Database | PostgreSQL 16 |
|
|
371
|
+
| Auth | JWT middleware / OAuth2 |
|
|
372
|
+
| Hosting | Containerized (Docker / Kubernetes / Fly.io) |
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### Project layout
|
|
376
|
+
|
|
377
|
+
```
|
|
378
|
+
{module-root}/
|
|
379
|
+
├── cmd/
|
|
380
|
+
│ └── api/main.go # Application entrypoint
|
|
381
|
+
├── internal/
|
|
382
|
+
│ ├── domain/ # Aggregates, Value Objects, Domain Events
|
|
383
|
+
│ │ ├── common/
|
|
384
|
+
│ │ ├── {boundedcontext}/
|
|
385
|
+
│ │ │ ├── entity.go
|
|
386
|
+
│ │ │ ├── valueobject.go
|
|
387
|
+
│ │ │ ├── event.go
|
|
388
|
+
│ │ │ ├── service.go
|
|
389
|
+
│ │ │ └── repository.go # Interface only
|
|
390
|
+
│ │ └── sharedkernel/
|
|
391
|
+
│ ├── application/ # Use cases
|
|
392
|
+
│ │ ├── command/
|
|
393
|
+
│ │ └── query/
|
|
394
|
+
│ ├── infrastructure/ # GORM repo impls, external clients
|
|
395
|
+
│ │ ├── persistence/
|
|
396
|
+
│ │ └── external/
|
|
397
|
+
│ └── handler/ # HTTP handlers (Gin routes)
|
|
398
|
+
└── go.mod
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
`internal/` enforces Go's import boundary — packages outside the module
|
|
402
|
+
cannot import from `internal/...`.
|
|
403
|
+
|
|
404
|
+
### Domain purity check
|
|
405
|
+
|
|
406
|
+
`internal/domain/` packages must not import:
|
|
407
|
+
|
|
408
|
+
- `github.com/gin-gonic/gin` or any HTTP router package
|
|
409
|
+
- `gorm.io/gorm` (Domain declares repository interfaces; GORM lives in
|
|
410
|
+
Infrastructure)
|
|
411
|
+
- `net/http` types (`http.Request`, `http.ResponseWriter`)
|
|
412
|
+
- Encoding tags (e.g. `gorm:"primaryKey"`, `json:"..."`) on Domain
|
|
413
|
+
entities — keep tag-free, do encoding via separate Infrastructure
|
|
414
|
+
models
|
|
415
|
+
|
|
416
|
+
CI check: `go vet` plus a custom `go-arch-lint` or `golangci-lint` rule
|
|
417
|
+
forbidding `internal/domain` from importing the above.
|
|
418
|
+
|
|
419
|
+
### Test framework
|
|
420
|
+
|
|
421
|
+
`go test` (standard library) + `stretchr/testify` for assertions.
|
|
422
|
+
Run with `go test ./...`.
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## PHP / Laravel (Brownfield migration)
|
|
427
|
+
|
|
428
|
+
> Older PHP monoliths (Symfony 2/3, CodeIgniter, custom) follow similar
|
|
429
|
+
> extraction patterns; the snippets below are for a modern Laravel app
|
|
430
|
+
> already on Laravel 10+ that wants to introduce a Domain layer.
|
|
431
|
+
|
|
432
|
+
### `_overview.md` stack table
|
|
433
|
+
|
|
434
|
+
```markdown
|
|
435
|
+
| Item | Current |
|
|
436
|
+
|------|---------|
|
|
437
|
+
| Language | PHP 8.3 |
|
|
438
|
+
| Framework | Laravel 11 |
|
|
439
|
+
| ORM / persistence | Eloquent ORM (Active Record pattern — see Domain note) |
|
|
440
|
+
| Test framework | PHPUnit 11 (or Pest 2) |
|
|
441
|
+
| Database | MySQL 8 / MariaDB 10 |
|
|
442
|
+
| UI | Blade templates / Inertia + Vue / API-only |
|
|
443
|
+
| Auth | Laravel Breeze / Sanctum / Passport |
|
|
444
|
+
| Hosting | Laravel Forge / shared hosting / containerized |
|
|
445
|
+
| Target architecture | Same Laravel + extracted Domain layer + repository abstractions |
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Project layout
|
|
449
|
+
|
|
450
|
+
```
|
|
451
|
+
app/
|
|
452
|
+
├── Domain/ # Extracted domain logic (framework-pure)
|
|
453
|
+
│ ├── Common/
|
|
454
|
+
│ ├── {BoundedContext}/
|
|
455
|
+
│ │ ├── Entities/ # Plain PHP classes (NOT Eloquent models)
|
|
456
|
+
│ │ ├── ValueObjects/
|
|
457
|
+
│ │ ├── Events/
|
|
458
|
+
│ │ ├── Services/
|
|
459
|
+
│ │ └── Repositories/ # Interfaces only
|
|
460
|
+
│ └── SharedKernel/
|
|
461
|
+
├── Application/ # Use cases, command/query handlers
|
|
462
|
+
│ ├── Commands/
|
|
463
|
+
│ └── Queries/
|
|
464
|
+
├── Infrastructure/ # Eloquent repository implementations
|
|
465
|
+
│ ├── Persistence/
|
|
466
|
+
│ │ ├── Eloquent/ # Eloquent models live HERE, not in Domain
|
|
467
|
+
│ │ └── Repositories/
|
|
468
|
+
│ └── External/
|
|
469
|
+
├── Http/ # Controllers, middleware (Laravel-managed)
|
|
470
|
+
│ ├── Controllers/
|
|
471
|
+
│ └── Middleware/
|
|
472
|
+
└── Providers/
|
|
473
|
+
|
|
474
|
+
tests/
|
|
475
|
+
├── Unit/Domain/
|
|
476
|
+
├── Feature/Application/
|
|
477
|
+
└── Feature/Http/
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Domain purity check
|
|
481
|
+
|
|
482
|
+
`app/Domain/` classes must not extend / use:
|
|
483
|
+
|
|
484
|
+
- `Illuminate\Database\Eloquent\Model` (Eloquent models are Infrastructure)
|
|
485
|
+
- `Illuminate\Http\Request` / `Response`
|
|
486
|
+
- `Illuminate\Support\Facades\*` (DB, Auth, Cache, etc.)
|
|
487
|
+
- Laravel attribute / trait magic on Domain entities
|
|
488
|
+
|
|
489
|
+
CI check: a Laravel-aware static analysis rule (Larastan / PHPStan with a
|
|
490
|
+
custom architecture rule) forbidding `app/Domain/` from referencing the
|
|
491
|
+
above.
|
|
492
|
+
|
|
493
|
+
### Test framework
|
|
494
|
+
|
|
495
|
+
`PHPUnit` (`phpunit/phpunit`) or `Pest` (`pestphp/pest`). Run with
|
|
496
|
+
`./vendor/bin/phpunit` or `./vendor/bin/pest`.
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
## Adding your stack
|
|
501
|
+
|
|
502
|
+
If your stack isn't listed (Rust, Ruby/Rails, Kotlin native, Elixir, etc.),
|
|
503
|
+
the pattern is always the same:
|
|
504
|
+
|
|
505
|
+
1. Identify your stack's **domain layer convention** (folder / package /
|
|
506
|
+
namespace where pure business code lives)
|
|
507
|
+
2. Identify the **delivery / entrypoint layer** (controllers, handlers,
|
|
508
|
+
routes, CLI commands, message consumers, job runners)
|
|
509
|
+
3. Identify the **persistence layer** (ORM, query builder, raw driver)
|
|
510
|
+
4. Domain purity check = "no imports / usings / extends from delivery,
|
|
511
|
+
persistence, or framework runtime packages"
|
|
512
|
+
5. Express the layer separation in a CI-enforceable rule appropriate to
|
|
513
|
+
the stack (ArchUnit, ESLint, import-linter, go-arch-lint, Larastan,
|
|
514
|
+
etc.)
|
|
515
|
+
|
|
516
|
+
Contributions of additional stacks via PR are welcome.
|
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
> migration. This guide is a manual checklist. The CLI only warns when
|
|
9
9
|
> it detects legacy paths; it does not modify existing files.
|
|
10
10
|
|
|
11
|
+
> **Audience reality (2026-05-15)**: To date, the only known user of
|
|
12
|
+
> this guide has been the **OBTS** migration (a single, completed
|
|
13
|
+
> one-off). Dflow has not had broad pre-V1 adoption; this guide is
|
|
14
|
+
> maintained as a contingency endpoint for `dflow doctor` and
|
|
15
|
+
> `dflow init` warning messages, not as documentation of an active
|
|
16
|
+
> migration program. If you reach this page via those tool outputs
|
|
17
|
+
> and your case isn't covered below, please open a docs feedback issue
|
|
18
|
+
> so the guide can be extended.
|
|
19
|
+
|
|
11
20
|
## When You Need This Guide
|
|
12
21
|
|
|
13
22
|
Skip this guide if you started using Dflow at `dflow-sdd-ddd@0.1.0`
|
|
@@ -22,7 +31,8 @@ Read this guide if any of the following are true:
|
|
|
22
31
|
canonical English vocabulary documented in
|
|
23
32
|
`TEMPLATE-LANGUAGE-GLOSSARY.md`.
|
|
24
33
|
- Your AI instructions point teammates to `/dflow:init-project`
|
|
25
|
-
instead of `
|
|
34
|
+
instead of the Dflow CLI init command (`dflow init`, or
|
|
35
|
+
`npx dflow-sdd-ddd init` on the no-install path).
|
|
26
36
|
- Your `CLAUDE.md` (or equivalent root instruction file) was generated
|
|
27
37
|
by an early Dflow variant that wrote a full Claude-only file rather
|
|
28
38
|
than the V1 multi-AI thin shim that points to
|
|
@@ -42,11 +52,12 @@ independent.
|
|
|
42
52
|
- Open these V1 reference files for cross-checking:
|
|
43
53
|
- `TEMPLATE-LANGUAGE-GLOSSARY.md` — canonical English headings.
|
|
44
54
|
- `TEMPLATE-COVERAGE.md` — V1 file layout and parity matrix.
|
|
45
|
-
- `docs/evaluating-dflow.md` — what a fresh V1 `init` produces, if
|
|
55
|
+
- `docs/evaluating-dflow.en.md` — what a fresh V1 `init` produces, if
|
|
46
56
|
you want to spin up a sample project to compare against.
|
|
47
57
|
- For an on-demand read-only summary of legacy artifacts in your
|
|
48
|
-
project, run `dflow doctor
|
|
49
|
-
|
|
58
|
+
project, run `dflow doctor` (or `npx dflow-sdd-ddd doctor` on the
|
|
59
|
+
no-install path). The command lists detected legacy paths and missing
|
|
60
|
+
V1 fields; it never modifies files.
|
|
50
61
|
|
|
51
62
|
## Migration Steps
|
|
52
63
|
|
|
@@ -124,7 +135,14 @@ grep -rn "## 業務規則\|## 行為情境\|## 領域模型" dflow/specs/
|
|
|
124
135
|
Pre-V1 documentation may have instructed teammates to start a Dflow
|
|
125
136
|
project by running `/dflow:init-project` from inside an AI agent. V1
|
|
126
137
|
removed that runtime slash command (PROPOSAL-014). The init flow now
|
|
127
|
-
runs as a shell command:
|
|
138
|
+
runs as a shell command. Install Dflow globally and run:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm install -g dflow-sdd-ddd
|
|
142
|
+
dflow init
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
If you cannot or do not want to install globally, use the no-install path:
|
|
128
146
|
|
|
129
147
|
```bash
|
|
130
148
|
npx dflow-sdd-ddd init
|
|
@@ -155,8 +173,8 @@ early Dflow form that wrote a full file rather than a thin shim:
|
|
|
155
173
|
dflow configure-agents
|
|
156
174
|
```
|
|
157
175
|
|
|
158
|
-
This command adds shims for any AI tools you select.
|
|
159
|
-
overwrite an existing `CLAUDE.md`; instead, it writes a
|
|
176
|
+
This command adds shims for any AI tools you select. `dflow configure-agents`
|
|
177
|
+
does not overwrite an existing `CLAUDE.md`; instead, it writes a
|
|
160
178
|
`dflow/specs/shared/<tool>-md-snippet.md` that you can merge into the
|
|
161
179
|
existing file at your own pace.
|
|
162
180
|
|
|
@@ -199,11 +217,11 @@ them, only to keep V1 a clean cut.
|
|
|
199
217
|
|
|
200
218
|
## Where To Go Next
|
|
201
219
|
|
|
202
|
-
- `docs/evaluating-dflow.md` for what a fresh V1 `init` produces, in
|
|
220
|
+
- `docs/evaluating-dflow.en.md` for what a fresh V1 `init` produces, in
|
|
203
221
|
case you want to compare against your migrated project.
|
|
204
222
|
- Per-tool walkthroughs under `docs/` for the AI tool you use:
|
|
205
|
-
- `docs/using-with-claude-code.md`
|
|
206
|
-
- `docs/using-with-codex.md`
|
|
223
|
+
- `docs/using-with-claude-code.en.md`
|
|
224
|
+
- `docs/using-with-codex.en.md`
|
|
207
225
|
- `TEMPLATE-COVERAGE.md` for the V1 logical / generated file parity
|
|
208
226
|
between Greenfield and Brownfield tracks.
|
|
209
227
|
|
|
@@ -44,6 +44,19 @@ Examples:
|
|
|
44
44
|
- Changing command behavior in a way that invalidates existing docs.
|
|
45
45
|
- Replacing a workflow contract that AI agents rely on.
|
|
46
46
|
|
|
47
|
+
Counter-examples (NOT breaking):
|
|
48
|
+
|
|
49
|
+
- Replacing stack-specific framing with stack-neutral umbrella terms when
|
|
50
|
+
the architectural meaning is unchanged (e.g., "Code-Behind" →
|
|
51
|
+
"delivery/entrypoint code") — adopter's existing files are not
|
|
52
|
+
rewritten by Dflow.
|
|
53
|
+
- Renaming an init placeholder if the previous name still resolves via a
|
|
54
|
+
backward-compat alias and the substituted value is identical (e.g.,
|
|
55
|
+
`{ASP.NET Core version}` continuing to resolve while `{Framework version}`
|
|
56
|
+
becomes canonical).
|
|
57
|
+
- Adding a new optional placeholder; existing templates that don't use it
|
|
58
|
+
are unaffected.
|
|
59
|
+
|
|
47
60
|
## Release Ownership
|
|
48
61
|
|
|
49
62
|
Dflow currently has four release surfaces:
|