@open-mercato/cli 0.4.7-main-1768da2e43 → 0.4.7

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 (51) hide show
  1. package/build.mjs +8 -1
  2. package/dist/agentic/claude-code/CLAUDE.md.template +1 -0
  3. package/dist/agentic/claude-code/hooks/entity-migration-check.ts +121 -0
  4. package/dist/agentic/claude-code/mcp.json.example +13 -0
  5. package/dist/agentic/claude-code/settings.json +16 -0
  6. package/dist/agentic/codex/enforcement-rules.md +20 -0
  7. package/dist/agentic/codex/mcp.json.example +12 -0
  8. package/dist/agentic/cursor/hooks/entity-migration-check.mjs +69 -0
  9. package/dist/agentic/cursor/hooks.json +10 -0
  10. package/dist/agentic/cursor/mcp.json.example +13 -0
  11. package/dist/agentic/cursor/rules/entity-guard.mdc +29 -0
  12. package/dist/agentic/cursor/rules/generated-guard.mdc +12 -0
  13. package/dist/agentic/cursor/rules/open-mercato.mdc +34 -0
  14. package/dist/agentic/shared/AGENTS.md.template +180 -0
  15. package/dist/agentic/shared/ai/lessons.md +4 -0
  16. package/dist/agentic/shared/ai/skills/backend-ui-design/SKILL.md +197 -0
  17. package/dist/agentic/shared/ai/skills/backend-ui-design/references/ui-components.md +233 -0
  18. package/dist/agentic/shared/ai/skills/code-review/SKILL.md +144 -0
  19. package/dist/agentic/shared/ai/skills/code-review/references/review-checklist.md +77 -0
  20. package/dist/agentic/shared/ai/skills/data-model-design/SKILL.md +512 -0
  21. package/dist/agentic/shared/ai/skills/data-model-design/references/mikro-orm-cheatsheet.md +146 -0
  22. package/dist/agentic/shared/ai/skills/eject-and-customize/SKILL.md +318 -0
  23. package/dist/agentic/shared/ai/skills/integration-builder/SKILL.md +722 -0
  24. package/dist/agentic/shared/ai/skills/integration-builder/references/adapter-contracts.md +762 -0
  25. package/dist/agentic/shared/ai/skills/module-scaffold/SKILL.md +614 -0
  26. package/dist/agentic/shared/ai/skills/module-scaffold/references/naming-conventions.md +61 -0
  27. package/dist/agentic/shared/ai/skills/spec-writing/SKILL.md +76 -0
  28. package/dist/agentic/shared/ai/skills/spec-writing/references/spec-checklist.md +50 -0
  29. package/dist/agentic/shared/ai/skills/spec-writing/references/spec-template.md +86 -0
  30. package/dist/agentic/shared/ai/skills/system-extension/SKILL.md +858 -0
  31. package/dist/agentic/shared/ai/skills/system-extension/references/extension-contracts.md +271 -0
  32. package/dist/agentic/shared/ai/skills/troubleshooter/SKILL.md +421 -0
  33. package/dist/agentic/shared/ai/skills/troubleshooter/references/diagnostic-commands.md +101 -0
  34. package/dist/agentic/shared/ai/specs/README.md +26 -0
  35. package/dist/agentic/shared/ai/specs/SPEC-000-template.md +35 -0
  36. package/dist/lib/agentic-init.js +54 -0
  37. package/dist/lib/agentic-init.js.map +7 -0
  38. package/dist/lib/agentic-setup.js +209 -0
  39. package/dist/lib/agentic-setup.js.map +7 -0
  40. package/dist/lib/generators/module-registry.js +3 -3
  41. package/dist/lib/generators/module-registry.js.map +2 -2
  42. package/dist/lib/testing/integration.js +8 -2
  43. package/dist/lib/testing/integration.js.map +2 -2
  44. package/dist/mercato.js +5 -0
  45. package/dist/mercato.js.map +2 -2
  46. package/package.json +7 -4
  47. package/src/lib/agentic-init.ts +69 -0
  48. package/src/lib/agentic-setup.ts +277 -0
  49. package/src/lib/generators/module-registry.ts +3 -3
  50. package/src/lib/testing/integration.ts +8 -2
  51. package/src/mercato.ts +7 -0
@@ -0,0 +1,197 @@
1
+ ---
2
+ name: backend-ui-design
3
+ description: Design and implement consistent backend/backoffice interfaces using @open-mercato/ui. Use when building admin pages, CRUD interfaces, data tables, forms, detail pages, or any backoffice UI.
4
+ ---
5
+
6
+ # Backend UI Design
7
+
8
+ Guide for creating consistent, production-grade backend interfaces using the `@open-mercato/ui` component library. All implementations must use existing components for visual and behavioral consistency.
9
+
10
+ For complete component API reference, see `references/ui-components.md`.
11
+
12
+ ## Design Principles
13
+
14
+ 1. **Consistency First**: Every page should feel like part of the same application.
15
+ 2. **Component Reuse**: Never create custom implementations when a shared component exists.
16
+ 3. **Data Density**: Admin users need information-rich interfaces. Optimize for scanning.
17
+ 4. **Keyboard Navigation**: `Cmd/Ctrl+Enter` for primary actions, `Escape` to cancel.
18
+ 5. **Clear Hierarchy**: Page → Section → Content. Use `PageHeader`, `PageBody`, consistent spacing.
19
+
20
+ ## Required Component Library
21
+
22
+ ALWAYS import from `@open-mercato/ui`.
23
+
24
+ ### Core Layout
25
+
26
+ ```tsx
27
+ import { Page, PageHeader, PageBody } from '@open-mercato/ui/backend/Page'
28
+
29
+ <Page>
30
+ <PageHeader>{/* Title, actions, breadcrumbs */}</PageHeader>
31
+ <PageBody>{/* Main content */}</PageBody>
32
+ </Page>
33
+ ```
34
+
35
+ ### Data Display (Lists)
36
+
37
+ Use `DataTable` for ALL tabular data. Never implement custom tables.
38
+
39
+ ```tsx
40
+ import { DataTable } from '@open-mercato/ui/backend/DataTable'
41
+ import type { FilterDef } from '@open-mercato/ui/backend/FilterBar'
42
+ import { RowActions } from '@open-mercato/ui/backend/RowActions'
43
+ import { TruncatedCell } from '@open-mercato/ui/backend/TruncatedCell'
44
+ import { BooleanIcon, EnumBadge } from '@open-mercato/ui/backend/ValueIcons'
45
+ ```
46
+
47
+ Column patterns:
48
+ - Text: `TruncatedCell` with `meta.maxWidth`
49
+ - Boolean: `BooleanIcon`
50
+ - Status/enum: `EnumBadge` with severity presets
51
+ - Actions: `RowActions` for context menus
52
+
53
+ ### Forms
54
+
55
+ Use `CrudForm` for ALL forms. Never build from scratch.
56
+
57
+ ```tsx
58
+ import { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'
59
+ ```
60
+
61
+ Field types: `text`, `textarea`, `number`, `email`, `password`, `select`, `multiselect`, `combobox`, `checkbox`, `switch`, `date`, `datetime`, `custom`.
62
+
63
+ ### Form Headers & Footers
64
+
65
+ ```tsx
66
+ import { FormHeader, FormFooter, FormActionButtons, ActionsDropdown } from '@open-mercato/ui/backend/forms'
67
+ ```
68
+
69
+ - **`FormHeader mode="edit"`** — compact header for CrudForm pages
70
+ - **`FormHeader mode="detail"`** — large header for view/detail pages with entity type label, title, status badge, and Actions dropdown
71
+ - **`FormFooter`** — footer wrapping `FormActionButtons`
72
+ - **`ActionsDropdown`** — groups additional context actions (Convert, Send, Print). Delete is never inside the dropdown.
73
+
74
+ ### Dialogs
75
+
76
+ ```tsx
77
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'
78
+
79
+ // Dialog forms MUST use embedded={true}
80
+ <CrudForm fields={fields} onSubmit={handleSubmit} embedded={true} submitLabel="Save" />
81
+ ```
82
+
83
+ ### Detail Pages
84
+
85
+ ```tsx
86
+ import { DetailFieldsSection, LoadingMessage, ErrorMessage, TabEmptyState } from '@open-mercato/ui/backend/detail'
87
+ import { NotesSection } from '@open-mercato/ui/backend/detail/NotesSection'
88
+ import { TagsSection } from '@open-mercato/ui/backend/detail/TagsSection'
89
+ import { CustomDataSection } from '@open-mercato/ui/backend/detail/CustomDataSection'
90
+ ```
91
+
92
+ ### Notifications
93
+
94
+ ```tsx
95
+ import { flash } from '@open-mercato/ui/backend/FlashMessages'
96
+
97
+ flash('Record saved successfully', 'success')
98
+ flash('Failed to save record', 'error')
99
+ flash('This action cannot be undone', 'warning')
100
+ ```
101
+
102
+ NEVER use `alert()`, `console.log()`, or custom toast implementations.
103
+
104
+ ### Loading & Error States
105
+
106
+ ```tsx
107
+ import { Spinner } from '@open-mercato/ui/primitives/spinner'
108
+ import { DataLoader } from '@open-mercato/ui/primitives/DataLoader'
109
+ import { Notice } from '@open-mercato/ui/primitives/Notice'
110
+ import { ErrorNotice } from '@open-mercato/ui/primitives/ErrorNotice'
111
+ import { EmptyState } from '@open-mercato/ui/backend/EmptyState'
112
+ import { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'
113
+ ```
114
+
115
+ ### Primitives
116
+
117
+ ```tsx
118
+ import { Button } from '@open-mercato/ui/primitives/button'
119
+ import { Input } from '@open-mercato/ui/primitives/input'
120
+ import { Label } from '@open-mercato/ui/primitives/label'
121
+ import { Badge } from '@open-mercato/ui/primitives/badge'
122
+ import { Switch } from '@open-mercato/ui/primitives/switch'
123
+ import { SimpleTooltip } from '@open-mercato/ui/primitives/tooltip'
124
+ ```
125
+
126
+ ## API Integration
127
+
128
+ ```tsx
129
+ import { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
130
+ import { createCrud, updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
131
+ import { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'
132
+
133
+ const handleCreate = async (values: FormValues) => {
134
+ const result = await createCrud<ResponseType>('module/resource', values)
135
+ if (result.ok) {
136
+ flash('Created successfully', 'success')
137
+ router.push(`/backend/module/${result.result.id}`)
138
+ }
139
+ return result
140
+ }
141
+ ```
142
+
143
+ ## Custom Fields Integration
144
+
145
+ ```tsx
146
+ import { useCustomFieldDefinitions } from '@open-mercato/ui/backend/utils/customFieldDefs'
147
+ import { buildCustomFieldFormFields } from '@open-mercato/ui/backend/utils/customFieldForms'
148
+ import { buildCustomFieldColumns } from '@open-mercato/ui/backend/utils/customFieldColumns'
149
+ import { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'
150
+ ```
151
+
152
+ ## Implementation Checklist
153
+
154
+ - [ ] Forms use `CrudForm` (not custom)
155
+ - [ ] Tables use `DataTable` (not custom)
156
+ - [ ] Notifications use `flash()` (not alert/toast)
157
+ - [ ] Dialog forms have `embedded={true}`
158
+ - [ ] Keyboard: `Cmd/Ctrl+Enter` (submit), `Escape` (cancel)
159
+ - [ ] Loading states use `LoadingMessage` or `DataLoader`
160
+ - [ ] Error states use `ErrorMessage`, `ErrorNotice`, or `Notice variant="error"`
161
+ - [ ] Empty states use `EmptyState`
162
+ - [ ] Column truncation uses `meta.truncate` and `meta.maxWidth`
163
+ - [ ] Boolean values use `BooleanIcon`
164
+ - [ ] Status/enum values use `EnumBadge`
165
+ - [ ] Row actions use `RowActions` with stable `id` values
166
+ - [ ] API calls use `apiCall`/`apiCallOrThrow` (not raw `fetch`)
167
+
168
+ ## Anti-Patterns
169
+
170
+ 1. Custom form implementations — use `CrudForm`
171
+ 2. Manual table markup — use `DataTable`
172
+ 3. Custom toast/notification — use `flash()`
173
+ 4. Inline styles — use Tailwind classes
174
+ 5. Hardcoded colors — use theme variables
175
+ 6. Missing loading states — every async operation needs feedback
176
+ 7. Missing error handling — every failure needs messaging
177
+ 8. Missing keyboard shortcuts — all dialogs need `Cmd+Enter` and `Escape`
178
+ 9. Custom truncation — use `TruncatedCell` with `meta.maxWidth`
179
+ 10. Direct `fetch()` — use `apiCall`/`apiCallOrThrow`
180
+
181
+ ## Visual Guidelines
182
+
183
+ ### Spacing
184
+ - `p-4` for cards, `p-6` for page sections
185
+ - `gap-4` or `gap-6` for flex/grid layouts
186
+ - `space-y-4` or `space-y-6` for vertical rhythm
187
+
188
+ ### Colors
189
+ - Use semantic colors from theme (no hardcoded hex)
190
+ - Destructive: `variant="destructive"` on buttons
191
+ - Status badges: `useSeverityPreset()`
192
+
193
+ ### Layout Patterns
194
+ - **List pages**: FilterBar + DataTable + Pagination
195
+ - **Detail pages**: Header + Tabs/Sections + Related data
196
+ - **Create/Edit**: Full-page CrudForm or Dialog with embedded CrudForm
197
+ - **Settings**: Grouped sections with inline editing
@@ -0,0 +1,233 @@
1
+ # UI Components Reference
2
+
3
+ Complete reference of all available UI components in `@open-mercato/ui`.
4
+
5
+ ## Package Structure
6
+
7
+ ```
8
+ @open-mercato/ui/
9
+ ├── primitives/ # Base UI components (shadcn-style)
10
+ ├── backend/ # Full-featured admin components
11
+ ├── frontend/ # Public-facing components
12
+ └── theme/ # Theme and provider setup
13
+ ```
14
+
15
+ ## PRIMITIVES (`@open-mercato/ui/primitives/*`)
16
+
17
+ | Component | Import Path | Purpose |
18
+ |-----------|-------------|---------|
19
+ | **Button** | `@open-mercato/ui/primitives/button` | Core button with variants (default, outline, ghost, destructive) |
20
+ | **Input** | `@open-mercato/ui/primitives/input` | Text input field |
21
+ | **Label** | `@open-mercato/ui/primitives/label` | Form label component |
22
+ | **Textarea** | `@open-mercato/ui/primitives/textarea` | Multi-line text input |
23
+ | **Dialog** | `@open-mercato/ui/primitives/dialog` | Modal dialog (Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter) |
24
+ | **Tooltip** | `@open-mercato/ui/primitives/tooltip` | Hover tooltip + `SimpleTooltip` utility component |
25
+ | **Table** | `@open-mercato/ui/primitives/table` | Table structure (Table, TableHeader, TableBody, TableRow, TableHead, TableCell) |
26
+ | **Alert** | `@open-mercato/ui/primitives/alert` | Alert boxes (Alert, AlertTitle, AlertDescription) with variants |
27
+ | **Badge** | `@open-mercato/ui/primitives/badge` | Small badge/tag labels with variants |
28
+ | **Separator** | `@open-mercato/ui/primitives/separator` | Visual divider line |
29
+ | **Switch** | `@open-mercato/ui/primitives/switch` | Toggle switch control |
30
+ | **Spinner** | `@open-mercato/ui/primitives/spinner` | Loading spinner animation |
31
+ | **Notice** | `@open-mercato/ui/primitives/Notice` | Contextual notice/hint with variants (`error`, `info`, `warning`) and optional `compact` mode |
32
+ | **ErrorNotice** | `@open-mercato/ui/primitives/ErrorNotice` | Convenience wrapper around `<Notice variant="error">` with default title/message |
33
+ | **DataLoader** | `@open-mercato/ui/primitives/DataLoader` | Loading state wrapper with spinner and optional skeleton |
34
+
35
+ ## BACKEND COMPONENTS (`@open-mercato/ui/backend/*`)
36
+
37
+ ### Core Layout & Navigation
38
+
39
+ | Component | Import Path | Purpose | Key Props |
40
+ |-----------|-------------|---------|-----------|
41
+ | **AppShell** | `@open-mercato/ui/backend/AppShell` | Main application shell with sidebar, header, breadcrumbs | `navigation`, `user`, `children` |
42
+ | **Page, PageHeader, PageBody** | `@open-mercato/ui/backend/Page` | Page layout containers | - |
43
+ | **UserMenu** | `@open-mercato/ui/backend/UserMenu` | User profile dropdown with logout | `user`, `onLogout` |
44
+ | **FlashMessages, flash** | `@open-mercato/ui/backend/FlashMessages` | Toast notifications. Use `flash(message, type)` programmatically | Type: 'success' \| 'error' \| 'warning' \| 'info' |
45
+
46
+ ### Data Display & Tables
47
+
48
+ | Component | Import Path | Purpose | Key Props |
49
+ |-----------|-------------|---------|-----------|
50
+ | **DataTable** | `@open-mercato/ui/backend/DataTable` | Feature-rich table with sorting, filtering, pagination, export, perspectives | `columns`, `data`, `filters`, `pagination`, `perspective`, `onRowClick` |
51
+ | **TruncatedCell** | `@open-mercato/ui/backend/TruncatedCell` | Table cell with text truncation and tooltip | `value`, `maxWidth` |
52
+ | **EmptyState** | `@open-mercato/ui/backend/EmptyState` | Empty state placeholder | `title`, `description`, `action`, `icon` |
53
+ | **RowActions** | `@open-mercato/ui/backend/RowActions` | Context menu for row actions | `items: {label, href?, onSelect?, destructive?}[]` |
54
+ | **FilterBar** | `@open-mercato/ui/backend/FilterBar` | Search and filter UI bar | `filters`, `values`, `onApply`, `onClear` |
55
+ | **ValueIcons** | `@open-mercato/ui/backend/ValueIcons` | `BooleanIcon`, `EnumBadge`, `useSeverityPreset()` | - |
56
+
57
+ ### Forms
58
+
59
+ | Component | Import Path | Purpose | Key Props |
60
+ |-----------|-------------|---------|-----------|
61
+ | **CrudForm** | `@open-mercato/ui/backend/CrudForm` | Complete CRUD form with field registry, groups, custom fields, validation | `fields`, `groups`, `initialValues`, `onSubmit`, `schema`, `embedded`, `extraActions` |
62
+ | **FormHeader** | `@open-mercato/ui/backend/forms` | Unified page header with `edit` mode (compact, for CrudForm) and `detail` mode (large title, entity type label, status badge, Actions dropdown) | `mode`, `backHref`, `title`, `actions`, `menuActions`, `onDelete`, `statusBadge` |
63
+ | **FormFooter** | `@open-mercato/ui/backend/forms` | Form footer wrapping FormActionButtons with embedded/dialog layout awareness | `actions`, `embedded`, `className` |
64
+ | **FormActionButtons** | `@open-mercato/ui/backend/forms` | Atomic button bar: [extraActions] [Delete] [Cancel] [Save]. Shared by header and footer. | `showDelete`, `onDelete`, `cancelHref`, `submit` |
65
+ | **ActionsDropdown** | `@open-mercato/ui/backend/forms` | Dropdown menu for additional context actions (Convert, Send, Print). Only visible when items are provided. Delete is never inside the dropdown. | `items: ActionItem[]`, `label`, `size` |
66
+ | **JsonBuilder** | `@open-mercato/ui/backend/JsonBuilder` | Interactive JSON editor with "Raw JSON" and "Builder" tabs | `value`, `onChange`, `disabled` |
67
+ | **JsonDisplay** | `@open-mercato/ui/backend/JsonDisplay` | Read-only JSON viewer with expand/collapse | `data`, `title`, `maxInitialDepth`, `showCopy` |
68
+
69
+ ### Input Components (`@open-mercato/ui/backend/inputs/*`)
70
+
71
+ | Component | Import Path | Purpose | Key Props |
72
+ |-----------|-------------|---------|-----------|
73
+ | **TagsInput** | `@open-mercato/ui/backend/inputs/TagsInput` | Multi-tag input with suggestions | `value`, `onChange`, `placeholder`, `suggestions` |
74
+ | **ComboboxInput** | `@open-mercato/ui/backend/inputs/ComboboxInput` | Searchable dropdown (single value) | `value`, `onChange`, `options`, `placeholder` |
75
+ | **PhoneNumberField** | `@open-mercato/ui/backend/inputs/PhoneNumberField` | Phone input with formatting | `value`, `onChange`, `checkDuplicate` |
76
+ | **LookupSelect** | `@open-mercato/ui/backend/inputs/LookupSelect` | Async lookup/search select | `value`, `onChange`, `onSearch`, `renderItem` |
77
+ | **SwitchableMarkdownInput** | `@open-mercato/ui/backend/inputs/SwitchableMarkdownInput` | Text/markdown toggle input | `value`, `onChange`, `placeholder` |
78
+
79
+ ### Detail Page Components (`@open-mercato/ui/backend/detail/*`)
80
+
81
+ | Component | Import Path | Purpose | Key Props |
82
+ |-----------|-------------|---------|-----------|
83
+ | **DetailFieldsSection** | `@open-mercato/ui/backend/detail/DetailFieldsSection` | Entity field display with inline editing | `fields`, `entity`, `onUpdate` |
84
+ | **InlineTextEditor** | `@open-mercato/ui/backend/detail/InlineEditors` | Click-to-edit text field | `value`, `onSave`, `label` |
85
+ | **InlineMultilineEditor** | `@open-mercato/ui/backend/detail/InlineEditors` | Click-to-edit textarea | `value`, `onSave`, `label` |
86
+ | **InlineSelectEditor** | `@open-mercato/ui/backend/detail/InlineEditors` | Click-to-edit select | `value`, `onSave`, `options`, `label` |
87
+ | **NotesSection** | `@open-mercato/ui/backend/detail/NotesSection` | Notes/comments section with markdown | `notes`, `onAdd`, `onUpdate`, `onDelete` |
88
+ | **TagsSection** | `@open-mercato/ui/backend/detail/TagsSection` | Tag management section | `tags`, `onAdd`, `onRemove`, `suggestions` |
89
+ | **CustomDataSection** | `@open-mercato/ui/backend/detail/CustomDataSection` | Custom fields display | `data`, `fieldDefinitions` |
90
+ | **LoadingMessage** | `@open-mercato/ui/backend/detail` | Loading state with spinner | `message` |
91
+ | **ErrorMessage** | `@open-mercato/ui/backend/detail` | Error alert with action | `title`, `description`, `action` |
92
+ | **TabEmptyState** | `@open-mercato/ui/backend/detail` | Empty state for tabs | `message`, `action` |
93
+
94
+ ## BACKEND UTILITIES (`@open-mercato/ui/backend/utils/*`)
95
+
96
+ | Utility | Import Path | Purpose | Key Exports |
97
+ |---------|-------------|---------|-------------|
98
+ | **apiCall** | `@open-mercato/ui/backend/utils/apiCall` | HTTP client with auth | `apiCall`, `apiCallOrThrow`, `readApiResultOrThrow` |
99
+ | **api** | `@open-mercato/ui/backend/utils/api` | Low-level API utils | `apiFetch` |
100
+ | **crud** | `@open-mercato/ui/backend/utils/crud` | CRUD operation helpers | `createCrud`, `updateCrud`, `deleteCrud` |
101
+ | **serverErrors** | `@open-mercato/ui/backend/utils/serverErrors` | Error mapping | `mapCrudServerErrorToFormErrors`, `createCrudFormError`, `raiseCrudError` |
102
+ | **customFieldValues** | `@open-mercato/ui/backend/utils/customFieldValues` | Custom field value helpers | `collectCustomFieldValues`, `normalizeCustomFieldSubmitValue` |
103
+ | **customFieldDefs** | `@open-mercato/ui/backend/utils/customFieldDefs` | Field definition fetching | `useCustomFieldDefinitions` |
104
+ | **customFieldForms** | `@open-mercato/ui/backend/utils/customFieldForms` | Form field generation | `buildCustomFieldFormFields` |
105
+ | **customFieldColumns** | `@open-mercato/ui/backend/utils/customFieldColumns` | Column builders | `buildCustomFieldColumns` |
106
+ | **customFieldFilters** | `@open-mercato/ui/backend/utils/customFieldFilters` | Filter definitions | `useCustomFieldFilters` |
107
+
108
+ ## Common Usage Patterns
109
+
110
+ ### Flash Messages
111
+ ```tsx
112
+ import { flash } from '@open-mercato/ui/backend/FlashMessages'
113
+
114
+ flash('Record saved successfully', 'success')
115
+ flash('Failed to save record', 'error')
116
+ // Types: 'success' | 'error' | 'warning' | 'info'
117
+ ```
118
+
119
+ ### DataTable with Filters
120
+ ```tsx
121
+ import { DataTable } from '@open-mercato/ui/backend/DataTable'
122
+ import type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'
123
+
124
+ const filters: FilterDef[] = [
125
+ { id: 'search', type: 'text', label: 'Search', placeholder: 'Search...' },
126
+ { id: 'status', type: 'select', label: 'Status', options: [...] },
127
+ ]
128
+
129
+ <DataTable
130
+ title="Items"
131
+ columns={columns}
132
+ data={data}
133
+ filters={filters}
134
+ filterValues={filterValues}
135
+ onFiltersApply={handleFiltersApply}
136
+ onFiltersClear={handleFiltersClear}
137
+ pagination={{ page, pageSize, total, totalPages, onPageChange }}
138
+ onRowClick={(row) => router.push(`/items/${row.id}`)}
139
+ />
140
+ ```
141
+
142
+ ### CrudForm
143
+ ```tsx
144
+ import { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'
145
+
146
+ const fields: CrudField[] = [
147
+ { id: 'name', label: 'Name', type: 'text', required: true },
148
+ { id: 'description', label: 'Description', type: 'textarea' },
149
+ { id: 'status', label: 'Status', type: 'select', options: [...] },
150
+ { id: 'config', label: 'Config', type: 'custom', component: (props) => <JsonBuilder {...props} /> },
151
+ ]
152
+
153
+ const groups: CrudFormGroup[] = [
154
+ { id: 'basic', title: 'Basic Info', column: 1, fields: ['name', 'description'] },
155
+ { id: 'settings', title: 'Settings', column: 1, fields: ['status', 'config'] },
156
+ ]
157
+
158
+ <CrudForm
159
+ title="Create Item"
160
+ fields={fields}
161
+ groups={groups}
162
+ initialValues={{}}
163
+ onSubmit={handleSubmit}
164
+ submitLabel="Save"
165
+ embedded={true} // For use inside dialogs
166
+ extraActions={<Button onClick={handleDelete}>Delete</Button>}
167
+ />
168
+ ```
169
+
170
+ ### Dialog with Form
171
+ ```tsx
172
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'
173
+ import { CrudForm } from '@open-mercato/ui/backend/CrudForm'
174
+
175
+ <Dialog open={isOpen} onOpenChange={onClose}>
176
+ <DialogContent className="sm:max-w-2xl [&_.grid]:!grid-cols-1">
177
+ <DialogHeader>
178
+ <DialogTitle>Edit Item</DialogTitle>
179
+ </DialogHeader>
180
+ <CrudForm
181
+ fields={fields}
182
+ groups={groups}
183
+ initialValues={initialValues}
184
+ onSubmit={handleSubmit}
185
+ embedded={true}
186
+ submitLabel="Save"
187
+ />
188
+ </DialogContent>
189
+ </Dialog>
190
+ ```
191
+
192
+ ### Detail Page with Inline Editing
193
+ ```tsx
194
+ import { DetailFieldsSection, LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'
195
+
196
+ if (isLoading) return <LoadingMessage message="Loading..." />
197
+ if (error) return <ErrorMessage title="Error" description={error.message} />
198
+
199
+ <DetailFieldsSection
200
+ fields={[
201
+ { id: 'name', label: 'Name', type: 'text' },
202
+ { id: 'status', label: 'Status', type: 'select', options: [...] },
203
+ ]}
204
+ entity={entity}
205
+ onUpdate={handleUpdate}
206
+ />
207
+ ```
208
+
209
+ ### API Calls
210
+ ```tsx
211
+ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
212
+ import { createCrud, updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
213
+
214
+ // Generic API call
215
+ const result = await apiCall<ResponseType>('/api/endpoint', { method: 'POST', body: JSON.stringify(data) })
216
+ if (result.ok) {
217
+ // result.result contains the parsed JSON response
218
+ }
219
+
220
+ // CRUD operations
221
+ const created = await createCrud<ItemType>('module/items', payload)
222
+ const updated = await updateCrud<ItemType>('module/items', id, payload)
223
+ const deleted = await deleteCrud('module/items', id)
224
+ ```
225
+
226
+ ## Important Notes
227
+
228
+ 1. **Always use `flash()` for notifications** - Don't use `alert()` or custom toast implementations
229
+ 2. **Use `CrudForm` for forms** - Provides consistent validation, field rendering, and keyboard shortcuts
230
+ 3. **Use `DataTable` for lists** - Includes filtering, sorting, pagination, export, and perspectives
231
+ 4. **Use `JsonBuilder` for JSON editing** - Provides both raw JSON and visual builder modes
232
+ 5. **Dialog forms need `embedded={true}`** - And add `[&_.grid]:!grid-cols-1` to DialogContent for single-column layout
233
+ 6. **Support Cmd/Ctrl+Enter and Escape** - All dialogs should support these keyboard shortcuts
@@ -0,0 +1,144 @@
1
+ ---
2
+ name: code-review
3
+ description: Review code changes for architecture, security, conventions, and quality compliance. Use when reviewing pull requests, code changes, or auditing code quality.
4
+ ---
5
+
6
+ # Code Review
7
+
8
+ Review code changes against Open Mercato architecture rules, security requirements, and quality standards.
9
+
10
+ ## Review Workflow
11
+
12
+ 1. **Scope**: Identify changed files. Classify by layer (entity, API route, validator, backend page, subscriber, worker, command, widget).
13
+ 2. **Gather context**: Read `AGENTS.md` for module conventions. Check `.ai/specs/` for active specs. Read `.ai/lessons.md` for known pitfalls.
14
+ 3. **CI/CD verification gate (MANDATORY)**: Run the checks below. Every gate MUST pass. See **CI/CD Gate** section.
15
+ 4. **Run checklist**: Apply rules from `references/review-checklist.md`. Flag violations with severity, file, and fix suggestion.
16
+ 5. **Test coverage**: Verify changed behavior is covered by tests. Flag missing coverage.
17
+ 6. **Cross-module impact**: If the change touches events, extensions, or widgets, verify consumers handle the contract correctly.
18
+ 7. **Output**: Produce the review report.
19
+
20
+ ## CI/CD Verification Gate (MANDATORY)
21
+
22
+ **NEVER claim code is "ready to merge" without running these checks.** If any step fails, it MUST be fixed before the review can pass.
23
+
24
+ | # | Command | What it checks | If it fails |
25
+ |---|---------|----------------|-------------|
26
+ | 1 | `yarn generate` | Module registries are up to date | Run it — it generates missing files |
27
+ | 2 | `yarn typecheck` | TypeScript types are correct | Fix type errors |
28
+ | 3 | `yarn test` | All unit tests pass | Fix failing tests |
29
+ | 4 | `yarn build` | The app builds successfully | Fix build errors |
30
+
31
+ **Rules**:
32
+ - Steps 2 and 3 can run in parallel.
33
+ - Every failure is a **Critical** finding — even if it appears unrelated to the current changes.
34
+ - The review output MUST include actual pass/fail results. Do not assume — run and report.
35
+
36
+ ## Output Format
37
+
38
+ ```markdown
39
+ # Code Review: {change description}
40
+
41
+ ## Summary
42
+ {1-3 sentences: what the change does, overall assessment}
43
+
44
+ ## CI/CD Verification
45
+
46
+ | Gate | Status | Notes |
47
+ |------|--------|-------|
48
+ | `yarn generate` | PASS/FAIL | |
49
+ | `yarn typecheck` | PASS/FAIL | |
50
+ | `yarn test` | PASS/FAIL | |
51
+ | `yarn build` | PASS/FAIL | |
52
+
53
+ ## Findings
54
+
55
+ ### Critical
56
+ {Security, data integrity, tenant isolation violations}
57
+
58
+ ### High
59
+ {Architecture violations, missing required exports}
60
+
61
+ ### Medium
62
+ {Convention violations, suboptimal patterns}
63
+
64
+ ### Low
65
+ {Suggestions, minor improvements}
66
+
67
+ ## Checklist
68
+ {From references/review-checklist.md — mark [x] passing, [ ] failing with explanation}
69
+ ```
70
+
71
+ Omit empty severity sections.
72
+
73
+ ## Severity Classification
74
+
75
+ | Severity | Criteria | Action |
76
+ |----------|----------|--------|
77
+ | **Critical** | Security vulnerability, cross-tenant leak, data corruption, missing auth | MUST fix before merge |
78
+ | **High** | Architecture violation, missing required export, broken module contract | MUST fix before merge |
79
+ | **Medium** | Convention violation, suboptimal pattern, missing best practice | Should fix |
80
+ | **Low** | Style suggestion, minor improvement | Nice to have |
81
+
82
+ ## Quick Rule Reference
83
+
84
+ ### Architecture
85
+
86
+ - **NO direct ORM relationships between modules** — use FK IDs, fetch separately
87
+ - **Always filter by `organization_id`** for tenant-scoped entities
88
+ - **Use DI (Awilix)** to inject services — never `new` directly
89
+ - **NO direct module-to-module calls** for side effects — use events
90
+ - **Cross-module data**: use extension entities + `data/extensions.ts`
91
+
92
+ ### Security
93
+
94
+ - **Validate all inputs with zod** in `data/validators.ts`
95
+ - **Use `findWithDecryption`** instead of raw `em.find`/`em.findOne`
96
+ - **Hash passwords with bcryptjs (cost >= 10)** — never log credentials
97
+ - **Every endpoint MUST declare auth guards** (`requireAuth`, `requireRoles`, `requireFeatures`)
98
+
99
+ ### Data Integrity
100
+
101
+ - **Never hand-write migrations** — update entities, run `yarn db:generate`
102
+ - **Validate migration scope** — autogenerated doesn't mean correct
103
+ - **Workers/subscribers MUST be idempotent**
104
+ - **Commands MUST be undoable** — include before/after snapshots
105
+
106
+ ### Naming
107
+
108
+ - Modules: **plural, snake_case** (folders and `id`)
109
+ - JS/TS identifiers: **camelCase**
110
+ - Database: **snake_case**, table names plural
111
+ - Standard columns: `id`, `created_at`, `updated_at`, `deleted_at`, `is_active`, `organization_id`
112
+
113
+ ### UI & HTTP
114
+
115
+ - Forms: `CrudForm` — never custom
116
+ - Tables: `DataTable` — never manual markup
117
+ - Notifications: `flash()` — never `alert()` or custom toast
118
+ - API calls: `apiCall`/`apiCallOrThrow` — never raw `fetch`
119
+ - Dialogs: `Cmd/Ctrl+Enter` (submit), `Escape` (cancel)
120
+ - `pageSize` MUST be <= 100
121
+
122
+ ### Code Quality
123
+
124
+ - No `any` types — use zod + `z.infer`
125
+ - No empty `catch` blocks
126
+ - No one-letter variable names
127
+ - Boolean parsing: use `parseBooleanToken`/`parseBooleanWithDefault`
128
+ - Don't add docstrings/comments to code you didn't change
129
+
130
+ ## Review Heuristics
131
+
132
+ 1. **New files**: Check if `yarn generate` is needed. Verify auto-discovery paths.
133
+ 2. **Entity changes**: Check if `yarn db:generate` is needed. Look for missing tenant columns.
134
+ 3. **Migration sanity**: Inspect SQL content. Reject unrelated schema churn.
135
+ 4. **New API routes**: Verify `openApi` export, auth guards, zod validation, tenant filtering.
136
+ 5. **Event emitters**: Verify event is declared in `events.ts` with `as const`.
137
+ 6. **Commands**: Verify undoable, before/after snapshots.
138
+ 7. **UI changes**: Verify `CrudForm`/`DataTable`, `flash()`, keyboard shortcuts, loading/error states.
139
+ 8. **Test coverage**: Verify unit/integration tests cover new behavior.
140
+
141
+ ## Reference Materials
142
+
143
+ - [Review Checklist](references/review-checklist.md)
144
+ - [AGENTS.md](../../../AGENTS.md)
@@ -0,0 +1,77 @@
1
+ # Code Review Checklist
2
+
3
+ ## 1. Architecture & Module Independence
4
+
5
+ - [ ] No ORM relationships between modules — FK IDs only
6
+ - [ ] No direct module-to-module function calls for side effects
7
+ - [ ] DI (Awilix) used for service wiring
8
+ - [ ] No cross-tenant data exposure
9
+ - [ ] Code in correct location (`src/modules/<id>/`)
10
+
11
+ ## 2. Security
12
+
13
+ - [ ] All inputs validated with zod in `data/validators.ts`
14
+ - [ ] No `any` types
15
+ - [ ] Auth guards on all endpoints (`requireAuth`, `requireRoles`, `requireFeatures`)
16
+ - [ ] Passwords hashed with bcryptjs (cost >= 10)
17
+ - [ ] No credentials logged or in error messages
18
+ - [ ] `findWithDecryption` used instead of raw `em.find`/`em.findOne`
19
+ - [ ] Tenant isolation: queries filter by `organization_id`
20
+
21
+ ## 3. Data Integrity & ORM
22
+
23
+ - [ ] No hand-written migrations — entities updated, `yarn db:generate` run
24
+ - [ ] Migration scope matches PR intent (no unrelated schema churn)
25
+ - [ ] UUID primary keys with standard columns (`id`, `created_at`, `updated_at`)
26
+ - [ ] Soft delete via `deleted_at` where applicable
27
+ - [ ] Atomic transactions for multi-step writes
28
+
29
+ ## 4. API Routes
30
+
31
+ - [ ] `openApi` exported for documentation
32
+ - [ ] `metadata` exported with auth guards
33
+ - [ ] Zod validation on request body
34
+ - [ ] Tenant scoping in queries
35
+ - [ ] `apiCall` used instead of raw `fetch`
36
+ - [ ] `pageSize <= 100`
37
+
38
+ ## 5. Events & Commands
39
+
40
+ - [ ] Events declared in `events.ts` with `createModuleEvents` and `as const`
41
+ - [ ] Subscribers export `metadata` with `{ event, persistent?, id? }`
42
+ - [ ] Workers export `metadata` with `{ queue, id?, concurrency? }`
43
+ - [ ] All mutations implemented as commands with undo logic
44
+ - [ ] Side effects outside `withAtomicFlush`
45
+
46
+ ## 6. UI & Backend Pages
47
+
48
+ - [ ] Forms use `CrudForm` (not custom)
49
+ - [ ] Tables use `DataTable` (not custom)
50
+ - [ ] Notifications use `flash()` (not alert/toast)
51
+ - [ ] Dialog forms have `embedded={true}`
52
+ - [ ] Keyboard: `Cmd/Ctrl+Enter` submit, `Escape` cancel
53
+ - [ ] Loading states: `LoadingMessage` or `DataLoader`
54
+ - [ ] Error states: `ErrorMessage` or `ErrorNotice`
55
+ - [ ] Empty states: `EmptyState`
56
+ - [ ] `RowActions` items have stable `id` values
57
+ - [ ] i18n: `useT()` client-side — no hardcoded strings
58
+
59
+ ## 7. Naming Conventions
60
+
61
+ - [ ] Modules: plural, snake_case
62
+ - [ ] JS/TS identifiers: camelCase
63
+ - [ ] DB tables/columns: snake_case, plural table names
64
+ - [ ] Feature naming: `<module>.<action>` (e.g. `inventory.view`)
65
+ - [ ] Event naming: `module.entity.action` (singular entity, past tense)
66
+
67
+ ## 8. Anti-Patterns
68
+
69
+ - [ ] No cross-module ORM links
70
+ - [ ] No plural entity/command/event naming
71
+ - [ ] No direct `fetch()` calls
72
+ - [ ] No custom toast/notification implementations
73
+ - [ ] No inline styles (use Tailwind)
74
+ - [ ] No hardcoded colors (use theme)
75
+ - [ ] No empty `catch` blocks
76
+ - [ ] No `any` types
77
+ - [ ] No missing loading/error states