aw-spec-cli 0.1.16 → 0.1.18

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.
Files changed (70) hide show
  1. package/assets/.appweaver/DESIGN-FORMAT.md +18 -18
  2. package/assets/.appweaver/ORCH-DIALECT.md +1 -3
  3. package/assets/.appweaver/RULE-PARTITION.md +29 -13
  4. package/assets/.appweaver/STACK-PROFILES.md +10 -9
  5. package/assets/.appweaver/orchestrator/.state/smoke.state.json +32 -0
  6. package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +4 -1
  7. package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +251 -0
  8. package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +104 -35
  9. package/assets/.appweaver/orchestrator/orchestrator.py +5 -4
  10. package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +94 -36
  11. package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +1 -1
  12. package/assets/.appweaver/orchestrator/rev-templates/domain-model-template.skeleton.md +115 -0
  13. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +2 -9
  14. package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +16 -40
  15. package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +38 -17
  16. package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +8 -8
  17. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +10 -11
  18. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +673 -0
  19. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +535 -0
  20. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +643 -0
  21. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +84 -701
  22. package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
  23. package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +7 -7
  24. package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +16 -14
  25. package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +2 -2
  26. package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +243 -144
  27. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +877 -578
  28. package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +4 -4
  29. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +32 -91
  30. package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
  31. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +836 -514
  32. package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +2 -2
  33. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +132 -0
  34. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +38 -5
  35. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +3 -3
  36. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +271 -979
  37. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +1085 -3385
  38. package/assets/.appweaver/scripts/bash/aw-xref.sh +1 -2
  39. package/assets/.appweaver/scripts/bash/common.sh +47 -0
  40. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +914 -3220
  41. package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +1 -2
  42. package/assets/.appweaver/scripts/python/aw-payload-parity.py +19 -3
  43. package/assets/.appweaver/scripts/python/aw-stack.py +6 -2
  44. package/assets/.appweaver/scripts/python/aw-xref.py +86 -350
  45. package/assets/.appweaver/templates/constitution-ui-template.md +1 -1
  46. package/assets/.appweaver/templates/delta-design-template.md +120 -30
  47. package/assets/.appweaver/templates/delta-domain-model-template.md +81 -0
  48. package/assets/.appweaver/templates/delta-spec-template.md +43 -17
  49. package/assets/.appweaver/templates/design-template.md +68 -98
  50. package/assets/.appweaver/templates/domain-model-template.md +130 -0
  51. package/assets/.appweaver/templates/okf-concept-template.md +2 -2
  52. package/assets/.appweaver/templates/source-map-template.md +3 -3
  53. package/assets/.appweaver/templates/spec-template.md +100 -122
  54. package/assets/.appweaver/templates/ui-delta-design-template.md +159 -0
  55. package/assets/.appweaver/templates/ui-design-template.md +46 -75
  56. package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +7 -18
  57. package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +34 -39
  58. package/assets/guardrails/requirement-spec.txt +2 -2
  59. package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
  60. package/package.json +1 -1
  61. package/assets/.appweaver/orchestrator/modules/delta-design.orch.yaml +0 -105
  62. package/assets/.appweaver/orchestrator/modules/spec-state-gate.orch.yaml +0 -87
  63. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-delta-design.orch.yaml +0 -251
  64. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-design.orch.yaml +0 -813
  65. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-delta.orch.yaml +0 -253
  66. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-ui.orch.yaml +0 -663
  67. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan-ui.orch.yaml +0 -600
  68. package/assets/.appweaver/orchestrator/workflows/aw-spec-story-plan.orch.yaml +0 -1147
  69. package/assets/.appweaver/orchestrator/workflows/aw-spec-sync-stories.orch.yaml +0 -1121
  70. package/assets/.appweaver/templates/story-template.md +0 -178
@@ -1,57 +1,41 @@
1
- # Design: [AGGREGATE]
1
+ # Backend Plan: [AGGREGATE]
2
2
 
3
3
  **Aggregate (feature)**: `[Aggregate]` <!-- the feature = the aggregate, e.g. Order -->
4
4
 
5
- **Design home**: `specs/[Aggregate]/backend-plan.md` <!-- the service lane; the frontend twin is frontend-plan.md, owned by /appweaver plan-ui -->
5
+ **Plan home**: `specs/[Aggregate]/backend-plan.md`
6
6
 
7
7
  **Source spec**: `specs/[Aggregate]/spec.md`
8
8
 
9
- **Version**: v1.0 <!-- SCRIPT-OWNED: plan-stamp sets this to the spec version this plan derives from. Never edit it by hand. -->
9
+ **Version**: v1.0 <!-- moves in lockstep with the spec; every applied change request bumps this — see Change History -->
10
10
 
11
11
  **Status**: Draft
12
12
 
13
13
  <!--
14
14
  WHAT THIS DOCUMENT IS
15
15
  =====================
16
- The single, living High-Level Design (HLD) for ONE aggregate — the FEATURE-LEVEL
17
- ARCHITECTURAL CONFIRMATION. It is the MEDIATOR between spec.md (WHAT/WHY,
18
- tech-agnostic) and the generated code (HOW, tech-specific). It is NOT code: it
19
- carries structure, contracts, behaviour, and decisions — enough for ANY capable LLM
20
- to generate correct, spec-satisfying code on ANY target stack, but no complete
21
- method bodies.
16
+ The single, living High-Level Design (HLD) for ONE aggregate. It is the
17
+ MEDIATOR between spec.md (WHAT/WHY, tech-agnostic) and the generated code
18
+ (HOW, tech-specific). It is NOT code: it carries structure, contracts,
19
+ behaviour, and decisions — enough for ANY capable LLM to generate correct,
20
+ spec-satisfying code on ANY target stack, but no complete method bodies.
22
21
 
23
- spec.md ──▶ backend-plan.md ──▶ story-backend-plan.md ──▶ code (+ tests)
24
- behaviour structure & the story's slice generated by `implement`
25
- (FR/BR/CN/SC) decisions (HLD) (concrete, ephemeral)
26
-
27
- It is LONG-LIVED and moves FORWARD with the spec: /appweaver plan authors it, and
28
- conforms it whenever the spec's Change History says something it realises has moved.
29
- Story designs READ it and never write back — nothing merges into this document.
22
+ spec.md ──▶ backend-plan.md ──▶ code (+ tests)
23
+ behaviour structure & generated by `implement`
24
+ (FR/BR/US/SC) decisions (HLD) (stack-bound at generation time)
30
25
 
31
26
  ANCHORING RULES
32
- - Every design element traces UP to a spec id (FR-/BR-/CN-/DC-/IC-/SC-) and the
33
- whole spec is covered DOWN here (see §6 Traceability). No design element without
34
- a spec reason; no spec requirement without a design home.
27
+ - Every design element traces UP to a spec id (FR-/BR-/CN-/DC-/IC-/US-/SC-) and
28
+ the whole spec is covered DOWN here (see §6 Traceability). No design element
29
+ without a spec reason; no spec requirement without a design home.
35
30
  - THE SPEC IS THE ONLY DOMAIN INPUT. Design reads the spec + the technical/
36
31
  architecture standards — NOT the domain rule files. The domain reached this doc
37
32
  only as spec ids: business invariants (BR-), domain-derived constraints (CN- —
38
33
  retention/immutability/audit/limits), data classification (DC-), and interop
39
34
  obligations (IC-). Realise each of those; invent no domain rule the spec omits
40
35
  (if one seems missing, record it as an Assumption in §7, never smuggle it in).
41
- - THE CODE IS THE WHAT-EXISTS INPUT, and it is a different authority from the spec.
42
- Where code already realises this feature, the plan describes and ADJUSTS TO the
43
- structure that is actually there rather than an idealised one, and names any
44
- deliberate divergence as a §8 WA-n. The code never overrides the spec on
45
- BEHAVIOUR, and it may not introduce a domain rule the spec omits — code that
46
- contradicts the spec is a finding to report, not a design to bless.
47
- - NO STORY IDS ANYWHERE IN THIS DOCUMENT. Stories live in stories/ and cite the
48
- requirement ids they deliver; this design traces to FR-/BR-, which is what keeps
49
- it stable while the backlog churns, is reprioritised and is re-raised.
50
- - Feature = aggregate. Commands (CreateOrder, UpdateOrder…) are REQUIREMENTS
51
- (FR-n) in the spec, not features and not stories. One aggregate = one
52
- backend-plan.md = one owning design for its code files. A later requirement is
53
- CONFORMED into this document by /appweaver plan's update mode — never a new
54
- design doc, and never a delta document.
36
+ - Feature = aggregate. Commands (CreateOrder, UpdateOrder…) are USER STORIES,
37
+ not features. One aggregate = one backend-plan.md = one owning design for its code
38
+ files. A later requirement is a delta on THIS doc, never a new one.
55
39
 
56
40
  WHAT LIVES ELSEWHERE (do NOT repeat it here — it is identical for every feature)
57
41
  - The clean-architecture layering + dependency rule (API → Application → Domain
@@ -63,13 +47,6 @@
63
47
  - Physical persistence (PKs/FKs, columns, indexes, JSON shapes, migration SQL)
64
48
  belongs to a technical-data-model. This doc states WHAT is stored and WHICH
65
49
  port persists it, not the schema.
66
- - THE PUBLISHED SURFACE belongs to `interfaces.md`, this feature's APPEND-ONLY
67
- interface log — the anchor the frontend lane designs against. /appweaver plan
68
- publishes each entry there (the script assigns IF-nnn, the date and
69
- status: proposed); /appweaver plan-ui and the FE story designs READ the latest
70
- entry per id. §3 here is the INDEX that cites those ids, never a second copy of
71
- the contract: two copies drift, and only the log has a lifecycle and a
72
- supersedes: chain.
73
50
 
74
51
  TECHNOLOGY-AGNOSTIC (mandatory)
75
52
  - Express behaviour as SIGNATURES + pre/post/invariant/raises pseudocode and
@@ -117,13 +94,16 @@ trade-off. Layering follows the project architecture standard (constitution).]
117
94
  ## 1. Domain Layer
118
95
 
119
96
  <!--
120
- FOLLOW spec.md EXACTLY. This is not a fresh model — it is the DDD elaboration of
121
- what the spec already fixes:
122
- • Entities & value objects = the spec's "Key Entities" (SAME names).
123
- • Invariants = the spec's "Business Rules" (BR-nnn) — cite each.
124
- • Aggregate boundary = the spec's "Scope & Assumptions → Aggregate Boundary"
97
+ FOLLOW THE CONTEXT'S DOMAIN MODEL EXACTLY — specs/[Context]/domain-model.md. This is
98
+ not a fresh model; it is the DDD elaboration of what the model already fixes, and the
99
+ model is the canonical definition every spec in the context cites:
100
+ • Entities & value objects = the model's `## Aggregate: <Root>` entities (SAME names).
101
+ • Invariants = the model's Invariants (BR-nnn) — cite each, never restate.
102
+ • Aggregate boundary = the model's "Boundary" block
125
103
  (owns vs references-by-id vs out-of-scope).
126
- • Lifecycle / states = the states the spec describes.
104
+ • Lifecycle / states = the states the model describes.
105
+ The SPEC supplies behaviour — requirements, stories, lifted CN-/DC-/IC-/UX- items —
106
+ and cites the invariants by id. Structure comes from the model, behaviour from the spec.
127
107
  • Domain-derived constraints = the spec's "Constraints & NFRs" (CN-nnn) that are
128
108
  structural here — e.g. immutability, append-only audit,
129
109
  no-hard-delete → realised as VO immutability, a domain
@@ -138,7 +118,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
138
118
  invariants, behaviours). Repeat the blocks as the aggregate needs.
139
119
  -->
140
120
 
141
- ### 1.1 Aggregate structure *(from the spec's Aggregate Boundary — verbatim)*
121
+ ### 1.1 Aggregate structure *(from the domain model's Boundary — cite, never restate)*
142
122
 
143
123
  - **Aggregate root**: `[Root]` — [what it guards; the transaction boundary]
144
124
  - **Entities (owned)**: `[Entity]` — [role]; …
@@ -151,7 +131,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
151
131
 
152
132
  | Event | Raised by | Trigger | Key payload | Serves |
153
133
  |---|---|---|---|---|
154
- | `[EntityStateChanged]` | `[Root/Entity]` | [what causes it] | `[id, key fields]` | FR-00X · BR-00Z |
134
+ | `[EntityStateChanged]` | `[Root/Entity]` | [what causes it] | `[id, key fields]` | FR-00X · US-Y |
155
135
 
156
136
  ### 1.3 Entities
157
137
 
@@ -185,7 +165,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
185
165
  Invariant: [what must hold — maps to a spec BR-nnn]
186
166
  Post-condition: [resulting state / outputs]
187
167
  Raises: [DomainEvent]
188
- Serves: FR-00X · BR-00Z
168
+ Serves: FR-00X · US-Y · BR-00Z
189
169
  ```
190
170
 
191
171
  **Invariants** *(always-true; each maps to a spec BR-nnn — do not add rules absent from the spec)*
@@ -205,13 +185,13 @@ trade-off. Layering follows the project architecture standard (constitution).]
205
185
  Purpose: [why this can't live on one entity]
206
186
  Steps: 1. … 2. … 3. …
207
187
  Touches: [aggregates/ports coordinated]
208
- Serves: FR-00X
188
+ Serves: FR-00X · US-Y
209
189
  ```
210
190
 
211
191
  ## 2. Application Layer
212
192
 
213
193
  <!--
214
- Use-cases: one command/query per requirement action (FR-n), its handler's orchestration,
194
+ Use-cases: one command/query per user-story action, its handler's orchestration,
215
195
  the ports it depends on, application-level rules (authorization, input validation,
216
196
  transaction + event publication), and the request/response DTO shapes. Consumes
217
197
  Domain types and the PORTS the Domain/Application defines; NEVER touches
@@ -229,9 +209,9 @@ trade-off. Layering follows the project architecture standard (constitution).]
229
209
 
230
210
  ### 2.2 Use-cases (commands / queries)
231
211
 
232
- <!-- One block per use-case = one requirement action. This is the LLM's unit of work. -->
212
+ <!-- One block per use-case = one user-story action. This is the LLM's unit of work. -->
233
213
 
234
- #### `[Command/Query]` — Serves FR-00X
214
+ #### `[Command/Query]` — Serves US-Y · FR-00X
235
215
 
236
216
  - **Type**: command (writes) | query (reads)
237
217
  - **Request (DTO)**: `{ [field]: [type], … }`
@@ -247,41 +227,33 @@ trade-off. Layering follows the project architecture standard (constitution).]
247
227
  4. [persist via port] (single transaction boundary)
248
228
  5. [publish domain events]
249
229
  6. return [Response]
250
- On failure: [which error → which published-interface status; the contract is the
251
- IF- entry cited in §3]
230
+ On failure: [which error → which API status in §3]
252
231
  ```
253
232
  - **Emits**: `[DomainEvent]` (from §1.2)
254
233
 
255
- ## 3. API Layer — the published surface (INDEX; the wording lives in `interfaces.md`)
234
+ ## 3. API Layer
256
235
 
257
236
  <!--
258
- The contract other systems and the frontend couple to. Describe it at PROTOCOL level
259
- (REST assumed per the constitution — adapt for gRPC/GraphQL/CLI if the stack differs),
260
- NEVER as controller code. Delegates to an Application use-case; no business logic here.
261
-
262
- WHERE IT LIVES. Each published interface is an entry in `specs/[Aggregate]/interfaces.md`,
263
- the append-only interface log: route/verb, auth, request and response shapes, status
264
- codes and the error contract. `plan` publishes those entries — the script assigns the
265
- IF-nnn id, the date and status: proposed — and `plan-ui`, the FE story designs and any
266
- consuming feature read the LATEST entry per id. This section is the INDEX only.
267
-
268
- HOW TO FILL IT
269
- - An interface that ALREADY has an entry in the log (it is in context on an update
270
- run): cite its IF- id here, and describe nothing.
271
- - An interface being published for the FIRST TIME in this run: describe it in the
272
- "Interface" cell in one line and leave the IF- id cell as `(this run)` — the log
273
- assigns the real id after this document is written, and the next update run cites
274
- it. Never invent an IF- number: the script is the only id authority.
275
- - CHANGING a published interface is a NEW entry that supersedes the old one, never
276
- an edit to the existing entry and never a change to this table alone.
277
- - Every row cites the spec ids it serves and the use-case that implements it, so
278
- §6 Traceability and the analyze gate can follow the chain both ways.
237
+ The contract other systems couple to. Describe it at PROTOCOL level (REST assumed
238
+ per the constitution — adapt for gRPC/GraphQL/CLI if the stack differs), NOT as
239
+ controller code. Pin route, verb, auth, request/response shape, status codes, and
240
+ the error contract. Delegates to an Application use-case; no business logic here.
279
241
  -->
280
242
 
281
- | Interface | IF- id | Serves | Implemented by |
282
- |---|---|---|---|
283
- | `[VERB] [/route]` — [purpose] | IF-00n | FR-00X | `[Command/Query]` (§2.2) |
284
- | `[DomainEvent]` published outside this feature | (this run) | FR-00X · BR-00X | §2.2 emits, §1.2 |
243
+ ### `[VERB] [/route]` — [purpose] · Serves US-Y · FR-00X
244
+
245
+ - **Auth**: [required role/scope]
246
+ - **Request**: `[path/query params]` + body `{ [field]: [type], … }`
247
+ - **Success**: `2xx` → `{ [response shape] }`
248
+ - **Errors** *(the error contract)*:
249
+
250
+ | Status | When | Body shape |
251
+ |---|---|---|
252
+ | 400 | [validation failure] | `{ errors: [{ field, message }] }` |
253
+ | 403 | [unauthorized] | `{ error }` |
254
+ | 409 | [conflict / duplicate — maps to a BR] | `{ error }` |
255
+
256
+ - **Maps to**: `[Command/Query]` (§2.2)
285
257
 
286
258
  ## 4. Infrastructure Layer
287
259
 
@@ -347,12 +319,12 @@ trade-off. Layering follows the project architecture standard (constitution).]
347
319
  ## 6. Traceability (the spine)
348
320
 
349
321
  <!--
350
- The two-way guarantee: every FR/BR/CN/DC/IC/SC has a design home, and every
322
+ The two-way guarantee: every FR/BR/CN/DC/IC/US/SC has a design home, and every
351
323
  design element has a spec reason. This is what makes impact analysis exact and lets
352
324
  the analyze gate verify coverage. Keep it complete — EVERY CN-/DC-/IC- in the spec
353
325
  MUST appear as a row here (that is how the analyze gate proves no lifted constraint
354
- was dropped). The Domain rows MUST match the spec's Key Entities and Business Rules
355
- exactly.
326
+ was dropped). The Domain rows MUST match the domain model's entities and BR-nnn
327
+ invariants exactly.
356
328
  -->
357
329
 
358
330
  | Spec id | Type | Design element(s) | Layer |
@@ -362,6 +334,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
362
334
  | CN-001 | constraint | [where realised — §1 invariant / §4 persistence / §5 cross-cutting] | [layer] |
363
335
  | DC-001 | classification | [exposure enforcement — §2 projection / §5 data-protection] | App·Infra |
364
336
  | IC-001 | contract | [adapter/port realising it — §4.2] | Infra |
337
+ | US-1 | story | [end-to-end elements realising it] | all |
365
338
  | SC-001 | success | [where it is met + how verified] | [layer] |
366
339
 
367
340
  ## 7. Assumptions (to clarify later)
@@ -399,19 +372,16 @@ trade-off. Layering follows the project architecture standard (constitution).]
399
372
  ## 9. Change History
400
373
 
401
374
  <!--
402
- The living-truth ledger, in lockstep with spec.md — MANDATORY, and the one section
403
- whose loss is refused rather than absorbed: plan-stamp writes no baseline at all if
404
- this section went missing, so a dropped ledger can never be silently stamped over.
405
-
406
- SCRIPT-OWNED. `plan-stamp` is the only writer: it appends one row per update naming
407
- the requirement ids conformed, and moves the **Version** header to the spec version
408
- this plan now derives from. The model writes NO version and NO row, ever — not here,
409
- not in the header. Newest last.
410
-
411
- Three columns, matching exactly what the stamp writes: the derived spec version, the
412
- date, and what changed (the conformed ids are carried in that cell).
375
+ The living-truth ledger. A row is appended when this plan is RE-DERIVED to carry a
376
+ change — this document is derived from spec.md and the context's domain-model.md, and
377
+ finalize-delta merges a change into those two, never into this one. close-delta archives
378
+ the CR, bumps the minor version in active_version.json and stamps that number into this
379
+ document's **Version** header, so a header ahead of the newest row below means exactly
380
+ what it says: the plan has not been re-derived since that version. A change to this
381
+ aggregate is planned as a DELTA (delta-design: ADDED / MODIFIED / REMOVED sections) in
382
+ the change's own directory, never as a new design doc. Newest last.
413
383
  -->
414
384
 
415
- | Version | Date | Change |
416
- |---------|------|--------|
417
- | v1.0 | [DATE] | Initial design |
385
+ | Version | Date | Change | User stories | CR |
386
+ |---------|------|--------|--------------|-----|
387
+ | v1.0 | [DATE] | Initial design | US-1 | — |
@@ -0,0 +1,130 @@
1
+ # Domain Model — [BOUNDED CONTEXT]
2
+
3
+ **Bounded context**: `[Context]`
4
+
5
+ **Model home**: `specs/[Context]/domain-model.md`
6
+
7
+ **Context version**: v1.0 <!-- script-stamped; close-delta bumps it when a closing delta touched the model -->
8
+
9
+ <!--
10
+ THE CANONICAL DOMAIN MODEL FOR THIS BOUNDED CONTEXT. The aggregate root lives HERE
11
+ and nowhere else — not in any spec.md. Every spec in specs/[Context]/ REFERENCES the
12
+ aggregates, entities and invariants below by name and id, and never restates them.
13
+
14
+ Why here and not in the spec: an aggregate root is a fact about the CONTEXT, not about
15
+ one feature. Aggregates are referenced across specs, and a per-spec copy of the same
16
+ root drifts — two specs end up asserting different invariants for one aggregate and
17
+ nothing arbitrates. One home means there is nothing to arbitrate.
18
+
19
+ This document is AUTHORED, not derived. It legitimately holds things no single spec
20
+ states: cross-aggregate invariants, the context map, and aggregates that exist for
21
+ consistency reasons alone.
22
+
23
+ WRITERS, in order:
24
+ • specify (first run in this context) — creates it and models the first aggregate(s).
25
+ • specify (later runs) — writes specs/[Context]/domain-model.<CR-id>.delta.md instead;
26
+ the master is untouched while a change is open.
27
+ • finalize-delta — merges a delta into this file, ONE `## Aggregate:` SECTION AT A TIME.
28
+ • close-delta — stamps the context version and appends the Change History row.
29
+ plan / implement READ this file and never write it. It is technology-agnostic: no
30
+ language, no persistence, no framework. Where an invariant is ENFORCED is a plan
31
+ concern and is recorded in backend-plan.md, never here.
32
+
33
+ MERGE UNIT = one `## Aggregate: <Name>` section. Two open deltas touching DIFFERENT
34
+ aggregates never collide; two touching the SAME one are a real semantic conflict and
35
+ are gated rather than silently merged.
36
+ -->
37
+
38
+ ## Ubiquitous Language
39
+
40
+ <!--
41
+ ACTION REQUIRED: the terms this context uses, and what each means HERE. The same word
42
+ can mean something different in another context — that is the point of the boundary.
43
+ Every spec, plan and test in specs/[Context]/ uses these terms and no synonyms.
44
+ -->
45
+
46
+ | Term | Means in this context | Not to be confused with |
47
+ |---|---|---|
48
+ | [Order] | [a customer's committed request for goods] | [Cart — uncommitted, in the Sales context] |
49
+
50
+ ## Aggregate: [Root]
51
+
52
+ <!--
53
+ ONE SECTION PER AGGREGATE ROOT. This is the merge unit — repeat the whole block for
54
+ each root. `Serving specs` lists the features whose spec.md references this aggregate;
55
+ it is what makes a cross-spec aggregate visible from the model side.
56
+ -->
57
+
58
+ **Serving specs**: `[Feature]`, `[OtherFeature]` <!-- features that reference this aggregate -->
59
+
60
+ **Last changed**: v1.0 · [CR-ID or "initial"]
61
+
62
+ ### Boundary
63
+
64
+ - **Owns**: [entities/behaviour inside the consistency boundary — e.g. Order, OrderLine]
65
+ - **References (by id, not owned)**: [CustomerId, ProductId — no navigable link]
66
+ - **Out of scope / non-goals**: [explicitly excluded — e.g. payment settlement]
67
+
68
+ ### Entities
69
+
70
+ - **[Root — e.g. Order]** *(aggregate root)*: [what it represents; key attributes; lifecycle/states, e.g. Draft → Submitted → Fulfilled]
71
+ - **[Entity — e.g. OrderLine]**: [what it represents; relationship to the root]
72
+
73
+ ### Value objects
74
+
75
+ - **[VO — e.g. Money]**: [what it represents; why it has no identity]
76
+
77
+ ### Domain events
78
+
79
+ | Event | Raised by | Trigger | Key payload |
80
+ |---|---|---|---|
81
+ | `[OrderSubmitted]` | `[Order]` | [what causes it] | `[orderId, total]` |
82
+
83
+ ### Invariants
84
+
85
+ <!--
86
+ ACTION REQUIRED: constraints that must ALWAYS hold for this aggregate, independent of
87
+ any single operation. STABLE ids (BR-nnn) — specs cite these ids and never restate the
88
+ rule. An invariant belongs to the aggregate, and the aggregate belongs to the context,
89
+ which is why it is defined here rather than in any one spec.
90
+ -->
91
+
92
+ - **BR-001**: [An order's total MUST never be negative.]
93
+ - **BR-002**: [A submitted order MUST always have at least one line item.]
94
+
95
+ ## Cross-Aggregate Invariants
96
+
97
+ <!--
98
+ Rules that span two or more aggregates in this context, and therefore belong to no
99
+ single spec and no single aggregate section. Eventually-consistent by nature — an
100
+ aggregate is the transaction boundary, so a rule crossing one cannot be enforced
101
+ atomically. State the rule and how convergence is expected, never the mechanism.
102
+ "None (as of v1.0)" when there are none — never delete the section.
103
+ -->
104
+
105
+ - **XBR-001**: [A Customer's credit exposure across all open Orders MUST NOT exceed their limit. Converges on OrderSubmitted.]
106
+
107
+ ## Context Map
108
+
109
+ <!--
110
+ This context's relationships to OTHER bounded contexts: upstream/downstream direction,
111
+ and the pattern (customer-supplier, conformist, anti-corruption layer, shared kernel,
112
+ published language). References across a context boundary are ALWAYS by id.
113
+ "None (as of v1.0)" while this is the only context.
114
+ -->
115
+
116
+ | Other context | Direction | Pattern | What crosses |
117
+ |---|---|---|---|
118
+ | [Billing] | downstream | [customer-supplier] | [OrderSubmitted event; OrderId] |
119
+
120
+ ## Change History
121
+
122
+ <!--
123
+ The model's living-truth ledger. close-delta appends a row when a closing delta touched
124
+ this model, carrying the context version it ships as and the aggregate it changed.
125
+ The model never writes its own version — scripts stamp it. Newest last.
126
+ -->
127
+
128
+ | Context version | Date | Aggregate | Change | Feature | CR |
129
+ |---|---|---|---|---|---|
130
+ | v1.0 | [DATE] | [Root] | Initial model | [Feature] | — |
@@ -76,7 +76,7 @@ ui_source_files:
76
76
 
77
77
  <!--
78
78
  2–4 sentences: the aggregate root, what it guards, its transaction boundary.
79
- Greenfield: distilled from design.md §1 (Domain Model). Brownfield: from the
79
+ Greenfield: distilled from the context's domain-model.md. Brownfield: from the
80
80
  reverse-engineered spec/design. Prose only — the edges live in the two tables below.
81
81
  -->
82
82
 
@@ -86,7 +86,7 @@ ui_source_files:
86
86
 
87
87
  <!--
88
88
  FORWARD edges — the sibling aggregates THIS one references. Derived DETERMINISTICALLY
89
- from design.md §1 — the model section, "References (by id, not owned)" — plus its
89
+ from domain-model.md — the aggregate's Boundary block, "References (by id, not owned)" — plus its
90
90
  External integrations table (Integration Contracts), kept
91
91
  to targets that are real project aggregates (a specs/<Target>/ or an existing concept).
92
92
  This is the PRUNE INDEX: reconcile-on-write reads it to find where this slice wrote, so
@@ -6,7 +6,7 @@
6
6
 
7
7
  **Origin**: `reverse-engineered` <!-- greenfield | reverse-engineered | migrated -->
8
8
 
9
- **Version**: v1.0 <!-- moves in lockstep with spec.md / design.md -->
9
+ **Version**: v1.0 <!-- moves in lockstep with spec.md / backend-plan.md -->
10
10
 
11
11
  **Baseline commit**: `[short-sha]` <!-- the inventory HEAD this slice was adopted from -->
12
12
 
@@ -23,10 +23,10 @@
23
23
 
24
24
  LegacyArtefact ↔ FR/BR/US ↔ Spec-section ↔ Design-element ↔ Code ↔ Commit
25
25
 
26
- This is a SIDECAR: spec.md and design.md stay clean, forward-loop documents
26
+ This is a SIDECAR: spec.md and backend-plan.md stay clean, forward-loop documents
27
27
  (the CR delta loop + forward pipeline consume them unchanged). The brownfield
28
28
  provenance lives HERE and in the `origin:` frontmatter — never as extra
29
- structure inside spec.md / design.md.
29
+ structure inside spec.md / backend-plan.md.
30
30
 
31
31
  CONFIDENCE travels with each row: `certain` (the code states it outright) vs
32
32
  `inferred` (reverse-engineering had to reason). Inferred rows are the Adopt