@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,254 +0,0 @@
1
- # React — Hooks, React Query & Zustand Patterns
2
-
3
- ## React Query — Query Hook
4
-
5
- ```typescript
6
- // features/order/queries/order.queries.ts
7
- import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
8
- import { orderApi } from '@/api/order.api';
9
- import type { CreateOrderPayload, Order } from '../types';
10
-
11
- // Query key factory — single source of truth for cache invalidation
12
- export const orderKeys = {
13
- all: ['ORDERS'] as const,
14
- lists: () => [...orderKeys.all, 'list'] as const,
15
- list: (customerId: number) => [...orderKeys.lists(), { customerId }] as const,
16
- detail: (id: number) => [...orderKeys.all, 'detail', id] as const,
17
- };
18
-
19
- // @trace.implements=ORD-UC1-SC1
20
- // @trace.source=specs/order/order-management/bdd/ORD-UC1.feature
21
- export function useOrderList(customerId: number) {
22
- return useQuery({
23
- queryKey: orderKeys.list(customerId),
24
- queryFn: () => orderApi.getByCustomer(customerId),
25
- staleTime: 30_000,
26
- });
27
- }
28
-
29
- // @trace.implements=ORD-UC2-SC1
30
- // @trace.source=specs/order/order-management/bdd/ORD-UC2.feature
31
- export function useCreateOrder() {
32
- const queryClient = useQueryClient();
33
-
34
- return useMutation({
35
- mutationFn: (payload: CreateOrderPayload) => orderApi.create(payload),
36
- onSuccess: (_, variables) => {
37
- // Invalidate order list for this customer
38
- queryClient.invalidateQueries({ queryKey: orderKeys.list(variables.customerId) });
39
- },
40
- });
41
- }
42
- ```
43
-
44
- ## API Client (Axios)
45
-
46
- ```typescript
47
- // api/order.api.ts
48
- import { apiClient } from '@/api/client';
49
- import type { CreateOrderPayload, Order, PaginatedResponse } from '@/features/order/types';
50
-
51
- export const orderApi = {
52
- getByCustomer: (customerId: number) =>
53
- apiClient.get<PaginatedResponse<Order>>('/v1/orders', { params: { customerId } })
54
- .then(res => res.data),
55
-
56
- getById: (id: number) =>
57
- apiClient.get<Order>(`/v1/orders/${id}`).then(res => res.data),
58
-
59
- create: (payload: CreateOrderPayload) =>
60
- apiClient.post<Order>('/v1/orders', payload).then(res => res.data),
61
-
62
- cancel: (id: number) =>
63
- apiClient.patch<void>(`/v1/orders/${id}/cancel`).then(res => res.data),
64
- };
65
- ```
66
-
67
- ```typescript
68
- // api/client.ts — Axios instance with auth interceptor
69
- import axios from 'axios';
70
-
71
- export const apiClient = axios.create({
72
- baseURL: import.meta.env.VITE_API_URL,
73
- headers: { 'Content-Type': 'application/json' },
74
- });
75
-
76
- apiClient.interceptors.request.use(config => {
77
- const token = localStorage.getItem('access_token');
78
- if (token) config.headers.Authorization = `Bearer ${token}`;
79
- return config;
80
- });
81
-
82
- apiClient.interceptors.response.use(
83
- res => res,
84
- error => {
85
- if (error.response?.status === 401) {
86
- // redirect to login
87
- window.location.href = '/login';
88
- }
89
- return Promise.reject(error);
90
- }
91
- );
92
- ```
93
-
94
- ## Zustand Store (Client State)
95
-
96
- ```typescript
97
- // features/cart/store/cart.store.ts
98
- import { create } from 'zustand';
99
- import { persist } from 'zustand/middleware';
100
- import type { CartItem } from '../types';
101
-
102
- interface CartStore {
103
- items: CartItem[];
104
- addItem: (item: CartItem) => void;
105
- removeItem: (productId: number) => void;
106
- clearCart: () => void;
107
- total: () => number;
108
- }
109
-
110
- export const useCartStore = create<CartStore>()(
111
- persist(
112
- (set, get) => ({
113
- items: [],
114
-
115
- addItem: (item) =>
116
- set(state => {
117
- const existing = state.items.find(i => i.productId === item.productId);
118
- if (existing) {
119
- return {
120
- items: state.items.map(i =>
121
- i.productId === item.productId
122
- ? { ...i, quantity: i.quantity + item.quantity }
123
- : i
124
- ),
125
- };
126
- }
127
- return { items: [...state.items, item] };
128
- }),
129
-
130
- removeItem: (productId) =>
131
- set(state => ({ items: state.items.filter(i => i.productId !== productId) })),
132
-
133
- clearCart: () => set({ items: [] }),
134
-
135
- total: () => get().items.reduce((sum, i) => sum + i.price * i.quantity, 0),
136
- }),
137
- { name: 'cart-storage' }
138
- )
139
- );
140
- ```
141
-
142
- ## Feature Component (Container)
143
-
144
- ```tsx
145
- // features/order/components/OrderListPage.tsx
146
- // @trace.implements=ORD-UC1-SC1
147
- // @trace.source=specs/order/order-management/bdd/ORD-UC1.feature
148
- import { useAuth } from '@/hooks/useAuth';
149
- import { useOrderList } from '../queries/order.queries';
150
- import { OrderCard } from './OrderCard';
151
-
152
- export function OrderListPage() {
153
- const { user } = useAuth();
154
- const { data: orders, isLoading, isError } = useOrderList(user.id);
155
-
156
- if (isLoading) return <div>Loading...</div>;
157
- if (isError) return <div>Failed to load orders.</div>;
158
-
159
- return (
160
- <div className="order-list">
161
- {orders?.map(order => (
162
- <OrderCard key={order.id} order={order} />
163
- ))}
164
- {orders?.length === 0 && <p>No orders yet.</p>}
165
- </div>
166
- );
167
- }
168
- ```
169
-
170
- ## React Hook Form + Zod
171
-
172
- ```tsx
173
- // features/order/components/CreateOrderForm.tsx
174
- import { useForm } from 'react-hook-form';
175
- import { zodResolver } from '@hookform/resolvers/zod';
176
- import { z } from 'zod';
177
- import { useCreateOrder } from '../queries/order.queries';
178
-
179
- const createOrderSchema = z.object({
180
- customerId: z.number().positive(),
181
- items: z.array(z.object({
182
- productId: z.number().positive(),
183
- quantity: z.number().int().min(1),
184
- })).min(1, 'At least one item required'),
185
- });
186
-
187
- type CreateOrderForm = z.infer<typeof createOrderSchema>;
188
-
189
- export function CreateOrderForm({ customerId }: { customerId: number }) {
190
- const { mutate: createOrder, isPending } = useCreateOrder();
191
-
192
- const { register, handleSubmit, formState: { errors } } = useForm<CreateOrderForm>({
193
- resolver: zodResolver(createOrderSchema),
194
- defaultValues: { customerId, items: [] },
195
- });
196
-
197
- const onSubmit = (data: CreateOrderForm) => createOrder(data);
198
-
199
- return (
200
- <form onSubmit={handleSubmit(onSubmit)}>
201
- {/* form fields */}
202
- {errors.items && <p className="error">{errors.items.message}</p>}
203
- <button type="submit" disabled={isPending}>
204
- {isPending ? 'Creating...' : 'Create Order'}
205
- </button>
206
- </form>
207
- );
208
- }
209
- ```
210
-
211
- ## Test with React Testing Library + MSW
212
-
213
- ```tsx
214
- // features/order/__tests__/OrderListPage.test.tsx
215
- // @trace.verifies=ORD-UC1
216
- // @trace.test_type=integration
217
- import { render, screen, waitFor } from '@testing-library/react';
218
- import { http, HttpResponse } from 'msw';
219
- import { server } from '@/test/server';
220
- import { renderWithProviders } from '@/test/utils';
221
- import { OrderListPage } from '../components/OrderListPage';
222
-
223
- describe('OrderListPage', () => {
224
- it('displays orders after successful fetch', async () => {
225
- server.use(
226
- http.get('/v1/orders', () =>
227
- HttpResponse.json([
228
- { id: 1, status: 'pending', customerId: 42, items: [] },
229
- ])
230
- )
231
- );
232
-
233
- renderWithProviders(<OrderListPage />, { user: { id: 42 } });
234
-
235
- expect(screen.getByText('Loading...')).toBeInTheDocument();
236
-
237
- await waitFor(() =>
238
- expect(screen.queryByText('Loading...')).not.toBeInTheDocument()
239
- );
240
-
241
- expect(screen.getByText('Order #1')).toBeInTheDocument();
242
- });
243
-
244
- it('shows empty state when no orders exist', async () => {
245
- server.use(http.get('/v1/orders', () => HttpResponse.json([])));
246
-
247
- renderWithProviders(<OrderListPage />, { user: { id: 42 } });
248
-
249
- await waitFor(() =>
250
- expect(screen.getByText('No orders yet.')).toBeInTheDocument()
251
- );
252
- });
253
- });
254
- ```
@@ -1,14 +0,0 @@
1
- name: "React"
2
- version: "1.0.0"
3
- description: "React 18 SPA with hooks, React Query, and Zustand"
4
- language: "TypeScript"
5
- framework: "React"
6
- stack_type: "frontend"
7
- default_layer_order:
8
- - Types / interfaces
9
- - API client (React Query hooks)
10
- - State store (Zustand)
11
- - Custom hooks (business logic)
12
- - UI components (presentational)
13
- - Page / feature components (container)
14
- test_framework: "Vitest + React Testing Library"
@@ -1,63 +0,0 @@
1
- build:
2
- compile: "npm run build"
3
- test: "npm test"
4
- run: "npm run dev"
5
- lint: "npm run lint"
6
-
7
- architecture:
8
- style: "Feature-based (components → hooks → queries → store)"
9
- key_rules:
10
- - "Business logic lives in custom hooks, not in components"
11
- - "Server state managed by React Query (useQuery / useMutation)"
12
- - "Client-only UI state managed by Zustand or useState"
13
- - "Components must be pure functions — no direct API calls inside JSX"
14
- - "Shared UI primitives in components/ui/, feature logic in features/{name}/"
15
- - "Never fetch data directly in a component — use a custom hook"
16
- folder_structure: |
17
- src/
18
- ├── api/ ← axios instance, interceptors
19
- ├── components/
20
- │ └── ui/ ← reusable primitives (Button, Modal, Table...)
21
- ├── features/
22
- │ └── {domain}/
23
- │ ├── components/ ← feature-specific UI
24
- │ ├── hooks/ ← useOrderList, useCreateOrder...
25
- │ ├── queries/ ← React Query definitions
26
- │ ├── store/ ← Zustand slice (if needed)
27
- │ └── types.ts
28
- ├── pages/ ← route-level page components
29
- └── lib/ ← utilities, formatters, constants
30
-
31
- coding_standards:
32
- naming:
33
- components: "PascalCase (e.g., OrderList, CreateOrderModal)"
34
- hooks: "camelCase with 'use' prefix (e.g., useOrderList, useCreateOrder)"
35
- query_keys: "SCREAMING_SNAKE_CASE array (e.g., ['ORDER_LIST', customerId])"
36
- stores: "camelCase + Store suffix (e.g., useCartStore)"
37
- files:
38
- component: "{Feature}.tsx"
39
- hook: "use{Feature}.ts"
40
- query: "{feature}.queries.ts"
41
- store: "{feature}.store.ts"
42
- types: "{feature}.types.ts"
43
- patterns:
44
- data_fetching: "React Query (TanStack Query v5)"
45
- global_state: "Zustand slices"
46
- forms: "React Hook Form + Zod validation"
47
- api_client: "Axios with interceptors for auth + error handling"
48
- error_boundary: "React ErrorBoundary wraps each feature route"
49
-
50
- testing:
51
- unit: "Vitest + React Testing Library"
52
- e2e: "Playwright or Cypress"
53
- patterns:
54
- - "Test behavior, not implementation — query by role/label, not className"
55
- - "Mock React Query with a QueryClient wrapper in test setup"
56
- - "Use MSW (Mock Service Worker) to mock API calls in tests"
57
- - "renderWithProviders() helper wraps component with QueryClient + Router"
58
-
59
- trace_tags:
60
- implements: "// @trace.implements={UC-ID}-SC{N}"
61
- source: "// @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
62
- verifies: "// @trace.verifies={UC-ID}"
63
- test_type: "// @trace.test_type=unit|integration"
@@ -1,14 +0,0 @@
1
- name: "React Native"
2
- version: "1.0.0"
3
- description: "Cross-platform mobile (iOS + Android) with React Native / Expo"
4
- language: "TypeScript"
5
- framework: "React Native"
6
- stack_type: "mobile"
7
- default_layer_order:
8
- - Types / interfaces
9
- - API client (React Query hooks)
10
- - State store (Zustand)
11
- - Custom hooks (business logic)
12
- - UI components (presentational)
13
- - Screen / feature components (container)
14
- test_framework: "Jest + React Native Testing Library"
@@ -1,56 +0,0 @@
1
- build:
2
- compile: "npx expo export / npx react-native build-android"
3
- test: "jest"
4
- run: "npx expo start / npx react-native run-ios"
5
- lint: "eslint . && tsc --noEmit"
6
-
7
- architecture:
8
- style: "Feature-based (screens → hooks → queries → store)"
9
- key_rules:
10
- - "Business logic lives in custom hooks, not in screen components"
11
- - "Server state managed by React Query (TanStack Query)"
12
- - "Navigation state managed by React Navigation"
13
- - "Native modules wrapped in a service layer — never called directly in components"
14
- - "Shared UI primitives in src/components/ui/, feature screens in src/features/{name}/"
15
- folder_structure: |
16
- src/
17
- ├── api/ ← axios instance, interceptors
18
- ├── components/
19
- │ └── ui/ ← reusable primitives (AppButton, AppInput...)
20
- ├── features/
21
- │ └── {domain}/
22
- │ ├── components/
23
- │ ├── hooks/
24
- │ ├── queries/
25
- │ └── screens/
26
- ├── navigation/ ← React Navigation stacks/tabs
27
- ├── store/ ← Zustand slices
28
- └── lib/ ← utils, formatters, constants
29
-
30
- coding_standards:
31
- naming:
32
- components: "PascalCase (e.g., OrderListScreen, CreateOrderForm)"
33
- hooks: "camelCase with 'use' prefix (e.g., useOrderList)"
34
- screens: "PascalCase + Screen suffix (e.g., OrderDetailScreen)"
35
- files:
36
- screen: "{Feature}Screen.tsx"
37
- component: "{Feature}.tsx"
38
- hook: "use{Feature}.ts"
39
- patterns:
40
- state_management: "Zustand + React Query"
41
- navigation: "React Navigation v6 (Stack + Tab + Drawer)"
42
- networking: "Axios"
43
- forms: "React Hook Form + Zod"
44
- storage: "MMKV or AsyncStorage"
45
-
46
- testing:
47
- unit: "Jest + React Native Testing Library"
48
- e2e: "Detox or Maestro"
49
- patterns:
50
- - "Test by accessibility label or testID — never by style/className"
51
- - "Mock native modules in jest setup"
52
- - "Use renderWithProviders() with NavigationContainer + QueryClient"
53
-
54
- trace_tags:
55
- implements: "// @trace.implements={UC-ID}-SC{N}"
56
- source: "// @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
@@ -1,14 +0,0 @@
1
- name: "Vue"
2
- version: "1.0.0"
3
- description: "Vue 3 SPA with Composition API, Pinia, and Vue Query"
4
- language: "TypeScript"
5
- framework: "Vue 3"
6
- stack_type: "frontend"
7
- default_layer_order:
8
- - Types / interfaces
9
- - API client (Vue Query / composables)
10
- - State store (Pinia)
11
- - Composables (business logic)
12
- - UI components (presentational)
13
- - Page / feature components (container)
14
- test_framework: "Vitest + Vue Test Utils"
@@ -1,65 +0,0 @@
1
- build:
2
- compile: "npm run build"
3
- test: "npm run test"
4
- run: "npm run dev"
5
- lint: "npm run lint"
6
-
7
- architecture:
8
- style: "Feature-based (components → composables → queries → store)"
9
- key_rules:
10
- - "Business logic lives in composables, not in component setup()"
11
- - "Server state managed by Vue Query (@tanstack/vue-query)"
12
- - "Client-only UI state managed by Pinia stores"
13
- - "Components must be pure — no direct API calls inside <template> or setup()"
14
- - "Shared UI primitives in components/ui/, feature logic in features/{name}/"
15
- - "Never fetch data directly in a component — use a composable"
16
- - "Props defined with defineProps<{}>(), emits with defineEmits<{}>()"
17
- folder_structure: |
18
- src/
19
- ├── api/ ← axios instance, interceptors
20
- ├── components/
21
- │ └── ui/ ← reusable primitives (BaseButton, BaseInput...)
22
- ├── features/
23
- │ └── {domain}/
24
- │ ├── components/ ← feature-specific UI
25
- │ ├── composables/ ← useOrderList, useCreateOrder...
26
- │ ├── queries/ ← Vue Query definitions
27
- │ ├── store/ ← Pinia slice (if needed)
28
- │ └── types.ts
29
- ├── pages/ ← route-level page components (Vue Router)
30
- ├── router/ ← route definitions
31
- └── lib/ ← utilities, formatters, constants
32
-
33
- coding_standards:
34
- naming:
35
- components: "PascalCase (e.g., OrderList, CreateOrderModal)"
36
- composables: "camelCase with 'use' prefix (e.g., useOrderList, useCreateOrder)"
37
- stores: "camelCase + Store suffix (e.g., useCartStore) — defined with defineStore()"
38
- query_keys: "SCREAMING_SNAKE_CASE string/array (e.g., ['ORDER_LIST', customerId])"
39
- files:
40
- component: "{Feature}.vue"
41
- composable: "use{Feature}.ts"
42
- query: "{feature}.queries.ts"
43
- store: "{feature}.store.ts"
44
- types: "{feature}.types.ts"
45
- patterns:
46
- data_fetching: "Vue Query (TanStack Query v5 for Vue)"
47
- global_state: "Pinia stores"
48
- forms: "VeeValidate + Zod"
49
- api_client: "Axios with interceptors for auth + error handling"
50
- reactivity: "ref() for primitives, reactive() for objects, computed() for derived state"
51
-
52
- testing:
53
- unit: "Vitest + Vue Test Utils"
54
- e2e: "Playwright or Cypress"
55
- patterns:
56
- - "Test behavior, not implementation — query by role/label via @testing-library/vue"
57
- - "Mock Vue Query with VueQueryPlugin wrapper in test setup"
58
- - "Use MSW (Mock Service Worker) to mock API calls in tests"
59
- - "mountWithProviders() helper wraps component with Pinia + VueQuery + Router"
60
-
61
- trace_tags:
62
- implements: "// @trace.implements={UC-ID}-SC{N}"
63
- source: "// @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
64
- verifies: "// @trace.verifies={UC-ID}"
65
- test_type: "// @trace.test_type=unit|integration"
@@ -1,80 +0,0 @@
1
- # Data Protection Rules
2
-
3
- > These rules are loaded by `steps/context-loader.md` at the start of every command.
4
- > AI agents MUST follow these rules without exception.
5
-
6
- ---
7
-
8
- ## NEVER Read — Sensitive Files
9
-
10
- The following file patterns contain credentials, secrets, or private keys.
11
- **Do NOT read, display, log, or reference their contents under any circumstance.**
12
-
13
- ### Environment & Secrets
14
- - `.env`
15
- - `.env.*` (e.g., `.env.local`, `.env.production`, `.env.staging`)
16
- - `*.secret`
17
- - `secrets/` (entire directory)
18
- - `.secrets/` (entire directory)
19
- - `*credentials*`
20
-
21
- ### Cryptographic Keys & Certificates
22
- - `*.key`
23
- - `*.pem`
24
- - `*.p12`
25
- - `*.pfx`
26
- - `*.jks`
27
- - `*.keystore`
28
- - `*.crt` / `*.cert`
29
-
30
- ### Framework-Specific Config Files (may contain DB passwords, API keys)
31
- - `application-prod.yml` / `application-prod.properties`
32
- - `application-production.yml`
33
- - `appsettings.Production.json`
34
- - `appsettings.Staging.json`
35
- - `database.yml` (Rails)
36
- - `config/master.key` (Rails)
37
- - `storage/oauth-private.key`
38
-
39
- ### Files Matching Dangerous Keywords
40
- Any file whose name contains (case-insensitive):
41
- - `password`
42
- - `passwd`
43
- - `secret`
44
- - `private_key`
45
- - `api_key`
46
- - `access_token`
47
- - `auth_token`
48
-
49
- ---
50
-
51
- ## NEVER Write or Modify
52
-
53
- - Any file listed above
54
- - `*.lock` files that are not package lock files (e.g., `*.lock` outside of `package-lock.json`, `yarn.lock`, `composer.lock`)
55
-
56
- ---
57
-
58
- ## NEVER Execute via Bash
59
-
60
- - Commands that print secrets: `printenv`, `env | grep -i secret`, `cat .env`
61
- - Commands that expose credentials: `docker inspect`, `kubectl get secret -o yaml`
62
- - Git commands that may expose history of secrets: `git show`, `git log -p` on config files
63
-
64
- ---
65
-
66
- ## Safe Alternatives
67
-
68
- If context about environment configuration is needed:
69
-
70
- 1. Ask the user to describe the configuration **without sharing actual values**.
71
- 2. Reference the **structure** of config (keys, not values): "I see you use `DATABASE_URL` — I'll generate code that reads from that variable."
72
- 3. Use placeholder values in generated code: `process.env.DATABASE_URL` or `${DATABASE_URL}`.
73
-
74
- ---
75
-
76
- ## If a Sensitive File is Accidentally Accessed
77
-
78
- 1. Do NOT display or repeat any content from the file.
79
- 2. Immediately stop and notify the user: "I've detected a sensitive file. I will not read or use its contents."
80
- 3. Ask the user what they actually need (usually it's the structure, not the values).
package/rules/workflow.md DELETED
@@ -1,99 +0,0 @@
1
- # Workflow Rules
2
-
3
- > General AI behavior rules for all spec-driven-docs commands.
4
- > Loaded by `steps/context-loader.md` at the start of every command.
5
-
6
- ---
7
-
8
- ## Checkpoints
9
-
10
- Ba mức, định nghĩa đầy đủ ở `steps/gate.md` Bước 3a — **đây chỉ là bản tóm tắt, gate là nguồn**:
11
-
12
- | Mức | Lệnh nào | `--yes` bỏ qua? |
13
- |---|---|:---:|
14
- | **Không chặn** | read-only (`/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs`) | — |
15
- | **Chặn thường** | mọi lệnh sinh/sửa artifact | ✅ |
16
- | **Chặn CỨNG** | ghi đè file đã có · `--resume` · migrate · prune | ❌ |
17
-
18
- - CHECKPOINT phải nêu **target đã phân giải**, và **mọi cờ 🔴/⚠️ mà context-loader đã tính**
19
- (`active_service = unresolved`, `Status ≠ FULL`, CLAUDE.md thiếu, target resolve bằng wildcard).
20
- - **KHÔNG lặp lại** những gì `[CTX LOADED]` vừa in ngay phía trên. Sạch hết thì CHECKPOINT
21
- chỉ hai dòng.
22
- - `--yes` bỏ qua *chặn thường*, **không** bỏ qua *chặn cứng*, và **không** tắt việc in cờ.
23
-
24
- > **Vì sao ba mức thay vì "always show" (G41):** bản cũ viết *"**Always** show a CHECKPOINT"*
25
- > rồi ngay dòng sau lại cấp một ngoại lệ cho lệnh read-only — mà `gate.md` **không hề thực thi**
26
- > ngoại lệ đó. Hai file cùng được nạp vào mọi lệnh và nói ngược nhau. Cộng thêm: cổng luôn in
27
- > ra một bảng giống hệt nhau, 20 lần cho một feature, nên `Y` thành phản xạ và cổng hỏng **âm
28
- > thầm** — vẫn hiện, vẫn được trả lời, chỉ là không ai đọc. Cổng chỉ ồn khi thật sự có chuyện
29
- > thì mới được đọc.
30
-
31
- ## Scope Control
32
-
33
- - Work only within the scope explicitly confirmed at CHECKPOINT.
34
- - Do NOT create files outside the directories specified in `project-context.yaml → paths`.
35
- - If new scope is discovered mid-command, STOP and ask: "I found additional scope [{description}]. Should I include it? (Y/N)"
36
-
37
- ## Trace Contract
38
-
39
- > **Phạm vi:** mục này áp cho **repo framework**. Ở project consumer, `.agent/` là mirror sinh
40
- > ra và `bin/` không được cài — contract ở đó là **read-only**: thấy lệch thì **báo**, đừng tự
41
- > sửa (xem `.agent/README.md`). Việc duy nhất chạy được ở project là **kiểm sổ trace**:
42
- > `npx @educa-corp/sdd-framework --lint-trace`.
43
-
44
- - Contract trace (field `@trace.*`, cột `.tsv`, path pattern, giá trị enum) có **một
45
- nguồn-sự-thật máy đọc**: `bin/trace-schema.json`. Bản cho người đọc:
46
- `docs/04-reference/trace-schema.md` — giữ hai file đồng bộ.
47
- - **Canh contract ≠ canh dữ liệu.** `bin/self-check.js` đọc **file lệnh** và kiểm *"lệnh có gọi
48
- đúng tên cột không"* — nó không bao giờ mở một `.tsv` thật. `bin/lint-trace.js` mở sổ thật.
49
- Cần cả hai: sổ 24 cột được ghi **bằng tay**, hàng chục lần mỗi feature; một dấu tab thiếu ở
50
- ô 17 dồn mọi ô sau đó sang trái, ô 21 `status` nhận một ngày tháng, và **không cờ nào bật**.
51
- Thêm cột/vocabulary mới → khai binding cho `lint-trace` **ngay**; R8 fail build nếu quên.
52
- - Đổi contract (thêm/bỏ/đổi nghĩa một field, path, hay giá trị enum) → **sửa
53
- `bin/trace-schema.json` TRƯỚC**, rồi mới sửa lệnh. `npm run build` chạy
54
- `bin/self-check.js` và **fail** nếu lệnh lệch schema.
55
- - Field có consumer mà **không có producer** là lỗi chặn build — đó chính là hình dạng
56
- của G1 (`@trace.sc_version`: 3 consumer, 0 producer, DRIFT chết mà không ai báo).
57
- - **Làm mất hiệu lực ≠ ghi đè.** Cột trace có chủ sở hữu rõ ràng — `dev_selftest`/`dev_selftest_at`
58
- thuộc `/dev-run-test` · `qc_status`/`qc_run_at` thuộc `/qc-run-test` · `test_count`/`test_classes`
59
- thuộc `/dev-gen-test` — và **chỉ chủ được ghi giá trị KHẲNG ĐỊNH** (`pass`/`fail`/số lượng).
60
- Nhưng lệnh nào làm giá trị đó **HẾT ĐÚNG** (spec đổi, code đổi) thì **BẮT BUỘC** hạ nó về giá
61
- trị "chưa biết" (`not_run` / `—`). Giữ một `pass` đã hết hiệu lực là **báo cáo sai**, không phải
62
- tôn trọng quyền sở hữu.
63
- *Tiền lệ đúng có sẵn: `/fix-bug` hạ `dev_selftest → not_run` với lý do "code vừa đổi nên tín
64
- hiệu self-test cũ hết hiệu lực". Cùng lý do đó áp cho MỌI lệnh làm đổi spec hoặc code.*
65
- **Ngoại lệ có chủ ý:** `qc_owner`/`qc_blocked_by` (con trỏ tới bug — spec đổi không làm bug biến
66
- mất) và `test_count`/`test_classes` (test vẫn tồn tại trên đĩa; số lượng không sai, chỉ nội dung
67
- cũ → **cảnh báo**, không hạ số, để tỷ lệ coverage không nhảy loạn).
68
- - **Mỗi audit flag phải quan sát được ở CẢ BA tầng.** Mọi giá trị trong
69
- `vocabularies.audit_flags` bắt buộc có đủ: **(1)** một counter `{flag_lowercase}_count`
70
- trong Step 7 + `summary` của `trace-report.json` · **(2)** một mảng trong `issues` ·
71
- **(3)** một khối trong report terminal. Thiếu tầng nào = cờ vô hình ở tầng đó.
72
- `bin/self-check.js` R7 ép tầng (1) — **không có ngoại lệ**. Đây là hình dạng của G33:
73
- 7/10 cờ có counter, 3 cái không, nên dashboard (chỉ đọc `summary`) không tổng hợp
74
- được — và bất đối xứng 7/10 là bẫy cho người viết dashboard: đọc `summary` rồi tưởng đủ.
75
-
76
- ## Code Generation
77
-
78
- - Never generate code for files not backed by a `.feature` spec (unless `/fix-bug` or `/debug`).
79
- - Always add `@trace.implements` tags on controller-level methods.
80
- - Never overwrite existing business logic without explicit confirmation.
81
- - Build must pass before committing: run `{conventions.build_command}` and fix errors (max 3 retries).
82
-
83
- ## File Operations
84
-
85
- - Prefer **editing** existing files over replacing them entirely.
86
- - When creating new files, check if a similar file already exists first.
87
- - Never delete files unless explicitly instructed.
88
-
89
- ## Communication
90
-
91
- - Report in the language the user writes in (Vietnamese if user uses Vietnamese, English otherwise).
92
- - Keep reports structured: status, artifacts created, next recommended command.
93
- - If unsure about business intent, ask — do not guess and generate wrong spec.
94
-
95
- ## Error Handling
96
-
97
- - If a tool call fails (file not found, build error, etc.), report the specific error clearly.
98
- - Do NOT silently skip errors or pretend success.
99
- - Suggest a concrete fix, not just "please check the error".