aw-spec-cli 0.1.18 → 0.1.20
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/assets/.appweaver/DESIGN-FORMAT.md +63 -31
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +62 -14
- package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +10 -6
- package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +9 -1
- package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +21 -0
- package/assets/.appweaver/orchestrator/orchestrator.py +23 -1
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +22 -13
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +6 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +399 -131
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +199 -38
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +159 -25
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +20 -9
- package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +183 -40
- package/assets/.appweaver/orchestrator/workflows/aw-spec-deploy.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +311 -36
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +221 -40
- package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +217 -174
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +494 -109
- package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +83 -18
- package/assets/.appweaver/orchestrator/workflows/aw-spec-recall-delta.orch.yaml +319 -0
- package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +29 -23
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +143 -34
- package/assets/.appweaver/scripts/bash/aw-inventory.sh +15 -0
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +878 -51
- package/assets/.appweaver/scripts/bash/aw-xref.sh +3 -0
- package/assets/.appweaver/scripts/bash/common.sh +28 -1
- package/assets/.appweaver/scripts/powershell/aw-inventory.ps1 +15 -0
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +868 -51
- package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +3 -0
- package/assets/.appweaver/scripts/python/aw-inventory.py +1832 -65
- package/assets/.appweaver/scripts/python/aw-xref.py +500 -81
- package/assets/.appweaver/templates/delta-design-template.md +1 -1
- package/assets/.appweaver/templates/delta-domain-model-template.md +1 -1
- package/assets/.appweaver/templates/delta-spec-template.md +4 -3
- package/assets/.appweaver/templates/design-template.md +56 -40
- package/assets/.appweaver/templates/okf-concept-template.md +11 -1
- package/assets/.appweaver/templates/proposed-inventory-template.md +127 -0
- package/assets/.appweaver/templates/source-map-template.md +5 -3
- package/assets/.appweaver/templates/spec-template.md +24 -21
- package/assets/.appweaver/templates/ui-delta-design-template.md +1 -1
- package/assets/.appweaver/templates/ui-design-template.md +11 -7
- package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.pack.txt +4489 -361
- package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.pack.txt +2274 -125
- package/assets/guardrails/domain/healthcare/auditing.domain.md +3 -3
- package/assets/guardrails/domain/pharma/auditing.domain.md +3 -3
- package/assets/guardrails/technology/dotnet-webapi/api-versioning.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/auditing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/authorization.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/clean-architecture.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/cqrs.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/data-classification.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/eventing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/modular-monolith.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/persistence.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/vertical-slices.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/zero-trust.md +1 -1
- package/assets/guardrails/technology/nextjs/accessibility-implementation.md +1 -1
- package/assets/guardrails/technology/nextjs/api-integration.dotnet-webapi.md +1 -1
- package/assets/guardrails/technology/nextjs/api-integration.java-spring.md +1 -1
- package/assets/guardrails/technology/nextjs/auth-session.md +1 -1
- package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
- package/assets/guardrails/technology/nextjs/design-system.md +1 -1
- package/assets/guardrails/technology/nextjs/error-handling.md +1 -1
- package/assets/guardrails/technology/nextjs/forms-and-validation.md +1 -1
- package/assets/guardrails/technology/nextjs/i18n.md +1 -1
- package/assets/guardrails/technology/nextjs/performance-budgets.md +1 -1
- package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
- package/assets/guardrails/technology/nextjs/state-management.md +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Bounded context**: `[Context]`
|
|
4
4
|
|
|
5
|
-
**Feature
|
|
5
|
+
**Feature**: `[Feature]` <!-- the feature whose change this is; the aggregates it changes are listed under "Aggregates touched" -->
|
|
6
6
|
|
|
7
7
|
**Wave**: [N] <!-- script-stamped; same wave = developable in parallel, higher wave = after -->
|
|
8
8
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Delta Spec — [CR-ID]: [TITLE]
|
|
2
2
|
|
|
3
|
-
**Feature
|
|
3
|
+
**Feature**: [Feature]
|
|
4
4
|
|
|
5
5
|
**Change type**: [new-requirement | changed-requirement | defect | refactor]
|
|
6
6
|
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
Standards (UX-n). A CR that changes a retention/audit rule, a data-exposure rule, an
|
|
22
22
|
interop obligation or a project-wide experience standard is a CN-/DC-/IC-/UX- delta, not
|
|
23
23
|
a smuggled code change. A UX- delta states the standard only — never a screen, page or
|
|
24
|
-
component, which the prototype and frontend-plan.md settle. Adding a command
|
|
25
|
-
UpdateOrder to
|
|
24
|
+
component, which the prototype and frontend-plan.md settle. Adding a command to THIS
|
|
25
|
+
feature (e.g. UpdateOrder to Order) is a new user story (US-n). Whether a capability is
|
|
26
|
+
a feature of its own is the developer's decision, made when they select the feature.
|
|
26
27
|
|
|
27
28
|
MODEL CHANGES DO NOT BELONG HERE. A new entity, a changed aggregate boundary or a new
|
|
28
29
|
or amended invariant (BR-n) goes in this change's domain-model delta — the "Model delta"
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
# Backend Plan: [
|
|
1
|
+
# Backend Plan: [FEATURE]
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Feature**: `[Feature]` <!-- the capability scope the developer chose; the aggregate(s) it acts on are the spec's "Acts on aggregate(s)" line -->
|
|
4
4
|
|
|
5
|
-
**Plan home**: `specs/[
|
|
5
|
+
**Plan home**: `specs/[Context]/[Feature]/backend-plan.md`
|
|
6
6
|
|
|
7
|
-
**Source spec**: `specs/[
|
|
7
|
+
**Source spec**: `specs/[Context]/[Feature]/spec.md` <!-- behaviour: what the system must DO -->
|
|
8
|
+
|
|
9
|
+
**Source model**: `specs/[Context]/domain-model.md` <!-- structure: what the domain IS -->
|
|
8
10
|
|
|
9
11
|
**Version**: v1.0 <!-- moves in lockstep with the spec; every applied change request bumps this — see Change History -->
|
|
10
12
|
|
|
@@ -13,29 +15,40 @@
|
|
|
13
15
|
<!--
|
|
14
16
|
WHAT THIS DOCUMENT IS
|
|
15
17
|
=====================
|
|
16
|
-
The single, living High-Level Design (HLD) for ONE
|
|
18
|
+
The single, living High-Level Design (HLD) for ONE feature — the capability scope
|
|
19
|
+
the developer chose, over the aggregate(s) its spec says it acts on. It is the
|
|
17
20
|
MEDIATOR between spec.md (WHAT/WHY, tech-agnostic) and the generated code
|
|
18
21
|
(HOW, tech-specific). It is NOT code: it carries structure, contracts,
|
|
19
22
|
behaviour, and decisions — enough for ANY capable LLM to generate correct,
|
|
20
23
|
spec-satisfying code on ANY target stack, but no complete method bodies.
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
(
|
|
25
|
+
domain-model.md ─┐
|
|
26
|
+
structure ├─▶ backend-plan.md ──▶ code (+ tests)
|
|
27
|
+
(BR-nnn) │ structure & generated by `implement`
|
|
28
|
+
spec.md ──┘ decisions (HLD) (stack-bound at generation time)
|
|
29
|
+
behaviour
|
|
30
|
+
(FR/US/SC/CN/DC/IC)
|
|
25
31
|
|
|
26
32
|
ANCHORING RULES
|
|
27
|
-
- Every design element traces UP to
|
|
28
|
-
the
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
- Every design element traces UP to an id — behaviour ids (FR-/US-/SC-/CN-/DC-/IC-)
|
|
34
|
+
from the spec, invariant ids (BR-) from the context's domain-model.md — and the
|
|
35
|
+
whole spec is covered DOWN here (see §6 Traceability). No design element without
|
|
36
|
+
a reason in one of those two; no spec requirement without a design home.
|
|
37
|
+
- TWO AUTHORITIES, NOT ONE. Structure comes from the MODEL, behaviour from the SPEC.
|
|
38
|
+
domain-model.md fixes the aggregate's entities, value objects, boundary and
|
|
39
|
+
invariants; spec.md says what the system must DO with them and cites each invariant
|
|
40
|
+
by id. Design reads BOTH, plus the technical/architecture standards — but NOT the
|
|
41
|
+
domain rule files: a domain rule reaches this doc only as an id already lifted into
|
|
42
|
+
one of the two (BR- in the model; CN-/DC-/IC- in the spec). Realise each of those;
|
|
43
|
+
invent no entity, value object or rule that neither states (if one seems missing,
|
|
44
|
+
record it as an Assumption in §7, never smuggle it in).
|
|
45
|
+
- One feature = one backend-plan.md. A feature is the capability scope the developer
|
|
46
|
+
chose: it may act on several aggregates, and several features may act on one. Its
|
|
47
|
+
operations (CreateOrder, UpdateOrder…) are USER STORIES here, and a later requirement
|
|
48
|
+
on this feature is a delta on THIS doc, never a new one. An aggregate's shared code
|
|
49
|
+
(its root, entities, value objects, repository) is realised by every plan whose
|
|
50
|
+
feature acts on it: each plan names only the members its feature needs, and the
|
|
51
|
+
code extends the shared file instead of regenerating it.
|
|
39
52
|
|
|
40
53
|
WHAT LIVES ELSEWHERE (do NOT repeat it here — it is identical for every feature)
|
|
41
54
|
- The clean-architecture layering + dependency rule (API → Application → Domain
|
|
@@ -68,13 +81,13 @@
|
|
|
68
81
|
## 0. Design Overview
|
|
69
82
|
|
|
70
83
|
<!--
|
|
71
|
-
One paragraph: the architectural shape of this
|
|
84
|
+
One paragraph: the architectural shape of this feature and the 3–5 decisions
|
|
72
85
|
that matter most (why this boundary, the lifecycle model, the hardest trade-off).
|
|
73
86
|
This is the orientation a reviewer or an LLM reads first. The standing layering /
|
|
74
87
|
dependency rule is NOT restated here — it is the project architecture standard.
|
|
75
88
|
-->
|
|
76
89
|
|
|
77
|
-
[The architectural essence of this
|
|
90
|
+
[The architectural essence of this feature in 3–6 sentences: its purpose, its
|
|
78
91
|
lifecycle spine, the key structural choices specific to it, and the single biggest
|
|
79
92
|
trade-off. Layering follows the project architecture standard (constitution).]
|
|
80
93
|
|
|
@@ -111,9 +124,11 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
111
124
|
performance-as-a-limit land in §4 Infra / §5 Cross-Cutting.)
|
|
112
125
|
You MAY add design-level structure — domain events, state machines, behaviour
|
|
113
126
|
signatures — but ONLY to REALISE spec behaviour. Do NOT invent an entity, value
|
|
114
|
-
object, or
|
|
115
|
-
|
|
116
|
-
|
|
127
|
+
object, or invariant THE MODEL does not define, do NOT invent behaviour THE SPEC
|
|
128
|
+
does not state, and do NOT contradict either. If a genuinely new concept is
|
|
129
|
+
unavoidable, record it as an Assumption (§7, DA-n) and flag it — never smuggle it
|
|
130
|
+
in: a missing entity or invariant is a gap in the model, which /appweaver specify
|
|
131
|
+
owns and this document may not close. Pure business model: no framework, no persistence, no I/O.
|
|
117
132
|
Model this section on a rich DDD reference (entities, VOs, events, state machines,
|
|
118
133
|
invariants, behaviours). Repeat the blocks as the aggregate needs.
|
|
119
134
|
-->
|
|
@@ -138,7 +153,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
138
153
|
<!--
|
|
139
154
|
Per entity: attributes (conceptual types), lifecycle state machine if it has one,
|
|
140
155
|
behaviours as SIGNATURE + pre/post/invariant/raises pseudocode (the most LLM-guidable,
|
|
141
|
-
stack-neutral form), and the invariants it enforces (each = a
|
|
156
|
+
stack-neutral form), and the invariants it enforces (each = a BR-nnn THE MODEL defines).
|
|
142
157
|
-->
|
|
143
158
|
|
|
144
159
|
#### `[Entity]` [(Aggregate Root)]
|
|
@@ -162,13 +177,14 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
162
177
|
```
|
|
163
178
|
[Entity].[Behaviour]([params])
|
|
164
179
|
Pre-condition: [required state / inputs]
|
|
165
|
-
Invariant: [what must hold — maps to a
|
|
180
|
+
Invariant: [what must hold — maps to a BR-nnn in the domain model]
|
|
166
181
|
Post-condition: [resulting state / outputs]
|
|
167
182
|
Raises: [DomainEvent]
|
|
168
183
|
Serves: FR-00X · US-Y · BR-00Z
|
|
169
184
|
```
|
|
170
185
|
|
|
171
|
-
**Invariants** *(always-true; each
|
|
186
|
+
**Invariants** *(always-true; each cites a BR-nnn the domain model defines — never restate its
|
|
187
|
+
text, and do not add a rule the model does not carry)*
|
|
172
188
|
|
|
173
189
|
- [Invariant statement] — **BR-00X**
|
|
174
190
|
|
|
@@ -287,7 +303,7 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
287
303
|
|
|
288
304
|
### 4.3 Wiring & migrations
|
|
289
305
|
|
|
290
|
-
- **Composition**: bind `[Port] → [Adapter]` for this
|
|
306
|
+
- **Composition**: bind `[Port] → [Adapter]` for this feature.
|
|
291
307
|
- **Migrations needed**: [yes → what changes conceptually / no]. The Run phase applies them.
|
|
292
308
|
|
|
293
309
|
## 5. Cross-Cutting Concerns
|
|
@@ -320,22 +336,22 @@ trade-off. Layering follows the project architecture standard (constitution).]
|
|
|
320
336
|
|
|
321
337
|
<!--
|
|
322
338
|
The two-way guarantee: every FR/BR/CN/DC/IC/US/SC has a design home, and every
|
|
323
|
-
design element has a
|
|
324
|
-
the analyze gate verify coverage. Keep it complete — EVERY CN-/DC-/IC- in the spec
|
|
339
|
+
design element has a reason in one of the two authorities. This is what makes impact
|
|
340
|
+
analysis exact and lets the analyze gate verify coverage. Keep it complete — EVERY CN-/DC-/IC- in the spec
|
|
325
341
|
MUST appear as a row here (that is how the analyze gate proves no lifted constraint
|
|
326
342
|
was dropped). The Domain rows MUST match the domain model's entities and BR-nnn
|
|
327
343
|
invariants exactly.
|
|
328
344
|
-->
|
|
329
345
|
|
|
330
|
-
|
|
|
331
|
-
|
|
332
|
-
| FR-001 | requirement | `[Root].[Behaviour]`, `[Command]`, `[VERB /route]` | Domain·App·API |
|
|
333
|
-
| BR-001 | invariant | `[Root]` invariant / `[VO]` validation | Domain |
|
|
334
|
-
| CN-001 | constraint | [where realised — §1 invariant / §4 persistence / §5 cross-cutting] | [layer] |
|
|
335
|
-
| DC-001 | classification | [exposure enforcement — §2 projection / §5 data-protection] | App·Infra |
|
|
336
|
-
| IC-001 | contract | [adapter/port realising it — §4.2] | Infra |
|
|
337
|
-
| US-1 | story | [end-to-end elements realising it] | all |
|
|
338
|
-
| SC-001 | success | [where it is met + how verified] | [layer] |
|
|
346
|
+
| Id | Source | Type | Design element(s) | Layer |
|
|
347
|
+
|---|---|---|---|---|
|
|
348
|
+
| FR-001 | spec | requirement | `[Root].[Behaviour]`, `[Command]`, `[VERB /route]` | Domain·App·API |
|
|
349
|
+
| BR-001 | model | invariant | `[Root]` invariant / `[VO]` validation | Domain |
|
|
350
|
+
| CN-001 | spec | constraint | [where realised — §1 invariant / §4 persistence / §5 cross-cutting] | [layer] |
|
|
351
|
+
| DC-001 | spec | classification | [exposure enforcement — §2 projection / §5 data-protection] | App·Infra |
|
|
352
|
+
| IC-001 | spec | contract | [adapter/port realising it — §4.2] | Infra |
|
|
353
|
+
| US-1 | spec | story | [end-to-end elements realising it] | all |
|
|
354
|
+
| SC-001 | spec | success | [where it is met + how verified] | [layer] |
|
|
339
355
|
|
|
340
356
|
## 7. Assumptions (to clarify later)
|
|
341
357
|
|
|
@@ -3,6 +3,8 @@ type: aggregate
|
|
|
3
3
|
title: [Aggregate]
|
|
4
4
|
description: [one line — what this aggregate is and the invariant/boundary it guards]
|
|
5
5
|
origin: greenfield
|
|
6
|
+
bounded_context:
|
|
7
|
+
features:
|
|
6
8
|
source_files:
|
|
7
9
|
ui_source_files:
|
|
8
10
|
---
|
|
@@ -17,8 +19,16 @@ ui_source_files:
|
|
|
17
19
|
as it generates the aggregate's code;
|
|
18
20
|
• brownfield — `inventory` seeds it and `adopt` enriches it.
|
|
19
21
|
|
|
22
|
+
A CONCEPT IS AN AGGREGATE, NEVER A FEATURE. A feature is a capability scope the
|
|
23
|
+
developer chose; it may act on several aggregates, and several features may act on
|
|
24
|
+
one. `features:` lists every feature known to act on this aggregate — implement and
|
|
25
|
+
adopt add their feature, and a feature is never removed from it by a later write.
|
|
26
|
+
`bounded_context:` names the context the aggregate belongs to.
|
|
27
|
+
|
|
20
28
|
WHO WRITES WHAT (do not cross these lanes):
|
|
21
|
-
• Frontmatter, Overview, Depends-On →
|
|
29
|
+
• Frontmatter, Overview, Depends-On → the implement/adopt of every feature that
|
|
30
|
+
acts on this aggregate. Depends-On is the
|
|
31
|
+
union over all of them.
|
|
22
32
|
• Cross-References → the OTHER aggregates that USE this one; each
|
|
23
33
|
writes its own row (never hand-edit them here).
|
|
24
34
|
One addition inside the first lane: `analyze-slice` MERGES (never replaces) the files its
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Proposed Inventory
|
|
2
|
+
|
|
3
|
+
<!-- TEMPLATE-NOTE
|
|
4
|
+
This is the TEMPLATE for the document `/appweaver inventory` generates at
|
|
5
|
+
specs/proposed-inventory.md. Every TEMPLATE-NOTE block is stripped on generation,
|
|
6
|
+
so nothing in here reaches the produced file.
|
|
7
|
+
|
|
8
|
+
UNLIKE EVERY OTHER TEMPLATE IN THIS DIRECTORY, THIS ONE IS FILLED BY A SCRIPT,
|
|
9
|
+
NOT BY AN AGENT. aw-inventory.py substitutes each token below with the result of
|
|
10
|
+
its scan. There are no [PLACEHOLDER] tokens for an author to complete — a token
|
|
11
|
+
left in the output is a bug, not an unfinished section.
|
|
12
|
+
|
|
13
|
+
Override it per project at
|
|
14
|
+
.appweaver/templates/overrides/proposed-inventory-template.md to change the
|
|
15
|
+
wording, the ordering or the guidance. Keep every token you want filled; drop
|
|
16
|
+
one and that section simply does not appear.
|
|
17
|
+
|
|
18
|
+
Tokens, each written in single braces:
|
|
19
|
+
root · head · date · strategy · reason · files · code · coverage
|
|
20
|
+
probe_table · context_table · feature_table
|
|
21
|
+
splits_section · cycles_section
|
|
22
|
+
-->
|
|
23
|
+
<!-- Generated by `/appweaver inventory`. Edit freely, then run
|
|
24
|
+
`/appweaver inventory apply`. -->
|
|
25
|
+
|
|
26
|
+
**Repository:** `{root}` · **Commit:** `{head}` · **Generated:** {date}
|
|
27
|
+
**Pass A strategy:** `{strategy}` — {reason}
|
|
28
|
+
**Scanned:** {files} files, {code} source files · **Coverage:** {coverage}%
|
|
29
|
+
|
|
30
|
+
This file is the **boundary map for this codebase, and it is yours to change.** Nothing
|
|
31
|
+
below was decided by a person yet — it is what a deterministic scan of the source
|
|
32
|
+
proposes. Read it, correct it, then run `/appweaver inventory apply`, which validates
|
|
33
|
+
your edits and regenerates the machine map that `/appweaver onboard` reads.
|
|
34
|
+
|
|
35
|
+
## How to edit this file
|
|
36
|
+
|
|
37
|
+
- **Rename** a feature or a bounded context by editing its cell. Names are the
|
|
38
|
+
identity — renaming a feature here renames the slice onboard will create.
|
|
39
|
+
- **Move** a feature to another context by editing its Bounded Context cell.
|
|
40
|
+
A feature lives in exactly one context.
|
|
41
|
+
- **Merge** two features by giving them the same name; their files combine, and the
|
|
42
|
+
merged feature acts on every aggregate its rows name — that is how one feature spans
|
|
43
|
+
several aggregates. Keep those rows in the same Bounded Context.
|
|
44
|
+
- **Split** a feature by adding a row with the same Aggregate and a different
|
|
45
|
+
Feature name. Name the split from the capability, not the noun —
|
|
46
|
+
`PatientRegistration`, not a second `Patient`.
|
|
47
|
+
- **Reorder** by editing Depends On. Waves are recomputed on apply, so you do
|
|
48
|
+
not maintain wave numbers by hand.
|
|
49
|
+
- Rows you delete are dropped from the map and never onboarded.
|
|
50
|
+
|
|
51
|
+
The Aggregate column must name an aggregate the scan found; everything else is
|
|
52
|
+
yours. `apply` reports anything it cannot resolve rather than guessing.
|
|
53
|
+
|
|
54
|
+
## How these boundaries were found
|
|
55
|
+
|
|
56
|
+
Three passes over the source. None of them reads a specification, a rule file or an
|
|
57
|
+
exemplar from another project — the code is the only evidence.
|
|
58
|
+
|
|
59
|
+
**Pass A — what must stay consistent together.** Groups the source into candidate
|
|
60
|
+
aggregates. Three strategies can do this, and only those the evidence supports are
|
|
61
|
+
offered:
|
|
62
|
+
|
|
63
|
+
| strategy | the evidence it reads | available when |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `structure` | the repo's own organising axis — a vertical slice, a layer folder under a module, a layer carried as a project-name suffix, or a layer at the top with the module repeated as a noun | always |
|
|
66
|
+
| `reference` | the `using` / `import` / `require` graph, clustered after removing the high-fan-in nodes that are shared kernel rather than features | enough import-parseable source |
|
|
67
|
+
| `persistence` | the schema itself — `DbSet<T>`, `[Table]`, JPA `@Entity`, `schema.prisma`, `CREATE TABLE` — with roots derived by ownership: an entity that owns others' lifecycles and is referenced from outside by id | ORM / schema / migration evidence found |
|
|
68
|
+
|
|
69
|
+
`structure` always runs whichever strategy is chosen, because the other two produce
|
|
70
|
+
unnamed clusters and need it to give each one a directory and a human name.
|
|
71
|
+
|
|
72
|
+
**Pass B — what can be cut over together.** Reads the application, API and UI surface
|
|
73
|
+
only, and emits *signals*, never decisions: route families (`[Route("orders")]`,
|
|
74
|
+
`@RequestMapping`, `app.get('/orders/…')`), command/handler groups, UI router segments,
|
|
75
|
+
and rates of change from git history. **Two distinct route families on one aggregate is
|
|
76
|
+
a split candidate** — proposed below, never applied.
|
|
77
|
+
|
|
78
|
+
Three of the five tests for a feature boundary are computable — one cutover seam,
|
|
79
|
+
stable file ownership, one bounded context — and two are not: whether it serves one
|
|
80
|
+
business need, and whether it can be demonstrated independently. Those two are why this
|
|
81
|
+
file is editable.
|
|
82
|
+
|
|
83
|
+
**Pass C — the proposal.** One aggregate becomes one feature with the same name. That
|
|
84
|
+
is the default and not a failure. A split is proposed only where Pass B found the
|
|
85
|
+
evidence, and is shown with that evidence for you to accept or ignore. One endpoint is
|
|
86
|
+
never a feature; neither is one whole bounded context.
|
|
87
|
+
|
|
88
|
+
**Bounded contexts** are derived above Pass A and voted from where each candidate's
|
|
89
|
+
files actually live. A feature belongs to exactly one context — the context of the
|
|
90
|
+
primary aggregate it acts on. A feature that needs another context's aggregate
|
|
91
|
+
references it by id and stays a separate feature over there.
|
|
92
|
+
|
|
93
|
+
## Strategy probe
|
|
94
|
+
|
|
95
|
+
The clustering each available strategy produced on this tree. The chosen one is
|
|
96
|
+
marked; re-run with `--strategy <name>` to pick another.
|
|
97
|
+
|
|
98
|
+
{probe_table}
|
|
99
|
+
|
|
100
|
+
## Bounded Contexts
|
|
101
|
+
|
|
102
|
+
Onboard one context at a time, in this order. A context is ready when every context it
|
|
103
|
+
depends on has been onboarded.
|
|
104
|
+
|
|
105
|
+
{context_table}
|
|
106
|
+
|
|
107
|
+
## Features
|
|
108
|
+
|
|
109
|
+
Dependency order. **Wave 0 depends on nothing** and can be onboarded first; a feature in
|
|
110
|
+
wave N depends only on features in earlier waves. Edit any cell except Wave, which is
|
|
111
|
+
recomputed.
|
|
112
|
+
|
|
113
|
+
{feature_table}
|
|
114
|
+
{splits_section}{cycles_section}
|
|
115
|
+
## What happens after you apply this
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
/appweaver inventory apply validates these edits, regenerates the machine map
|
|
119
|
+
/appweaver onboard <Context> once per context, in the order above:
|
|
120
|
+
reverse-engineers the governance and creates
|
|
121
|
+
specs/<Context>/<Feature>/ for each feature
|
|
122
|
+
/appweaver adopt <Feature> just-in-time, per feature: reverse-engineers its
|
|
123
|
+
spec, plans and domain-model section
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Re-running `/appweaver inventory` re-derives this file from the code and **discards
|
|
127
|
+
your edits** — apply them first. Re-running `apply` is safe and idempotent.
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
# Source Map: [
|
|
1
|
+
# Source Map: [FEATURE]
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Feature**: `[Feature]` <!-- the capability scope confirmed in the boundary map, e.g. MedicinalProduct or PatientRegistration -->
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**Acts on aggregate(s)**: `[Aggregate]` <!-- the same names the spec's Domain Model Reference gives -->
|
|
6
|
+
|
|
7
|
+
**Source home**: `specs/[Context]/[Feature]/source-map.md`
|
|
6
8
|
|
|
7
9
|
**Origin**: `reverse-engineered` <!-- greenfield | reverse-engineered | migrated -->
|
|
8
10
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Specification: [
|
|
1
|
+
# Specification: [FEATURE]
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Feature**: `[Feature]` <!-- the capability scope the developer chose, e.g. Order or PatientRegistration; the aggregate(s) it acts on are named under Domain Model Reference -->
|
|
4
4
|
|
|
5
|
-
**Spec home**: `specs/[
|
|
5
|
+
**Spec home**: `specs/[Context]/[Feature]/`
|
|
6
6
|
|
|
7
7
|
**Version**: v1.0 <!-- living truth; every applied change request bumps this — see Change History -->
|
|
8
8
|
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
and is referenced from here by name and id. That split is what lets one aggregate be
|
|
18
18
|
acted on by several specs without any of them owning its definition.
|
|
19
19
|
|
|
20
|
-
Every operation
|
|
21
|
-
|
|
20
|
+
Every operation within this feature's scope (CreateOrder, UpdateOrder, …) is a USER
|
|
21
|
+
STORY below. A later requirement on this feature is a new US-n added as a delta (see
|
|
22
22
|
delta-spec-template.md), never a new spec folder. One spec + one plan per declared
|
|
23
23
|
lane — the PLAN derives from this document and the domain model together.
|
|
24
24
|
|
|
25
25
|
Section order is intentional: establish the business need and scope, then the stable
|
|
26
|
-
core the
|
|
26
|
+
core the feature's BEHAVIOUR is (requirements → constraints → data classification →
|
|
27
27
|
integration contracts → experience standards → edge cases), then the prioritized user
|
|
28
28
|
journeys that exercise it, then measurable success.
|
|
29
29
|
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
## Business Need
|
|
40
40
|
|
|
41
41
|
<!--
|
|
42
|
-
ACTION REQUIRED: Why this
|
|
42
|
+
ACTION REQUIRED: Why this feature exists — the problem, the affected users,
|
|
43
43
|
and the value delivered. Business-facing; no implementation detail.
|
|
44
44
|
-->
|
|
45
45
|
|
|
46
|
-
[The problem this
|
|
46
|
+
[The problem this feature solves, who it serves, and the value it delivers.]
|
|
47
47
|
|
|
48
48
|
## Scope & Assumptions
|
|
49
49
|
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
### Experience Scope
|
|
84
84
|
|
|
85
85
|
<!--
|
|
86
|
-
The experience envelope this
|
|
86
|
+
The experience envelope this feature is specified against: WHO reaches it through a
|
|
87
87
|
UI, THROUGH WHAT, and the floor the frontend lane has to hold. Scope, not requirement —
|
|
88
88
|
it bounds what the Experience Standards and the prototype are held to, and it is the
|
|
89
89
|
only place the spec describes the delivery surface at all.
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
surface to bound: write "None (as of vX.Y)" — never delete the section.
|
|
98
98
|
-->
|
|
99
99
|
|
|
100
|
-
- **Actors**: [the user roles that reach this
|
|
100
|
+
- **Actors**: [the user roles that reach this feature through a UI — e.g. clinician, scheduler; distinct from a system/API caller]
|
|
101
101
|
- **Channels**: [where the experience is delivered — e.g. responsive web; internal back-office only]
|
|
102
102
|
- **Device / viewport floor**: [the smallest supported surface — e.g. 360 px wide]
|
|
103
103
|
- **Browser / platform floor**: [the oldest supported targets — e.g. the last two major versions of evergreen browsers]
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
|
|
131
131
|
<!--
|
|
132
132
|
ACTION REQUIRED (when the domain applies; else "None (as of vX.Y)"). Constraints the
|
|
133
|
-
|
|
133
|
+
feature MUST satisfy that are NEITHER functional behaviour (those are FR) NOR
|
|
134
134
|
always-true business invariants (those are BR): the regulatory, retention,
|
|
135
135
|
immutability, audit-mandate, and performance-as-a-limit rules. Many are LIFTED here
|
|
136
136
|
by specify from the domain rule files (e.g. persistence.domain, auditing.domain,
|
|
@@ -147,8 +147,8 @@
|
|
|
147
147
|
## Data Classification *(domain lift — DC)*
|
|
148
148
|
|
|
149
149
|
<!--
|
|
150
|
-
ACTION REQUIRED (when the
|
|
151
|
-
The sensitivity taxonomy for this
|
|
150
|
+
ACTION REQUIRED (when the feature handles sensitive data; else "None (as of vX.Y)").
|
|
151
|
+
The sensitivity taxonomy for this feature's data and the exposure rules that follow:
|
|
152
152
|
which categories exist, which Key-Entity fields fall in each, and where each category
|
|
153
153
|
MAY / MUST NOT appear (public API surface, logs, metrics, traces, external projections).
|
|
154
154
|
Lifted by specify from the domain data-classification rules. Design enforces these; the
|
|
@@ -165,8 +165,8 @@
|
|
|
165
165
|
## Integration Contracts *(domain lift — IC)*
|
|
166
166
|
|
|
167
167
|
<!--
|
|
168
|
-
ACTION REQUIRED (when the
|
|
169
|
-
external contracts this
|
|
168
|
+
ACTION REQUIRED (when the feature interoperates; else "None (as of vX.Y)"). The
|
|
169
|
+
external contracts this feature MUST satisfy — interoperability obligations lifted by
|
|
170
170
|
specify from the domain interop rules (e.g. FHIR/HL7/DICOM projections, terminology
|
|
171
171
|
services, inbound feeds). State each at CONTRACT level: which standard, which resources,
|
|
172
172
|
direction (inbound/outbound), projection vs system-of-record — NOT the adapter design
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
|
|
183
183
|
<!--
|
|
184
184
|
ACTION REQUIRED (when the frontend lane's rules apply; else "None (as of vX.Y)").
|
|
185
|
-
The PROJECT-WIDE experience standards this
|
|
185
|
+
The PROJECT-WIDE experience standards this feature's UI must satisfy, lifted here by
|
|
186
186
|
specify out of the frontend lane's constitution (constitution.ui.md — the UX-* principle
|
|
187
187
|
series) and the mapped ux/ rule files, exactly as CN-/DC-/IC- lift the domain rules.
|
|
188
188
|
The lift is what makes them binding: the prototype phase and the FRONTEND LANES of plan
|
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
- **UX-001**: [Accessibility conformance — e.g. every user-facing surface MUST meet [standard, level]; every task in the User Stories is completable keyboard-only. — lifted from UX-II, ux/accessibility-standards.md]
|
|
209
209
|
- **UX-002**: [Interaction states — e.g. every asynchronous operation MUST present its loading, empty, partial-failure, recovery and success states; no state leaves the user without a next action. — lifted from UX-IV, ux/interaction-states.md]
|
|
210
210
|
- **UX-003**: [Content and language — e.g. user-facing text uses the context's ubiquitous language; every error names what happened and what to do next; regulated wording is reproduced verbatim. — lifted from UX-V, ux/content-design.md]
|
|
211
|
-
- **UX-004**: [Journey integrity — e.g. each US-n is completable without leaving this
|
|
211
|
+
- **UX-004**: [Journey integrity — e.g. each US-n is completable without leaving this feature's surface; destructive actions are confirmed and reversible. — lifted from ux/journey-mapping.md]
|
|
212
212
|
- **UX-005**: [Responsiveness-as-a-limit — e.g. an interaction acknowledges input within [n] ms and shows progress past [n] s. A front-end bound; the server-side budget it depends on is CN-nnn.]
|
|
213
213
|
|
|
214
214
|
## Edge Cases & Exceptional Scenarios
|
|
@@ -289,10 +289,13 @@
|
|
|
289
289
|
|
|
290
290
|
<!--
|
|
291
291
|
The living-truth ledger. Every applied change request appends a row here, carrying
|
|
292
|
-
the version it ships as. finalize-delta writes the row when it
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
292
|
+
the version it ships as. finalize-delta writes the row when it MERGES the delta, with
|
|
293
|
+
the CR id and `(pending)` in the Version cell — at that point the number does not exist
|
|
294
|
+
yet. close-delta then archives the CR, bumps the minor version in active_version.json,
|
|
295
|
+
and stamps that same number into this document's **Version** header AND into the pending
|
|
296
|
+
cell — one mechanism, one stage, so header, row and active_version.json never disagree.
|
|
297
|
+
A row still reading `(pending)` is a change that merged and has not closed. The model
|
|
298
|
+
never writes a version here or anywhere; scripts stamp it. Newest last.
|
|
296
299
|
-->
|
|
297
300
|
|
|
298
301
|
| Version | Date | Change | User stories | CR |
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Frontend Plan: [
|
|
1
|
+
# Frontend Plan: [FEATURE]
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Feature**: `[Feature]` <!-- the capability scope the developer chose; the aggregate(s) it acts on are the spec's "Acts on aggregate(s)" line -->
|
|
4
4
|
|
|
5
|
-
**Plan home**: `specs/[
|
|
5
|
+
**Plan home**: `specs/[Context]/[Feature]/frontend-plan.md`
|
|
6
6
|
|
|
7
|
-
**Source spec**: `specs/[
|
|
7
|
+
**Source spec**: `specs/[Context]/[Feature]/spec.md`
|
|
8
8
|
|
|
9
9
|
**Lane**: `[lane id]` — the frontend lane declared in `.appweaver/stacks.json`
|
|
10
10
|
|
|
@@ -32,9 +32,13 @@
|
|
|
32
32
|
- UX- LIVES HERE AND ONLY HERE. The spec's Experience Standards are this
|
|
33
33
|
document's to realise — backend-plan.md deliberately excludes them, so a UX- that
|
|
34
34
|
reaches neither design is a dropped requirement.
|
|
35
|
-
- THE SPEC IS THE ONLY DOMAIN INPUT
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
- THE SPEC IS THE ONLY DOMAIN INPUT for this lane. This document reads the spec
|
|
36
|
+
+ the lane's own standards, never the domain rule files. A domain rule the
|
|
37
|
+
spec omits is an §8 assumption, never an invention. (The SERVICE lane reads a
|
|
38
|
+
second authority, the context's domain-model.md, because it realises the
|
|
39
|
+
aggregate's structure. This lane does not: it consumes the published surface
|
|
40
|
+
at §5, not the domain, so the model is not in its context and an entity or
|
|
41
|
+
invariant is never this document's to state.)
|
|
38
42
|
- THE SERVICE LANE ENTERS ONLY AT §5. Cite the operations this surface
|
|
39
43
|
consumes; never restate, re-derive or contradict the service design, and
|
|
40
44
|
never place server-side behaviour here.
|