@educa-corp/sdd-framework 0.6.0 → 0.7.1

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 (223) hide show
  1. package/bin/gate-trace.js +25 -2
  2. package/bin/index.js +32 -5
  3. package/bin/lint-trace.js +41 -0
  4. package/bin/self-check.js +430 -3
  5. package/bin/trace-schema.json +418 -31
  6. package/core/FRAMEWORK_VERSION +1 -1
  7. package/{commands/extend-prd.md → core/commands/amend-prd.md} +206 -173
  8. package/core/commands/dev-run-test.md +48 -10
  9. package/core/commands/extend-prd.md +39 -12
  10. package/core/commands/generate-bdd.md +52 -10
  11. package/core/commands/generate-code.md +35 -2
  12. package/core/commands/generate-tech-docs.md +36 -4
  13. package/core/commands/map-testids.md +1 -1
  14. package/core/commands/qc-run-test.md +29 -3
  15. package/core/commands/refine-prd.md +13 -2
  16. package/core/commands/review-context.md +43 -8
  17. package/core/commands/sync.md +105 -1
  18. package/core/commands/validate-traces.md +289 -16
  19. package/core/rules/workflow.md +34 -0
  20. package/core/steps/context-loader.md +27 -6
  21. package/core/templates/feature.template +1 -1
  22. package/core/templates/project-context.yaml +3 -3
  23. package/core/templates/tech-design.template.md +2 -2
  24. package/docs/02-concepts/architecture.md +37 -1
  25. package/docs/02-concepts/overview.md +1 -1
  26. package/docs/02-concepts/pipeline-steps/02-specification.md +13 -7
  27. package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +2 -0
  28. package/docs/02-concepts/pipeline-steps/08-qc-automation.md +1 -0
  29. package/docs/02-concepts/pipeline-steps/09-validate-traces.md +34 -3
  30. package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +10 -1
  31. package/docs/02-concepts/traceability.md +187 -183
  32. package/docs/03-guides/architect.md +13 -4
  33. package/docs/03-guides/developer.md +1 -0
  34. package/docs/03-guides/product-owner.md +89 -72
  35. package/docs/03-guides/tester-qa.md +81 -81
  36. package/docs/04-reference/commands.md +148 -134
  37. package/docs/04-reference/trace-schema.md +45 -1
  38. package/docs/explain/02b-extend-prd.md +1 -1
  39. package/docs/explain/02c-amend-prd.md +152 -0
  40. package/docs/explain/06-generate-bdd.md +1 -1
  41. package/docs/explain/13-dev-run-test.md +15 -1
  42. package/docs/explain/19-qc-run-test.md +91 -87
  43. package/docs/explain/21-validate-traces.md +79 -75
  44. package/docs/explain/28-sync.md +25 -0
  45. package/docs/explain/README.md +136 -135
  46. package/package.json +1 -8
  47. package/commands/debug.md +0 -529
  48. package/commands/debug.tmpl +0 -260
  49. package/commands/define-product.md +0 -438
  50. package/commands/define-product.tmpl +0 -225
  51. package/commands/dev-gen-test.md +0 -700
  52. package/commands/dev-gen-test.tmpl +0 -490
  53. package/commands/dev-run-test.md +0 -435
  54. package/commands/dev-run-test.tmpl +0 -225
  55. package/commands/dev-smoke-test.md +0 -374
  56. package/commands/dev-smoke-test.tmpl +0 -217
  57. package/commands/extend-prd.tmpl +0 -273
  58. package/commands/fix-bug.md +0 -519
  59. package/commands/fix-bug.tmpl +0 -197
  60. package/commands/generate-architecture.md +0 -354
  61. package/commands/generate-architecture.tmpl +0 -197
  62. package/commands/generate-bdd.md +0 -923
  63. package/commands/generate-bdd.tmpl +0 -590
  64. package/commands/generate-code.md +0 -859
  65. package/commands/generate-code.tmpl +0 -649
  66. package/commands/generate-design-spec.md +0 -737
  67. package/commands/generate-design-spec.tmpl +0 -524
  68. package/commands/generate-prd.md +0 -722
  69. package/commands/generate-prd.tmpl +0 -226
  70. package/commands/generate-spec-manifest.md +0 -321
  71. package/commands/generate-spec-manifest.tmpl +0 -164
  72. package/commands/generate-tech-docs.md +0 -920
  73. package/commands/generate-tech-docs.tmpl +0 -273
  74. package/commands/learn.md +0 -399
  75. package/commands/learn.tmpl +0 -130
  76. package/commands/map-testids.md +0 -238
  77. package/commands/map-testids.tmpl +0 -81
  78. package/commands/propose-scenario.md +0 -359
  79. package/commands/propose-scenario.tmpl +0 -202
  80. package/commands/qc-analyze.md +0 -269
  81. package/commands/qc-analyze.tmpl +0 -112
  82. package/commands/qc-design-test.md +0 -226
  83. package/commands/qc-design-test.tmpl +0 -69
  84. package/commands/qc-plan.md +0 -206
  85. package/commands/qc-plan.tmpl +0 -49
  86. package/commands/qc-report.md +0 -217
  87. package/commands/qc-report.tmpl +0 -60
  88. package/commands/qc-review.md +0 -210
  89. package/commands/qc-review.tmpl +0 -53
  90. package/commands/qc-run-test.md +0 -326
  91. package/commands/qc-run-test.tmpl +0 -116
  92. package/commands/refine-prd.md +0 -653
  93. package/commands/refine-prd.tmpl +0 -281
  94. package/commands/report-bug.md +0 -305
  95. package/commands/report-bug.tmpl +0 -148
  96. package/commands/review-code.md +0 -415
  97. package/commands/review-code.tmpl +0 -146
  98. package/commands/review-context.md +0 -902
  99. package/commands/review-context.tmpl +0 -530
  100. package/commands/review-tech-docs.md +0 -561
  101. package/commands/review-tech-docs.tmpl +0 -404
  102. package/commands/setup-ai-first.md +0 -602
  103. package/commands/setup-ai-first.tmpl +0 -450
  104. package/commands/sync.md +0 -430
  105. package/commands/sync.tmpl +0 -429
  106. package/commands/update-framework.md +0 -203
  107. package/commands/update-framework.tmpl +0 -202
  108. package/commands/validate-traces.md +0 -1077
  109. package/commands/validate-traces.tmpl +0 -920
  110. package/hooks/data-guard.js +0 -232
  111. package/hooks/settings.json +0 -19
  112. package/modules/android-compose/module.yaml +0 -13
  113. package/modules/android-compose/stack-profile.yaml +0 -57
  114. package/modules/angular/architecture-snippets/component-patterns.md +0 -187
  115. package/modules/angular/module.yaml +0 -6
  116. package/modules/angular/stack-profile.yaml +0 -38
  117. package/modules/context-engineering/architecture-snippets/context-design.md +0 -119
  118. package/modules/context-engineering/module.yaml +0 -9
  119. package/modules/context-engineering/stack-profile.yaml +0 -61
  120. package/modules/dotnet/architecture-snippets/clean-arch.md +0 -160
  121. package/modules/dotnet/module.yaml +0 -6
  122. package/modules/dotnet/stack-profile.yaml +0 -50
  123. package/modules/flutter/module.yaml +0 -14
  124. package/modules/flutter/stack-profile.yaml +0 -59
  125. package/modules/golang/architecture-snippets/domain-layout.md +0 -283
  126. package/modules/golang/module.yaml +0 -6
  127. package/modules/golang/stack-profile.yaml +0 -40
  128. package/modules/ios-swiftui/module.yaml +0 -13
  129. package/modules/ios-swiftui/stack-profile.yaml +0 -55
  130. package/modules/java-spring/architecture-snippets/layered-arch.md +0 -201
  131. package/modules/java-spring/module.yaml +0 -15
  132. package/modules/java-spring/stack-profile.yaml +0 -28
  133. package/modules/nextjs/architecture-snippets/app-router-patterns.md +0 -269
  134. package/modules/nextjs/module.yaml +0 -14
  135. package/modules/nextjs/stack-profile.yaml +0 -74
  136. package/modules/nuxt/module.yaml +0 -14
  137. package/modules/nuxt/stack-profile.yaml +0 -58
  138. package/modules/phaser-game/architecture-snippets/phaser-scene-patterns.md +0 -646
  139. package/modules/phaser-game/module.yaml +0 -15
  140. package/modules/phaser-game/stack-profile.yaml +0 -90
  141. package/modules/php-laravel/architecture-snippets/service-repository.md +0 -302
  142. package/modules/php-laravel/module.yaml +0 -15
  143. package/modules/php-laravel/stack-profile.yaml +0 -56
  144. package/modules/qc-playwright/stack-profile.yaml +0 -66
  145. package/modules/react/architecture-snippets/hooks-query-patterns.md +0 -254
  146. package/modules/react/module.yaml +0 -14
  147. package/modules/react/stack-profile.yaml +0 -63
  148. package/modules/react-native/module.yaml +0 -14
  149. package/modules/react-native/stack-profile.yaml +0 -56
  150. package/modules/vue/module.yaml +0 -14
  151. package/modules/vue/stack-profile.yaml +0 -65
  152. package/rules/data-protection.md +0 -80
  153. package/rules/workflow.md +0 -99
  154. package/skills/code/SKILL.md +0 -19
  155. package/skills/code/SKILL.tmpl +0 -19
  156. package/skills/debug/SKILL.md +0 -19
  157. package/skills/debug/SKILL.tmpl +0 -19
  158. package/skills/design-spec/SKILL.md +0 -11
  159. package/skills/design-spec/SKILL.tmpl +0 -11
  160. package/skills/discovery/SKILL.md +0 -14
  161. package/skills/discovery/SKILL.tmpl +0 -14
  162. package/skills/prd/SKILL.md +0 -19
  163. package/skills/prd/SKILL.tmpl +0 -19
  164. package/skills/qc/qa-analyst/DOC_GAPS.template.md +0 -63
  165. package/skills/qc/qa-analyst/acceptance-criteria.md +0 -60
  166. package/skills/qc/qa-analyst/business-rules.md +0 -59
  167. package/skills/qc/qa-analyst/data-flow.md +0 -64
  168. package/skills/qc/qa-analyst/spec-breakdown.md +0 -61
  169. package/skills/qc/qa-designer/e2e/journey.md +0 -41
  170. package/skills/qc/qa-designer/exploratory/charter.md +0 -68
  171. package/skills/qc/qa-designer/exploratory/explore-to-functional.md +0 -43
  172. package/skills/qc/qa-designer/functional/api.md +0 -45
  173. package/skills/qc/qa-designer/functional/gui-feature.md +0 -46
  174. package/skills/qc/qa-designer/functional/gui-screen.md +0 -52
  175. package/skills/qc/qa-designer/integration/api.md +0 -42
  176. package/skills/qc/qa-designer/integration/db.md +0 -39
  177. package/skills/qc/qa-designer/integration/gui.md +0 -40
  178. package/skills/qc/qa-designer/integration/kafka.md +0 -40
  179. package/skills/qc/qa-designer/non-functional.md +0 -40
  180. package/skills/qc/qa-planner/test-plan.md +0 -120
  181. package/skills/qc/qa-reviewer/script/e2e.md +0 -87
  182. package/skills/qc/qa-reviewer/script/exploratory.md +0 -45
  183. package/skills/qc/qa-reviewer/script/functional.md +0 -101
  184. package/skills/qc/qa-reviewer/script/integration.md +0 -91
  185. package/skills/qc/qa-reviewer/script/non-functional.md +0 -126
  186. package/skills/qc/qa-reviewer/test-case/e2e.md +0 -73
  187. package/skills/qc/qa-reviewer/test-case/exploratory.md +0 -43
  188. package/skills/qc/qa-reviewer/test-case/functional.md +0 -76
  189. package/skills/qc/qa-reviewer/test-case/integration.md +0 -69
  190. package/skills/qc/qa-reviewer/test-case/non-functional.md +0 -73
  191. package/skills/qc/qa-runner/e2e.md +0 -49
  192. package/skills/qc/qa-runner/exploratory/session.md +0 -36
  193. package/skills/qc/qa-runner/functional/api.md +0 -35
  194. package/skills/qc/qa-runner/functional/gui-feature.md +0 -51
  195. package/skills/qc/qa-runner/functional/gui-screen.md +0 -55
  196. package/skills/qc/qa-runner/integration.md +0 -47
  197. package/skills/qc/qa-runner/non-functional.md +0 -49
  198. package/skills/qc/qa-runner/report/report.md +0 -37
  199. package/skills/setup-ai-first/SKILL.md +0 -19
  200. package/skills/setup-ai-first/SKILL.tmpl +0 -19
  201. package/skills/spec/SKILL.md +0 -19
  202. package/skills/spec/SKILL.tmpl +0 -19
  203. package/skills/test/SKILL.md +0 -18
  204. package/skills/test/SKILL.tmpl +0 -18
  205. package/steps/business-language.md +0 -56
  206. package/steps/capture-lesson.md +0 -112
  207. package/steps/context-loader.md +0 -406
  208. package/steps/gate.md +0 -151
  209. package/steps/report-footer.md +0 -125
  210. package/steps/review-fanout.md +0 -159
  211. package/steps/spawn-agent.md +0 -129
  212. package/steps/trace-mirror.md +0 -53
  213. package/templates/README.md +0 -70
  214. package/templates/architecture.template.md +0 -394
  215. package/templates/ci/trace-gate.yml +0 -146
  216. package/templates/design-spec.template.md +0 -217
  217. package/templates/feature.template +0 -123
  218. package/templates/hooks/pre-push +0 -61
  219. package/templates/platform-guide.template.md +0 -145
  220. package/templates/prd.template.md +0 -283
  221. package/templates/product-definition.template.md +0 -188
  222. package/templates/project-context.yaml +0 -212
  223. package/templates/tech-design.template.md +0 -490
@@ -1,13 +0,0 @@
1
- name: "iOS (SwiftUI)"
2
- version: "1.0.0"
3
- description: "Native iOS development with SwiftUI + Swift"
4
- language: "Swift"
5
- framework: "SwiftUI"
6
- stack_type: "mobile"
7
- default_layer_order:
8
- - Models / entities
9
- - Repository (data sources)
10
- - UseCase (business operations)
11
- - ViewModel (ObservableObject state)
12
- - View (SwiftUI presentation)
13
- test_framework: "XCTest + Quick/Nimble"
@@ -1,55 +0,0 @@
1
- build:
2
- compile: "xcodebuild -scheme {AppName} -configuration Release"
3
- test: "xcodebuild test -scheme {AppName}"
4
- run: "Open in Xcode → Run (⌘R)"
5
- lint: "swiftlint"
6
-
7
- architecture:
8
- style: "MVVM + Clean Architecture (View → ViewModel → UseCase → Repository)"
9
- key_rules:
10
- - "Views are pure SwiftUI — no business logic, no direct API calls"
11
- - "ViewModels are ObservableObject classes; bind via @StateObject / @ObservedObject"
12
- - "UseCases encapsulate single business operations"
13
- - "Repositories abstract data sources (network, cache, local DB)"
14
- - "Dependency injection via environment or constructor injection"
15
- - "Use Combine or async/await for async flows — never DispatchQueue in ViewModel"
16
- folder_structure: |
17
- Sources/
18
- ├── Core/
19
- │ ├── Network/ ← URLSession wrapper, interceptors
20
- │ ├── Theme/ ← Color, Font, Spacing tokens
21
- │ └── Utils/
22
- ├── Shared/
23
- │ └── Components/ ← reusable SwiftUI views (AppButton, AppTextField...)
24
- ├── Features/
25
- │ └── {Domain}/
26
- │ ├── Views/
27
- │ ├── ViewModels/
28
- │ ├── UseCases/
29
- │ └── Repository/
30
-
31
- coding_standards:
32
- naming:
33
- views: "PascalCase + View suffix (e.g., OrderListView, CreateOrderView)"
34
- viewmodels: "PascalCase + ViewModel suffix (e.g., OrderListViewModel)"
35
- usecases: "PascalCase + UseCase suffix (e.g., CreateOrderUseCase)"
36
- files:
37
- view: "{Feature}View.swift"
38
- viewmodel: "{Feature}ViewModel.swift"
39
- usecase: "{Feature}UseCase.swift"
40
- patterns:
41
- async: "async/await + Combine"
42
- navigation: "NavigationStack (iOS 16+)"
43
- persistence: "Core Data or SwiftData"
44
- networking: "URLSession or Alamofire"
45
-
46
- testing:
47
- unit: "XCTest + Quick/Nimble"
48
- ui: "XCUITest"
49
- patterns:
50
- - "Test ViewModel by injecting mock repositories"
51
- - "UI tests use accessibility identifiers — set .accessibilityIdentifier on Views"
52
-
53
- trace_tags:
54
- implements: "// @trace.implements={UC-ID}-SC{N}"
55
- source: "// @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
@@ -1,201 +0,0 @@
1
- # Java Spring Boot — Layered Architecture Code Patterns
2
-
3
- ## Controller Pattern
4
-
5
- ```java
6
- @RestController
7
- @RequestMapping("/v1/orders")
8
- @RequiredArgsConstructor
9
- // @trace.implements=ORDER-UC1-SC1
10
- // @trace.source=specs/order/order-management/bdd/ORDER-UC1-create-order.feature
11
- public class OrderController {
12
-
13
- private final OrderFacade orderFacade;
14
-
15
- @PostMapping
16
- public ResponseEntity<ApiResponse<OrderResponse>> createOrder(
17
- @Valid @RequestBody CreateOrderRequest request) {
18
- OrderResponse result = orderFacade.createOrder(request);
19
- return ResponseEntity.status(HttpStatus.CREATED)
20
- .body(ApiResponse.success(result));
21
- }
22
-
23
- @GetMapping("/{id}")
24
- // @trace.implements=ORDER-UC1-SC2
25
- public ResponseEntity<ApiResponse<OrderResponse>> getOrder(@PathVariable Long id) {
26
- OrderResponse result = orderFacade.getOrder(id);
27
- return ResponseEntity.ok(ApiResponse.success(result));
28
- }
29
- }
30
- ```
31
-
32
- ## Service Interface Pattern
33
-
34
- ```java
35
- public interface OrderService {
36
- OrderResponse createOrder(CreateOrderRequest request);
37
- OrderResponse getOrderById(Long id);
38
- void cancelOrder(Long id);
39
- }
40
- ```
41
-
42
- ## Service Implementation Pattern
43
-
44
- ```java
45
- @Service
46
- @RequiredArgsConstructor
47
- @Transactional(readOnly = true)
48
- public class OrderServiceImpl implements OrderService {
49
-
50
- private final OrderRepository orderRepository;
51
- private final OrderMapper orderMapper;
52
-
53
- @Override
54
- @Transactional
55
- public OrderResponse createOrder(CreateOrderRequest request) {
56
- Order order = orderMapper.toEntity(request);
57
- order.setStatus(OrderStatus.PENDING);
58
- Order saved = orderRepository.save(order);
59
- return orderMapper.toResponse(saved);
60
- }
61
-
62
- @Override
63
- public OrderResponse getOrderById(Long id) {
64
- Order order = orderRepository.findById(id)
65
- .orElseThrow(() -> new ResourceNotFoundException("Order", id));
66
- return orderMapper.toResponse(order);
67
- }
68
-
69
- @Override
70
- @Transactional
71
- public void cancelOrder(Long id) {
72
- Order order = orderRepository.findById(id)
73
- .orElseThrow(() -> new ResourceNotFoundException("Order", id));
74
- order.setStatus(OrderStatus.CANCELLED);
75
- }
76
- }
77
- ```
78
-
79
- ## Repository Interface Pattern
80
-
81
- ```java
82
- @Repository
83
- public interface OrderRepository extends JpaRepository<Order, Long> {
84
-
85
- List<Order> findByCustomerIdAndStatus(Long customerId, OrderStatus status);
86
-
87
- @Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.id = :id")
88
- Optional<Order> findByIdWithItems(@Param("id") Long id);
89
-
90
- Page<Order> findByCreatedAtBetween(
91
- LocalDateTime from, LocalDateTime to, Pageable pageable);
92
- }
93
- ```
94
-
95
- ## DTO Pattern
96
-
97
- ```java
98
- // Request DTO
99
- @Data
100
- @NoArgsConstructor
101
- @AllArgsConstructor
102
- public class CreateOrderRequest {
103
- @NotNull(message = "customerId is required")
104
- private Long customerId;
105
-
106
- @NotEmpty(message = "items must not be empty")
107
- private List<OrderItemRequest> items;
108
-
109
- @NotBlank(message = "shippingAddress is required")
110
- private String shippingAddress;
111
- }
112
-
113
- // Response DTO
114
- @Data
115
- @Builder
116
- @NoArgsConstructor
117
- @AllArgsConstructor
118
- public class OrderResponse {
119
- private Long id;
120
- private Long customerId;
121
- private OrderStatus status;
122
- private List<OrderItemResponse> items;
123
- private BigDecimal totalAmount;
124
- private LocalDateTime createdAt;
125
- }
126
- ```
127
-
128
- ## MapStruct Mapper Pattern
129
-
130
- ```java
131
- @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.ERROR)
132
- public interface OrderMapper {
133
-
134
- @Mapping(target = "id", ignore = true)
135
- @Mapping(target = "status", ignore = true)
136
- @Mapping(target = "createdAt", ignore = true)
137
- Order toEntity(CreateOrderRequest request);
138
-
139
- OrderResponse toResponse(Order order);
140
-
141
- List<OrderResponse> toResponseList(List<Order> orders);
142
- }
143
- ```
144
-
145
- ## ApiResponse Wrapper Pattern
146
-
147
- ```java
148
- @Data
149
- @Builder
150
- @NoArgsConstructor
151
- @AllArgsConstructor
152
- public class ApiResponse<T> {
153
- private boolean success;
154
- private T data;
155
- private String message;
156
- private String errorCode;
157
- private LocalDateTime timestamp;
158
-
159
- public static <T> ApiResponse<T> success(T data) {
160
- return ApiResponse.<T>builder()
161
- .success(true)
162
- .data(data)
163
- .timestamp(LocalDateTime.now())
164
- .build();
165
- }
166
-
167
- public static <T> ApiResponse<T> error(String errorCode, String message) {
168
- return ApiResponse.<T>builder()
169
- .success(false)
170
- .errorCode(errorCode)
171
- .message(message)
172
- .timestamp(LocalDateTime.now())
173
- .build();
174
- }
175
- }
176
- ```
177
-
178
- ## Facade Pattern (optional orchestration layer)
179
-
180
- ```java
181
- @Service
182
- @RequiredArgsConstructor
183
- public class OrderFacade {
184
-
185
- private final OrderService orderService;
186
- private final InventoryService inventoryService;
187
- private final NotificationService notificationService;
188
-
189
- public OrderResponse createOrder(CreateOrderRequest request) {
190
- // 1. Validate inventory
191
- inventoryService.validateAvailability(request.getItems());
192
- // 2. Create order
193
- OrderResponse order = orderService.createOrder(request);
194
- // 3. Reserve inventory
195
- inventoryService.reserveItems(order.getId(), request.getItems());
196
- // 4. Send confirmation
197
- notificationService.sendOrderConfirmation(order);
198
- return order;
199
- }
200
- }
201
- ```
@@ -1,15 +0,0 @@
1
- name: "Java Spring Boot"
2
- version: "1.0.0"
3
- description: "Spring Boot 3.x with layered architecture"
4
- language: "Java"
5
- framework: "Spring Boot"
6
- stack_type: "backend"
7
- default_layer_order:
8
- - DTO
9
- - Entity/Model
10
- - Repository
11
- - Service interface
12
- - Service impl
13
- - Facade (optional)
14
- - Controller
15
- test_framework: "JUnit 5 + Mockito"
@@ -1,28 +0,0 @@
1
- build:
2
- compile: "mvn clean install -DskipTests"
3
- test: "mvn test"
4
- run: "mvn spring-boot:run"
5
-
6
- architecture:
7
- style: "Layered (Controller → Facade → Service → Repository)"
8
- key_rules:
9
- - "Controllers must not contain business logic"
10
- - "Services own transaction boundaries (@Transactional)"
11
- - "Repositories use Spring Data JPA"
12
- - "Facades orchestrate multiple services (optional layer)"
13
-
14
- coding_standards:
15
- naming:
16
- classes: "PascalCase"
17
- methods: "camelCase"
18
- packages: "lowercase.snake_case"
19
- patterns:
20
- response_wrapper: "ApiResponse<T>"
21
- mapping: "MapStruct"
22
- exception_base: "ResourceNotFoundException"
23
-
24
- trace_tags:
25
- implements: "@trace.implements={UC-ID}-SC{N}"
26
- source: "@trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
27
- verifies: "@trace.verifies={UC-ID}"
28
- test_type: "@trace.test_type=unit|integration"
@@ -1,269 +0,0 @@
1
- # Next.js App Router — Server Components, Server Actions & DAL Patterns
2
-
3
- ## Data Access Layer (server-only)
4
-
5
- ```typescript
6
- // lib/dal/orders.dal.ts
7
- // @trace.source=specs/order/order-management/bdd/ORD-UC1.feature
8
- import 'server-only'; // prevents accidental import on client
9
- import { db } from '@/lib/db';
10
- import type { Order } from '@/types/order';
11
-
12
- export async function getOrderById(id: number): Promise<Order | null> {
13
- return db.order.findUnique({
14
- where: { id },
15
- include: { items: { include: { product: true } }, customer: true },
16
- });
17
- }
18
-
19
- export async function listOrdersByCustomer(customerId: number): Promise<Order[]> {
20
- return db.order.findMany({
21
- where: { customerId },
22
- include: { items: true },
23
- orderBy: { createdAt: 'desc' },
24
- });
25
- }
26
- ```
27
-
28
- ## Server Component (Data Fetching + Layout)
29
-
30
- ```tsx
31
- // app/(dashboard)/orders/page.tsx
32
- // @trace.implements=ORD-UC1-SC1
33
- // @trace.source=specs/order/order-management/bdd/ORD-UC1.feature
34
- import { listOrdersByCustomer } from '@/lib/dal/orders.dal';
35
- import { getCurrentUser } from '@/lib/auth';
36
- import { OrderCard } from './_components/OrderCard';
37
- import { EmptyState } from '@/components/ui/EmptyState';
38
-
39
- export default async function OrdersPage() {
40
- const user = await getCurrentUser();
41
- const orders = await listOrdersByCustomer(user.id);
42
-
43
- return (
44
- <section>
45
- <h1>My Orders</h1>
46
- {orders.length === 0 ? (
47
- <EmptyState message="No orders yet." />
48
- ) : (
49
- <ul>
50
- {orders.map(order => (
51
- <OrderCard key={order.id} order={order} />
52
- ))}
53
- </ul>
54
- )}
55
- </section>
56
- );
57
- }
58
- ```
59
-
60
- ## Zod Schema (shared server + client)
61
-
62
- ```typescript
63
- // lib/validations/order.schema.ts
64
- import { z } from 'zod';
65
-
66
- export const createOrderSchema = z.object({
67
- customerId: z.number().positive(),
68
- items: z.array(z.object({
69
- productId: z.number().positive(),
70
- quantity: z.number().int().min(1, 'Quantity must be at least 1'),
71
- })).min(1, 'At least one item is required'),
72
- });
73
-
74
- export type CreateOrderInput = z.infer<typeof createOrderSchema>;
75
- ```
76
-
77
- ## Server Action (Mutation)
78
-
79
- ```typescript
80
- // lib/actions/order.actions.ts
81
- 'use server';
82
- // @trace.implements=ORD-UC2-SC1
83
- // @trace.source=specs/order/order-management/bdd/ORD-UC2.feature
84
-
85
- import { revalidatePath } from 'next/cache';
86
- import { redirect } from 'next/navigation';
87
- import { createOrderSchema } from '@/lib/validations/order.schema';
88
- import { db } from '@/lib/db';
89
- import { getCurrentUser } from '@/lib/auth';
90
-
91
- // Returns { error } on failure, redirects on success
92
- export async function createOrder(formData: FormData) {
93
- const user = await getCurrentUser();
94
-
95
- const parsed = createOrderSchema.safeParse({
96
- customerId: user.id,
97
- items: JSON.parse(formData.get('items') as string),
98
- });
99
-
100
- if (!parsed.success) {
101
- return { error: parsed.error.flatten().fieldErrors };
102
- }
103
-
104
- try {
105
- await db.order.create({
106
- data: {
107
- customerId: parsed.data.customerId,
108
- status: 'pending',
109
- items: {
110
- create: parsed.data.items.map(item => ({
111
- productId: item.productId,
112
- quantity: item.quantity,
113
- })),
114
- },
115
- },
116
- });
117
- } catch {
118
- return { error: { _form: ['Failed to create order. Please try again.'] } };
119
- }
120
-
121
- revalidatePath('/orders');
122
- redirect('/orders');
123
- }
124
-
125
- export async function cancelOrder(orderId: number) {
126
- const user = await getCurrentUser();
127
-
128
- const order = await db.order.findFirst({
129
- where: { id: orderId, customerId: user.id },
130
- });
131
-
132
- if (!order) return { error: 'Order not found.' };
133
- if (order.status !== 'pending') return { error: 'Only pending orders can be cancelled.' };
134
-
135
- await db.order.update({ where: { id: orderId }, data: { status: 'cancelled' } });
136
-
137
- revalidatePath('/orders');
138
- return { success: true };
139
- }
140
- ```
141
-
142
- ## Client Component (Interactive UI)
143
-
144
- ```tsx
145
- // app/(dashboard)/orders/_components/CancelOrderButton.tsx
146
- 'use client';
147
- // @trace.implements=ORD-UC3-SC1
148
- // @trace.source=specs/order/order-management/bdd/ORD-UC3.feature
149
- import { useTransition } from 'react';
150
- import { cancelOrder } from '@/lib/actions/order.actions';
151
-
152
- interface Props {
153
- orderId: number;
154
- disabled?: boolean;
155
- }
156
-
157
- export function CancelOrderButton({ orderId, disabled }: Props) {
158
- const [isPending, startTransition] = useTransition();
159
-
160
- const handleCancel = () => {
161
- startTransition(async () => {
162
- const result = await cancelOrder(orderId);
163
- if (result?.error) {
164
- alert(result.error); // replace with toast in real app
165
- }
166
- });
167
- };
168
-
169
- return (
170
- <button
171
- onClick={handleCancel}
172
- disabled={disabled || isPending}
173
- className="btn-danger"
174
- >
175
- {isPending ? 'Cancelling...' : 'Cancel Order'}
176
- </button>
177
- );
178
- }
179
- ```
180
-
181
- ## API Route (for webhooks / external consumers)
182
-
183
- ```typescript
184
- // app/api/orders/webhook/route.ts
185
- import { NextRequest, NextResponse } from 'next/server';
186
- import { verifyWebhookSignature } from '@/lib/webhook';
187
- import { db } from '@/lib/db';
188
-
189
- export async function POST(request: NextRequest) {
190
- const body = await request.json();
191
-
192
- if (!verifyWebhookSignature(request, body)) {
193
- return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
194
- }
195
-
196
- if (body.event === 'payment.completed') {
197
- await db.order.update({
198
- where: { id: body.orderId },
199
- data: { status: 'paid', paidAt: new Date() },
200
- });
201
- }
202
-
203
- return NextResponse.json({ received: true });
204
- }
205
- ```
206
-
207
- ## Loading + Error Boundaries
208
-
209
- ```tsx
210
- // app/(dashboard)/orders/loading.tsx
211
- export default function OrdersLoading() {
212
- return (
213
- <div className="order-skeleton">
214
- {Array.from({ length: 3 }).map((_, i) => (
215
- <div key={i} className="skeleton-card animate-pulse" />
216
- ))}
217
- </div>
218
- );
219
- }
220
- ```
221
-
222
- ```tsx
223
- // app/(dashboard)/orders/error.tsx
224
- 'use client';
225
- export default function OrdersError({ error, reset }: {
226
- error: Error & { digest?: string };
227
- reset: () => void;
228
- }) {
229
- return (
230
- <div className="error-state">
231
- <p>Failed to load orders: {error.message}</p>
232
- <button onClick={reset}>Try again</button>
233
- </div>
234
- );
235
- }
236
- ```
237
-
238
- ## Playwright E2E Test
239
-
240
- ```typescript
241
- // e2e/orders/create-order.spec.ts
242
- // @trace.verifies=ORD-UC2
243
- // @trace.test_type=e2e
244
- import { test, expect } from '@playwright/test';
245
- import { loginAs } from '../fixtures/auth';
246
-
247
- test.describe('Create Order', () => {
248
- test.use({ storageState: 'e2e/.auth/customer.json' }); // reuse auth state
249
-
250
- test('customer creates an order successfully', async ({ page }) => {
251
- await page.goto('/orders/new');
252
-
253
- await page.getByLabel('Product').selectOption({ label: 'Wireless Headphones' });
254
- await page.getByLabel('Quantity').fill('2');
255
- await page.getByRole('button', { name: 'Add to Cart' }).click();
256
- await page.getByRole('button', { name: 'Place Order' }).click();
257
-
258
- await expect(page).toHaveURL(/\/orders\/\d+/);
259
- await expect(page.getByText('Order placed successfully')).toBeVisible();
260
- });
261
-
262
- test('shows validation error when cart is empty', async ({ page }) => {
263
- await page.goto('/orders/new');
264
- await page.getByRole('button', { name: 'Place Order' }).click();
265
-
266
- await expect(page.getByText('At least one item is required')).toBeVisible();
267
- });
268
- });
269
- ```
@@ -1,14 +0,0 @@
1
- name: "Next.js"
2
- version: "1.0.0"
3
- description: "Next.js 14+ App Router with Server Components, Server Actions, and React Query"
4
- language: "TypeScript"
5
- framework: "Next.js"
6
- stack_type: "fullstack"
7
- default_layer_order:
8
- - Types / interfaces
9
- - Server Actions (mutations)
10
- - Data access layer (DAL) — server-side DB/API calls
11
- - Server Components (data fetching + layout)
12
- - Client Components (interactive UI)
13
- - API Routes (for external consumers / webhooks)
14
- test_framework: "Vitest + React Testing Library + Playwright (E2E)"
@@ -1,74 +0,0 @@
1
- build:
2
- compile: "npm run build"
3
- test: "npm test"
4
- run: "npm run dev"
5
- lint: "npm run lint"
6
- e2e: "npx playwright test"
7
-
8
- architecture:
9
- style: "App Router — Server Components + Server Actions + Client Components"
10
- key_rules:
11
- - "Default to Server Components — only add 'use client' when interactivity is needed"
12
- - "Data fetching happens in Server Components or Server Actions — never in useEffect"
13
- - "Server Actions handle all mutations (form submits, data writes)"
14
- - "Data Access Layer (DAL) abstracts all DB/external API calls — used only on server"
15
- - "Client Components are 'leaf nodes' — keep them small and focused on interactivity"
16
- - "API Routes (/api) used only for external consumers or webhooks, not for own UI"
17
- - "Use Next.js cache() and unstable_cache for data memoization"
18
- folder_structure: |
19
- app/
20
- ├── (auth)/ ← route group: auth pages
21
- ├── (dashboard)/ ← route group: authenticated pages
22
- │ └── orders/
23
- │ ├── page.tsx ← Server Component (list page)
24
- │ ├── [id]/
25
- │ │ └── page.tsx ← Server Component (detail page)
26
- │ └── _components/ ← feature-scoped Client Components
27
- ├── api/ ← API Routes (webhooks, external consumers)
28
- └── layout.tsx
29
- lib/
30
- ├── dal/ ← Data Access Layer (server-only DB/API calls)
31
- │ └── orders.dal.ts
32
- ├── actions/ ← Server Actions
33
- │ └── order.actions.ts
34
- └── validations/ ← Zod schemas (shared server+client)
35
- └── order.schema.ts
36
- components/
37
- └── ui/ ← shared primitive Client Components
38
-
39
- coding_standards:
40
- naming:
41
- server_components: "PascalCase, no suffix — co-locate in app/ route folder"
42
- client_components: "PascalCase + 'use client' at top — in _components/ folders"
43
- server_actions: "camelCase verb + noun (e.g., createOrder, cancelOrder) in lib/actions/"
44
- dal_functions: "camelCase (e.g., getOrderById, listOrdersByCustomer) in lib/dal/"
45
- files:
46
- page: "app/{route}/page.tsx"
47
- layout: "app/{route}/layout.tsx"
48
- server_action: "lib/actions/{domain}.actions.ts"
49
- dal: "lib/dal/{domain}.dal.ts"
50
- schema: "lib/validations/{domain}.schema.ts"
51
- patterns:
52
- mutations: "Server Actions with useFormState / useTransition"
53
- data_fetching: "Server Component async/await + fetch with revalidate options"
54
- client_state: "Zustand or Context API (avoid for server-derived data)"
55
- forms: "React Hook Form (client) OR native <form> with Server Actions"
56
- error_handling: "error.tsx (route-level) + try/catch in Server Actions returning {error}"
57
- loading: "loading.tsx (Suspense boundary) per route segment"
58
- auth: "next-auth v5 (Auth.js) or middleware-based session check"
59
-
60
- testing:
61
- unit: "Vitest + React Testing Library for Client Components"
62
- integration: "Vitest + MSW for Server Actions"
63
- e2e: "Playwright — full browser tests"
64
- patterns:
65
- - "Test Server Components by rendering with async render utilities"
66
- - "Mock fetch/DB calls for Server Action tests"
67
- - "Playwright tests cover full user flows (auth → action → result)"
68
- - "Use @playwright/test fixtures for auth state reuse"
69
-
70
- trace_tags:
71
- implements: "// @trace.implements={UC-ID}-SC{N}"
72
- source: "// @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
73
- verifies: "// @trace.verifies={UC-ID}"
74
- test_type: "// @trace.test_type=unit|e2e"
@@ -1,14 +0,0 @@
1
- name: "Nuxt"
2
- version: "1.0.0"
3
- description: "Nuxt 3 with SSR/SSG, Composition API, Pinia, and useFetch"
4
- language: "TypeScript"
5
- framework: "Nuxt 3"
6
- stack_type: "frontend"
7
- default_layer_order:
8
- - Types / interfaces
9
- - Server API routes (server/api/)
10
- - Composables (useFetch / useAsyncData)
11
- - State store (Pinia)
12
- - UI components (presentational)
13
- - Page components (pages/)
14
- test_framework: "Vitest + Vue Test Utils + @nuxt/test-utils"