siesa-agents 2.1.50 → 2.1.52
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.
- package/bmad/bmm/workflows/3-solutioning/create-architecture/data/company-standards/database-conventions.md +667 -0
- package/bmad/bmm/workflows/3-solutioning/create-architecture/data/company-standards/technical-preferences-ux.md +2 -2
- package/bmad/bmm/workflows/3-solutioning/create-architecture/data/project-types.csv +1 -1
- package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +3 -3
- package/bmad/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +15 -13
- package/bmad/bmm/workflows/generate-project-context/steps/step-01-discover.md +2 -1
- package/bmad/bmm/workflows/generate-project-context/steps/step-02-generate.md +1 -1
- package/bmad/bmm/workflows/testarch/framework/checklist.md +1 -1
- package/bmad/bmm/workflows/testarch/framework/instructions.md +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
# PostgreSQL Database Conventions
|
|
2
|
+
|
|
3
|
+
## 1. PostgreSQL Database Conventions
|
|
4
|
+
|
|
5
|
+
### 1.1 Tables
|
|
6
|
+
|
|
7
|
+
**Convention:** snake_case, PLURAL or SINGULAR form (configurable per project)
|
|
8
|
+
|
|
9
|
+
**EF Core Pluralization:** This standard supports both approaches:
|
|
10
|
+
- **Option A (Pluralization Enabled):** EF Core automatically pluralizes table names
|
|
11
|
+
- **Option B (Pluralization Disabled):** Manual control with singular names
|
|
12
|
+
|
|
13
|
+
**Example with Pluralization Enabled:**
|
|
14
|
+
```sql
|
|
15
|
+
-- ✅ CORRECT (Plural, snake_case)
|
|
16
|
+
CREATE TABLE products ( ... ); -- class: Product
|
|
17
|
+
CREATE TABLE customers ( ... ); -- class: Customer
|
|
18
|
+
CREATE TABLE order_items ( ... ); -- class: OrderItem
|
|
19
|
+
CREATE TABLE user_roles ( ... ); -- class: UserRole
|
|
20
|
+
|
|
21
|
+
-- ❌ INCORRECT
|
|
22
|
+
CREATE TABLE Products ( ... ); -- PascalCase
|
|
23
|
+
CREATE TABLE product ( ... ); -- Singular (if pluralization enabled)
|
|
24
|
+
CREATE TABLE product-items ( ... ); -- Hyphens not allowed
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Example with Pluralization Disabled:**
|
|
28
|
+
```sql
|
|
29
|
+
-- ✅ CORRECT (Singular, snake_case)
|
|
30
|
+
CREATE TABLE product ( ... ); -- class: Product
|
|
31
|
+
CREATE TABLE customer ( ... ); -- class: Customer
|
|
32
|
+
CREATE TABLE order_item ( ... ); -- class: OrderItem
|
|
33
|
+
CREATE TABLE user_role ( ... ); -- class: UserRole
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Key Identifiers:**
|
|
37
|
+
- **Primary Key (Guid):** Use `id` column name
|
|
38
|
+
- **Business Identifier (string):** Use `code` column name
|
|
39
|
+
|
|
40
|
+
```sql
|
|
41
|
+
-- ✅ CORRECT (with pluralization)
|
|
42
|
+
CREATE TABLE products (
|
|
43
|
+
id UUID PRIMARY KEY DEFAULT uuidv7(),
|
|
44
|
+
code VARCHAR(50) NOT NULL,
|
|
45
|
+
name VARCHAR(200) NOT NULL,
|
|
46
|
+
price DECIMAL(18,2) NOT NULL,
|
|
47
|
+
is_active BOOLEAN DEFAULT true,
|
|
48
|
+
created_at TIMESTAMP DEFAULT NOW(),
|
|
49
|
+
created_by_user_id UUID REFERENCES users(id)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
CREATE UNIQUE INDEX uk_products_code ON products(code);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 1.2 Columns
|
|
56
|
+
|
|
57
|
+
**Convention:** snake_case (mapped automatically from C# PascalCase properties)
|
|
58
|
+
|
|
59
|
+
```sql
|
|
60
|
+
-- ✅ CORRECT (snake_case, PostgreSQL standard)
|
|
61
|
+
CREATE TABLE products (
|
|
62
|
+
id UUID PRIMARY KEY, -- PK
|
|
63
|
+
code VARCHAR(50), -- Business identifier
|
|
64
|
+
name VARCHAR(200),
|
|
65
|
+
price DECIMAL(18,2),
|
|
66
|
+
is_active BOOLEAN, -- Boolean flag
|
|
67
|
+
created_at TIMESTAMP, -- Audit field
|
|
68
|
+
created_by_user_id UUID REFERENCES users(id),
|
|
69
|
+
updated_at TIMESTAMP,
|
|
70
|
+
updated_by_user_id UUID REFERENCES users(id)
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
-- C# class with PascalCase (maps automatically)
|
|
74
|
+
public class Product
|
|
75
|
+
{
|
|
76
|
+
public Guid ID { get; set; } // → id
|
|
77
|
+
public string Code { get; set; } // → code
|
|
78
|
+
public string Name { get; set; } // → name
|
|
79
|
+
public decimal Price { get; set; } // → price
|
|
80
|
+
public bool IsActive { get; set; } // → is_active
|
|
81
|
+
public DateTime CreatedAt { get; set; } // → created_at
|
|
82
|
+
public Guid CreatedByUserID { get; set; } // → created_by_user_id
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
-- ❌ INCORRECT
|
|
86
|
+
CREATE TABLE products (
|
|
87
|
+
ID UUID PRIMARY KEY, -- PascalCase
|
|
88
|
+
Price DECIMAL(18,2), -- PascalCase
|
|
89
|
+
IsActive BOOLEAN, -- PascalCase
|
|
90
|
+
created-at TIMESTAMP, -- Hyphens not allowed
|
|
91
|
+
Created_At TIMESTAMP -- Mixed case
|
|
92
|
+
);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Acronym Columns:**
|
|
96
|
+
```sql
|
|
97
|
+
-- C# properties with acronyms
|
|
98
|
+
public string APIKey { get; set; } // → api_key
|
|
99
|
+
public string HTTPEndpoint { get; set; } // → http_endpoint
|
|
100
|
+
public string XMLContent { get; set; } // → xml_content
|
|
101
|
+
public string JSONPayload { get; set; } // → json_payload
|
|
102
|
+
public int HTTPStatusCode { get; set; } // → http_status_code
|
|
103
|
+
|
|
104
|
+
-- PostgreSQL columns (snake_case)
|
|
105
|
+
CREATE TABLE api_configurations (
|
|
106
|
+
id UUID PRIMARY KEY,
|
|
107
|
+
api_key VARCHAR(100),
|
|
108
|
+
http_endpoint VARCHAR(500),
|
|
109
|
+
xml_content TEXT,
|
|
110
|
+
json_payload JSONB,
|
|
111
|
+
http_status_code INTEGER
|
|
112
|
+
);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 1.3 Foreign Key Columns
|
|
116
|
+
|
|
117
|
+
**Convention:** C# uses `{EntityName}ID`, database uses `{entity_name}_id` (snake_case)
|
|
118
|
+
|
|
119
|
+
**Foreign Keys:**
|
|
120
|
+
|
|
121
|
+
Use the exact entity name + ID suffix in C#. Database columns are automatically converted to snake_case.
|
|
122
|
+
|
|
123
|
+
```sql
|
|
124
|
+
-- ✅ CORRECT - Specific entity references (snake_case in database)
|
|
125
|
+
CREATE TABLE orders (
|
|
126
|
+
id UUID PRIMARY KEY,
|
|
127
|
+
customer_id UUID REFERENCES customers(id), -- FK to customers table
|
|
128
|
+
product_id UUID REFERENCES products(id), -- FK to products table
|
|
129
|
+
company_id UUID REFERENCES companies(id), -- FK to companies table
|
|
130
|
+
warehouse_id UUID REFERENCES warehouses(id) -- FK to warehouses table
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
-- C# class (PascalCase properties → snake_case columns)
|
|
134
|
+
public class Order
|
|
135
|
+
{
|
|
136
|
+
public Guid ID { get; set; } // → id
|
|
137
|
+
public Guid CustomerID { get; set; } // → customer_id
|
|
138
|
+
public Guid ProductID { get; set; } // → product_id
|
|
139
|
+
public Guid CompanyID { get; set; } // → company_id
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Multiple References to Same Entity:**
|
|
144
|
+
|
|
145
|
+
When a table has multiple foreign keys to the same entity, use a context prefix to differentiate them.
|
|
146
|
+
|
|
147
|
+
**Pattern:** C# uses `{Context}{EntityName}ID`, database uses `{context}_{entity_name}_id`
|
|
148
|
+
|
|
149
|
+
```sql
|
|
150
|
+
-- ✅ CORRECT - Multiple FKs to same entity with context prefix
|
|
151
|
+
CREATE TABLE shipments (
|
|
152
|
+
id UUID PRIMARY KEY,
|
|
153
|
+
origin_warehouse_id UUID REFERENCES warehouses(id), -- Origin warehouse
|
|
154
|
+
destination_warehouse_id UUID REFERENCES warehouses(id), -- Destination warehouse
|
|
155
|
+
shipped_at TIMESTAMP
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
CREATE TABLE transfers (
|
|
159
|
+
id UUID PRIMARY KEY,
|
|
160
|
+
source_account_id UUID REFERENCES accounts(id), -- Source account
|
|
161
|
+
destination_account_id UUID REFERENCES accounts(id), -- Destination account
|
|
162
|
+
amount DECIMAL(18,2)
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
CREATE TABLE transactions (
|
|
166
|
+
id UUID PRIMARY KEY,
|
|
167
|
+
sender_user_id UUID REFERENCES users(id), -- Sender user
|
|
168
|
+
receiver_user_id UUID REFERENCES users(id), -- Receiver user
|
|
169
|
+
amount DECIMAL(18,2)
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
-- C# classes
|
|
173
|
+
public class Shipment
|
|
174
|
+
{
|
|
175
|
+
public Guid ID { get; set; }
|
|
176
|
+
public Guid OriginWarehouseID { get; set; } // → origin_warehouse_id
|
|
177
|
+
public Guid DestinationWarehouseID { get; set; } // → destination_warehouse_id
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public class Transfer
|
|
181
|
+
{
|
|
182
|
+
public Guid ID { get; set; }
|
|
183
|
+
public Guid SourceAccountID { get; set; } // → source_account_id
|
|
184
|
+
public Guid DestinationAccountID { get; set; } // → destination_account_id
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Common Context Prefixes:**
|
|
189
|
+
- `Origin` / `Destination` - Origin and destination locations
|
|
190
|
+
- `Source` / `Destination` - Source and destination entities
|
|
191
|
+
- `Sender` / `Receiver` - Sender and receiver in transactions
|
|
192
|
+
- `Parent` / `Child` - Hierarchical relationships
|
|
193
|
+
- `Primary` / `Secondary` - Primary and secondary references
|
|
194
|
+
- `Manager` / `Subordinate` - Management relationships
|
|
195
|
+
|
|
196
|
+
**Audit Foreign Keys:**
|
|
197
|
+
|
|
198
|
+
For audit fields that reference Users, use `{Action}ByUserID` pattern in C#:
|
|
199
|
+
|
|
200
|
+
```sql
|
|
201
|
+
-- ✅ CORRECT - Explicit User references with action context (snake_case in database)
|
|
202
|
+
CREATE TABLE products (
|
|
203
|
+
id UUID PRIMARY KEY,
|
|
204
|
+
code VARCHAR(50),
|
|
205
|
+
name VARCHAR(200),
|
|
206
|
+
created_by_user_id UUID REFERENCES users(id), -- Who created
|
|
207
|
+
updated_by_user_id UUID REFERENCES users(id), -- Who last updated
|
|
208
|
+
created_at TIMESTAMP,
|
|
209
|
+
updated_at TIMESTAMP
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
-- C# class
|
|
213
|
+
public class Product
|
|
214
|
+
{
|
|
215
|
+
public Guid ID { get; set; } // → id
|
|
216
|
+
public string Code { get; set; } // → code
|
|
217
|
+
public string Name { get; set; } // → name
|
|
218
|
+
public Guid CreatedByUserID { get; set; } // → created_by_user_id
|
|
219
|
+
public Guid? UpdatedByUserID { get; set; } // → updated_by_user_id
|
|
220
|
+
public DateTime CreatedAt { get; set; } // → created_at
|
|
221
|
+
public DateTime? UpdatedAt { get; set; } // → updated_at
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Rationale:**
|
|
226
|
+
- C# `ProductID` is clearer than `ID` (ID of what?)
|
|
227
|
+
- C# `CreatedByUserID` is clearer than `CreatedBy` (created by what entity?)
|
|
228
|
+
- Database `product_id` follows PostgreSQL convention (snake_case)
|
|
229
|
+
- Self-documenting: no need to check FK constraints to understand relationships
|
|
230
|
+
- Consistent pattern: `{EntityName}ID` in C# → `{entity_name}_id` in database
|
|
231
|
+
|
|
232
|
+
```sql
|
|
233
|
+
-- ❌ INCORRECT - Generic or ambiguous names
|
|
234
|
+
CreatedBy UUID -- By what entity? Users? Systems?
|
|
235
|
+
product_id UUID -- C# side (should be ProductID in PascalCase)
|
|
236
|
+
Product_ID UUID -- Mixed case
|
|
237
|
+
PRODUCTID UUID -- All caps
|
|
238
|
+
ProductId UUID -- camelCase suffix (prefer ID)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 1.4 Indexes
|
|
242
|
+
|
|
243
|
+
**Convention:** `ix_{table}_{column(s)}` or `uk_{table}_{column(s)}` (for unique) in snake_case
|
|
244
|
+
|
|
245
|
+
```sql
|
|
246
|
+
-- ✅ CORRECT (all snake_case)
|
|
247
|
+
CREATE INDEX ix_products_code ON products(code);
|
|
248
|
+
CREATE INDEX ix_products_name ON products(name);
|
|
249
|
+
CREATE INDEX ix_products_is_active ON products(is_active);
|
|
250
|
+
CREATE INDEX ix_orders_customer_id ON orders(customer_id);
|
|
251
|
+
CREATE INDEX ix_user_roles_user_id ON user_roles(user_id);
|
|
252
|
+
|
|
253
|
+
-- For multi-column indexes
|
|
254
|
+
CREATE INDEX ix_orders_customer_id_created_at ON orders(customer_id, created_at);
|
|
255
|
+
|
|
256
|
+
-- For unique indexes, use uk_ prefix
|
|
257
|
+
CREATE UNIQUE INDEX uk_products_code ON products(code);
|
|
258
|
+
CREATE UNIQUE INDEX uk_customers_email ON customers(email);
|
|
259
|
+
|
|
260
|
+
-- ❌ INCORRECT
|
|
261
|
+
CREATE INDEX ProductCodeIndex ON products(code); -- PascalCase
|
|
262
|
+
CREATE INDEX idx_Products_Code ON products(code); -- Mixed case
|
|
263
|
+
CREATE INDEX idx_orders_CustomerID ON orders(customer_id); -- PascalCase column
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 1.5 Constraints
|
|
267
|
+
|
|
268
|
+
**Convention:** `{type}_{table}_{column(s)}` in snake_case
|
|
269
|
+
|
|
270
|
+
```sql
|
|
271
|
+
-- Primary Key
|
|
272
|
+
CONSTRAINT pk_products PRIMARY KEY (id)
|
|
273
|
+
|
|
274
|
+
-- Foreign Key
|
|
275
|
+
CONSTRAINT fk_orders_customers FOREIGN KEY (customer_id) REFERENCES customers(id)
|
|
276
|
+
CONSTRAINT fk_orders_products FOREIGN KEY (product_id) REFERENCES products(id)
|
|
277
|
+
|
|
278
|
+
-- Unique
|
|
279
|
+
CONSTRAINT uk_products_code UNIQUE (code)
|
|
280
|
+
CONSTRAINT uk_customers_email UNIQUE (email)
|
|
281
|
+
|
|
282
|
+
-- Check
|
|
283
|
+
CONSTRAINT chk_products_price_positive CHECK (price > 0)
|
|
284
|
+
CONSTRAINT chk_orders_quantity_positive CHECK (quantity > 0)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 1.6 PostgreSQL Schemas
|
|
288
|
+
|
|
289
|
+
**Convention:** lowercase with underscores (snake_case)
|
|
290
|
+
|
|
291
|
+
```sql
|
|
292
|
+
-- ✅ CORRECT
|
|
293
|
+
CREATE SCHEMA authentication;
|
|
294
|
+
CREATE SCHEMA inventory;
|
|
295
|
+
CREATE SCHEMA sales;
|
|
296
|
+
CREATE SCHEMA accounting;
|
|
297
|
+
CREATE SCHEMA product_management;
|
|
298
|
+
|
|
299
|
+
-- ❌ INCORRECT
|
|
300
|
+
CREATE SCHEMA Authentication; -- PascalCase
|
|
301
|
+
CREATE SCHEMA ProductManagement; -- PascalCase
|
|
302
|
+
CREATE SCHEMA "product-management"; -- Hyphenated (prefer underscores)
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Schema-to-Service Mapping Example:**
|
|
306
|
+
|
|
307
|
+
| Microservice | Schema Name | Purpose |
|
|
308
|
+
|--------------|-------------|---------|
|
|
309
|
+
| AuthenticationService | `authentication` | Users, Roles, Permissions |
|
|
310
|
+
| InventoryService | `inventory` | Products, Warehouses, Stock |
|
|
311
|
+
| SalesService | `sales` | Customers, Orders, Invoices |
|
|
312
|
+
| AccountingService | `accounting` | Accounts, Ledgers, Transactions |
|
|
313
|
+
|
|
314
|
+
**EF Core Configuration:**
|
|
315
|
+
|
|
316
|
+
```csharp
|
|
317
|
+
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
318
|
+
{
|
|
319
|
+
// Set default schema for all entities in this context
|
|
320
|
+
modelBuilder.HasDefaultSchema("inventory");
|
|
321
|
+
|
|
322
|
+
// Configure specific entity table names
|
|
323
|
+
modelBuilder.Entity<Product>(entity =>
|
|
324
|
+
{
|
|
325
|
+
entity.ToTable("products", "inventory");
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// Apply snake_case naming to all entities
|
|
329
|
+
modelBuilder.ApplySnakeCaseNaming();
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### 1.7 Projection Tables (Cross-Service References)
|
|
334
|
+
|
|
335
|
+
**Convention:** C# class `{PREFIX}_{Entity}Prj`, database table `{prefix}_{origin_table_name}_prj` (snake_case)
|
|
336
|
+
|
|
337
|
+
**Purpose:** Tables that maintain eventual-consistent copies of data from other microservices for referential integrity without database-level foreign keys.
|
|
338
|
+
|
|
339
|
+
**Pattern:**
|
|
340
|
+
```
|
|
341
|
+
Prefix: 4 uppercase characters identifying the source service/module
|
|
342
|
+
C# Class: {PREFIX}_{Entity}Prj (singular - class convention)
|
|
343
|
+
Database: {prefix}_{origin_table_name}_prj (maintains origin table plurality)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**Rule:** The projection table name must maintain the same plurality (singular/plural) as the origin table it projects from.
|
|
347
|
+
|
|
348
|
+
**Prefix Examples:**
|
|
349
|
+
- `AUTH` - Authentication service
|
|
350
|
+
- `INVT` - Inventory service
|
|
351
|
+
- `SALE` - Sales service
|
|
352
|
+
- `ACCT` - Accounting service
|
|
353
|
+
- `PROD` - Product management service
|
|
354
|
+
|
|
355
|
+
**Examples:**
|
|
356
|
+
|
|
357
|
+
| Origin Table | Origin Schema | C# Class | Database Projection | Consumer Schema | Purpose |
|
|
358
|
+
|--------------|---------------|----------|---------------------|-----------------|---------|
|
|
359
|
+
| users | authentication | **AUTH_UserPrj** | **auth_users_prj** | accounting | Audit fields (created_by_user_id) |
|
|
360
|
+
| users | authentication | **AUTH_UserPrj** | **auth_users_prj** | inventory | Audit fields (created_by_user_id) |
|
|
361
|
+
| products | inventory | **INVT_ProductPrj** | **invt_products_prj** | sales | Product references (product_id) |
|
|
362
|
+
| customers | sales | **SALE_CustomerPrj** | **sale_customers_prj** | accounting | Customer references (customer_id) |
|
|
363
|
+
| accounts | accounting | **ACCT_AccountPrj** | **acct_accounts_prj** | sales | Account references (account_id) |
|
|
364
|
+
|
|
365
|
+
**SQL Schema Template:**
|
|
366
|
+
|
|
367
|
+
```sql
|
|
368
|
+
-- ✅ CORRECT: Projection table in consumer schema (snake_case with prefix, maintains origin plurality)
|
|
369
|
+
-- Schema: inventory (consuming users from authentication service)
|
|
370
|
+
-- Origin: users (plural) → Projection: auth_users_prj (plural)
|
|
371
|
+
CREATE TABLE auth_users_prj (
|
|
372
|
+
id UUID PRIMARY KEY,
|
|
373
|
+
code VARCHAR(50) NOT NULL,
|
|
374
|
+
name VARCHAR(200) NOT NULL,
|
|
375
|
+
is_active BOOLEAN NOT NULL,
|
|
376
|
+
last_synced_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
CREATE INDEX ix_auth_users_prj_code ON auth_users_prj(code);
|
|
380
|
+
CREATE INDEX ix_auth_users_prj_is_active ON auth_users_prj(is_active);
|
|
381
|
+
|
|
382
|
+
-- Schema: sales (consuming products from inventory service)
|
|
383
|
+
-- Origin: products (plural) → Projection: invt_products_prj (plural)
|
|
384
|
+
CREATE TABLE invt_products_prj (
|
|
385
|
+
id UUID PRIMARY KEY,
|
|
386
|
+
code VARCHAR(50) NOT NULL,
|
|
387
|
+
name VARCHAR(200) NOT NULL,
|
|
388
|
+
price DECIMAL(18,2),
|
|
389
|
+
is_active BOOLEAN NOT NULL,
|
|
390
|
+
last_synced_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
-- ❌ INCORRECT: Old naming conventions
|
|
394
|
+
CREATE TABLE UsersPrj (...); -- PascalCase (wrong)
|
|
395
|
+
CREATE TABLE user_projection (...); -- Too verbose (wrong)
|
|
396
|
+
CREATE TABLE users_prj (...); -- Missing prefix (wrong)
|
|
397
|
+
CREATE TABLE auth_user_prj (...); -- Wrong plurality (origin is plural 'users')
|
|
398
|
+
CREATE TABLE AUTH_UsersPrj (...); -- PascalCase in DB (wrong)
|
|
399
|
+
CREATE TABLE authUserPrj (...); -- camelCase (wrong)
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**C# Entity Example:**
|
|
403
|
+
|
|
404
|
+
```csharp
|
|
405
|
+
// ✅ CORRECT: C# class uses PREFIX_EntityPrj pattern
|
|
406
|
+
public class AUTH_UserPrj
|
|
407
|
+
{
|
|
408
|
+
public Guid ID { get; set; }
|
|
409
|
+
public string Code { get; set; } = null!;
|
|
410
|
+
public string Name { get; set; } = null!;
|
|
411
|
+
public bool IsActive { get; set; }
|
|
412
|
+
public DateTime LastSyncedAt { get; set; }
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
public class INVT_ProductPrj
|
|
416
|
+
{
|
|
417
|
+
public Guid ID { get; set; }
|
|
418
|
+
public string Code { get; set; } = null!;
|
|
419
|
+
public string Name { get; set; } = null!;
|
|
420
|
+
public decimal Price { get; set; }
|
|
421
|
+
public bool IsActive { get; set; }
|
|
422
|
+
public DateTime LastSyncedAt { get; set; }
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// DbContext with explicit table mapping
|
|
426
|
+
public DbSet<AUTH_UserPrj> AUTH_UserPrj => Set<AUTH_UserPrj>();
|
|
427
|
+
public DbSet<INVT_ProductPrj> INVT_ProductPrj => Set<INVT_ProductPrj>();
|
|
428
|
+
|
|
429
|
+
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
430
|
+
{
|
|
431
|
+
modelBuilder.Entity<AUTH_UserPrj>(entity =>
|
|
432
|
+
{
|
|
433
|
+
// Table name maintains origin table plurality (users → auth_users_prj)
|
|
434
|
+
entity.ToTable("auth_users_prj", "inventory");
|
|
435
|
+
// Column mappings applied automatically via SnakeCaseNamingConvention
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
modelBuilder.Entity<INVT_ProductPrj>(entity =>
|
|
439
|
+
{
|
|
440
|
+
// Table name maintains origin table plurality (products → invt_products_prj)
|
|
441
|
+
entity.ToTable("invt_products_prj", "sales");
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**Synchronization:**
|
|
447
|
+
- Via domain events (message bus): `UserCreated`, `UserUpdated`, `ProductUpdated`
|
|
448
|
+
- Eventual consistency model
|
|
449
|
+
- No database-level FK constraints
|
|
450
|
+
- Application-level validation before insert
|
|
451
|
+
|
|
452
|
+
**Usage in Business Tables:**
|
|
453
|
+
|
|
454
|
+
```sql
|
|
455
|
+
-- Business table references projection (no FK constraint)
|
|
456
|
+
CREATE TABLE orders (
|
|
457
|
+
id UUID PRIMARY KEY DEFAULT uuidv7(),
|
|
458
|
+
customer_id UUID NOT NULL, -- References sale_customers_prj.id (no FK)
|
|
459
|
+
created_by_user_id UUID NOT NULL, -- References auth_users_prj.id (no FK)
|
|
460
|
+
amount DECIMAL(18,2) NOT NULL,
|
|
461
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
-- Validation in application layer before insert:
|
|
465
|
+
-- 1. Check sale_customers_prj
|
|
466
|
+
-- 2. Check auth_users_prj
|
|
467
|
+
-- 3. Then insert order
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Rationale:**
|
|
471
|
+
- **4-char prefix:** Identifies source service/module clearly (`AUTH`, `INVT`, `SALE`, `ACCT`)
|
|
472
|
+
- **`Prj` suffix in C#:** Short (3 chars), recognizable abbreviation for "Projection"
|
|
473
|
+
- **Brevity over verbosity:** `AUTH_UserPrj` preferred over `AuthenticationUserProjection`
|
|
474
|
+
- **snake_case in database:** Consistent with PostgreSQL standard
|
|
475
|
+
- **Maintains origin plurality:** `users` → `auth_users_prj`, `products` → `invt_products_prj` (clear relationship to origin)
|
|
476
|
+
- **Direct mapping:** Visual consistency between origin and projection (`users` ↔ `auth_users_prj`)
|
|
477
|
+
- **Self-documenting:** Clear distinction from origin table via prefix + `_prj` suffix
|
|
478
|
+
- **Namespace isolation:** Prefix prevents naming collisions across services
|
|
479
|
+
- **Query clarity:** Queries clearly show which origin table is being referenced
|
|
480
|
+
|
|
481
|
+
**Plurality Examples:**
|
|
482
|
+
|
|
483
|
+
```csharp
|
|
484
|
+
// With Pluralization Enabled (origin tables are plural)
|
|
485
|
+
Origin: users (plural) → Projection: auth_users_prj (plural)
|
|
486
|
+
Origin: products (plural) → Projection: invt_products_prj (plural)
|
|
487
|
+
Origin: categories (plural) → Projection: acct_categories_prj (plural)
|
|
488
|
+
|
|
489
|
+
// With Pluralization Disabled (origin tables are singular)
|
|
490
|
+
Origin: user (singular) → Projection: auth_user_prj (singular)
|
|
491
|
+
Origin: product (singular) → Projection: invt_product_prj (singular)
|
|
492
|
+
Origin: category (singular) → Projection: acct_category_prj (singular)
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
**Key Principle:** Always mirror the origin table's plurality in the projection table name for maximum clarity and consistency.
|
|
496
|
+
|
|
497
|
+
## 2. EF Core Mapping Strategy
|
|
498
|
+
|
|
499
|
+
### 2.1 Strategy: Automatic snake_case Conversion
|
|
500
|
+
|
|
501
|
+
**Decision:** C# classes use idiomatic PascalCase, PostgreSQL uses idiomatic snake_case. EF Core automatically converts between them via `SnakeCaseNamingConvention`.
|
|
502
|
+
|
|
503
|
+
**Benefits:**
|
|
504
|
+
- ✅ Idiomatic C# code (PascalCase properties)
|
|
505
|
+
- ✅ PostgreSQL standard naming (snake_case columns)
|
|
506
|
+
- ✅ Zero manual `[Column]` or `[Table]` attributes needed
|
|
507
|
+
- ✅ Handles acronyms correctly (APIKey → api_key, HTTPClient → http_client)
|
|
508
|
+
- ✅ Single source of truth (C# classes define structure)
|
|
509
|
+
|
|
510
|
+
**Implementation:**
|
|
511
|
+
|
|
512
|
+
```csharp
|
|
513
|
+
// File: Shared/EntityFramework/SnakeCaseNamingConvention.cs
|
|
514
|
+
public static class SnakeCaseNamingConvention
|
|
515
|
+
{
|
|
516
|
+
public static string ToSnakeCase(string input)
|
|
517
|
+
{
|
|
518
|
+
if (string.IsNullOrEmpty(input)) return input;
|
|
519
|
+
|
|
520
|
+
// Handle acronyms and PascalCase correctly:
|
|
521
|
+
// ID → id, APIKey → api_key, CreatedAt → created_at, HTTPClient → http_client
|
|
522
|
+
var snakeCase = Regex.Replace(input, "([a-z0-9])([A-Z])", "$1_$2");
|
|
523
|
+
snakeCase = Regex.Replace(snakeCase, "([A-Z]+)([A-Z][a-z])", "$1_$2");
|
|
524
|
+
return snakeCase.ToLowerInvariant();
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
public static void ApplySnakeCaseNaming(this ModelBuilder modelBuilder)
|
|
528
|
+
{
|
|
529
|
+
foreach (var entity in modelBuilder.Model.GetEntityTypes())
|
|
530
|
+
{
|
|
531
|
+
// Convert table names: Product → product (or products if pluralization enabled)
|
|
532
|
+
entity.SetTableName(ToSnakeCase(entity.GetTableName()));
|
|
533
|
+
|
|
534
|
+
// Convert column names: CreatedAt → created_at
|
|
535
|
+
foreach (var property in entity.GetProperties())
|
|
536
|
+
{
|
|
537
|
+
property.SetColumnName(ToSnakeCase(property.Name));
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Convert indexes: ix_Product_Code → ix_product_code
|
|
541
|
+
foreach (var index in entity.GetIndexes())
|
|
542
|
+
{
|
|
543
|
+
var prefix = index.IsUnique ? "uk_" : "ix_";
|
|
544
|
+
var tableName = ToSnakeCase(entity.GetTableName());
|
|
545
|
+
var columnNames = string.Join("_", index.Properties.Select(p => ToSnakeCase(p.Name)));
|
|
546
|
+
index.SetDatabaseName($"{prefix}{tableName}_{columnNames}");
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Convert FK constraints: fk_Order_Customer → fk_order_customer
|
|
550
|
+
foreach (var foreignKey in entity.GetForeignKeys())
|
|
551
|
+
{
|
|
552
|
+
var dependentTable = ToSnakeCase(foreignKey.DeclaringEntityType.GetTableName());
|
|
553
|
+
var principalTable = ToSnakeCase(foreignKey.PrincipalEntityType.GetTableName());
|
|
554
|
+
foreignKey.SetConstraintName($"fk_{dependentTable}_{principalTable}");
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Example Mapping:**
|
|
562
|
+
|
|
563
|
+
```csharp
|
|
564
|
+
// C# Entity (idiomatic PascalCase)
|
|
565
|
+
public class Product
|
|
566
|
+
{
|
|
567
|
+
public Guid ID { get; set; } // → id
|
|
568
|
+
public string Code { get; set; } // → code
|
|
569
|
+
public string Name { get; set; } // → name
|
|
570
|
+
public decimal Price { get; set; } // → price
|
|
571
|
+
public bool IsActive { get; set; } // → is_active
|
|
572
|
+
public DateTime CreatedAt { get; set; } // → created_at
|
|
573
|
+
public Guid CreatedByUserID { get; set; } // → created_by_user_id
|
|
574
|
+
public string APIKey { get; set; } // → api_key
|
|
575
|
+
public string HTTPEndpoint { get; set; } // → http_endpoint
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// PostgreSQL Table (PostgreSQL standard snake_case) - GENERATED AUTOMATICALLY
|
|
579
|
+
CREATE TABLE products ( -- or 'product' if pluralization disabled
|
|
580
|
+
id UUID PRIMARY KEY DEFAULT uuidv7(),
|
|
581
|
+
code VARCHAR(50) NOT NULL,
|
|
582
|
+
name VARCHAR(200) NOT NULL,
|
|
583
|
+
price DECIMAL(18,2) NOT NULL,
|
|
584
|
+
is_active BOOLEAN NOT NULL,
|
|
585
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
586
|
+
created_by_user_id UUID NOT NULL REFERENCES users(id),
|
|
587
|
+
api_key VARCHAR(100),
|
|
588
|
+
http_endpoint VARCHAR(500)
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
CREATE UNIQUE INDEX uk_products_code ON products(code);
|
|
592
|
+
CREATE INDEX ix_products_is_active ON products(is_active);
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### 2.2 DbContext Configuration
|
|
596
|
+
|
|
597
|
+
**CRITICAL:** Apply snake_case naming **AFTER** all entity configurations:
|
|
598
|
+
|
|
599
|
+
```csharp
|
|
600
|
+
// Example DbContext
|
|
601
|
+
public class ApplicationDbContext : DbContext
|
|
602
|
+
{
|
|
603
|
+
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
604
|
+
{
|
|
605
|
+
// Set schema
|
|
606
|
+
modelBuilder.HasDefaultSchema("inventory");
|
|
607
|
+
|
|
608
|
+
// Configure entities (explicit table naming)
|
|
609
|
+
modelBuilder.Entity<Product>(entity =>
|
|
610
|
+
{
|
|
611
|
+
// Explicit snake_case table name
|
|
612
|
+
// Use "products" if pluralization enabled, "product" if disabled
|
|
613
|
+
entity.ToTable("products", "inventory");
|
|
614
|
+
|
|
615
|
+
entity.HasKey(e => e.ID);
|
|
616
|
+
|
|
617
|
+
entity.Property(e => e.Code).IsRequired().HasMaxLength(50);
|
|
618
|
+
entity.HasIndex(e => e.Code).IsUnique();
|
|
619
|
+
|
|
620
|
+
entity.Property(e => e.Price).HasPrecision(18, 2);
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// CRITICAL: Apply snake_case naming LAST
|
|
624
|
+
modelBuilder.ApplySnakeCaseNaming();
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
**Why apply last?** The convention needs to process all configured entities, indexes, and constraints.
|
|
630
|
+
|
|
631
|
+
### 2.3 When to Use [Column] or [Table] Attributes
|
|
632
|
+
|
|
633
|
+
**Short answer: RARELY**
|
|
634
|
+
|
|
635
|
+
The `SnakeCaseNamingConvention` handles all mapping automatically. Manual attributes are:
|
|
636
|
+
- ❌ Usually not needed
|
|
637
|
+
- ❌ Can create inconsistency
|
|
638
|
+
- ❌ Bypass the convention
|
|
639
|
+
- ❌ Increase maintenance burden
|
|
640
|
+
|
|
641
|
+
```csharp
|
|
642
|
+
// ❌ INCORRECT - Don't use manual attributes (convention handles this)
|
|
643
|
+
public class Product
|
|
644
|
+
{
|
|
645
|
+
[Column("price")] // WRONG - convention handles this
|
|
646
|
+
public decimal Price { get; set; }
|
|
647
|
+
|
|
648
|
+
[Table("products")] // WRONG - use ToTable() in OnModelCreating instead
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// ✅ CORRECT - Let convention handle everything
|
|
652
|
+
public class Product
|
|
653
|
+
{
|
|
654
|
+
public decimal Price { get; set; } // → price automatically
|
|
655
|
+
}
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
**Exception:** If you legitimately need a database column name that doesn't follow snake_case (e.g., legacy integration), document it clearly and use `[Column]` with a comment explaining why.
|
|
659
|
+
|
|
660
|
+
## 3. Tooling
|
|
661
|
+
|
|
662
|
+
### 3.1 SQL - pg_format
|
|
663
|
+
|
|
664
|
+
```bash
|
|
665
|
+
# Format SQL files with snake_case
|
|
666
|
+
pg_format --function-case 2 --keyword-case 2 --spaces 2 migration.sql
|
|
667
|
+
```
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
Based on Frontend Development Standards and Clean Architecture Implementation
|
|
5
5
|
|
|
6
6
|
### Technology Stack
|
|
7
|
-
- **Framework**:
|
|
7
|
+
- **Framework**: Vite 6+ with TanStack Router
|
|
8
8
|
- **Language**: TypeScript (strict mode)
|
|
9
9
|
- **Styling**: TailwindCSS + Shadcn/ui + Radix UI
|
|
10
|
-
- **State Management**: Zustand
|
|
10
|
+
- **State Management**: Zustand + TanStack Query
|
|
11
11
|
- **Testing**: Vitest + React Testing Library
|
|
12
12
|
- **Architecture**: Clean Architecture with DDD patterns
|
|
13
13
|
- **Loading States**: React Loading Skeleton (for placeholders/preloading)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
project_type,detection_signals,description,typical_starters
|
|
2
|
-
web_app,"website,web application,browser,frontend,UI,interface",Web-based applications running in browsers,
|
|
2
|
+
web_app,"website,web application,browser,frontend,UI,interface",Web-based applications running in browsers,Vite, Remix
|
|
3
3
|
mobile_app,"mobile,iOS,Android,app,smartphone,tablet",Native mobile applications,React Native, Expo, Flutter
|
|
4
4
|
api_backend,"API,REST,GraphQL,backend,service,microservice",Backend services and APIs,NestJS, Express, Fastify
|
|
5
5
|
full_stack,"full-stack,complete,web+mobile,frontend+backend",Applications with both frontend and backend,T3 App, RedwoodJS, Blitz
|
|
@@ -87,7 +87,7 @@ No existing technical preferences found in project context file. We'll establish
|
|
|
87
87
|
{{primary_technology_category}} Preferences:
|
|
88
88
|
|
|
89
89
|
- **Languages**: Do you have preferences between TypeScript/JavaScript, Python, Go, Rust, etc.?
|
|
90
|
-
- **Frameworks**: Any existing familiarity or preferences (React, Vue, Angular,
|
|
90
|
+
- **Frameworks**: Any existing familiarity or preferences (React, Vue, Angular, Vite, etc.)?
|
|
91
91
|
- **Databases**: Any preferences or existing infrastructure (PostgreSQL, MongoDB, MySQL, etc.)?
|
|
92
92
|
|
|
93
93
|
**Development Experience:**
|
|
@@ -111,11 +111,11 @@ These preferences will help me recommend the most suitable starter templates and
|
|
|
111
111
|
|
|
112
112
|
Based on project context analysis and technical preferences, identify the primary technology stack:
|
|
113
113
|
|
|
114
|
-
- **Web application** → Look for
|
|
114
|
+
- **Web application** → Look for Vite, Remix, SvelteKit starters
|
|
115
115
|
- **Mobile app** → Look for React Native, Expo, Flutter starters
|
|
116
116
|
- **API/Backend** → Look for NestJS, Express, Fastify, Supabase starters
|
|
117
117
|
- **CLI tool** → Look for CLI framework starters (oclif, commander, etc.)
|
|
118
|
-
- **Full-stack** → Look for T3, RedwoodJS, Blitz
|
|
118
|
+
- **Full-stack** → Look for T3, RedwoodJS, Blitz starters
|
|
119
119
|
- **Desktop** → Look for Electron, Tauri starters
|
|
120
120
|
|
|
121
121
|
### 2. UX Requirements Consideration
|
|
@@ -133,39 +133,41 @@ Generate a comprehensive directory structure showing all files and directories:
|
|
|
133
133
|
|
|
134
134
|
**Technology-Specific Structure Examples:**
|
|
135
135
|
|
|
136
|
-
**
|
|
136
|
+
**Vite + TanStack Full-Stack:**
|
|
137
137
|
|
|
138
138
|
```
|
|
139
139
|
project-name/
|
|
140
140
|
├── README.md
|
|
141
141
|
├── package.json
|
|
142
|
-
├──
|
|
142
|
+
├── vite.config.ts
|
|
143
143
|
├── tailwind.config.js
|
|
144
144
|
├── tsconfig.json
|
|
145
|
-
├── .env
|
|
145
|
+
├── .env
|
|
146
146
|
├── .env.example
|
|
147
147
|
├── .gitignore
|
|
148
148
|
├── .github/
|
|
149
149
|
│ └── workflows/
|
|
150
150
|
│ └── ci.yml
|
|
151
151
|
├── src/
|
|
152
|
-
│ ├──
|
|
153
|
-
│
|
|
154
|
-
│
|
|
155
|
-
│
|
|
152
|
+
│ ├── main.tsx
|
|
153
|
+
│ ├── App.tsx
|
|
154
|
+
│ ├── index.css
|
|
155
|
+
│ ├── assets/
|
|
156
156
|
│ ├── components/
|
|
157
157
|
│ │ ├── ui/
|
|
158
158
|
│ │ ├── forms/
|
|
159
159
|
│ │ └── features/
|
|
160
|
+
│ ├── hooks/
|
|
160
161
|
│ ├── lib/
|
|
161
|
-
│ │ ├──
|
|
162
|
+
│ │ ├── query-client.ts
|
|
162
163
|
│ │ ├── auth.ts
|
|
163
164
|
│ │ └── utils.ts
|
|
164
|
-
│ ├──
|
|
165
|
-
│
|
|
166
|
-
├──
|
|
167
|
-
│
|
|
168
|
-
│
|
|
165
|
+
│ ├── routes/
|
|
166
|
+
│ │ ├── __root.tsx
|
|
167
|
+
│ │ ├── index.tsx
|
|
168
|
+
│ │ └── ...
|
|
169
|
+
│ ├── stores/
|
|
170
|
+
│ └── types/
|
|
169
171
|
├── tests/
|
|
170
172
|
│ ├── __mocks__/
|
|
171
173
|
│ ├── components/
|
|
@@ -60,6 +60,7 @@ Check for and load company-specific technology standards:
|
|
|
60
60
|
**If directory exists, load ALL markdown files:**
|
|
61
61
|
|
|
62
62
|
- `technology-stack.md` - Predefined technology stack and versions
|
|
63
|
+
- `database-conventions.md` - PostgreSQL database naming conventions
|
|
63
64
|
- `backend-standards.md` - Backend development patterns and rules
|
|
64
65
|
- `frontend-standards.md` - Frontend development patterns
|
|
65
66
|
- `architecture-patterns.md` - Architectural decision patterns
|
|
@@ -78,7 +79,7 @@ When loading company standards, specifically look for and highlight:
|
|
|
78
79
|
- 🔴 **siesa-ui-kit requirement** - Must check siesa-ui-kit before creating components
|
|
79
80
|
- 🔴 **Spanish UI text** - All user-facing text must be in Spanish
|
|
80
81
|
- 🔴 **DateTimeOffset** - Use DateTimeOffset not DateTime for PostgreSQL
|
|
81
|
-
- Technology stack versions (.NET 10,
|
|
82
|
+
- Technology stack versions (.NET 10, Vite 6+, etc.)
|
|
82
83
|
|
|
83
84
|
Report: "✅ Estándares corporativos cargados: {count} archivos con {rules_count} reglas críticas"
|
|
84
85
|
|
|
@@ -125,7 +125,7 @@ Document framework-specific patterns:
|
|
|
125
125
|
Should I add any other React-specific rules?"
|
|
126
126
|
|
|
127
127
|
**Other Framework Rules:**
|
|
128
|
-
Adapt for Vue, Angular,
|
|
128
|
+
Adapt for Vue, Angular, Vite, Express, etc.
|
|
129
129
|
|
|
130
130
|
### 4. Testing Rules
|
|
131
131
|
|
|
@@ -10,7 +10,7 @@ Before starting the workflow:
|
|
|
10
10
|
|
|
11
11
|
- [ ] Project root contains valid `package.json`
|
|
12
12
|
- [ ] No existing modern E2E framework detected (`playwright.config.*`, `cypress.config.*`)
|
|
13
|
-
- [ ] Project type identifiable (React, Vue, Angular,
|
|
13
|
+
- [ ] Project type identifiable (React, Vue, Angular, Vite, Node, etc.)
|
|
14
14
|
- [ ] Bundler identifiable (Vite, Webpack, Rollup, esbuild) or not applicable
|
|
15
15
|
- [ ] User has write permissions to create directories and files
|
|
16
16
|
|
|
@@ -29,7 +29,7 @@ Initialize a production-ready test framework architecture (Playwright or Cypress
|
|
|
29
29
|
|
|
30
30
|
1. **Validate package.json**
|
|
31
31
|
- Read `{project-root}/package.json`
|
|
32
|
-
- Extract project type (React, Vue, Angular,
|
|
32
|
+
- Extract project type (React, Vue, Angular, Vite, Node, etc.)
|
|
33
33
|
- Identify bundler (Vite, Webpack, Rollup, esbuild)
|
|
34
34
|
- Note existing test dependencies
|
|
35
35
|
|