class-ai-agent 1.2.0

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 (93) hide show
  1. package/.claude/CLAUDE.md +155 -0
  2. package/.claude/agents/backend.md +395 -0
  3. package/.claude/agents/code-reviewer.md +110 -0
  4. package/.claude/agents/copywriter-seo.md +236 -0
  5. package/.claude/agents/frontend.md +384 -0
  6. package/.claude/agents/project-manager.md +201 -0
  7. package/.claude/agents/qa.md +221 -0
  8. package/.claude/agents/security-auditor.md +143 -0
  9. package/.claude/agents/systems-architect.md +211 -0
  10. package/.claude/agents/test-engineer.md +123 -0
  11. package/.claude/agents/ui-ux-designer.md +210 -0
  12. package/.claude/commands/build.md +132 -0
  13. package/.claude/commands/debug.md +242 -0
  14. package/.claude/commands/deploy.md +40 -0
  15. package/.claude/commands/fix-issue.md +42 -0
  16. package/.claude/commands/plan.md +125 -0
  17. package/.claude/commands/review.md +50 -0
  18. package/.claude/commands/simplify.md +222 -0
  19. package/.claude/commands/spec.md +95 -0
  20. package/.claude/commands/test.md +214 -0
  21. package/.claude/references/accessibility-checklist.md +174 -0
  22. package/.claude/references/performance-checklist.md +150 -0
  23. package/.claude/references/security-checklist.md +94 -0
  24. package/.claude/references/testing-patterns.md +183 -0
  25. package/.claude/rules/api-conventions.md +79 -0
  26. package/.claude/rules/clean-code.md +205 -0
  27. package/.claude/rules/code-style.md +86 -0
  28. package/.claude/rules/database.md +60 -0
  29. package/.claude/rules/error-handling.md +92 -0
  30. package/.claude/rules/git-workflow.md +77 -0
  31. package/.claude/rules/monitoring.md +311 -0
  32. package/.claude/rules/naming-conventions.md +260 -0
  33. package/.claude/rules/project-structure.md +65 -0
  34. package/.claude/rules/security.md +90 -0
  35. package/.claude/rules/system-design.md +162 -0
  36. package/.claude/rules/tech-stack.md +456 -0
  37. package/.claude/rules/testing.md +104 -0
  38. package/.claude/settings.json +14 -0
  39. package/.claude/skills/code-review/SKILL.md +208 -0
  40. package/.claude/skills/deploy/SKILL.md +68 -0
  41. package/.claude/skills/deploy/deploy.md +735 -0
  42. package/.claude/skills/incremental-implementation/SKILL.md +210 -0
  43. package/.claude/skills/security-review/SKILL.md +71 -0
  44. package/.claude/skills/tdd/SKILL.md +217 -0
  45. package/.cursor/CURSOR.md +112 -0
  46. package/.cursor/agents/backend.md +395 -0
  47. package/.cursor/agents/code-reviewer.md +110 -0
  48. package/.cursor/agents/copywriter-seo.md +236 -0
  49. package/.cursor/agents/frontend.md +384 -0
  50. package/.cursor/agents/project-manager.md +201 -0
  51. package/.cursor/agents/qa.md +221 -0
  52. package/.cursor/agents/security-auditor.md +143 -0
  53. package/.cursor/agents/systems-architect.md +211 -0
  54. package/.cursor/agents/test-engineer.md +123 -0
  55. package/.cursor/agents/ui-ux-designer.md +210 -0
  56. package/.cursor/commands/build.md +132 -0
  57. package/.cursor/commands/debug.md +242 -0
  58. package/.cursor/commands/deploy.md +40 -0
  59. package/.cursor/commands/fix-issue.md +42 -0
  60. package/.cursor/commands/plan.md +125 -0
  61. package/.cursor/commands/review.md +50 -0
  62. package/.cursor/commands/simplify.md +222 -0
  63. package/.cursor/commands/spec.md +95 -0
  64. package/.cursor/commands/test.md +214 -0
  65. package/.cursor/references/accessibility-checklist.md +174 -0
  66. package/.cursor/references/performance-checklist.md +150 -0
  67. package/.cursor/references/security-checklist.md +94 -0
  68. package/.cursor/references/testing-patterns.md +183 -0
  69. package/.cursor/rules/api-conventions.mdc +85 -0
  70. package/.cursor/rules/clean-code.mdc +211 -0
  71. package/.cursor/rules/code-style.mdc +92 -0
  72. package/.cursor/rules/cursor-overview.mdc +35 -0
  73. package/.cursor/rules/database.mdc +66 -0
  74. package/.cursor/rules/error-handling.mdc +98 -0
  75. package/.cursor/rules/git-workflow.mdc +83 -0
  76. package/.cursor/rules/monitoring.mdc +317 -0
  77. package/.cursor/rules/naming-conventions.mdc +266 -0
  78. package/.cursor/rules/project-structure.mdc +71 -0
  79. package/.cursor/rules/security.mdc +95 -0
  80. package/.cursor/rules/system-design.mdc +168 -0
  81. package/.cursor/rules/tech-stack.mdc +462 -0
  82. package/.cursor/rules/testing.mdc +110 -0
  83. package/.cursor/settings.json +8 -0
  84. package/.cursor/skills/code-review/SKILL.md +208 -0
  85. package/.cursor/skills/deploy/SKILL.md +68 -0
  86. package/.cursor/skills/deploy/deploy.md +735 -0
  87. package/.cursor/skills/incremental-implementation/SKILL.md +210 -0
  88. package/.cursor/skills/security-review/SKILL.md +71 -0
  89. package/.cursor/skills/tdd/SKILL.md +217 -0
  90. package/AGENTS.md +11 -0
  91. package/README.md +405 -0
  92. package/bin/class-ai-agent.cjs +176 -0
  93. package/package.json +38 -0
@@ -0,0 +1,94 @@
1
+ # Security Checklist
2
+
3
+ > Quick reference for security review. See `.claude/rules/security.md` for full rules.
4
+
5
+ ## Pre-Commit Checks
6
+
7
+ - [ ] No secrets in code (API keys, passwords, tokens)
8
+ - [ ] `.gitignore` excludes sensitive files (`.env`, credentials)
9
+ - [ ] `.env.example` contains only placeholder values
10
+ - [ ] No hardcoded URLs with credentials
11
+
12
+ ## Authentication
13
+
14
+ - [ ] Passwords hashed with bcrypt (rounds >= 12) or argon2
15
+ - [ ] Session cookies: `httpOnly`, `secure`, `sameSite: 'lax'`
16
+ - [ ] JWT tokens have reasonable expiry (15min access, 7d refresh)
17
+ - [ ] Rate limiting on auth endpoints (max 10 attempts/15min)
18
+ - [ ] Logout invalidates session/token
19
+
20
+ ## Authorization
21
+
22
+ - [ ] Every endpoint checks authentication
23
+ - [ ] Resource ownership verified (no IDOR)
24
+ - [ ] API keys are scoped appropriately
25
+ - [ ] JWT signature, expiration, and issuer validated
26
+ - [ ] Admin functions protected
27
+
28
+ ## Input Validation
29
+
30
+ - [ ] All user input validated at system boundary
31
+ - [ ] Allowlist validation preferred over blocklist
32
+ - [ ] String lengths constrained
33
+ - [ ] Numeric ranges validated
34
+ - [ ] File uploads restricted by type and size
35
+ - [ ] SQL queries parameterized (never string concat)
36
+
37
+ ## Security Headers
38
+
39
+ ```javascript
40
+ // Required headers
41
+ Content-Security-Policy: default-src 'self'
42
+ Strict-Transport-Security: max-age=31536000; includeSubDomains
43
+ X-Content-Type-Options: nosniff
44
+ X-Frame-Options: DENY
45
+ Permissions-Policy: geolocation=(), camera=()
46
+ ```
47
+
48
+ ## CORS
49
+
50
+ - [ ] Restrictive origin allowlist (no `*` in production)
51
+ - [ ] Credentials mode appropriate
52
+ - [ ] Methods and headers restricted
53
+
54
+ ## Data Protection
55
+
56
+ - [ ] Sensitive fields excluded from API responses
57
+ - [ ] No secrets in logs
58
+ - [ ] PII encrypted when required
59
+ - [ ] HTTPS enforced
60
+ - [ ] Database backups encrypted
61
+
62
+ ## Dependencies
63
+
64
+ ```bash
65
+ # Run regularly
66
+ npm audit
67
+ npm audit fix
68
+ ```
69
+
70
+ - [ ] No critical vulnerabilities
71
+ - [ ] Dependencies up to date
72
+ - [ ] Lock file committed
73
+
74
+ ## Error Handling
75
+
76
+ - [ ] Generic error messages in production
77
+ - [ ] No stack traces exposed
78
+ - [ ] No database details in errors
79
+ - [ ] No internal paths revealed
80
+
81
+ ## OWASP Top 10 Quick Check
82
+
83
+ | # | Vulnerability | Check |
84
+ |---|--------------|-------|
85
+ | 1 | Broken Access Control | Auth on all endpoints? |
86
+ | 2 | Cryptographic Failures | Secrets encrypted? HTTPS? |
87
+ | 3 | Injection | Inputs sanitized? Queries parameterized? |
88
+ | 4 | Insecure Design | Threat modeling done? |
89
+ | 5 | Security Misconfiguration | Headers set? Defaults changed? |
90
+ | 6 | Vulnerable Components | `npm audit` clean? |
91
+ | 7 | Auth Failures | Rate limiting? Strong passwords? |
92
+ | 8 | Data Integrity | Signatures verified? |
93
+ | 9 | Logging Failures | Security events logged? |
94
+ | 10 | SSRF | External URLs validated? |
@@ -0,0 +1,183 @@
1
+ # Testing Patterns Reference
2
+
3
+ > Quick reference for test patterns. See `.claude/rules/testing.md` for full rules.
4
+
5
+ ## Test Pyramid
6
+
7
+ ```
8
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
9
+ β”‚ E2E β”‚ 5% Critical user flows
10
+ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
11
+ β”‚ Integ β”‚ 15% API + DB interactions
12
+ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
13
+ β”‚ Unit β”‚ 80% Pure logic, fast
14
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
15
+ ```
16
+
17
+ ## Test Structure (AAA)
18
+
19
+ ```javascript
20
+ it('should [expected behavior] when [condition]', () => {
21
+ // Arrange β€” Setup
22
+ const user = createTestUser({ role: 'admin' });
23
+
24
+ // Act β€” Execute
25
+ const result = checkPermission(user, 'delete');
26
+
27
+ // Assert β€” Verify
28
+ expect(result).toBe(true);
29
+ });
30
+ ```
31
+
32
+ ## Unit Test Example
33
+
34
+ ```javascript
35
+ describe('calculateDiscount', () => {
36
+ it('should return 10% for orders over $100', () => {
37
+ expect(calculateDiscount(150)).toBe(15);
38
+ });
39
+
40
+ it('should return 0 for orders under $100', () => {
41
+ expect(calculateDiscount(50)).toBe(0);
42
+ });
43
+
44
+ it('should handle edge case at exactly $100', () => {
45
+ expect(calculateDiscount(100)).toBe(0);
46
+ });
47
+ });
48
+ ```
49
+
50
+ ## Integration Test Example
51
+
52
+ ```javascript
53
+ describe('POST /api/users', () => {
54
+ it('should create user and return 201', async () => {
55
+ const response = await request(app)
56
+ .post('/api/users')
57
+ .send({ email: 'test@example.com', name: 'Test' })
58
+ .set('Authorization', `Bearer ${token}`);
59
+
60
+ expect(response.status).toBe(201);
61
+ expect(response.body.data.email).toBe('test@example.com');
62
+
63
+ // Verify in database
64
+ const user = await db.user.findUnique({
65
+ where: { email: 'test@example.com' }
66
+ });
67
+ expect(user).toBeDefined();
68
+ });
69
+ });
70
+ ```
71
+
72
+ ## E2E Test Example (Playwright)
73
+
74
+ ```javascript
75
+ test('user can complete checkout flow', async ({ page }) => {
76
+ // Login
77
+ await page.goto('/login');
78
+ await page.fill('[name="email"]', 'user@example.com');
79
+ await page.fill('[name="password"]', 'password');
80
+ await page.click('button[type="submit"]');
81
+
82
+ // Add to cart
83
+ await page.goto('/products/1');
84
+ await page.click('button:has-text("Add to Cart")');
85
+
86
+ // Checkout
87
+ await page.goto('/checkout');
88
+ await page.fill('[name="card"]', '4242424242424242');
89
+ await page.click('button:has-text("Pay")');
90
+
91
+ // Verify
92
+ await expect(page.locator('.success-message')).toBeVisible();
93
+ });
94
+ ```
95
+
96
+ ## React Component Test
97
+
98
+ ```javascript
99
+ import { render, screen, fireEvent } from '@testing-library/react';
100
+
101
+ describe('Counter', () => {
102
+ it('should increment count when button clicked', () => {
103
+ render(<Counter initialCount={0} />);
104
+
105
+ const button = screen.getByRole('button', { name: /increment/i });
106
+ fireEvent.click(button);
107
+
108
+ expect(screen.getByText('Count: 1')).toBeInTheDocument();
109
+ });
110
+ });
111
+ ```
112
+
113
+ ## Test Doubles
114
+
115
+ ```javascript
116
+ // 1. Real (preferred)
117
+ const db = createTestDatabase();
118
+
119
+ // 2. Fake (in-memory)
120
+ const fakeUserRepo = {
121
+ users: [],
122
+ create(user) { this.users.push(user); return user; },
123
+ findById(id) { return this.users.find(u => u.id === id); }
124
+ };
125
+
126
+ // 3. Stub (canned response)
127
+ const stubbedApi = {
128
+ getUser: () => Promise.resolve({ id: '1', name: 'Test' })
129
+ };
130
+
131
+ // 4. Mock (verify interactions β€” use sparingly)
132
+ const mockLogger = vi.fn();
133
+ ```
134
+
135
+ ## Naming Convention
136
+
137
+ ```javascript
138
+ // Pattern: should [expected] when [condition]
139
+
140
+ // βœ… Good
141
+ 'should return null when user not found'
142
+ 'should throw ValidationError when email invalid'
143
+ 'should emit event when order placed'
144
+
145
+ // ❌ Bad
146
+ 'works'
147
+ 'test user'
148
+ 'error handling'
149
+ ```
150
+
151
+ ## Anti-Patterns
152
+
153
+ | Pattern | Problem | Fix |
154
+ |---------|---------|-----|
155
+ | Testing internals | Breaks on refactor | Test behavior |
156
+ | Shared state | Tests affect each other | Reset in beforeEach |
157
+ | Flaky tests | Random failures | Deterministic data |
158
+ | Over-mocking | False confidence | Real implementations |
159
+ | No assertions | Test always passes | Assert outcomes |
160
+ | Magic numbers | Hard to understand | Named constants |
161
+
162
+ ## Coverage Thresholds
163
+
164
+ ```javascript
165
+ // vitest.config.js
166
+ coverage: {
167
+ thresholds: {
168
+ lines: 80,
169
+ branches: 80,
170
+ functions: 80,
171
+ statements: 80
172
+ }
173
+ }
174
+ ```
175
+
176
+ ## Commands
177
+
178
+ ```bash
179
+ npm test # Run all tests
180
+ npm test -- --watch # Watch mode
181
+ npm test -- --coverage # Coverage report
182
+ npm run test:e2e # E2E tests
183
+ ```
@@ -0,0 +1,85 @@
1
+ ---
2
+ description: "API Conventions"
3
+ alwaysApply: false
4
+ globs: "**/*.{ts,tsx,js,jsx,mjs,cjs,json,md,prisma,yml,yaml}"
5
+ ---
6
+
7
+ # API Conventions
8
+
9
+ ## REST API Design Standards
10
+
11
+ ### URL Structure
12
+ - Use **kebab-case** for URL paths: `/api/user-profiles`
13
+ - Use **plural nouns** for resource collections: `/api/users`, `/api/products`
14
+ - Nest related resources: `/api/users/:id/orders`
15
+ - API version prefix: `/api/v1/...`
16
+
17
+ ### HTTP Methods
18
+ | Method | Usage |
19
+ |--------|-------|
20
+ | GET | Read resources (idempotent) |
21
+ | POST | Create new resource |
22
+ | PUT | Replace entire resource |
23
+ | PATCH | Partial update |
24
+ | DELETE | Remove resource |
25
+
26
+ ### HTTP Status Codes
27
+ | Code | Meaning |
28
+ |------|---------|
29
+ | 200 | OK β€” Successful GET/PUT/PATCH |
30
+ | 201 | Created β€” Successful POST |
31
+ | 204 | No Content β€” Successful DELETE |
32
+ | 400 | Bad Request β€” Invalid input |
33
+ | 401 | Unauthorized β€” Not authenticated |
34
+ | 403 | Forbidden β€” No permission |
35
+ | 404 | Not Found |
36
+ | 409 | Conflict |
37
+ | 422 | Unprocessable Entity β€” Validation failed |
38
+ | 500 | Internal Server Error |
39
+
40
+ ### Request/Response Format
41
+ ```json
42
+ // Success response
43
+ {
44
+ "success": true,
45
+ "data": { ... },
46
+ "message": "Optional message"
47
+ }
48
+
49
+ // Error response
50
+ {
51
+ "success": false,
52
+ "error": {
53
+ "code": "VALIDATION_ERROR",
54
+ "message": "Human readable message",
55
+ "details": [ ... ]
56
+ }
57
+ }
58
+
59
+ // Paginated list response
60
+ {
61
+ "success": true,
62
+ "data": [ ... ],
63
+ "pagination": {
64
+ "page": 1,
65
+ "limit": 20,
66
+ "total": 100,
67
+ "totalPages": 5
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### Naming Conventions
73
+ - Request/response body fields: **camelCase**
74
+ - Query parameters: **camelCase**
75
+ - Always return consistent field names
76
+
77
+ ### Filtering & Pagination
78
+ ```
79
+ GET /api/users?page=1&limit=20&sortBy=createdAt&order=desc
80
+ GET /api/products?category=electronics&minPrice=100
81
+ ```
82
+
83
+ ### Documentation
84
+ - Every endpoint MUST have JSDoc/Swagger annotations
85
+ - Include request body schema, response schema, and error codes
@@ -0,0 +1,211 @@
1
+ ---
2
+ description: "Clean Code β€” JavaScript Rules"
3
+ alwaysApply: false
4
+ globs: "**/*.{ts,tsx,js,jsx,mjs,cjs,json,md,prisma,yml,yaml}"
5
+ ---
6
+
7
+ # Clean Code β€” JavaScript Rules
8
+ > Source: [clean-code-javascript](https://github.com/ryanmcdermott/clean-code-javascript) by Ryan McDermott
9
+
10
+ ## πŸ“¦ Variables
11
+
12
+ ### βœ… Use meaningful, pronounceable names
13
+ ```js
14
+ // ❌ Bad
15
+ const yyyymmdstr = moment().format('YYYY/MM/DD');
16
+
17
+ // βœ… Good
18
+ const currentDate = moment().format('YYYY/MM/DD');
19
+ ```
20
+
21
+ ### βœ… Same vocabulary for same type
22
+ ```js
23
+ // ❌ getUserInfo(), getClientData(), getCustomerRecord()
24
+ // βœ… getUser()
25
+ ```
26
+
27
+ ### βœ… Use searchable names (no magic numbers)
28
+ ```js
29
+ // ❌ setTimeout(blastOff, 86400000);
30
+ const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000;
31
+ setTimeout(blastOff, MILLISECONDS_PER_DAY); // βœ…
32
+ ```
33
+
34
+ ### βœ… Use explanatory variables
35
+ ```js
36
+ // ❌ Bad
37
+ saveCityZipCode(address.match(regex)[1], address.match(regex)[2]);
38
+
39
+ // βœ… Good
40
+ const [_, city, zipCode] = address.match(cityZipCodeRegex) || [];
41
+ saveCityZipCode(city, zipCode);
42
+ ```
43
+
44
+ ### βœ… Avoid mental mapping β€” be explicit
45
+ ```js
46
+ // ❌ locations.forEach(l => { dispatch(l); });
47
+ // βœ… locations.forEach(location => { dispatch(location); });
48
+ ```
49
+
50
+ ### βœ… Don't add redundant context
51
+ ```js
52
+ // ❌ const Car = { carMake, carModel, carColor }
53
+ // βœ… const Car = { make, model, color }
54
+ ```
55
+
56
+ ### βœ… Use default parameters
57
+ ```js
58
+ // ❌ const name = name || 'Default';
59
+ // βœ… function create(name = 'Default') {}
60
+ ```
61
+
62
+ ---
63
+
64
+ ## πŸ”§ Functions
65
+
66
+ ### βœ… 2 arguments or fewer β€” use object destructuring for more
67
+ ```js
68
+ // ❌ function createMenu(title, body, buttonText, cancellable) {}
69
+ // βœ… function createMenu({ title, body, buttonText, cancellable }) {}
70
+ ```
71
+
72
+ ### βœ… Functions should do ONE thing
73
+ ```js
74
+ // ❌ emailClients() β€” fetches DB + checks active + sends email
75
+ // βœ… emailActiveClients() calls isActiveClient() separately
76
+ ```
77
+
78
+ ### βœ… Function names should say what they do
79
+ ```js
80
+ // ❌ addToDate(date, 1) β†’ unclear what is added
81
+ // βœ… addMonthToDate(1, date) β†’ crystal clear
82
+ ```
83
+
84
+ ### βœ… One level of abstraction per function
85
+ ```js
86
+ // ❌ parseBetterJSAlternative() β€” tokenizes + parses + AST walks in one function
87
+ // βœ… parseBetterJSAlternative() β†’ calls tokenize() β†’ calls parse()
88
+ ```
89
+
90
+ ### βœ… Remove duplicate code β€” extract shared logic
91
+ ### βœ… No flag parameters β€” split into separate functions
92
+ ```js
93
+ // ❌ function createFile(name, isTemp) { if (isTemp) ... }
94
+ // βœ… function createFile(name) {}
95
+ // function createTempFile(name) {}
96
+ ```
97
+
98
+ ### βœ… Avoid Side Effects
99
+ - Don't mutate global state
100
+ - Don't mutate function arguments (use copies)
101
+ ```js
102
+ // βœ… Return new array instead of mutating
103
+ function addItemToCart(cart, item) {
104
+ return [...cart, { item, date: Date.now() }];
105
+ }
106
+ ```
107
+
108
+ ### βœ… Favor functional programming
109
+ ```js
110
+ // ❌ for loop with mutations
111
+ // βœ… filter(), map(), reduce()
112
+ const totalOutput = programmerOutput
113
+ .filter(p => p.linesOfCode > 0)
114
+ .reduce((acc, p) => acc + p.linesOfCode, 0);
115
+ ```
116
+
117
+ ### βœ… Encapsulate conditionals
118
+ ```js
119
+ // ❌ if (fsm.state === 'fetching' && isEmpty(listNode)) {}
120
+ // βœ… if (shouldShowSpinner(fsmInstance, listNodeInstance)) {}
121
+ ```
122
+
123
+ ### βœ… Avoid negative conditionals
124
+ ```js
125
+ // ❌ if (!isNotDOMNodePresent(node)) {}
126
+ // βœ… if (isDOMNodePresent(node)) {}
127
+ ```
128
+
129
+ ### βœ… Remove dead code immediately
130
+
131
+ ---
132
+
133
+ ## πŸ›οΈ Classes
134
+
135
+ ### βœ… Prefer ES6 classes
136
+ ### βœ… Use method chaining (builder pattern)
137
+ ```js
138
+ class QueryBuilder {
139
+ select(fields) { this.fields = fields; return this; }
140
+ from(table) { this.table = table; return this; }
141
+ build() { return `SELECT ${this.fields} FROM ${this.table}`; }
142
+ }
143
+ new QueryBuilder().select('*').from('users').build();
144
+ ```
145
+
146
+ ### βœ… Prefer composition over inheritance
147
+ > "Favor has-a over is-a"
148
+
149
+ ---
150
+
151
+ ## 🧱 SOLID Principles
152
+
153
+ | Principle | Rule |
154
+ |-----------|------|
155
+ | **S** β€” Single Responsibility | One class = one job. Never combine unrelated concerns |
156
+ | **O** β€” Open/Closed | Open for extension, closed for modification |
157
+ | **L** β€” Liskov Substitution | Subclasses must be substitutable for their base class |
158
+ | **I** β€” Interface Segregation | Clients shouldn't depend on interfaces they don't use |
159
+ | **D** β€” Dependency Inversion | Depend on abstractions, not concretions |
160
+
161
+ ```js
162
+ // βœ… D β€” Dependency Inversion
163
+ class InventoryService {
164
+ constructor(inventoryRequester) { // inject the dependency
165
+ this.inventoryRequester = inventoryRequester;
166
+ }
167
+ requestItems(customer) {
168
+ return this.inventoryRequester.requestItem(customer.purchaseHistory);
169
+ }
170
+ }
171
+ ```
172
+
173
+ ---
174
+
175
+ ## ⚑ Concurrency
176
+
177
+ ### βœ… Use Promises over callbacks
178
+ ### βœ… Use async/await over Promises
179
+ ```js
180
+ // βœ… Clearest form
181
+ async function getCleanCodeArticle() {
182
+ try {
183
+ const response = await request.get(cleanCodeUrl);
184
+ await fs.writeFile('article.html', response);
185
+ } catch (err) {
186
+ console.error(err);
187
+ }
188
+ }
189
+ ```
190
+
191
+ ---
192
+
193
+ ## πŸ—’οΈ Comments
194
+
195
+ ### βœ… Only comment business logic complexity
196
+ ### ❌ Never leave commented-out code
197
+ ### ❌ No journal comments (use git log instead)
198
+ ### ❌ No positional markers (`/////`)
199
+ ```js
200
+ // βœ… Good comment β€” explains WHY
201
+ // We retry 3x because OAuth2 tokens can have clock skew
202
+ const MAX_RETRIES = 3;
203
+ ```
204
+
205
+ ---
206
+
207
+ ## πŸ“ Formatting
208
+
209
+ - Use consistent capitalization (camelCase for vars/fns, PascalCase for classes, UPPER_SNAKE for constants)
210
+ - Keep callers and callees close in the file
211
+ - Related code should appear together
@@ -0,0 +1,92 @@
1
+ ---
2
+ description: "Code Style Guide"
3
+ alwaysApply: false
4
+ globs: "**/*.{ts,tsx,js,jsx,mjs,cjs,json,md,prisma,yml,yaml}"
5
+ ---
6
+
7
+ # Code Style Guide
8
+
9
+ ## General Principles
10
+ - **Clarity over cleverness** β€” Write code that is easy to read and understand
11
+ - **Consistency** β€” Follow existing patterns in the codebase
12
+ - **DRY** β€” Don't Repeat Yourself, but don't over-abstract
13
+
14
+ ## JavaScript / TypeScript
15
+
16
+ ### Formatting
17
+ - Indentation: **2 spaces** (no tabs)
18
+ - Max line length: **100 characters**
19
+ - Use **single quotes** for strings
20
+ - Always use **semicolons**
21
+ - Trailing commas in multi-line structures
22
+
23
+ ### Naming
24
+ ```js
25
+ // Variables and functions: camelCase
26
+ const userProfile = {};
27
+ function getUserById(id) {}
28
+
29
+ // Classes and interfaces: PascalCase
30
+ class UserService {}
31
+ interface UserRepository {}
32
+
33
+ // Constants: UPPER_SNAKE_CASE
34
+ const MAX_RETRY_COUNT = 3;
35
+ const API_BASE_URL = 'https://api.example.com';
36
+
37
+ // Files: kebab-case
38
+ // user-service.js, auth-middleware.js
39
+ ```
40
+
41
+ ### Functions
42
+ ```js
43
+ // βœ… Good β€” Arrow functions for simple operations
44
+ const double = (x) => x * 2;
45
+
46
+ // βœ… Good β€” Named functions for complex logic
47
+ function processUserData(user) {
48
+ // ...
49
+ }
50
+
51
+ // ❌ Avoid β€” Functions longer than 30 lines (extract helpers)
52
+ ```
53
+
54
+ ### Async/Await
55
+ ```js
56
+ // βœ… Always use async/await over raw promises
57
+ async function fetchUser(id) {
58
+ try {
59
+ const user = await userRepository.findById(id);
60
+ return user;
61
+ } catch (error) {
62
+ throw new AppError('User not found', 404);
63
+ }
64
+ }
65
+
66
+ // ❌ Avoid promise chains
67
+ fetchUser(id).then(...).catch(...);
68
+ ```
69
+
70
+ ### Imports
71
+ ```js
72
+ // Order: 1. Node built-ins, 2. External deps, 3. Internal modules
73
+ import path from 'path';
74
+ import express from 'express';
75
+ import { UserService } from './user-service.js';
76
+ ```
77
+
78
+ ## Comments
79
+ ```js
80
+ // βœ… Explain WHY, not WHAT
81
+ // We retry 3 times because the external API has transient failures
82
+ const MAX_RETRIES = 3;
83
+
84
+ // ❌ Avoid obvious comments
85
+ // Set x to 5
86
+ const x = 5;
87
+ ```
88
+
89
+ ## File Organization
90
+ - One class/service per file
91
+ - Group related files in feature folders
92
+ - Index files for clean imports
@@ -0,0 +1,35 @@
1
+ ---
2
+ description: "Cursor agent workflow, principles, and where project guidance lives"
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Cursor agent β€” project workflow
7
+
8
+ This repo mirrors Claude Code’s `.claude/` layout under **`.cursor/`** for Cursor (Composer, Agent, inline Chat).
9
+
10
+ ## Development workflow
11
+
12
+ Use the same phase order as in `.cursor/CURSOR.md`:
13
+
14
+ 1. **Define** β€” prompt from `.cursor/commands/spec.md` (paste or attach)
15
+ 2. **Plan** β€” `.cursor/commands/plan.md`
16
+ 3. **Build** β€” `.cursor/commands/build.md` (TDD: `.cursor/skills/tdd/`)
17
+ 4. **Verify** β€” `.cursor/commands/test.md`
18
+ 5. **Review** β€” `.cursor/commands/review.md` (five-axis: `.cursor/skills/code-review/`)
19
+ 6. **Ship** β€” `.cursor/commands/deploy.md`
20
+
21
+ Supporting prompts: `debug`, `simplify`, `fix-issue` in `.cursor/commands/`.
22
+
23
+ ## Mandatory standards
24
+
25
+ - Follow **`.cursor/rules/`** (`.mdc`). **`security.mdc`** is always applied; other rule files apply when matching globs are in scope (see each file’s frontmatter).
26
+ - Prefer **tests first** and **small vertical slices** (see `.cursor/skills/incremental-implementation/`).
27
+ - Use **`.cursor/references/`** for checklists (security, testing, performance, accessibility).
28
+
29
+ ## Agents (personas)
30
+
31
+ Specialized instructions live in **`.cursor/agents/`**. In Cursor, **@ mention** the file you want (e.g. `@.cursor/agents/code-reviewer.md`) when you need that role.
32
+
33
+ ## Relation to `.claude/`
34
+
35
+ If both folders exist: **`.claude/`** targets Claude Code; **`.cursor/`** targets Cursor. Keep them aligned when you change workflows or standards.