@tailor-platform/erp-kit 0.0.1 → 0.1.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 (231) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +196 -28
  4. package/dist/cli.js +914 -0
  5. package/package.json +67 -8
  6. package/schemas/app-compose/actors.yml +34 -0
  7. package/schemas/app-compose/business-flow.yml +50 -0
  8. package/schemas/app-compose/requirements.yml +33 -0
  9. package/schemas/app-compose/resolver.yml +47 -0
  10. package/schemas/app-compose/screen.yml +81 -0
  11. package/schemas/app-compose/story.yml +67 -0
  12. package/schemas/module/command.yml +52 -0
  13. package/schemas/module/feature.yml +58 -0
  14. package/schemas/module/model.yml +70 -0
  15. package/schemas/module/module.yml +50 -0
  16. package/skills/1-module-docs/SKILL.md +111 -0
  17. package/skills/1-module-docs/references/structure.md +22 -0
  18. package/skills/2-module-feature-breakdown/SKILL.md +72 -0
  19. package/skills/2-module-feature-breakdown/references/commands.md +48 -0
  20. package/skills/2-module-feature-breakdown/references/models.md +29 -0
  21. package/skills/2-module-feature-breakdown/references/structure.md +22 -0
  22. package/skills/3-module-doc-review/SKILL.md +236 -0
  23. package/skills/3-module-doc-review/references/commands.md +54 -0
  24. package/skills/3-module-doc-review/references/models.md +29 -0
  25. package/skills/3-module-doc-review/references/testing.md +37 -0
  26. package/skills/4-module-tdd-implementation/SKILL.md +74 -0
  27. package/skills/4-module-tdd-implementation/references/commands.md +45 -0
  28. package/skills/4-module-tdd-implementation/references/db-relations.md +69 -0
  29. package/skills/4-module-tdd-implementation/references/errors.md +7 -0
  30. package/skills/4-module-tdd-implementation/references/exports.md +8 -0
  31. package/skills/4-module-tdd-implementation/references/models.md +30 -0
  32. package/skills/4-module-tdd-implementation/references/structure.md +22 -0
  33. package/skills/4-module-tdd-implementation/references/testing.md +37 -0
  34. package/skills/5-module-implementation-review/SKILL.md +408 -0
  35. package/skills/5-module-implementation-review/references/commands.md +45 -0
  36. package/skills/5-module-implementation-review/references/errors.md +7 -0
  37. package/skills/5-module-implementation-review/references/exports.md +8 -0
  38. package/skills/5-module-implementation-review/references/models.md +30 -0
  39. package/skills/5-module-implementation-review/references/testing.md +29 -0
  40. package/skills/app-compose-1-requirement-analysis/SKILL.md +89 -0
  41. package/skills/app-compose-1-requirement-analysis/references/structure.md +27 -0
  42. package/skills/app-compose-2-requirements-breakdown/SKILL.md +95 -0
  43. package/skills/app-compose-2-requirements-breakdown/references/screen-detailview.md +106 -0
  44. package/skills/app-compose-2-requirements-breakdown/references/screen-form.md +139 -0
  45. package/skills/app-compose-2-requirements-breakdown/references/screen-listview.md +153 -0
  46. package/skills/app-compose-2-requirements-breakdown/references/structure.md +27 -0
  47. package/skills/app-compose-3-doc-review/SKILL.md +116 -0
  48. package/skills/app-compose-3-doc-review/references/structure.md +27 -0
  49. package/skills/app-compose-4-design-mock/SKILL.md +256 -0
  50. package/skills/app-compose-4-design-mock/references/component.md +50 -0
  51. package/skills/app-compose-4-design-mock/references/screen-detailview.md +106 -0
  52. package/skills/app-compose-4-design-mock/references/screen-form.md +139 -0
  53. package/skills/app-compose-4-design-mock/references/screen-listview.md +153 -0
  54. package/skills/app-compose-4-design-mock/references/structure.md +27 -0
  55. package/skills/app-compose-5-design-mock-review/SKILL.md +290 -0
  56. package/skills/app-compose-5-design-mock-review/references/component.md +50 -0
  57. package/skills/app-compose-5-design-mock-review/references/screen-detailview.md +106 -0
  58. package/skills/app-compose-5-design-mock-review/references/screen-form.md +139 -0
  59. package/skills/app-compose-5-design-mock-review/references/screen-listview.md +153 -0
  60. package/skills/app-compose-6-implementation-spec/SKILL.md +127 -0
  61. package/skills/app-compose-6-implementation-spec/references/auth.md +72 -0
  62. package/skills/app-compose-6-implementation-spec/references/structure.md +27 -0
  63. package/skills/mock-scenario/SKILL.md +118 -0
  64. package/src/app.ts +1 -0
  65. package/src/cli.ts +120 -0
  66. package/src/commands/check.test.ts +30 -0
  67. package/src/commands/check.ts +66 -0
  68. package/src/commands/init.test.ts +88 -0
  69. package/src/commands/init.ts +120 -0
  70. package/src/commands/mock/index.ts +53 -0
  71. package/src/commands/mock/start.ts +179 -0
  72. package/src/commands/mock/validate.test.ts +185 -0
  73. package/src/commands/mock/validate.ts +198 -0
  74. package/src/commands/scaffold.test.ts +76 -0
  75. package/src/commands/scaffold.ts +119 -0
  76. package/src/commands/sync-check.test.ts +125 -0
  77. package/src/commands/sync-check.ts +182 -0
  78. package/src/integration.test.ts +63 -0
  79. package/src/mdschema.ts +48 -0
  80. package/src/mockServer.ts +55 -0
  81. package/src/module.ts +86 -0
  82. package/src/modules/accounting/.gitkeep +0 -0
  83. package/src/modules/coa-management/.gitkeep +0 -0
  84. package/src/modules/inventory/.gitkeep +0 -0
  85. package/src/modules/manufacturing/.gitkeep +0 -0
  86. package/src/modules/primitives/README.md +39 -0
  87. package/src/modules/primitives/command/activateCategory.test.ts +75 -0
  88. package/src/modules/primitives/command/activateCategory.ts +50 -0
  89. package/src/modules/primitives/command/activateCurrency.test.ts +70 -0
  90. package/src/modules/primitives/command/activateCurrency.ts +50 -0
  91. package/src/modules/primitives/command/activateUnit.test.ts +53 -0
  92. package/src/modules/primitives/command/activateUnit.ts +50 -0
  93. package/src/modules/primitives/command/convertAmount.test.ts +275 -0
  94. package/src/modules/primitives/command/convertAmount.ts +126 -0
  95. package/src/modules/primitives/command/convertQuantity.test.ts +219 -0
  96. package/src/modules/primitives/command/convertQuantity.ts +73 -0
  97. package/src/modules/primitives/command/createCategory.test.ts +126 -0
  98. package/src/modules/primitives/command/createCategory.ts +89 -0
  99. package/src/modules/primitives/command/createCurrency.test.ts +191 -0
  100. package/src/modules/primitives/command/createCurrency.ts +77 -0
  101. package/src/modules/primitives/command/createExchangeRate.test.ts +216 -0
  102. package/src/modules/primitives/command/createExchangeRate.ts +91 -0
  103. package/src/modules/primitives/command/createUnit.test.ts +214 -0
  104. package/src/modules/primitives/command/createUnit.ts +88 -0
  105. package/src/modules/primitives/command/deactivateCategory.test.ts +97 -0
  106. package/src/modules/primitives/command/deactivateCategory.ts +62 -0
  107. package/src/modules/primitives/command/deactivateCurrency.test.ts +85 -0
  108. package/src/modules/primitives/command/deactivateCurrency.ts +55 -0
  109. package/src/modules/primitives/command/deactivateUnit.test.ts +78 -0
  110. package/src/modules/primitives/command/deactivateUnit.ts +62 -0
  111. package/src/modules/primitives/command/setBaseCurrency.test.ts +98 -0
  112. package/src/modules/primitives/command/setBaseCurrency.ts +74 -0
  113. package/src/modules/primitives/command/setReferenceUnit.test.ts +108 -0
  114. package/src/modules/primitives/command/setReferenceUnit.ts +84 -0
  115. package/src/modules/primitives/db/currency.ts +30 -0
  116. package/src/modules/primitives/db/exchangeRate.ts +28 -0
  117. package/src/modules/primitives/db/unit.ts +32 -0
  118. package/src/modules/primitives/db/uomCategory.ts +32 -0
  119. package/src/modules/primitives/docs/commands/ActivateCategory.md +34 -0
  120. package/src/modules/primitives/docs/commands/ActivateCurrency.md +33 -0
  121. package/src/modules/primitives/docs/commands/ActivateUnit.md +34 -0
  122. package/src/modules/primitives/docs/commands/ConvertAmount.md +50 -0
  123. package/src/modules/primitives/docs/commands/ConvertQuantity.md +43 -0
  124. package/src/modules/primitives/docs/commands/CreateCategory.md +44 -0
  125. package/src/modules/primitives/docs/commands/CreateCurrency.md +47 -0
  126. package/src/modules/primitives/docs/commands/CreateExchangeRate.md +48 -0
  127. package/src/modules/primitives/docs/commands/CreateUnit.md +48 -0
  128. package/src/modules/primitives/docs/commands/DeactivateCategory.md +38 -0
  129. package/src/modules/primitives/docs/commands/DeactivateCurrency.md +38 -0
  130. package/src/modules/primitives/docs/commands/DeactivateUnit.md +38 -0
  131. package/src/modules/primitives/docs/commands/SetBaseCurrency.md +39 -0
  132. package/src/modules/primitives/docs/commands/SetReferenceUnit.md +43 -0
  133. package/src/modules/primitives/docs/features/currency-definitions.md +55 -0
  134. package/src/modules/primitives/docs/features/exchange-rates.md +61 -0
  135. package/src/modules/primitives/docs/features/unit-conversion.md +66 -0
  136. package/src/modules/primitives/docs/features/uom-categories.md +52 -0
  137. package/src/modules/primitives/docs/models/Currency.md +45 -0
  138. package/src/modules/primitives/docs/models/ExchangeRate.md +33 -0
  139. package/src/modules/primitives/docs/models/Unit.md +46 -0
  140. package/src/modules/primitives/docs/models/UoMCategory.md +44 -0
  141. package/src/modules/primitives/generated/kysely-tailordb.ts +95 -0
  142. package/src/modules/primitives/index.ts +40 -0
  143. package/src/modules/primitives/lib/errors.ts +138 -0
  144. package/src/modules/primitives/lib/types.ts +20 -0
  145. package/src/modules/primitives/module.ts +66 -0
  146. package/src/modules/primitives/permissions.ts +18 -0
  147. package/src/modules/primitives/tailor.config.ts +11 -0
  148. package/src/modules/primitives/testing/fixtures.ts +161 -0
  149. package/src/modules/product-management/.gitkeep +0 -0
  150. package/src/modules/purchase/.gitkeep +0 -0
  151. package/src/modules/sales/.gitkeep +0 -0
  152. package/src/modules/shared/createContext.test.ts +39 -0
  153. package/src/modules/shared/createContext.ts +15 -0
  154. package/src/modules/shared/defineCommand.test.ts +42 -0
  155. package/src/modules/shared/defineCommand.ts +19 -0
  156. package/src/modules/shared/definePermissions.test.ts +146 -0
  157. package/src/modules/shared/definePermissions.ts +94 -0
  158. package/src/modules/shared/entityTypes.ts +15 -0
  159. package/src/modules/shared/errors.ts +22 -0
  160. package/src/modules/shared/index.ts +1 -0
  161. package/src/modules/shared/internal.ts +13 -0
  162. package/src/modules/shared/requirePermission.test.ts +47 -0
  163. package/src/modules/shared/requirePermission.ts +8 -0
  164. package/src/modules/shared/types.ts +4 -0
  165. package/src/modules/supplier-management/.gitkeep +0 -0
  166. package/src/modules/supplier-portal/.gitkeep +0 -0
  167. package/src/modules/testing/index.ts +120 -0
  168. package/src/modules/user-management/README.md +38 -0
  169. package/src/modules/user-management/command/activateUser.test.ts +112 -0
  170. package/src/modules/user-management/command/activateUser.ts +67 -0
  171. package/src/modules/user-management/command/assignPermissionToRole.test.ts +119 -0
  172. package/src/modules/user-management/command/assignPermissionToRole.ts +87 -0
  173. package/src/modules/user-management/command/assignRoleToUser.test.ts +162 -0
  174. package/src/modules/user-management/command/assignRoleToUser.ts +93 -0
  175. package/src/modules/user-management/command/createPermission.test.ts +143 -0
  176. package/src/modules/user-management/command/createPermission.ts +66 -0
  177. package/src/modules/user-management/command/createRole.test.ts +115 -0
  178. package/src/modules/user-management/command/createRole.ts +52 -0
  179. package/src/modules/user-management/command/createUser.test.ts +198 -0
  180. package/src/modules/user-management/command/createUser.ts +85 -0
  181. package/src/modules/user-management/command/deactivateUser.test.ts +112 -0
  182. package/src/modules/user-management/command/deactivateUser.ts +67 -0
  183. package/src/modules/user-management/command/logAuditEvent.test.ts +179 -0
  184. package/src/modules/user-management/command/logAuditEvent.ts +59 -0
  185. package/src/modules/user-management/command/reactivateUser.test.ts +115 -0
  186. package/src/modules/user-management/command/reactivateUser.ts +67 -0
  187. package/src/modules/user-management/command/revokePermissionFromRole.test.ts +112 -0
  188. package/src/modules/user-management/command/revokePermissionFromRole.ts +81 -0
  189. package/src/modules/user-management/command/revokeRoleFromUser.test.ts +112 -0
  190. package/src/modules/user-management/command/revokeRoleFromUser.ts +81 -0
  191. package/src/modules/user-management/db/auditEvent.ts +47 -0
  192. package/src/modules/user-management/db/permission.ts +31 -0
  193. package/src/modules/user-management/db/role.ts +28 -0
  194. package/src/modules/user-management/db/rolePermission.ts +44 -0
  195. package/src/modules/user-management/db/user.ts +38 -0
  196. package/src/modules/user-management/db/userRole.ts +44 -0
  197. package/src/modules/user-management/docs/commands/ActivateUser.md +36 -0
  198. package/src/modules/user-management/docs/commands/AssignPermissionToRole.md +39 -0
  199. package/src/modules/user-management/docs/commands/AssignRoleToUser.md +43 -0
  200. package/src/modules/user-management/docs/commands/CreatePermission.md +35 -0
  201. package/src/modules/user-management/docs/commands/CreateRole.md +35 -0
  202. package/src/modules/user-management/docs/commands/CreateUser.md +41 -0
  203. package/src/modules/user-management/docs/commands/DeactivateUser.md +38 -0
  204. package/src/modules/user-management/docs/commands/LogAuditEvent.md +37 -0
  205. package/src/modules/user-management/docs/commands/ReactivateUser.md +37 -0
  206. package/src/modules/user-management/docs/commands/RevokePermissionFromRole.md +40 -0
  207. package/src/modules/user-management/docs/commands/RevokeRoleFromUser.md +40 -0
  208. package/src/modules/user-management/docs/features/audit-trail.md +80 -0
  209. package/src/modules/user-management/docs/features/role-based-access-control.md +76 -0
  210. package/src/modules/user-management/docs/features/user-account-management.md +64 -0
  211. package/src/modules/user-management/docs/models/AuditEvent.md +34 -0
  212. package/src/modules/user-management/docs/models/Permission.md +31 -0
  213. package/src/modules/user-management/docs/models/Role.md +31 -0
  214. package/src/modules/user-management/docs/models/RolePermission.md +33 -0
  215. package/src/modules/user-management/docs/models/User.md +47 -0
  216. package/src/modules/user-management/docs/models/UserRole.md +34 -0
  217. package/src/modules/user-management/docs/plans/2026-01-30-flattened-permissions-design.md +52 -0
  218. package/src/modules/user-management/executor/recomputeOnRolePermissionChange.ts +61 -0
  219. package/src/modules/user-management/generated/enums.ts +24 -0
  220. package/src/modules/user-management/generated/kysely-tailordb.ts +112 -0
  221. package/src/modules/user-management/index.ts +32 -0
  222. package/src/modules/user-management/lib/errors.ts +81 -0
  223. package/src/modules/user-management/lib/recomputeUserPermissions.ts +53 -0
  224. package/src/modules/user-management/lib/types.ts +31 -0
  225. package/src/modules/user-management/module.ts +77 -0
  226. package/src/modules/user-management/permissions.ts +15 -0
  227. package/src/modules/user-management/tailor.config.ts +11 -0
  228. package/src/modules/user-management/testing/fixtures.ts +98 -0
  229. package/src/schemas.ts +25 -0
  230. package/src/testing.ts +10 -0
  231. package/src/util.ts +3 -0
@@ -0,0 +1,27 @@
1
+ # Application Directory Structure
2
+
3
+ ```
4
+ {app_name}/
5
+ ├── backend/
6
+ │ ├── src/
7
+ │ │ ├── modules.ts # Declaring module usage
8
+ │ │ ├── modules/
9
+ │ │ │ └── {module-name}/ # Module-specific directory
10
+ │ │ │ ├── resolvers/ # API Definition to expose graphql apis
11
+ │ │ │ └── executors/ # PubSub Automation (one file per declaration)
12
+ │ │ └── generated/ # Auto-generated code (do not edit)
13
+ │ └── tailor.config.ts # tailor application config
14
+
15
+ └── frontend/
16
+ └── src/
17
+ ├── pages/ # File-based routing (auto-discovered by Vite plugin)
18
+ │ └── {page-path}/
19
+ │ ├── page.tsx
20
+ │ └── {page-path}/
21
+ │ ├── components/
22
+ │ └── page.tsx
23
+ ├── components/
24
+ │ └── ui/ # Generic UI components
25
+ ├── graphql/ # gql.tada settings
26
+ └── providers/ # react providers
27
+ ```
@@ -0,0 +1,290 @@
1
+ ---
2
+ name: app-compose-5-design-mock-review
3
+ description: Review design mockups (.pen files) against screen specifications. Use after completing design mockups with app-compose-4-design-mock. Validates visual consistency, detects regressions, and fixes layout issues.
4
+ ---
5
+
6
+ # Design Mockup Review Workflow
7
+
8
+ Review visual design mockups against Tier 3 screen documentation. Detect and fix regressions, layout issues, and specification mismatches.
9
+
10
+ ## Prerequisites
11
+
12
+ - `docs/screen/*.md` (screen specifications)
13
+ - `docs/design.pen` (design mockups from app-compose-4-design-mock)
14
+
15
+ ## Workflow Phases
16
+
17
+ ```
18
+ INVENTORY → PARITY CHECK → VISUAL REVIEW → REGRESSION FIX → VALIDATE
19
+ ```
20
+
21
+ ### Phase 1: Inventory
22
+
23
+ #### 1.1 Open Design File
24
+
25
+ ```
26
+ mcp__pencil__get_editor_state(include_schema: false)
27
+ mcp__pencil__open_document(filePathOrTemplate: "docs/design.pen")
28
+ ```
29
+
30
+ #### 1.2 List Design Screens
31
+
32
+ Extract top-level frames (screens) from design.pen:
33
+
34
+ ```
35
+ mcp__pencil__batch_get(
36
+ filePath: "docs/design.pen",
37
+ readDepth: 1
38
+ )
39
+ ```
40
+
41
+ Filter for screen frames (exclude design system components frame).
42
+
43
+ #### 1.3 List Screen Specifications
44
+
45
+ ```bash
46
+ ls docs/screen/*.md
47
+ ```
48
+
49
+ ### Phase 2: Parity Check
50
+
51
+ #### Screen Count Validation
52
+
53
+ | Check | Question |
54
+ | --------------- | ------------------------------------------------------------ |
55
+ | Count match | Does design.pen have same number of screens as screen/\*.md? |
56
+ | Name match | Does each screen in design.pen correspond to a spec file? |
57
+ | Missing screens | Any spec files without corresponding design frames? |
58
+
59
+ Create mapping table:
60
+
61
+ ```markdown
62
+ | Screen Spec | Design Frame | Status |
63
+ | ---------------- | -------------------------- | ---------- |
64
+ | {screen-name}.md | {Screen Name} ({frame-id}) | ✅ |
65
+ | {screen-name}.md | - | ❌ Missing |
66
+ ```
67
+
68
+ ### Phase 3: Visual Review
69
+
70
+ For each screen, perform detailed review:
71
+
72
+ #### 3.1 Screenshot Capture
73
+
74
+ ```
75
+ mcp__pencil__get_screenshot(filePath: "docs/design.pen", nodeId: "{frame-id}")
76
+ ```
77
+
78
+ #### 3.2 Specification Comparison
79
+
80
+ **For ListView screens:**
81
+
82
+ | Check | How to Verify |
83
+ | ---------------------- | ---------------------------------------------------- |
84
+ | Required columns exist | Compare spec table columns with design table headers |
85
+ | Column properties | Sortable/Filterable indicators if applicable |
86
+ | Action buttons | Create/Edit/Delete buttons per spec |
87
+ | Pagination | Present if list can be long |
88
+
89
+ **For Form screens:**
90
+
91
+ | Check | How to Verify |
92
+ | ---------------------- | ------------------------------------------------ |
93
+ | All input fields exist | Match spec field list with form fields |
94
+ | Field types correct | Text/Dropdown/Radio/Checkbox/FileUpload per spec |
95
+ | Required indicators | Required fields marked appropriately |
96
+ | Action buttons | Submit/Cancel buttons present |
97
+
98
+ **For DetailView screens:**
99
+
100
+ | Check | How to Verify |
101
+ | ----------------- | ---------------------------- |
102
+ | Displayed fields | All spec fields visible |
103
+ | Action buttons | Available actions per spec |
104
+ | Status indicators | Badges/Timeline if specified |
105
+
106
+ #### 3.3 Layout Problem Detection
107
+
108
+ ```
109
+ mcp__pencil__snapshot_layout(
110
+ filePath: "docs/design.pen",
111
+ parentId: "{frame-id}",
112
+ problemsOnly: true,
113
+ maxDepth: 10
114
+ )
115
+ ```
116
+
117
+ Common problems:
118
+
119
+ - `partially clipped` - Content overflows container
120
+ - `fully clipped` - Element completely hidden
121
+ - Negative coordinates - Mispositioned elements
122
+
123
+ ### Phase 4: Regression Fix
124
+
125
+ #### 4.1 Layout Issues
126
+
127
+ **Fixed height causing overflow:**
128
+
129
+ ```javascript
130
+ // Change fixed height to fit_content
131
+ U("{container-id}", { height: "fit_content", justifyContent: "start" });
132
+ ```
133
+
134
+ **Element positioning:**
135
+
136
+ ```javascript
137
+ // Reset position
138
+ U("{element-id}", { x: 0, y: 0 });
139
+ ```
140
+
141
+ #### 4.2 Style Inconsistencies
142
+
143
+ **Background color mismatch:**
144
+
145
+ ```javascript
146
+ // Use design token instead of hardcoded color
147
+ U("{frame-id}", { fill: "$--background" });
148
+ ```
149
+
150
+ **Missing icon:**
151
+
152
+ ```javascript
153
+ // Add icon to sidebar item
154
+ U("{frame-id}/{sidebar-id}/{menu-item-id}/{icon-id}", { iconFontName: "{icon-name}" });
155
+ ```
156
+
157
+ **Text not visible (missing fill):**
158
+
159
+ ```javascript
160
+ // Add fill color to text
161
+ U("{text-id}", { fill: "$--foreground" });
162
+ ```
163
+
164
+ #### 4.3 Missing Fields
165
+
166
+ **Add missing form field:**
167
+
168
+ ```javascript
169
+ newField = I("{form-container-id}", {
170
+ type: "ref",
171
+ ref: "{input-component-id}",
172
+ width: "fill_container",
173
+ descendants: {
174
+ "{label-id}": { content: "{field-label}" },
175
+ "{input-id}": { content: "{placeholder}" },
176
+ },
177
+ });
178
+ ```
179
+
180
+ #### 4.4 Common Component Fixes
181
+
182
+ | Issue | Fix Pattern |
183
+ | ----------------------- | ------------------------------------------------ |
184
+ | Card content overflow | Set `height: "fit_content"` on Card Content slot |
185
+ | Sidebar icons missing | Update `iconFontName` on menu item icon element |
186
+ | Text invisible | Add `fill: "$--foreground"` to text element |
187
+ | Inconsistent background | Use `$--background` instead of hex colors |
188
+
189
+ ### Phase 5: Validate
190
+
191
+ After fixes, re-verify each screen:
192
+
193
+ ```
194
+ mcp__pencil__get_screenshot(filePath: "docs/design.pen", nodeId: "{frame-id}")
195
+ ```
196
+
197
+ Check:
198
+
199
+ - Layout renders correctly
200
+ - All text visible
201
+ - Consistent styling
202
+ - No clipped elements
203
+
204
+ ## Review Report Template
205
+
206
+ ```markdown
207
+ ## Design Mockup Review Report
208
+
209
+ **Application:** {app-name}
210
+ **Design File:** docs/design.pen
211
+
212
+ ### Screen Inventory
213
+
214
+ | Screen | Spec File | Design Frame | Status |
215
+ | ------------- | ---------------- | ------------ | ------ |
216
+ | {screen-name} | {screen-name}.md | {frame-id} | ✅ |
217
+
218
+ ### Issues Found & Fixed
219
+
220
+ #### 1. [{screen-name}] - {issue-description}
221
+
222
+ - **Problem:** {description}
223
+ - **Root Cause:** {cause}
224
+ - **Fix Applied:** {fix}
225
+
226
+ ### Remaining Issues
227
+
228
+ - [ ] {issue-description}
229
+
230
+ ### Summary
231
+
232
+ | Category | Count |
233
+ | ---------------- | ------- |
234
+ | Screens Reviewed | {count} |
235
+ | Issues Found | {count} |
236
+ | Issues Fixed | {count} |
237
+ | Remaining | {count} |
238
+ ```
239
+
240
+ ## Design Token Reference
241
+
242
+ Retrieve available design tokens dynamically:
243
+
244
+ ```
245
+ mcp__pencil__get_variables(filePath: "docs/design.pen")
246
+ ```
247
+
248
+ Common token patterns:
249
+
250
+ - `$--background` / `$--foreground` - Base colors
251
+ - `$--card` / `$--border` - Card styling
252
+ - `$--primary` / `$--secondary` - Action colors
253
+ - `$--sidebar-*` - Sidebar-specific tokens
254
+ - `$--muted-*` - Subdued variants
255
+
256
+ ## Sidebar Component Reference
257
+
258
+ Retrieve sidebar component structure to find icon element paths:
259
+
260
+ ```
261
+ mcp__pencil__batch_get(
262
+ filePath: "docs/design.pen",
263
+ patterns: [{"reusable": true, "name": "Sidebar"}],
264
+ readDepth: 4
265
+ )
266
+ ```
267
+
268
+ To find icon names used in an existing screen's sidebar:
269
+
270
+ ```
271
+ mcp__pencil__batch_get(
272
+ filePath: "docs/design.pen",
273
+ nodeIds: ["{frame-id}/{sidebar-id}"],
274
+ readDepth: 5,
275
+ resolveInstances: true
276
+ )
277
+ ```
278
+
279
+ Look for `iconFontName` property in sidebar menu items. Icons use Lucide icon font family.
280
+
281
+ ## Next Step
282
+
283
+ After completing design review, use `/app-compose-6-implementation-spec` to create Tier 4 documentation (resolvers).
284
+
285
+ ## References
286
+
287
+ - [ListView screen](references/screen-listview.md)
288
+ - [Form screen](references/screen-form.md)
289
+ - [DetailView screen](references/screen-detailview.md)
290
+ - [Page components](references/component.md)
@@ -0,0 +1,50 @@
1
+ # Page Components
2
+
3
+ Page-specific components are placed in a `components/` directory, separated from page.tsx.
4
+
5
+ ```
6
+ {page-name}/
7
+ ├── components/
8
+ │ └── *.tsx
9
+ └── page.tsx
10
+ ```
11
+
12
+ ## Fragment Collocation
13
+
14
+ Components define and export their own GraphQL Fragment for the data they display. The parent page imports the Fragment and includes it in the query.
15
+
16
+ Use `graphql`, `FragmentOf`, and `readFragment` from `@/graphql`.
17
+
18
+ ```tsx
19
+ // components/user-card.tsx
20
+ import { graphql, type FragmentOf, readFragment } from "@/graphql";
21
+
22
+ export const UserCardFragment = graphql(`
23
+ fragment UserCard on User {
24
+ id
25
+ name
26
+ email
27
+ }
28
+ `);
29
+
30
+ export const UserCard = ({ user }: { user: FragmentOf<typeof UserCardFragment> }) => {
31
+ const data = readFragment(UserCardFragment, user);
32
+ return <div>{data.name}</div>;
33
+ };
34
+ ```
35
+
36
+ ```tsx
37
+ // page.tsx
38
+ import { UserCard, UserCardFragment } from "./components/user-card";
39
+
40
+ const UserQuery = graphql(
41
+ `
42
+ query User($id: ID!) {
43
+ user(id: $id) {
44
+ ...UserCard
45
+ }
46
+ }
47
+ `,
48
+ [UserCardFragment],
49
+ );
50
+ ```
@@ -0,0 +1,106 @@
1
+ # DetailView Screen Implementation
2
+
3
+ Implementation pattern for screens with `Screen Type: DetailView`.
4
+ Assumes `page.md` and `component.md` rules.
5
+
6
+ ## File Structure
7
+
8
+ ```
9
+ {screen-path}/[id]/
10
+ ├── components/
11
+ │ ├── {screen-name}-detail.tsx # Main content (left column)
12
+ │ └── {screen-name}-actions.tsx # Action sidebar (right column)
13
+ ├── edit/
14
+ │ ├── components/
15
+ │ │ └── edit-{screen-name}-form.tsx
16
+ │ └── page.tsx
17
+ └── page.tsx
18
+ ```
19
+
20
+ ## Layout
21
+
22
+ - Two-column layout: main content on the left, actions on the right.
23
+
24
+ ```tsx
25
+ const ResourcePage = () => {
26
+ const { id } = useParams();
27
+ const [{ data, error, fetching }, reexecuteQuery] = useQuery({
28
+ query: ResourceQuery,
29
+ variables: { id: id! },
30
+ });
31
+
32
+ if (fetching) return <Loading />;
33
+ if (error || !data?.resource) return <ErrorFallback ... />;
34
+
35
+ return (
36
+ <Layout columns={2} title="Resource Detail">
37
+ <Layout.Column>
38
+ <ResourceDetail resource={data.resource} />
39
+ </Layout.Column>
40
+ <Layout.Column>
41
+ <ResourceActions resource={data.resource} />
42
+ </Layout.Column>
43
+ </Layout>
44
+ );
45
+ };
46
+ ```
47
+
48
+ ## Left Column: Detail Component
49
+
50
+ Stack `DescriptionCard` and related tables vertically with `space-y-6`.
51
+
52
+ - `DescriptionCard` (`@tailor-platform/app-shell`): renders key-value fields declaratively.
53
+ - Complex content (tables, timelines): wrap in `<div className="rounded-lg border bg-card p-6">`.
54
+
55
+ ### DescriptionCard
56
+
57
+ ```tsx
58
+ <DescriptionCard
59
+ data={resource}
60
+ title="Overview"
61
+ columns={3}
62
+ fields={[
63
+ { key: "name", label: "Name", meta: { copyable: true } },
64
+ {
65
+ key: "status",
66
+ label: "Status",
67
+ type: "badge",
68
+ meta: { badgeVariantMap: { ACTIVE: "success", PENDING: "warning" } },
69
+ },
70
+ { type: "divider" },
71
+ {
72
+ key: "createdAt",
73
+ label: "Created At",
74
+ type: "date",
75
+ meta: { dateFormat: "medium" },
76
+ },
77
+ ]}
78
+ />
79
+ ```
80
+
81
+ Field types: `"text"` (default), `"badge"`, `"money"`, `"date"`, `"link"`, `"address"`, `"reference"`, `"divider"`
82
+
83
+ ## Right Column: Actions Component
84
+
85
+ Wrap in a `Card` component. Use `Button variant="ghost"` for each action item.
86
+
87
+ ```tsx
88
+ <Card>
89
+ <CardHeader>
90
+ <CardTitle>Actions</CardTitle>
91
+ </CardHeader>
92
+ <CardContent className="space-y-2">
93
+ <Button variant="ghost" className="w-full justify-start gap-2" asChild>
94
+ <Link to="edit">✎ Edit</Link>
95
+ </Button>
96
+ <Button variant="ghost" className="w-full justify-start gap-2" onClick={handler}>
97
+ ✓ Approve
98
+ </Button>
99
+ </CardContent>
100
+ </Card>
101
+ ```
102
+
103
+ - Navigation: `<Button variant="ghost" asChild><Link to="...">`
104
+ - Mutation: `<Button variant="ghost" onClick={handler}>` with custom resolvers (see `backend/resolvers.md`)
105
+ - Conditional: show/hide based on status
106
+ - Multiple cards: stack with `<div className="space-y-6">`
@@ -0,0 +1,139 @@
1
+ # Form Screen Implementation
2
+
3
+ Implementation pattern for screens with `Screen Type: Form`.
4
+ Assumes `page.md` and `component.md` rules.
5
+
6
+ ## File Structure
7
+
8
+ ```
9
+ {screen-path}/
10
+ ├── components/
11
+ │ └── {screen-name}-form.tsx # Form component with validation
12
+ └── page.tsx
13
+ ```
14
+
15
+ ## Page Component (page.tsx)
16
+
17
+ Form pages delegate mutation logic to the form component.
18
+
19
+ ```tsx
20
+ const ScreenNamePage = () => (
21
+ <Layout columns={1} title="Screen Title">
22
+ <Layout.Column>
23
+ <ScreenNameForm />
24
+ </Layout.Column>
25
+ </Layout>
26
+ );
27
+ ```
28
+
29
+ For edit forms that need existing data, co-locate data fetching in the page component:
30
+
31
+ ```tsx
32
+ const EditPage = () => {
33
+ const { id } = useParams();
34
+ const [{ data, error, fetching }] = useQuery({
35
+ query: ResourceQuery,
36
+ variables: { id: id! },
37
+ });
38
+
39
+ if (fetching) return <Loading />;
40
+ if (error || !data?.resource) return <ErrorFallback ... />;
41
+
42
+ return (
43
+ <Layout columns={1} title="Edit Resource">
44
+ <Layout.Column>
45
+ <EditResourceForm resource={data.resource} />
46
+ </Layout.Column>
47
+ </Layout>
48
+ );
49
+ };
50
+ ```
51
+
52
+ ## Form Component (components/{screen-name}-form.tsx)
53
+
54
+ ### Technology Stack
55
+
56
+ - `react-hook-form` — form state management
57
+ - `zod` + `@hookform/resolvers/zod` — validation
58
+ - `useMutation` (urql) — GraphQL mutation
59
+ - `useNavigate` (@tailor-platform/app-shell) — post-submit navigation
60
+
61
+ ### Pattern
62
+
63
+ ```tsx
64
+ const formSchema = z.object({
65
+ title: z.string().min(1, "Title is required"),
66
+ description: z.string().optional(),
67
+ });
68
+
69
+ type FormValues = z.infer<typeof formSchema>;
70
+
71
+ export const ScreenNameForm = () => {
72
+ const navigate = useNavigate();
73
+ const [, createResource] = useMutation(CreateMutation);
74
+
75
+ const form = useForm<FormValues>({
76
+ resolver: zodResolver(formSchema),
77
+ defaultValues: { title: "", description: "" },
78
+ });
79
+
80
+ const onSubmit = (values: FormValues) => {
81
+ void createResource({ input: values }).then((result) => {
82
+ if (!result.error) {
83
+ void navigate("..");
84
+ }
85
+ });
86
+ };
87
+
88
+ return (
89
+ <Form {...form}>
90
+ <form onSubmit={(e) => void form.handleSubmit(onSubmit)(e)} className="max-w-md space-y-4">
91
+ <FormField
92
+ control={form.control}
93
+ name="title"
94
+ render={({ field }) => (
95
+ <FormItem>
96
+ <FormLabel>Title</FormLabel>
97
+ <FormControl>
98
+ <Input placeholder="Enter title" {...field} />
99
+ </FormControl>
100
+ <FormMessage />
101
+ </FormItem>
102
+ )}
103
+ />
104
+ <div className="flex gap-2">
105
+ <Button type="submit">Create</Button>
106
+ <Button type="button" variant="outline" onClick={() => void navigate("..")}>
107
+ Cancel
108
+ </Button>
109
+ </div>
110
+ </form>
111
+ </Form>
112
+ );
113
+ };
114
+ ```
115
+
116
+ ## Field Type Mapping
117
+
118
+ | Field Type | Component | Zod Schema |
119
+ | ---------- | ------------------------------ | ------------------------------- |
120
+ | Text | `<Input />` | `z.string()` |
121
+ | Textarea | `<textarea className="..." />` | `z.string()` |
122
+ | Dropdown | `<Select />` | `z.string()` or `z.enum([...])` |
123
+ | Date | `<Input type="date" />` | `z.string()` (ISO format) |
124
+ | Number | `<Input type="number" />` | `z.coerce.number()` |
125
+ | Email | `<Input type="email" />` | `z.string().email()` |
126
+ | Checkbox | `<Checkbox />` | `z.boolean()` |
127
+ | Radio | `<RadioGroup />` | `z.enum([...])` |
128
+
129
+ ## Validation Mapping
130
+
131
+ - **Required: Yes** → `.min(1, "Field is required")` (string) / `.positive()` (number)
132
+ - **Required: No** → `.optional()`
133
+
134
+ ## Key Points
135
+
136
+ - Set `defaultValues` for all fields (empty string, false, etc.)
137
+ - Navigate to `".."` after successful mutation
138
+ - Cancel button must use `type="button"` to prevent form submit
139
+ - For edit forms, accept fragment data as props and pre-fill `defaultValues`