@nebulit/embuilder 0.1.39

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 (212) hide show
  1. package/README.md +254 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +138 -0
  4. package/package.json +49 -0
  5. package/templates/.claude/hooks/QUICKSTART.md +256 -0
  6. package/templates/.claude/hooks/README.md +533 -0
  7. package/templates/.claude/hooks/analyze-commit.sh +22 -0
  8. package/templates/.claude/hooks/analyze-commit.ts +518 -0
  9. package/templates/.claude/hooks/analyzers/README.md +198 -0
  10. package/templates/.claude/hooks/analyzers/code-quality-checker.ts +154 -0
  11. package/templates/.claude/hooks/analyzers/code-quality.md +54 -0
  12. package/templates/.claude/hooks/analyzers/commit-blocker-example.ts.disabled +110 -0
  13. package/templates/.claude/hooks/analyzers/commit-policy.md +49 -0
  14. package/templates/.claude/hooks/analyzers/event-model-validator.md +49 -0
  15. package/templates/.claude/hooks/analyzers/event-model-validator.ts +169 -0
  16. package/templates/.claude/hooks/analyzers/example-logger.ts +70 -0
  17. package/templates/.claude/hooks/analyzers/slice-scope-validator.md +81 -0
  18. package/templates/.claude/hooks/check-review-result.sh +47 -0
  19. package/templates/.claude/hooks/prepare-review.sh +34 -0
  20. package/templates/.claude/hooks/review-agent-prompt.md +42 -0
  21. package/templates/.claude/hooks/run-review-agent.sh +124 -0
  22. package/templates/.claude/settings.local.json +37 -0
  23. package/templates/.claude/skills/help/README.md +84 -0
  24. package/templates/.claude/skills/help/SKILL.md +393 -0
  25. package/templates/.claude/skills/help/templates/demo-config.json +6753 -0
  26. package/templates/.claude/skills/sample-slices/SKILL.md +8 -0
  27. package/templates/.claude/skills/sample-slices/templates/.slices/Library/addbook/code-slice.json +124 -0
  28. package/templates/.claude/skills/sample-slices/templates/.slices/Library/addbook/slice.json +255 -0
  29. package/templates/.claude/skills/sample-slices/templates/.slices/Library/availablebooks/slice.json +107 -0
  30. package/templates/.claude/skills/sample-slices/templates/.slices/index.json +20 -0
  31. package/templates/.claude/skills/sample-slices/templates/Cart/additem/slice.json +979 -0
  32. package/templates/.claude/skills/sample-slices/templates/Cart/archiveitem/slice.json +529 -0
  33. package/templates/.claude/skills/sample-slices/templates/Cart/cartitems/slice.json +1072 -0
  34. package/templates/.claude/skills/sample-slices/templates/Cart/cartwithproducts/slice.json +394 -0
  35. package/templates/.claude/skills/sample-slices/templates/Cart/changedprices/slice.json +88 -0
  36. package/templates/.claude/skills/sample-slices/templates/Cart/changeinventory/slice.json +264 -0
  37. package/templates/.claude/skills/sample-slices/templates/Cart/changeprice/slice.json +308 -0
  38. package/templates/.claude/skills/sample-slices/templates/Cart/clearcart/slice.json +358 -0
  39. package/templates/.claude/skills/sample-slices/templates/Cart/inventories/slice.json +203 -0
  40. package/templates/.claude/skills/sample-slices/templates/Cart/publishcart/slice.json +876 -0
  41. package/templates/.claude/skills/sample-slices/templates/Cart/removeitem/slice.json +560 -0
  42. package/templates/.claude/skills/sample-slices/templates/Cart/submitcart/slice.json +708 -0
  43. package/templates/.claude/skills/sample-slices/templates/Cart/submittedcartdata/slice.json +399 -0
  44. package/templates/.claude/skills/sample-slices/templates/index.json +108 -0
  45. package/templates/.claude/skills/slice-automation/SKILL.md +49 -0
  46. package/templates/.claude/skills/slice-state-change/SKILL.md +369 -0
  47. package/templates/.claude/skills/slice-state-change/templates/AddLocation/AddLocation.test.ts.sample +76 -0
  48. package/templates/.claude/skills/slice-state-change/templates/AddLocation/AddLocationCommand.ts.sample +84 -0
  49. package/templates/.claude/skills/slice-state-change/templates/AddLocation/routes.ts.sample +73 -0
  50. package/templates/.claude/skills/slice-state-change/templates/README.md +46 -0
  51. package/templates/.claude/skills/slice-state-view/SKILL.md +336 -0
  52. package/templates/.claude/skills/slice-state-view/templates/Locations/Locations.test.ts.sample +84 -0
  53. package/templates/.claude/skills/slice-state-view/templates/Locations/LocationsProjection.ts.sample +50 -0
  54. package/templates/.claude/skills/slice-state-view/templates/Locations/routes.ts.sample +46 -0
  55. package/templates/.claude/skills/slice-state-view/templates/README.md +109 -0
  56. package/templates/.claude/skills/slice-state-view/templates/Tables/Tables.test.ts.sample +104 -0
  57. package/templates/.claude/skills/slice-state-view/templates/Tables/TablesProjection.ts.sample +59 -0
  58. package/templates/.claude/skills/slice-state-view/templates/Tables/routes.ts.sample +46 -0
  59. package/templates/.claude/skills/slice-state-view/templates/V2__tables.sql +7 -0
  60. package/templates/.claude/skills/slice-state-view/templates/V8__locations.sql +7 -0
  61. package/templates/.claude/skills/test-analyzer/SKILL.md +373 -0
  62. package/templates/.claude/skills/test-analyzer/examples/specification-format.md +143 -0
  63. package/templates/.claude/skills/test-analyzer/examples/state-change-example.md +111 -0
  64. package/templates/.claude/skills/test-analyzer/examples/state-view-example.md +122 -0
  65. package/templates/AGENTS.md +110 -0
  66. package/templates/Claude.md +58 -0
  67. package/templates/README.md +178 -0
  68. package/templates/backend/.env +9 -0
  69. package/templates/backend/BACKEND_AUTH_SETUP.md +183 -0
  70. package/templates/backend/SWAGGER.md +213 -0
  71. package/templates/backend/eslint.config.mjs +31 -0
  72. package/templates/backend/flyway.conf +17 -0
  73. package/templates/backend/package.json +44 -0
  74. package/templates/backend/prd.json.example +64 -0
  75. package/templates/backend/public/assets/images/banner.png +0 -0
  76. package/templates/backend/public/assets/logo.png +0 -0
  77. package/templates/backend/public/file.svg +4 -0
  78. package/templates/backend/public/globe.svg +12 -0
  79. package/templates/backend/public/next.svg +6 -0
  80. package/templates/backend/public/vercel.svg +3 -0
  81. package/templates/backend/public/window.svg +5 -0
  82. package/templates/backend/server.ts +129 -0
  83. package/templates/backend/setup-env.sh +50 -0
  84. package/templates/backend/src/common/assertions.ts +6 -0
  85. package/templates/backend/src/common/db.ts +1 -0
  86. package/templates/backend/src/common/loadPostgresEventstore.ts +16 -0
  87. package/templates/backend/src/common/parseEndpoint.ts +51 -0
  88. package/templates/backend/src/common/replay.ts +9 -0
  89. package/templates/backend/src/common/routes.ts +19 -0
  90. package/templates/backend/src/common/testHelpers.ts +53 -0
  91. package/templates/backend/src/core/readmodel.ts +28 -0
  92. package/templates/backend/src/core/types.ts +26 -0
  93. package/templates/backend/src/process/process.ts +53 -0
  94. package/templates/backend/src/supabase/LoginHandler.ts +36 -0
  95. package/templates/backend/src/supabase/ProtectedPageProps.ts +21 -0
  96. package/templates/backend/src/supabase/README.md +171 -0
  97. package/templates/backend/src/supabase/api.ts +63 -0
  98. package/templates/backend/src/supabase/authMiddleware.ts +53 -0
  99. package/templates/backend/src/supabase/component.ts +12 -0
  100. package/templates/backend/src/supabase/requireUser.ts +72 -0
  101. package/templates/backend/src/supabase/serverProps.ts +25 -0
  102. package/templates/backend/src/supabase/staticProps.ts +10 -0
  103. package/templates/backend/src/swagger.ts +34 -0
  104. package/templates/backend/src/util/assertions.ts +6 -0
  105. package/templates/backend/supabase/config.toml +295 -0
  106. package/templates/backend/supabase/migrations/20260121155918593_catalogentries.sql.sample +23 -0
  107. package/templates/backend/supabase/seed.sql +1 -0
  108. package/templates/backend/tsconfig.json +31 -0
  109. package/templates/frontend/.env.development +3 -0
  110. package/templates/frontend/AGENTS.md +7 -0
  111. package/templates/frontend/README.md +73 -0
  112. package/templates/frontend/components.json +20 -0
  113. package/templates/frontend/eslint.config.js +26 -0
  114. package/templates/frontend/index.html +18 -0
  115. package/templates/frontend/package-lock.json +8347 -0
  116. package/templates/frontend/package.json +94 -0
  117. package/templates/frontend/postcss.config.js +6 -0
  118. package/templates/frontend/public/favicon.ico +0 -0
  119. package/templates/frontend/public/logo.png +0 -0
  120. package/templates/frontend/public/placeholder.svg +1 -0
  121. package/templates/frontend/public/robots.txt +14 -0
  122. package/templates/frontend/src/App.css +42 -0
  123. package/templates/frontend/src/App.tsx +47 -0
  124. package/templates/frontend/src/components/NavLink.tsx +28 -0
  125. package/templates/frontend/src/components/ProtectedRoute.tsx +24 -0
  126. package/templates/frontend/src/components/calendar/Calendar.tsx +302 -0
  127. package/templates/frontend/src/components/layout/DashboardLayout.tsx +21 -0
  128. package/templates/frontend/src/components/layout/Header.tsx +45 -0
  129. package/templates/frontend/src/components/layout/Sidebar.tsx +82 -0
  130. package/templates/frontend/src/components/tables/ReservationTemplates.tsx +189 -0
  131. package/templates/frontend/src/components/ui/accordion.tsx +52 -0
  132. package/templates/frontend/src/components/ui/alert-dialog.tsx +104 -0
  133. package/templates/frontend/src/components/ui/alert.tsx +43 -0
  134. package/templates/frontend/src/components/ui/aspect-ratio.tsx +5 -0
  135. package/templates/frontend/src/components/ui/avatar.tsx +38 -0
  136. package/templates/frontend/src/components/ui/badge.tsx +29 -0
  137. package/templates/frontend/src/components/ui/breadcrumb.tsx +90 -0
  138. package/templates/frontend/src/components/ui/button.tsx +47 -0
  139. package/templates/frontend/src/components/ui/calendar.tsx +54 -0
  140. package/templates/frontend/src/components/ui/card.tsx +43 -0
  141. package/templates/frontend/src/components/ui/carousel.tsx +224 -0
  142. package/templates/frontend/src/components/ui/chart.tsx +303 -0
  143. package/templates/frontend/src/components/ui/checkbox.tsx +26 -0
  144. package/templates/frontend/src/components/ui/collapsible.tsx +9 -0
  145. package/templates/frontend/src/components/ui/command.tsx +132 -0
  146. package/templates/frontend/src/components/ui/context-menu.tsx +178 -0
  147. package/templates/frontend/src/components/ui/dialog.tsx +95 -0
  148. package/templates/frontend/src/components/ui/drawer.tsx +87 -0
  149. package/templates/frontend/src/components/ui/dropdown-menu.tsx +179 -0
  150. package/templates/frontend/src/components/ui/form.tsx +129 -0
  151. package/templates/frontend/src/components/ui/hover-card.tsx +27 -0
  152. package/templates/frontend/src/components/ui/input-otp.tsx +61 -0
  153. package/templates/frontend/src/components/ui/input.tsx +22 -0
  154. package/templates/frontend/src/components/ui/label.tsx +17 -0
  155. package/templates/frontend/src/components/ui/menubar.tsx +207 -0
  156. package/templates/frontend/src/components/ui/navigation-menu.tsx +120 -0
  157. package/templates/frontend/src/components/ui/pagination.tsx +81 -0
  158. package/templates/frontend/src/components/ui/popover.tsx +29 -0
  159. package/templates/frontend/src/components/ui/progress.tsx +23 -0
  160. package/templates/frontend/src/components/ui/radio-group.tsx +36 -0
  161. package/templates/frontend/src/components/ui/resizable.tsx +37 -0
  162. package/templates/frontend/src/components/ui/scroll-area.tsx +38 -0
  163. package/templates/frontend/src/components/ui/select.tsx +143 -0
  164. package/templates/frontend/src/components/ui/separator.tsx +20 -0
  165. package/templates/frontend/src/components/ui/sheet.tsx +107 -0
  166. package/templates/frontend/src/components/ui/sidebar.tsx +637 -0
  167. package/templates/frontend/src/components/ui/skeleton.tsx +7 -0
  168. package/templates/frontend/src/components/ui/slider.tsx +23 -0
  169. package/templates/frontend/src/components/ui/sonner.tsx +27 -0
  170. package/templates/frontend/src/components/ui/stat-card.tsx +44 -0
  171. package/templates/frontend/src/components/ui/switch.tsx +27 -0
  172. package/templates/frontend/src/components/ui/table.tsx +72 -0
  173. package/templates/frontend/src/components/ui/tabs.tsx +53 -0
  174. package/templates/frontend/src/components/ui/textarea.tsx +21 -0
  175. package/templates/frontend/src/components/ui/toast.tsx +111 -0
  176. package/templates/frontend/src/components/ui/toaster.tsx +24 -0
  177. package/templates/frontend/src/components/ui/toggle-group.tsx +49 -0
  178. package/templates/frontend/src/components/ui/toggle.tsx +37 -0
  179. package/templates/frontend/src/components/ui/tooltip.tsx +28 -0
  180. package/templates/frontend/src/components/ui/use-toast.ts +3 -0
  181. package/templates/frontend/src/contexts/AuthContext.tsx +94 -0
  182. package/templates/frontend/src/contexts/RefreshContext.tsx +236 -0
  183. package/templates/frontend/src/hooks/api/index.ts +2 -0
  184. package/templates/frontend/src/hooks/api/useLocations.ts +15 -0
  185. package/templates/frontend/src/hooks/use-mobile.tsx +19 -0
  186. package/templates/frontend/src/hooks/use-toast.ts +186 -0
  187. package/templates/frontend/src/hooks/useApiContext.ts +11 -0
  188. package/templates/frontend/src/index.css +118 -0
  189. package/templates/frontend/src/integrations/supabase/client.ts +9 -0
  190. package/templates/frontend/src/lib/api-client.ts +136 -0
  191. package/templates/frontend/src/lib/api.ts +1028 -0
  192. package/templates/frontend/src/lib/utils.ts +6 -0
  193. package/templates/frontend/src/main.tsx +5 -0
  194. package/templates/frontend/src/pages/Auth.tsx +408 -0
  195. package/templates/frontend/src/pages/Dashboard.tsx +168 -0
  196. package/templates/frontend/src/pages/Menus.tsx +224 -0
  197. package/templates/frontend/src/pages/NotFound.tsx +24 -0
  198. package/templates/frontend/src/pages/Register.tsx +285 -0
  199. package/templates/frontend/src/test/example.test.ts +0 -0
  200. package/templates/frontend/src/test/setup.ts +15 -0
  201. package/templates/frontend/src/types/index.ts +8 -0
  202. package/templates/frontend/src/vite-env.d.ts +1 -0
  203. package/templates/frontend/tailwind.config.ts +101 -0
  204. package/templates/frontend/tsconfig.app.json +31 -0
  205. package/templates/frontend/tsconfig.json +16 -0
  206. package/templates/frontend/tsconfig.node.json +22 -0
  207. package/templates/frontend/vite.config.ts +21 -0
  208. package/templates/frontend/vitest.config.ts +16 -0
  209. package/templates/init.sh +1 -0
  210. package/templates/prompt.md +139 -0
  211. package/templates/ralph.sh +120 -0
  212. package/templates/server.mjs +505 -0
@@ -0,0 +1,143 @@
1
+ # Specification Format Template
2
+
3
+ ## Output File Structure
4
+
5
+ The `code-slice.json` file contains:
6
+
7
+ ```json
8
+ {
9
+ "id": "<slice-id-from-slice.json>",
10
+ "title": "<slice-title-from-slice.json>",
11
+ "specifications": [...]
12
+ }
13
+ ```
14
+
15
+ **CRITICAL:**
16
+ - MUST include `id` and `title` fields copied from the corresponding `slice.json` file
17
+ - NO commands, events, readmodels, or other slice metadata (only id, title, and specifications)
18
+ - Each specification must have complete nested objects with fields, NOT simple strings
19
+ - Given/when/then must be arrays of objects with full field definitions
20
+
21
+ ## Specification Object Template
22
+
23
+ ```json
24
+ {
25
+ "vertical": false,
26
+ "id": "<generated-id>",
27
+ "sliceName": "slice: <SliceName>",
28
+ "title": "spec: <test description>",
29
+ "given": [
30
+ {
31
+ "title": "<Event Title>",
32
+ "tags": [],
33
+ "id": "<generated-id>",
34
+ "index": 0,
35
+ "specRow": -1,
36
+ "type": "SPEC_EVENT",
37
+ "fields": [
38
+ {
39
+ "name": "fieldName",
40
+ "type": "String|Date|UUID|Integer|Boolean|Decimal",
41
+ "subfields": [],
42
+ "cardinality": "Single",
43
+ "example": ""
44
+ }
45
+ ],
46
+ "linkedId": "<linked-event-id-from-elements>"
47
+ }
48
+ ],
49
+ "when": [
50
+ {
51
+ "title": "<Command Title>",
52
+ "tags": [],
53
+ "id": "<generated-id>",
54
+ "index": 0,
55
+ "specRow": -1,
56
+ "type": "SPEC_COMMAND",
57
+ "fields": [
58
+ {
59
+ "name": "fieldName",
60
+ "type": "String|Date|UUID|Integer|Boolean|Decimal",
61
+ "subfields": [],
62
+ "cardinality": "Single",
63
+ "example": ""
64
+ }
65
+ ],
66
+ "linkedId": "<linked-command-id-from-elements>"
67
+ }
68
+ ],
69
+ "then": [
70
+ {
71
+ "title": "<Event or Error Title>",
72
+ "tags": [],
73
+ "id": "<generated-id>",
74
+ "index": 0,
75
+ "specRow": -1,
76
+ "type": "SPEC_EVENT|SPEC_ERROR|SPEC_READMODEL",
77
+ "fields": [
78
+ {
79
+ "name": "fieldName",
80
+ "type": "String|Date|UUID|Integer|Boolean|Decimal",
81
+ "subfields": [],
82
+ "cardinality": "Single",
83
+ "example": ""
84
+ }
85
+ ],
86
+ "linkedId": "<linked-event-id-from-elements>"
87
+ }
88
+ ],
89
+ "comments": [],
90
+ "linkedId": "<same-as-specification-id-above>"
91
+ }
92
+ ```
93
+
94
+ ## Given/When/Then Structure
95
+
96
+ ### For STATE_CHANGE Slices
97
+
98
+ - **given**: Array of event objects (preconditions - events that happened before)
99
+ - **when**: Array with single command object (the action being tested)
100
+ - **then**: Array of event/error objects (what happened as a result)
101
+
102
+ ### For STATE_VIEW Slices
103
+
104
+ - **given**: Array of event objects (events to be projected)
105
+ - **when**: Empty array `[]` (no command in projections)
106
+ - **then**: Array with readmodel assertion objects (SPEC_READMODEL type)
107
+
108
+ ## Field Object Structure
109
+
110
+ Each field in the `fields` array must have:
111
+
112
+ ```json
113
+ {
114
+ "name": "fieldName",
115
+ "type": "String|Date|UUID|Integer|Boolean|Decimal|Integer|List",
116
+ "subfields": [],
117
+ "cardinality": "Single|Multiple",
118
+ "example": "actual value from test"
119
+ }
120
+ ```
121
+
122
+ ### Field Type Mapping
123
+
124
+ Infer types from test data:
125
+ - String values → `"String"`
126
+ - UUID format → `"UUID"`
127
+ - Date strings (ISO format) → `"Date"` or `"DateTime"`
128
+ - Numbers with decimals → `"Decimal"`
129
+ - Whole numbers → `"Integer"`
130
+ - Boolean values → `"Boolean"`
131
+ - Arrays → `"List"` with element type
132
+
133
+ ### Cardinality
134
+
135
+ - `"Single"` - for single values
136
+ - `"Multiple"` - for arrays
137
+
138
+ ## Element Types
139
+
140
+ - `SPEC_COMMAND` - Command in `when` array (STATE_CHANGE only)
141
+ - `SPEC_EVENT` - Event in `given` or `then` arrays
142
+ - `SPEC_ERROR` - Error in `then` array (when test uses `thenThrows()`)
143
+ - `SPEC_READMODEL` - Readmodel assertion in `then` array (STATE_VIEW only)
@@ -0,0 +1,111 @@
1
+ # STATE_CHANGE Slice Example
2
+
3
+ ## Input Test File
4
+
5
+ **File:** `src/slices/ActivateShift/ActivateShift.test.ts`
6
+
7
+ ```typescript
8
+ describe('Activate Shift Specification', () => {
9
+ it('spec: Activate Shift - scenario', () => {
10
+ given([{
11
+ type: 'ShiftCreated',
12
+ data: { shiftId: '123', restaurantId: 'r1', startDate: '2026-01-15' }
13
+ }])
14
+ .when({ type: 'ActivateShift', data: { shiftId: '123', restaurantId: 'r1' }})
15
+ .then([{
16
+ type: 'ShiftActivated',
17
+ data: { shiftId: '123', restaurantId: 'r1' }
18
+ }])
19
+ });
20
+
21
+ it('spec: Activate Shift - shift not found', () => {
22
+ given([])
23
+ .when({ type: 'ActivateShift', data: { shiftId: '999', restaurantId: 'r1' }})
24
+ .thenThrows()
25
+ });
26
+ });
27
+ ```
28
+
29
+ ## Processing Steps
30
+
31
+ 1. Slice name detected: "ActivateShift" (from file path)
32
+ 2. Looks up in `.slices/index.json` → finds entry with `"slice": "slice: Activate Shift"`
33
+ 3. Gets folder: "activateshift" and context: "Restaurant Management"
34
+ 4. Reads: `.slices/Restaurant Management/activateshift/slice.json`
35
+ 5. Checks specifications array in slice.json for existing test specs
36
+ 6. First test found in slice.json specifications array → not included in code-slice.json
37
+ 7. Second test (error case) NOT in slice.json specifications array → included in code-slice.json
38
+ 8. **CRITICAL: Looks up real IDs from slice.json:**
39
+ - Command "Activate Shift" → finds `"id": "3458764657124632223"` in slice.json commands array
40
+ - Uses this real ID as `linkedId` for the command in the specification
41
+
42
+ ## Output
43
+
44
+ **File:** `src/slices/ActivateShift/code-slice.json`
45
+
46
+ ```json
47
+ {
48
+ "id": "3458764657124632353",
49
+ "title": "slice: Activate Shift",
50
+ "specifications": [
51
+ {
52
+ "vertical": false,
53
+ "id": "3458764660410459999",
54
+ "sliceName": "slice: Activate Shift",
55
+ "title": "spec: Activate Shift - shift not found",
56
+ "given": [],
57
+ "when": [
58
+ {
59
+ "title": "Activate Shift",
60
+ "tags": [],
61
+ "id": "3458764660410459998",
62
+ "index": 0,
63
+ "specRow": -1,
64
+ "type": "SPEC_COMMAND",
65
+ "fields": [
66
+ {
67
+ "name": "shiftId",
68
+ "type": "String",
69
+ "subfields": [],
70
+ "cardinality": "Single",
71
+ "example": "999"
72
+ },
73
+ {
74
+ "name": "restaurantId",
75
+ "type": "String",
76
+ "subfields": [],
77
+ "cardinality": "Single",
78
+ "example": "r1"
79
+ }
80
+ ],
81
+ "linkedId": "3458764657124632223"
82
+ }
83
+ ],
84
+ "then": [
85
+ {
86
+ "title": "Shift not found error",
87
+ "tags": [],
88
+ "id": "3458764660410459997",
89
+ "index": 0,
90
+ "specRow": -1,
91
+ "type": "SPEC_ERROR",
92
+ "fields": []
93
+ }
94
+ ],
95
+ "comments": [],
96
+ "linkedId": "3458764660410459999"
97
+ }
98
+ ]
99
+ }
100
+ ```
101
+
102
+ ## Key Points
103
+
104
+ - **Top-level fields**: `id` and `title` are copied from `.slices/Restaurant Management/activateshift/slice.json`
105
+ - **Given**: Empty array (no preconditions for error case)
106
+ - **When**: Single command object with full field definitions
107
+ - **CRITICAL**: `linkedId` is `"3458764657124632223"` - the REAL ID from slice.json commands array for "Activate Shift" command
108
+ - **Then**: Error object (SPEC_ERROR type) with empty fields
109
+ - Errors have no `linkedId` field (they don't represent elements in slice.json)
110
+ - Only the error case is included because the happy path specification already exists in slice.json specifications array
111
+ - If slice.json specifications array is empty, ALL test specifications would be included in code-slice.json
@@ -0,0 +1,122 @@
1
+ # STATE_VIEW Slice Example
2
+
3
+ ## Input Test File
4
+
5
+ **File:** `src/slices/ActivatedOnlineReservations/OnlineReservationStatus.test.ts`
6
+
7
+ ```typescript
8
+ describe('OnlineReservationStatus Specification', () => {
9
+ it('spec: Online reservation activated - sets active to true', async () => {
10
+ await given([{type: 'OnlineReservationActivated', data: {restaurantId: 'r1'}}])
11
+ .when([]) // empty for projections
12
+ .then(assertReadModel);
13
+ });
14
+
15
+ it('spec: Toggle online reservation - activates then deactivates', async () => {
16
+ await given([
17
+ {type: 'OnlineReservationActivated', data: {restaurantId: 'r1'}},
18
+ {type: 'OnlineReservationDeactivated', data: {restaurantId: 'r1'}}
19
+ ])
20
+ .when([]) // empty for projections
21
+ .then(assertReadModel);
22
+ });
23
+ });
24
+ ```
25
+
26
+ ## Processing Steps
27
+
28
+ 1. Slice name detected: "OnlineReservationStatus" (from file path or describe block)
29
+ 2. Looks up in `.slices/index.json` → searches for matching slice title
30
+ 3. Gets folder and context from index
31
+ 4. Reads corresponding `.slices/<context>/<folder>/slice.json`
32
+ 5. Compares test events with slice.json
33
+ 6. If "toggle" scenario not in slice.json → include in specifications
34
+ 7. **CRITICAL: Looks up real event IDs:**
35
+ - Events may be defined in other slices, but referenced in readmodel dependencies
36
+ - Search for event IDs in the readmodel's `dependencies` array with `type: "INBOUND"`
37
+ - "Online Reservation Activated" → ID `"3458764659470382480"` (from dependencies)
38
+ - "Online Reservation Deactivated" → ID `"3458764659470541221"` (from dependencies)
39
+
40
+ ## Output
41
+
42
+ **File:** `src/slices/ActivatedOnlineReservations/code-slice.json`
43
+
44
+ ```json
45
+ {
46
+ "id": "3458764659470991969",
47
+ "title": "slice: Activated Online reservations",
48
+ "specifications": [
49
+ {
50
+ "vertical": false,
51
+ "id": "3458764660410460001",
52
+ "sliceName": "slice: Online Reservation Status",
53
+ "title": "spec: Toggle online reservation - activates then deactivates",
54
+ "given": [
55
+ {
56
+ "title": "Online Reservation Activated",
57
+ "tags": [],
58
+ "id": "3458764660410460002",
59
+ "index": 0,
60
+ "specRow": -1,
61
+ "type": "SPEC_EVENT",
62
+ "fields": [
63
+ {
64
+ "name": "restaurantId",
65
+ "type": "String",
66
+ "subfields": [],
67
+ "cardinality": "Single",
68
+ "example": "r1"
69
+ }
70
+ ],
71
+ "linkedId": "3458764659470382480"
72
+ },
73
+ {
74
+ "title": "Online Reservation Deactivated",
75
+ "tags": [],
76
+ "id": "3458764660410460003",
77
+ "index": 1,
78
+ "specRow": -1,
79
+ "type": "SPEC_EVENT",
80
+ "fields": [
81
+ {
82
+ "name": "restaurantId",
83
+ "type": "String",
84
+ "subfields": [],
85
+ "cardinality": "Single",
86
+ "example": "r1"
87
+ }
88
+ ],
89
+ "linkedId": "3458764659470541221"
90
+ }
91
+ ],
92
+ "when": [],
93
+ "then": [
94
+ {
95
+ "title": "active = false in read model",
96
+ "tags": [],
97
+ "id": "3458764660410460004",
98
+ "index": 0,
99
+ "specRow": -1,
100
+ "type": "SPEC_READMODEL",
101
+ "fields": []
102
+ }
103
+ ],
104
+ "comments": [],
105
+ "linkedId": "3458764660410460001"
106
+ }
107
+ ]
108
+ }
109
+ ```
110
+
111
+ ## Key Points
112
+
113
+ - **Top-level fields**: `id` and `title` are copied from the corresponding `slice.json` in `.slices/Restaurant Management/activatedonlinereservations/slice.json`
114
+ - **Specification linkedId**: `"3458764660410460001"` matches the specification's `id` field (self-reference)
115
+ - **Given**: Array of events to be projected (this is where events go for STATE_VIEW)
116
+ - **CRITICAL**: Each event's `linkedId` uses the REAL event ID from slice.json
117
+ - "Online Reservation Activated" → `linkedId: "3458764659470382480"`
118
+ - "Online Reservation Deactivated" → `linkedId: "3458764659470541221"`
119
+ - For STATE_VIEW slices, look for event IDs in the readmodel's `dependencies` array
120
+ - **When**: Empty array (no command in projections)
121
+ - **Then**: Readmodel assertion (SPEC_READMODEL type)
122
+ - Only the "toggle" scenario is included because it represents additional behavior beyond basic projection
@@ -0,0 +1,110 @@
1
+ # Agent Learnings
2
+
3
+ This file captures patterns, gotchas, and best practices discovered during development.
4
+ Update this file as you learn new patterns that future iterations should know.
5
+
6
+ ## Core Principles
7
+
8
+ ### Event Model as Source of Truth
9
+ - Event model JSON files define the desired state
10
+ - Code must match the event model specification
11
+ - When in doubt, check the event model
12
+
13
+ ### File Organization
14
+ - Each slice lives in `src/slices/{SliceName}/`
15
+ - Keep slices self-contained and focused
16
+ - Follow consistent naming conventions
17
+
18
+ ## Event-Driven Architecture Patterns
19
+
20
+ ### State-Change Slices (Commands)
21
+ - Use `decide()` for business logic validation
22
+ - Use `evolve()` for state reconstruction from events
23
+ - State should only track what's needed for validation
24
+ - Simple commands can have empty state `{}`
25
+
26
+ ### State-View Slices (Queries)
27
+ - Projections build read models from events
28
+ - Read models are optimized for querying
29
+ - One read model per use case/view
30
+
31
+ ### Automation Slices
32
+ - Automations = State-Change + CRON processor
33
+ - Read from TODO list (work queue) read models
34
+ - Process one item at a time with `.limit(1)`
35
+ - Always wrap command execution in try-catch
36
+
37
+ ## Common Patterns
38
+
39
+ ### Stream IDs
40
+ - Use consistent stream ID patterns per aggregate
41
+ - Format: `{aggregate}-{id}` or `{context}-{aggregate}-{id}`
42
+ - Document stream ID patterns in each slice
43
+
44
+ ### Metadata
45
+ - Always include `correlation_id` and `causation_id`
46
+ - Use optional chaining: `metadata?.field`
47
+ - Include tenant/user IDs for multi-tenancy
48
+
49
+ ### Testing
50
+ - Use `DeciderSpecification.for()` for state-change tests
51
+ - Use `PostgreSQLProjectionSpec.for()` for state-view tests
52
+ - Test format: given/when/then
53
+ - Include both happy path and error scenarios
54
+
55
+ ## Database Patterns
56
+
57
+ ### Migrations
58
+ - Never modify existing migrations
59
+ - Always create new migrations for changes
60
+ - Use sequential version numbers (V1, V2, V3...)
61
+ - Check latest migration before creating new one
62
+
63
+ ### Tables
64
+ - Use snake_case for table and column names
65
+ - Include proper indexes for query performance
66
+ - Add tenant ID columns for multi-tenancy
67
+
68
+ ## TypeScript Best Practices
69
+
70
+ ### Types
71
+ - Use strict TypeScript mode
72
+ - Define explicit types for commands, events, and state
73
+ - Avoid `any` - use `unknown` if needed
74
+
75
+ ### Imports
76
+ - Use ES modules (import/export)
77
+ - Organize imports: external, internal, types
78
+ - Keep imports minimal and specific
79
+
80
+ ## Error Handling
81
+
82
+ ### Validation Errors
83
+ - Throw descriptive error messages
84
+ - Use error codes for common failures
85
+ - Map errors to user-friendly messages in routes
86
+
87
+ ### HTTP Status Codes
88
+ - 200: Success
89
+ - 400: Bad request (validation error)
90
+ - 401: Unauthorized
91
+ - 409: Conflict (business rule violation)
92
+ - 500: Server error
93
+
94
+ ## Code Quality
95
+
96
+ ### Before Committing
97
+ - Run `npm run build` - ensure TypeScript compiles
98
+ - Run `npm run test` - ensure all tests pass
99
+ - Update this file with new learnings
100
+ - Update progress.txt with iteration summary
101
+
102
+ ### Clean Code
103
+ - Follow existing patterns in codebase
104
+ - Keep functions focused and small
105
+ - Use descriptive names for variables and functions
106
+ - Comment complex business logic
107
+
108
+ ## Future Development Notes
109
+
110
+ Add your learnings here as you discover patterns specific to your domain and architecture.
@@ -0,0 +1,58 @@
1
+ # Project Configuration
2
+
3
+ Read Events in src/events to understand the global structure.
4
+
5
+ ## Framework & Styling
6
+
7
+ - **CSS Framework**: Use Bulma CSS exclusively for all styling
8
+ - **Assumption**: Bulma CSS is already available and imported in the project
9
+ - **Styling Guidelines**:
10
+ - Use Bulma's utility classes and components
11
+ - Follow Bulma's naming conventions and class structure
12
+ - Leverage Bulma's responsive design features
13
+ - Prefer Bulma components over custom CSS
14
+
15
+ ## File Structure Constraints
16
+
17
+ - **Strict Path Limitation**: if not instructed otherwise, only check `src/slices/{slicename}/*.ts`
18
+ - **Slice Organization**: Each feature/domain should be organized as a separate slice
19
+
20
+ ## Code Standards
21
+
22
+ - **Language**: TypeScript only
23
+ - **Module System**: Use ES modules (import/export)
24
+ - **Type Safety**: Ensure all code is properly typed
25
+
26
+ ## Development Guidelines
27
+
28
+ 1. Each slice should be self-contained and focused on a specific domain
29
+ 2. Use Bulma's grid system, components, and utilities for all UI-related code
30
+ 3. Maintain clear separation of concerns within each slice
31
+ 4. Follow TypeScript best practices for type definitions and interfaces
32
+
33
+ Only check src/slices/{slice}/*.ts, do not check subfolders, if not explicitely tasked to build the UI.
34
+ If not tasked explicitely to change routes, ignore routes*.ts
35
+
36
+ Ignore case for files and slices in prompts. "CartItems" slice is the same as "cartitemsrun t"
37
+
38
+ Do not change files with tests unless explicitely instructed: *.test.ts
39
+
40
+ After you are done, automatically run the tests for the slice that was edited.
41
+
42
+ ## Example Slice Structure
43
+
44
+ ```
45
+ src/slices/
46
+ ├── {slice-name}/
47
+ │ ├── CommandHandler.ts
48
+ │ ├── ui/
49
+ │ └── routes.ts
50
+ ```
51
+
52
+ ## Bulma Integration Notes
53
+
54
+ - Utilize Bulma's component library: navbar, cards, buttons, forms, modals, etc.
55
+ - Apply Bulma's spacing utilities: `m-*`, `p-*`, `has-text-*`, `has-background-*`
56
+ - Use Bulma's flexbox utilities for layouts
57
+ - Implement responsive design with Bulma's breakpoint classes
58
+ - Leverage Bulma's color palette and typography classes