aw-spec-cli 0.1.19 → 0.1.21

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 (75) hide show
  1. package/assets/.appweaver/DESIGN-FORMAT.md +17 -9
  2. package/assets/.appweaver/ORCH-DIALECT.md +8 -3
  3. package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +26 -3
  4. package/assets/.appweaver/orchestrator/orchestrator.py +65 -3
  5. package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +1 -1
  6. package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +4 -2
  7. package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +1 -1
  8. package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +1 -1
  9. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +121 -42
  10. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +7 -7
  11. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +145 -52
  12. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +18 -10
  13. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +306 -28
  14. package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +1 -1
  15. package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +1 -1
  16. package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +1 -1
  17. package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +4 -4
  18. package/assets/.appweaver/orchestrator/workflows/aw-spec-deploy.orch.yaml +1 -1
  19. package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +114 -30
  20. package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +140 -36
  21. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +385 -61
  22. package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +217 -174
  23. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +407 -107
  24. package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +1 -1
  25. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +49 -11
  26. package/assets/.appweaver/orchestrator/workflows/aw-spec-recall-delta.orch.yaml +1 -1
  27. package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +1 -1
  28. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +29 -23
  29. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +47 -23
  30. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +19 -11
  31. package/assets/.appweaver/scripts/bash/aw-inventory.sh +15 -0
  32. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +683 -92
  33. package/assets/.appweaver/scripts/bash/aw-xref.sh +3 -0
  34. package/assets/.appweaver/scripts/powershell/aw-inventory.ps1 +15 -0
  35. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +625 -64
  36. package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +3 -0
  37. package/assets/.appweaver/scripts/python/aw-crstate.py +194 -0
  38. package/assets/.appweaver/scripts/python/aw-foundation.py +151 -0
  39. package/assets/.appweaver/scripts/python/aw-inventory.py +1829 -63
  40. package/assets/.appweaver/scripts/python/aw-payload-parity.py +3 -0
  41. package/assets/.appweaver/scripts/python/aw-plan-coverage.py +423 -0
  42. package/assets/.appweaver/scripts/python/aw-stack.py +251 -28
  43. package/assets/.appweaver/scripts/python/aw-testlog.py +148 -0
  44. package/assets/.appweaver/scripts/python/aw-xref.py +500 -81
  45. package/assets/.appweaver/stack-profiles/dotnet-webapi.json +1 -0
  46. package/assets/.appweaver/stack-profiles/java-spring.json +1 -0
  47. package/assets/.appweaver/stack-profiles/node-express.json +1 -0
  48. package/assets/.appweaver/stack-profiles/python-fastapi.json +1 -0
  49. package/assets/.appweaver/templates/constitution-domain-template.md +17 -2
  50. package/assets/.appweaver/templates/delta-design-template.md +1 -1
  51. package/assets/.appweaver/templates/delta-domain-model-template.md +1 -1
  52. package/assets/.appweaver/templates/delta-spec-template.md +4 -3
  53. package/assets/.appweaver/templates/design-template.md +16 -11
  54. package/assets/.appweaver/templates/okf-concept-template.md +11 -1
  55. package/assets/.appweaver/templates/proposed-inventory-template.md +127 -0
  56. package/assets/.appweaver/templates/source-map-template.md +5 -3
  57. package/assets/.appweaver/templates/spec-template.md +17 -17
  58. package/assets/.appweaver/templates/ui-delta-design-template.md +1 -1
  59. package/assets/.appweaver/templates/ui-design-template.md +4 -4
  60. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.pack.txt +4489 -361
  61. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.pack.txt +2274 -125
  62. package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +10 -6
  63. package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +4 -0
  64. package/assets/guardrails/technology/dotnet-webapi/auditing.md +3 -1
  65. package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +5 -3
  66. package/assets/guardrails/technology/dotnet-webapi/cqrs.md +5 -1
  67. package/assets/guardrails/technology/dotnet-webapi/domain-driven-design.md +13 -5
  68. package/assets/guardrails/technology/dotnet-webapi/examples/cqrs.md +2 -0
  69. package/assets/guardrails/technology/dotnet-webapi/examples/domain-driven-design.md +6 -2
  70. package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +70 -0
  71. package/assets/guardrails/technology/dotnet-webapi/technology-constitution.md +3 -0
  72. package/assets/guardrails/technology/dotnet-webapi/testing.md +10 -0
  73. package/assets/guardrails/technology/nextjs/ui-constitution.md +8 -1
  74. package/package.json +1 -1
  75. package/assets/.appweaver/orchestrator/.state/smoke.state.json +0 -32
@@ -5,6 +5,7 @@
5
5
  "language": "C#",
6
6
  "ecosystem": "dotnet",
7
7
  "root": "src/",
8
+ "test_root": "tests/",
8
9
  "build": "dotnet build",
9
10
  "test": "dotnet test",
10
11
  "run": "dotnet run --project {{root}}",
@@ -5,6 +5,7 @@
5
5
  "language": "Java",
6
6
  "ecosystem": "java",
7
7
  "root": "src/main/java/",
8
+ "test_root": "src/test/java/",
8
9
  "run_from": "root",
9
10
  "build": "./mvn clean install",
10
11
  "test": "./mvn test",
@@ -5,6 +5,7 @@
5
5
  "language": "Node.js",
6
6
  "ecosystem": "node",
7
7
  "root": "src/",
8
+ "test_root": "tests/",
8
9
  "build": "npm run build",
9
10
  "test": "npm test",
10
11
  "run": "npm run dev",
@@ -5,6 +5,7 @@
5
5
  "language": "Python",
6
6
  "ecosystem": "python",
7
7
  "root": "app/",
8
+ "test_root": "tests/",
8
9
  "build": "python -m compileall {{root}}",
9
10
  "test": "pytest",
10
11
  "run": "uvicorn app.main:app --reload",
@@ -7,8 +7,8 @@
7
7
  project reverse-engineered by `onboard` that map points at the project's OWN generated
8
8
  domain rule files and its own charter, both derived from the code — same partition, a
9
9
  different corpus. It carries ONLY domain-specific material:
10
- the domain principles, domain identifiers/terminology, regulatory regime,
11
- interoperability surfaces, and domain governance overrides.
10
+ the project identity, the domain principles, domain identifiers/terminology, regulatory
11
+ regime, interoperability surfaces, and domain governance overrides.
12
12
 
13
13
  ══ THIS FILE IS SHAPE. THE MAPPED CORPUS IS CONTENT. ═════════════════════════════
14
14
  This template is part of the kit and governs projects in any industry. It therefore
@@ -35,6 +35,21 @@
35
35
  the detail. That keeps the authority/detail overlap to one line.
36
36
  -->
37
37
 
38
+ ## Project Identity
39
+
40
+ [PROJECT_IDENTITY_CONTENT]
41
+ <!--
42
+ Form: what this project IS in its domain — the regulated role it plays, the bounded
43
+ contexts it is organised into, and who consumes it and through what surface — each as a
44
+ short labelled line. Take them from the mapped charter's own identity section. Where the
45
+ project's domain-requirements states a different value (a different context list, a
46
+ narrower role), the project value is a DEVIATION: ratify it here, naming the charter line
47
+ it departs from and who approved it.
48
+
49
+ This section exists because specify loads THIS file and not the charter, so it is the
50
+ only way the project's contexts and consumers reach specify.
51
+ -->
52
+
38
53
  ## Adopted Modelling Standard
39
54
 
40
55
  [MODELLING_STANDARD_STATEMENT]
@@ -1,6 +1,6 @@
1
1
  # Delta Backend Plan — [CR-ID]: [TITLE]
2
2
 
3
- **Feature (aggregate slice)**: `[Feature]`
3
+ **Feature**: `[Feature]`
4
4
 
5
5
  **Lane**: backend — the service lane declared in `.appweaver/stacks.json`
6
6
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Bounded context**: `[Context]`
4
4
 
5
- **Feature (aggregate slice)**: `[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 (aggregate)**: [Aggregate]
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 (e.g.
25
- UpdateOrder to the Order aggregate) is a new user story (US-n), NOT a new feature.
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,10 @@
1
- # Backend Plan: [AGGREGATE]
1
+ # Backend Plan: [FEATURE]
2
2
 
3
- **Aggregate (feature)**: `[Aggregate]` <!-- the feature = the aggregate, e.g. Order -->
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/[Aggregate]/backend-plan.md`
5
+ **Plan home**: `specs/[Context]/[Feature]/backend-plan.md`
6
6
 
7
- **Source spec**: `specs/[Aggregate]/spec.md` <!-- behaviour: what the system must DO -->
7
+ **Source spec**: `specs/[Context]/[Feature]/spec.md` <!-- behaviour: what the system must DO -->
8
8
 
9
9
  **Source model**: `specs/[Context]/domain-model.md` <!-- structure: what the domain IS -->
10
10
 
@@ -15,7 +15,8 @@
15
15
  <!--
16
16
  WHAT THIS DOCUMENT IS
17
17
  =====================
18
- The single, living High-Level Design (HLD) for ONE aggregate. It is the
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
19
20
  MEDIATOR between spec.md (WHAT/WHY, tech-agnostic) and the generated code
20
21
  (HOW, tech-specific). It is NOT code: it carries structure, contracts,
21
22
  behaviour, and decisions — enough for ANY capable LLM to generate correct,
@@ -41,9 +42,13 @@
41
42
  one of the two (BR- in the model; CN-/DC-/IC- in the spec). Realise each of those;
42
43
  invent no entity, value object or rule that neither states (if one seems missing,
43
44
  record it as an Assumption in §7, never smuggle it in).
44
- - Feature = aggregate. Commands (CreateOrder, UpdateOrder…) are USER STORIES,
45
- not features. One aggregate = one backend-plan.md = one owning design for its code
46
- files. A later requirement is a delta on THIS doc, never a new one.
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.
47
52
 
48
53
  WHAT LIVES ELSEWHERE (do NOT repeat it here — it is identical for every feature)
49
54
  - The clean-architecture layering + dependency rule (API → Application → Domain
@@ -76,13 +81,13 @@
76
81
  ## 0. Design Overview
77
82
 
78
83
  <!--
79
- One paragraph: the architectural shape of this aggregate and the 3–5 decisions
84
+ One paragraph: the architectural shape of this feature and the 3–5 decisions
80
85
  that matter most (why this boundary, the lifecycle model, the hardest trade-off).
81
86
  This is the orientation a reviewer or an LLM reads first. The standing layering /
82
87
  dependency rule is NOT restated here — it is the project architecture standard.
83
88
  -->
84
89
 
85
- [The architectural essence of this aggregate in 3–6 sentences: its purpose, its
90
+ [The architectural essence of this feature in 3–6 sentences: its purpose, its
86
91
  lifecycle spine, the key structural choices specific to it, and the single biggest
87
92
  trade-off. Layering follows the project architecture standard (constitution).]
88
93
 
@@ -298,7 +303,7 @@ text, and do not add a rule the model does not carry)*
298
303
 
299
304
  ### 4.3 Wiring & migrations
300
305
 
301
- - **Composition**: bind `[Port] → [Adapter]` for this aggregate.
306
+ - **Composition**: bind `[Port] → [Adapter]` for this feature.
302
307
  - **Migrations needed**: [yes → what changes conceptually / no]. The Run phase applies them.
303
308
 
304
309
  ## 5. Cross-Cutting Concerns
@@ -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 → THIS aggregate's implement/adopt.
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: [AGGREGATE]
1
+ # Source Map: [FEATURE]
2
2
 
3
- **Aggregate (feature)**: `[Aggregate]` <!-- the feature = the aggregate, e.g. MedicinalProduct -->
3
+ **Feature**: `[Feature]` <!-- the capability scope confirmed in the boundary map, e.g. MedicinalProduct or PatientRegistration -->
4
4
 
5
- **Source home**: `specs/[Aggregate]/source-map.md`
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: [AGGREGATE]
1
+ # Specification: [FEATURE]
2
2
 
3
- **Aggregate (feature)**: `[Aggregate]` <!-- the feature = the aggregate, e.g. Order -->
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/[Aggregate]/`
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 on the aggregate (CreateOrder, UpdateOrder, …) is a USER STORY below —
21
- NOT a separate feature. A later requirement is a new US-n added as a delta (see
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 aggregate's BEHAVIOUR is (requirements → constraints → data classification →
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 aggregate exists — the problem, the affected users,
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 aggregate solves, who it serves, and the value it delivers.]
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 aggregate is specified against: WHO reaches it through a
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 aggregate through a UI — e.g. clinician, scheduler; distinct from a system/API caller]
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
- aggregate MUST satisfy that are NEITHER functional behaviour (those are FR) NOR
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 aggregate handles sensitive data; else "None (as of vX.Y)").
151
- The sensitivity taxonomy for this aggregate's data and the exposure rules that follow:
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 aggregate interoperates; else "None (as of vX.Y)"). The
169
- external contracts this aggregate MUST satisfy — interoperability obligations lifted by
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 aggregate's UI must satisfy, lifted here by
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 aggregate's surface; destructive actions are confirmed and reversible. — lifted from ux/journey-mapping.md]
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
@@ -1,6 +1,6 @@
1
1
  # Delta Frontend Plan — [CR-ID]: [TITLE]
2
2
 
3
- **Feature (aggregate slice)**: `[Feature]`
3
+ **Feature**: `[Feature]`
4
4
 
5
5
  **Lane**: `[lane id]` — the frontend lane declared in `.appweaver/stacks.json`
6
6
 
@@ -1,10 +1,10 @@
1
- # Frontend Plan: [AGGREGATE]
1
+ # Frontend Plan: [FEATURE]
2
2
 
3
- **Aggregate (feature)**: `[Aggregate]` <!-- the feature = the aggregate, e.g. Order -->
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/[Aggregate]/frontend-plan.md`
5
+ **Plan home**: `specs/[Context]/[Feature]/frontend-plan.md`
6
6
 
7
- **Source spec**: `specs/[Aggregate]/spec.md`
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