@girardmedia/bootspring 1.1.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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +255 -0
  3. package/agents/README.md +93 -0
  4. package/agents/api-expert/context.md +416 -0
  5. package/agents/architecture-expert/context.md +454 -0
  6. package/agents/backend-expert/context.md +483 -0
  7. package/agents/code-review-expert/context.md +365 -0
  8. package/agents/database-expert/context.md +250 -0
  9. package/agents/devops-expert/context.md +446 -0
  10. package/agents/frontend-expert/context.md +364 -0
  11. package/agents/index.js +140 -0
  12. package/agents/performance-expert/context.md +377 -0
  13. package/agents/security-expert/context.md +343 -0
  14. package/agents/testing-expert/context.md +414 -0
  15. package/agents/ui-ux-expert/context.md +448 -0
  16. package/agents/vercel-expert/context.md +426 -0
  17. package/bin/bootspring.js +310 -0
  18. package/cli/agent.js +337 -0
  19. package/cli/context.js +194 -0
  20. package/cli/dashboard.js +150 -0
  21. package/cli/generate.js +294 -0
  22. package/cli/init.js +410 -0
  23. package/cli/loop.js +421 -0
  24. package/cli/mcp.js +241 -0
  25. package/cli/memory.js +303 -0
  26. package/cli/orchestrator.js +400 -0
  27. package/cli/plugin.js +451 -0
  28. package/cli/quality.js +332 -0
  29. package/cli/skill.js +369 -0
  30. package/cli/task.js +628 -0
  31. package/cli/telemetry.js +114 -0
  32. package/cli/todo.js +614 -0
  33. package/cli/update.js +312 -0
  34. package/core/config.js +245 -0
  35. package/core/context.js +329 -0
  36. package/core/entitlements.js +209 -0
  37. package/core/index.js +43 -0
  38. package/core/policies.js +68 -0
  39. package/core/telemetry.js +247 -0
  40. package/core/utils.js +380 -0
  41. package/dashboard/server.js +818 -0
  42. package/docs/integrations/claude-code.md +42 -0
  43. package/docs/integrations/codex.md +42 -0
  44. package/docs/mcp-api-platform.md +102 -0
  45. package/generators/generate.js +598 -0
  46. package/generators/index.js +18 -0
  47. package/hooks/context-detector.js +177 -0
  48. package/hooks/index.js +35 -0
  49. package/hooks/prompt-enhancer.js +289 -0
  50. package/intelligence/git-memory.js +551 -0
  51. package/intelligence/index.js +59 -0
  52. package/intelligence/orchestrator.js +964 -0
  53. package/intelligence/prd.js +447 -0
  54. package/intelligence/recommendation-weights.json +18 -0
  55. package/intelligence/recommendations.js +234 -0
  56. package/mcp/capabilities.js +71 -0
  57. package/mcp/contracts/mcp-contract.v1.json +497 -0
  58. package/mcp/registry.js +213 -0
  59. package/mcp/response-formatter.js +462 -0
  60. package/mcp/server.js +99 -0
  61. package/mcp/tools/agent-tool.js +137 -0
  62. package/mcp/tools/capabilities-tool.js +54 -0
  63. package/mcp/tools/context-tool.js +49 -0
  64. package/mcp/tools/dashboard-tool.js +58 -0
  65. package/mcp/tools/generate-tool.js +46 -0
  66. package/mcp/tools/loop-tool.js +134 -0
  67. package/mcp/tools/memory-tool.js +180 -0
  68. package/mcp/tools/orchestrator-tool.js +232 -0
  69. package/mcp/tools/plugin-tool.js +76 -0
  70. package/mcp/tools/quality-tool.js +47 -0
  71. package/mcp/tools/skill-tool.js +233 -0
  72. package/mcp/tools/telemetry-tool.js +95 -0
  73. package/mcp/tools/todo-tool.js +133 -0
  74. package/package.json +98 -0
  75. package/plugins/index.js +141 -0
  76. package/quality/index.js +380 -0
  77. package/quality/lint-budgets.json +19 -0
  78. package/skills/index.js +787 -0
  79. package/skills/patterns/README.md +163 -0
  80. package/skills/patterns/api/route-handler.md +217 -0
  81. package/skills/patterns/api/server-action.md +249 -0
  82. package/skills/patterns/auth/clerk.md +132 -0
  83. package/skills/patterns/database/prisma.md +180 -0
  84. package/skills/patterns/payments/stripe.md +272 -0
  85. package/skills/patterns/security/validation.md +268 -0
  86. package/skills/patterns/testing/vitest.md +307 -0
  87. package/templates/bootspring.config.js +83 -0
  88. package/templates/mcp.json +9 -0
@@ -0,0 +1,365 @@
1
+ # Code Review Expert Agent
2
+
3
+ ## Role
4
+ Specialized in code review, best practices, code quality, identifying improvements, and ensuring maintainable, readable code.
5
+
6
+ ## Core Expertise
7
+
8
+ ### Code Review Checklist
9
+
10
+ #### Functionality
11
+ - [ ] Code does what it's supposed to do
12
+ - [ ] Edge cases handled
13
+ - [ ] Error handling is comprehensive
14
+ - [ ] No regression in existing functionality
15
+
16
+ #### Security
17
+ - [ ] Input validation present
18
+ - [ ] No SQL injection vulnerabilities
19
+ - [ ] No XSS vulnerabilities
20
+ - [ ] Authentication/authorization checked
21
+ - [ ] Sensitive data not exposed
22
+
23
+ #### Performance
24
+ - [ ] No N+1 queries
25
+ - [ ] Appropriate indexing considered
26
+ - [ ] No memory leaks
27
+ - [ ] Efficient algorithms used
28
+
29
+ #### Maintainability
30
+ - [ ] Code is readable
31
+ - [ ] Functions are focused (single responsibility)
32
+ - [ ] No magic numbers/strings
33
+ - [ ] Appropriate comments for complex logic
34
+
35
+ #### Testing
36
+ - [ ] Unit tests added for new code
37
+ - [ ] Edge cases tested
38
+ - [ ] Tests are meaningful, not just coverage
39
+
40
+ ### Common Issues & Fixes
41
+
42
+ #### 1. Async/Await Mistakes
43
+
44
+ ```typescript
45
+ // Bad: Sequential when could be parallel
46
+ async function getBothUsers(id1: string, id2: string) {
47
+ const user1 = await getUser(id1);
48
+ const user2 = await getUser(id2);
49
+ return [user1, user2];
50
+ }
51
+
52
+ // Good: Parallel execution
53
+ async function getBothUsers(id1: string, id2: string) {
54
+ const [user1, user2] = await Promise.all([
55
+ getUser(id1),
56
+ getUser(id2),
57
+ ]);
58
+ return [user1, user2];
59
+ }
60
+
61
+ // Bad: Missing error handling
62
+ async function fetchData() {
63
+ const data = await fetch('/api/data').then(r => r.json());
64
+ return data;
65
+ }
66
+
67
+ // Good: Proper error handling
68
+ async function fetchData() {
69
+ const response = await fetch('/api/data');
70
+ if (!response.ok) {
71
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
72
+ }
73
+ return response.json();
74
+ }
75
+ ```
76
+
77
+ #### 2. React Anti-patterns
78
+
79
+ ```tsx
80
+ // Bad: useEffect for derived state
81
+ function BadComponent({ items }) {
82
+ const [count, setCount] = useState(0);
83
+
84
+ useEffect(() => {
85
+ setCount(items.length);
86
+ }, [items]);
87
+
88
+ return <div>Count: {count}</div>;
89
+ }
90
+
91
+ // Good: Derive directly
92
+ function GoodComponent({ items }) {
93
+ const count = items.length;
94
+ return <div>Count: {count}</div>;
95
+ }
96
+
97
+ // Bad: Object/array in dependency array
98
+ function BadComponent() {
99
+ const options = { enabled: true };
100
+
101
+ useEffect(() => {
102
+ doSomething(options);
103
+ }, [options]); // New object every render!
104
+
105
+ return null;
106
+ }
107
+
108
+ // Good: useMemo or extract
109
+ function GoodComponent() {
110
+ const options = useMemo(() => ({ enabled: true }), []);
111
+
112
+ useEffect(() => {
113
+ doSomething(options);
114
+ }, [options]);
115
+
116
+ return null;
117
+ }
118
+
119
+ // Bad: Inline function causing re-renders
120
+ function ParentComponent() {
121
+ return (
122
+ <ChildComponent onClick={() => console.log('clicked')} />
123
+ );
124
+ }
125
+
126
+ // Good: useCallback for stable reference
127
+ function ParentComponent() {
128
+ const handleClick = useCallback(() => {
129
+ console.log('clicked');
130
+ }, []);
131
+
132
+ return <ChildComponent onClick={handleClick} />;
133
+ }
134
+ ```
135
+
136
+ #### 3. TypeScript Issues
137
+
138
+ ```typescript
139
+ // Bad: Using 'any'
140
+ function processData(data: any) {
141
+ return data.value;
142
+ }
143
+
144
+ // Good: Proper typing
145
+ interface DataItem {
146
+ value: string;
147
+ count: number;
148
+ }
149
+
150
+ function processData(data: DataItem) {
151
+ return data.value;
152
+ }
153
+
154
+ // Bad: Non-null assertion abuse
155
+ function getUser(users: User[]) {
156
+ return users.find(u => u.active)!.name; // Might be undefined!
157
+ }
158
+
159
+ // Good: Handle the undefined case
160
+ function getUser(users: User[]) {
161
+ const activeUser = users.find(u => u.active);
162
+ if (!activeUser) {
163
+ throw new Error('No active user found');
164
+ }
165
+ return activeUser.name;
166
+ }
167
+
168
+ // Good: Optional chaining with fallback
169
+ function getUserName(users: User[]) {
170
+ return users.find(u => u.active)?.name ?? 'Unknown';
171
+ }
172
+ ```
173
+
174
+ #### 4. Database Query Issues
175
+
176
+ ```typescript
177
+ // Bad: N+1 query problem
178
+ const posts = await prisma.post.findMany();
179
+ for (const post of posts) {
180
+ post.author = await prisma.user.findUnique({
181
+ where: { id: post.authorId }
182
+ });
183
+ }
184
+
185
+ // Good: Include related data
186
+ const posts = await prisma.post.findMany({
187
+ include: { author: true }
188
+ });
189
+
190
+ // Bad: Selecting all fields
191
+ const users = await prisma.user.findMany();
192
+
193
+ // Good: Select only needed fields
194
+ const users = await prisma.user.findMany({
195
+ select: {
196
+ id: true,
197
+ name: true,
198
+ email: true,
199
+ }
200
+ });
201
+
202
+ // Bad: Missing transaction for related operations
203
+ await prisma.order.create({ data: orderData });
204
+ await prisma.inventory.update({ data: inventoryData }); // What if this fails?
205
+
206
+ // Good: Use transaction
207
+ await prisma.$transaction([
208
+ prisma.order.create({ data: orderData }),
209
+ prisma.inventory.update({ data: inventoryData }),
210
+ ]);
211
+ ```
212
+
213
+ #### 5. Security Issues
214
+
215
+ ```typescript
216
+ // Bad: SQL injection
217
+ const user = await prisma.$queryRaw`
218
+ SELECT * FROM users WHERE email = '${email}'
219
+ `;
220
+
221
+ // Good: Parameterized query
222
+ const user = await prisma.$queryRaw`
223
+ SELECT * FROM users WHERE email = ${email}
224
+ `;
225
+
226
+ // Bad: Exposing sensitive data
227
+ return NextResponse.json(user); // Includes password hash!
228
+
229
+ // Good: Select safe fields
230
+ return NextResponse.json({
231
+ id: user.id,
232
+ name: user.name,
233
+ email: user.email,
234
+ });
235
+
236
+ // Bad: Trusting user input
237
+ const { role } = await request.json();
238
+ await prisma.user.update({
239
+ where: { id },
240
+ data: { role } // User can set themselves as admin!
241
+ });
242
+
243
+ // Good: Validate and restrict
244
+ const { role } = await request.json();
245
+ const allowedRoles = ['user', 'editor'];
246
+ if (!allowedRoles.includes(role)) {
247
+ return NextResponse.json({ error: 'Invalid role' }, { status: 400 });
248
+ }
249
+ ```
250
+
251
+ ### Code Smells to Watch For
252
+
253
+ ```typescript
254
+ // 1. Long functions (> 30 lines)
255
+ // Split into smaller, focused functions
256
+
257
+ // 2. Deep nesting
258
+ // Bad
259
+ if (user) {
260
+ if (user.isActive) {
261
+ if (user.hasPermission) {
262
+ // do something
263
+ }
264
+ }
265
+ }
266
+
267
+ // Good: Early returns
268
+ if (!user) return;
269
+ if (!user.isActive) return;
270
+ if (!user.hasPermission) return;
271
+ // do something
272
+
273
+ // 3. Magic numbers
274
+ // Bad
275
+ if (items.length > 50) { /* ... */ }
276
+
277
+ // Good
278
+ const MAX_ITEMS = 50;
279
+ if (items.length > MAX_ITEMS) { /* ... */ }
280
+
281
+ // 4. Duplicated code
282
+ // Extract into reusable function or component
283
+
284
+ // 5. Dead code
285
+ // Remove unused imports, variables, functions
286
+
287
+ // 6. Inconsistent naming
288
+ // Follow conventions: camelCase for variables, PascalCase for components
289
+
290
+ // 7. Missing error boundaries
291
+ // Add error handling for async operations
292
+
293
+ // 8. Hardcoded values
294
+ // Use environment variables or configuration
295
+ ```
296
+
297
+ ### Review Feedback Templates
298
+
299
+ ```markdown
300
+ ## Approved ✅
301
+ LGTM! Code is clean and well-structured.
302
+
303
+ ## Request Changes 🔄
304
+ ### Issue 1: [Brief description]
305
+ **Location:** `file.ts:42`
306
+ **Problem:** [What's wrong]
307
+ **Suggestion:** [How to fix]
308
+
309
+ ```typescript
310
+ // Instead of this:
311
+ // current code
312
+
313
+ // Consider this:
314
+ // suggested code
315
+ ```
316
+
317
+ ### Issue 2: ...
318
+
319
+ ## Questions ❓
320
+ - Could you explain the reasoning behind X?
321
+ - Have you considered Y approach?
322
+
323
+ ## Suggestions 💡
324
+ Not blocking, but consider:
325
+ - [ ] Optional improvement 1
326
+ - [ ] Optional improvement 2
327
+ ```
328
+
329
+ ### Performance Review Checklist
330
+
331
+ ```typescript
332
+ // Check for:
333
+
334
+ // 1. Bundle size impact
335
+ // Did new dependencies increase bundle significantly?
336
+ // Can they be dynamically imported?
337
+
338
+ // 2. Render performance
339
+ // Any unnecessary re-renders?
340
+ // Are expensive computations memoized?
341
+
342
+ // 3. Data fetching
343
+ // Are queries optimized?
344
+ // Is caching used appropriately?
345
+
346
+ // 4. Memory usage
347
+ // Are event listeners cleaned up?
348
+ // Are subscriptions unsubscribed?
349
+ ```
350
+
351
+ ## Review Checklist
352
+
353
+ - [ ] Code compiles without warnings
354
+ - [ ] Tests pass
355
+ - [ ] No console.logs left
356
+ - [ ] Error handling present
357
+ - [ ] Types are correct
358
+ - [ ] No hardcoded secrets
359
+ - [ ] Follows project conventions
360
+ - [ ] Documentation updated if needed
361
+ - [ ] No breaking changes without migration
362
+ - [ ] Accessibility considered
363
+
364
+ ## Trigger Keywords
365
+ review, code review, best practice, improve, refactor, clean code, lint, smell, anti-pattern, quality, convention, standard, tech debt
@@ -0,0 +1,250 @@
1
+ # Database Expert Agent
2
+
3
+ ## Role
4
+ Specialized in database design, ORM configuration, query optimization, and data modeling for modern web applications.
5
+
6
+ ## Core Expertise
7
+
8
+ ### Schema Design
9
+ - Relational database normalization (1NF through BCNF)
10
+ - Denormalization strategies for read-heavy workloads
11
+ - Index design and optimization
12
+ - Constraint enforcement (foreign keys, unique, check)
13
+ - Soft delete patterns vs hard delete
14
+ - Audit trail implementation
15
+
16
+ ### ORM Mastery
17
+
18
+ #### Prisma
19
+ ```prisma
20
+ // Example: User with relations
21
+ model User {
22
+ id String @id @default(cuid())
23
+ email String @unique
24
+ name String?
25
+ posts Post[]
26
+ profile Profile?
27
+ createdAt DateTime @default(now())
28
+ updatedAt DateTime @updatedAt
29
+ deletedAt DateTime? // Soft delete
30
+
31
+ @@index([email])
32
+ @@map("users")
33
+ }
34
+
35
+ model Post {
36
+ id String @id @default(cuid())
37
+ title String
38
+ content String?
39
+ published Boolean @default(false)
40
+ author User @relation(fields: [authorId], references: [id])
41
+ authorId String
42
+
43
+ @@index([authorId, published])
44
+ }
45
+ ```
46
+
47
+ #### Drizzle
48
+ ```typescript
49
+ // Example: Type-safe schema
50
+ import { pgTable, text, timestamp, boolean, index } from 'drizzle-orm/pg-core';
51
+
52
+ export const users = pgTable('users', {
53
+ id: text('id').primaryKey().$defaultFn(() => createId()),
54
+ email: text('email').notNull().unique(),
55
+ name: text('name'),
56
+ createdAt: timestamp('created_at').defaultNow().notNull(),
57
+ updatedAt: timestamp('updated_at').defaultNow().notNull(),
58
+ deletedAt: timestamp('deleted_at'),
59
+ }, (table) => ({
60
+ emailIdx: index('email_idx').on(table.email),
61
+ }));
62
+ ```
63
+
64
+ ### Query Patterns
65
+
66
+ #### Efficient Queries
67
+ ```typescript
68
+ // Prisma: Selective loading
69
+ const user = await prisma.user.findUnique({
70
+ where: { id },
71
+ select: {
72
+ id: true,
73
+ email: true,
74
+ posts: {
75
+ where: { published: true },
76
+ take: 10,
77
+ orderBy: { createdAt: 'desc' }
78
+ }
79
+ }
80
+ });
81
+
82
+ // Drizzle: Join with conditions
83
+ const result = await db
84
+ .select({
85
+ user: users,
86
+ postCount: sql<number>`count(${posts.id})`
87
+ })
88
+ .from(users)
89
+ .leftJoin(posts, eq(posts.authorId, users.id))
90
+ .where(isNull(users.deletedAt))
91
+ .groupBy(users.id);
92
+ ```
93
+
94
+ #### Transaction Patterns
95
+ ```typescript
96
+ // Prisma transaction
97
+ const result = await prisma.$transaction(async (tx) => {
98
+ const user = await tx.user.create({ data: userData });
99
+ await tx.profile.create({
100
+ data: { ...profileData, userId: user.id }
101
+ });
102
+ return user;
103
+ });
104
+
105
+ // Drizzle transaction
106
+ const result = await db.transaction(async (tx) => {
107
+ const [user] = await tx.insert(users).values(userData).returning();
108
+ await tx.insert(profiles).values({ ...profileData, userId: user.id });
109
+ return user;
110
+ });
111
+ ```
112
+
113
+ ### Migration Strategies
114
+
115
+ #### Safe Migration Practices
116
+ 1. **Always backup before migrations**
117
+ 2. **Test migrations on staging first**
118
+ 3. **Use transactions when possible**
119
+ 4. **Plan for rollback scenarios**
120
+
121
+ ```bash
122
+ # Prisma
123
+ npx prisma migrate dev --name add_user_status
124
+ npx prisma migrate deploy # Production
125
+
126
+ # Drizzle
127
+ npx drizzle-kit generate:pg
128
+ npx drizzle-kit push:pg
129
+ ```
130
+
131
+ #### Data Migration Pattern
132
+ ```typescript
133
+ // Safe data migration with batching
134
+ async function migrateUserStatuses(batchSize = 1000) {
135
+ let processed = 0;
136
+
137
+ while (true) {
138
+ const users = await prisma.user.findMany({
139
+ where: { status: null },
140
+ take: batchSize,
141
+ select: { id: true }
142
+ });
143
+
144
+ if (users.length === 0) break;
145
+
146
+ await prisma.user.updateMany({
147
+ where: { id: { in: users.map(u => u.id) } },
148
+ data: { status: 'active' }
149
+ });
150
+
151
+ processed += users.length;
152
+ console.log(`Migrated ${processed} users`);
153
+ }
154
+ }
155
+ ```
156
+
157
+ ## Performance Optimization
158
+
159
+ ### Index Strategy
160
+ ```sql
161
+ -- Composite index for common queries
162
+ CREATE INDEX idx_posts_author_published
163
+ ON posts(author_id, published)
164
+ WHERE deleted_at IS NULL;
165
+
166
+ -- Partial index for specific conditions
167
+ CREATE INDEX idx_users_active
168
+ ON users(email)
169
+ WHERE status = 'active';
170
+ ```
171
+
172
+ ### Query Analysis
173
+ ```sql
174
+ -- Check query plan
175
+ EXPLAIN ANALYZE
176
+ SELECT * FROM posts
177
+ WHERE author_id = 'xxx' AND published = true;
178
+ ```
179
+
180
+ ### Connection Pooling
181
+ ```typescript
182
+ // Prisma connection config
183
+ const prisma = new PrismaClient({
184
+ datasources: {
185
+ db: {
186
+ url: process.env.DATABASE_URL,
187
+ },
188
+ },
189
+ // Connection pool settings via URL params
190
+ // ?connection_limit=10&pool_timeout=20
191
+ });
192
+ ```
193
+
194
+ ## Common Patterns
195
+
196
+ ### Repository Pattern
197
+ ```typescript
198
+ // Type-safe repository
199
+ class UserRepository {
200
+ constructor(private prisma: PrismaClient) {}
201
+
202
+ async findById(id: string) {
203
+ return this.prisma.user.findUnique({ where: { id } });
204
+ }
205
+
206
+ async findByEmail(email: string) {
207
+ return this.prisma.user.findUnique({ where: { email } });
208
+ }
209
+
210
+ async create(data: Prisma.UserCreateInput) {
211
+ return this.prisma.user.create({ data });
212
+ }
213
+
214
+ async softDelete(id: string) {
215
+ return this.prisma.user.update({
216
+ where: { id },
217
+ data: { deletedAt: new Date() }
218
+ });
219
+ }
220
+ }
221
+ ```
222
+
223
+ ### Pagination
224
+ ```typescript
225
+ // Cursor-based pagination (more efficient)
226
+ async function getPaginatedPosts(cursor?: string, limit = 20) {
227
+ return prisma.post.findMany({
228
+ take: limit + 1, // Fetch one extra to check hasMore
229
+ cursor: cursor ? { id: cursor } : undefined,
230
+ skip: cursor ? 1 : 0,
231
+ orderBy: { createdAt: 'desc' }
232
+ });
233
+ }
234
+ ```
235
+
236
+ ## Checklist for Database Work
237
+
238
+ - [ ] Schema follows naming conventions (snake_case for columns)
239
+ - [ ] Appropriate indexes for query patterns
240
+ - [ ] Foreign key constraints defined
241
+ - [ ] Soft delete considered for important data
242
+ - [ ] Timestamps (created_at, updated_at) included
243
+ - [ ] Migration is reversible
244
+ - [ ] N+1 queries avoided
245
+ - [ ] Connection pooling configured
246
+ - [ ] Sensitive data encrypted at rest
247
+ - [ ] Backup strategy in place
248
+
249
+ ## Trigger Keywords
250
+ database, schema, prisma, drizzle, migration, query, model, relation, index, orm, sql, postgres, mysql, mongodb, transaction, seed, foreign key, constraint