commit 58598a4a49e6521e94220491bdf58bdf1069afb6 Author: Zhongwei Li Date: Sat Nov 29 18:21:19 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..0711088 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,11 @@ +{ + "name": "development-skills", + "description": "Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling", + "version": "1.0.0", + "author": { + "name": "Brock" + }, + "skills": [ + "./skills" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e2984ba --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# development-skills + +Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..40a0b10 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,61 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:Dieshen/claude_marketplace:plugins/development-skills", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "134df0ad0157ab8c4a7949e6ee174e8ab103b97a", + "treeHash": "f471eb9d305e7b9478ef6c528be094dec1b9211706fa781a73bc977ed250ccb8", + "generatedAt": "2025-11-28T10:10:25.019332Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "development-skills", + "description": "Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "b63b769ddbc49ca1e54f77089671ed4891448dff61554eeb8bc0d4b68603aa90" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "5cf7c8c173b9207f7eeb0663a4f803536d4f953a63b667413cdbe3f28a082e6a" + }, + { + "path": "skills/api-doc-generator.md", + "sha256": "b87823388a1c9d28206d39ee8f433b0e324765dad04a58fb3709a971505d83dc" + }, + { + "path": "skills/test-case-generator.md", + "sha256": "7ec6472e7008006d6a6c54612238d16ee6086d3b18a866509c04e993e9d1ec5b" + }, + { + "path": "skills/code-review.md", + "sha256": "54e5bec5fe6679d1504377cdb918162552974a7ecfc18631677cc467e6c2e044" + }, + { + "path": "skills/performance-profiler.md", + "sha256": "b9ff62ecbf7a04b234163edcf86d690444838ef93eb079f7053207cdc8a6e885" + }, + { + "path": "skills/adr-generator.md", + "sha256": "7cecaee6863728bf78ce605bdd2c43b95a80188eebd8e11e383ef9728f6ea322" + } + ], + "dirSha256": "f471eb9d305e7b9478ef6c528be094dec1b9211706fa781a73bc977ed250ccb8" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/adr-generator.md b/skills/adr-generator.md new file mode 100644 index 0000000..1aea62b --- /dev/null +++ b/skills/adr-generator.md @@ -0,0 +1,325 @@ +# Architecture Decision Record (ADR) Generator Skill + +Generate Architecture Decision Records to document important architectural decisions. + +## ADR Template + +```markdown +# ADR-{number}: {Title} + +## Status +{Proposed | Accepted | Deprecated | Superseded by ADR-XXX} + +## Context +What is the issue that we're seeing that is motivating this decision or change? + +## Decision +What is the change that we're proposing and/or doing? + +## Consequences +What becomes easier or more difficult to do because of this change? + +### Positive +- ... +- ... + +### Negative +- ... +- ... + +### Neutral +- ... + +## Alternatives Considered +What other options were evaluated? + +### Alternative 1: {Name} +**Description**: ... + +**Pros**: +- ... + +**Cons**: +- ... + +**Why not chosen**: ... + +### Alternative 2: {Name} +**Description**: ... + +**Pros**: +- ... + +**Cons**: +- ... + +**Why not chosen**: ... + +## Implementation Notes +Any specific implementation details or considerations. + +## References +- Link to relevant documentation +- Link to related ADRs +- Link to discussions +``` + +## Common ADR Topics + +### 1. Technology Selection +- Programming languages +- Frameworks and libraries +- Databases +- Cloud providers +- Message queues +- Caching solutions + +### 2. Architecture Patterns +- Microservices vs Monolith +- Event-driven architecture +- CQRS and Event Sourcing +- API Gateway patterns +- Service mesh adoption + +### 3. Data Management +- Database choice (SQL vs NoSQL) +- Data modeling approach +- Caching strategy +- Data migration strategy +- Backup and recovery + +### 4. Security +- Authentication mechanism +- Authorization approach +- Encryption standards +- Secret management +- API security + +### 5. Development Practices +- Branching strategy +- Code review process +- Testing strategy +- CI/CD pipeline +- Deployment strategy + +### 6. Infrastructure +- Hosting platform +- Containerization strategy +- Orchestration platform +- Monitoring and logging +- Disaster recovery + +## Example ADR + +```markdown +# ADR-001: Use PostgreSQL for Primary Database + +## Status +Accepted + +## Context +We need to select a database for our new e-commerce platform. The system needs to: +- Handle complex relational data (users, orders, products, inventory) +- Support ACID transactions for financial data +- Scale to millions of records +- Provide good query performance +- Support full-text search +- Be well-supported and documented + +## Decision +We will use PostgreSQL 16 as our primary database. + +## Consequences + +### Positive +- **ACID compliance**: Ensures data consistency for financial transactions +- **Rich data types**: JSON, arrays, and custom types provide flexibility +- **Full-text search**: Built-in FTS capabilities reduce dependency on external search engines +- **Mature ecosystem**: Excellent tooling, extensions, and community support +- **Strong consistency**: Suitable for financial and inventory data +- **Performance**: Query planner and indexing options provide good performance +- **Cost-effective**: Open-source with no licensing fees +- **Extensions**: PostGIS for location, pg_cron for scheduling, etc. + +### Negative +- **Vertical scaling**: Harder to scale horizontally compared to NoSQL +- **Operational complexity**: Requires expertise for tuning and maintenance +- **Read replicas**: Additional setup for read-heavy scaling +- **Storage**: Can be more storage-intensive than some alternatives + +### Neutral +- **Learning curve**: Team has SQL experience, so moderate learning curve +- **Hosting**: Available on all major cloud providers + +## Alternatives Considered + +### Alternative 1: MySQL +**Description**: Popular open-source relational database + +**Pros**: +- Widely used and supported +- Good performance for read-heavy workloads +- Large ecosystem + +**Cons**: +- Less advanced features than PostgreSQL +- JSON support not as robust +- Less powerful full-text search +- Some storage engines lack ACID compliance + +**Why not chosen**: PostgreSQL offers more advanced features that align better with our requirements (JSON, full-text search, complex queries). + +### Alternative 2: MongoDB +**Description**: Document-oriented NoSQL database + +**Pros**: +- Flexible schema +- Horizontal scaling +- Fast writes +- Good for rapidly changing data models + +**Cons**: +- Eventually consistent (can be configured for strong consistency with performance impact) +- Less suitable for complex relational queries +- Transactions across collections more complex +- Not ideal for financial data + +**Why not chosen**: Our data is highly relational and requires strong ACID guarantees for financial transactions. + +### Alternative 3: Amazon DynamoDB +**Description**: Fully managed NoSQL database service + +**Pros**: +- Fully managed, no ops overhead +- Excellent scalability +- Low latency +- Pay per usage + +**Cons**: +- Vendor lock-in +- Limited query capabilities +- More expensive at scale +- Requires different data modeling approach + +**Why not chosen**: Relational model better fits our use case, and we want to avoid vendor lock-in. + +## Implementation Notes + +1. **Version**: Use PostgreSQL 16 for latest features +2. **Hosting**: Deploy on AWS RDS for managed service benefits +3. **Extensions**: Enable pg_trgm for fuzzy search, pg_stat_statements for monitoring +4. **Connection Pooling**: Use PgBouncer for connection management +5. **Backup**: Daily automated backups with point-in-time recovery +6. **Monitoring**: CloudWatch metrics + custom dashboard +7. **Read Replicas**: Configure 2 read replicas for read-heavy queries +8. **Migration**: Use TypeORM migrations for schema changes + +## References +- [PostgreSQL Documentation](https://www.postgresql.org/docs/) +- [AWS RDS PostgreSQL](https://aws.amazon.com/rds/postgresql/) +- [Database Comparison Spike](https://company.com/docs/db-comparison) +- [Team Discussion Thread](https://company.slack.com/archives/C123/p456) +``` + +## Best Practices + +### 1. Number ADRs Sequentially +Use ADR-001, ADR-002, etc. Never reuse numbers. + +### 2. Keep ADRs Immutable +Once accepted, don't modify. Create new ADR to supersede if needed. + +### 3. Be Specific +Include concrete technical details, not vague statements. + +### 4. Document Trade-offs +Every decision has pros and cons. Document both honestly. + +### 5. Link Related ADRs +Reference related decisions to show evolution. + +### 6. Update Status +Mark as Deprecated or Superseded when decision changes. + +### 7. Include Team Input +Document that stakeholders were consulted. + +### 8. Write for Future Readers +Someone reading 2 years later should understand why the decision was made. + +### 9. Keep It Concise +Aim for 1-2 pages. Link to detailed analysis separately. + +### 10. Review Periodically +Revisit ADRs annually to ensure they're still relevant. + +## ADR Lifecycle + +1. **Proposed**: Initial draft, under discussion +2. **Accepted**: Team has agreed, implementation can proceed +3. **Implemented**: Decision has been executed +4. **Deprecated**: No longer recommended but not formally replaced +5. **Superseded**: Replaced by a newer ADR + +## Storage + +Store ADRs in version control: +``` +docs/ + architecture/ + decisions/ + 001-use-postgresql.md + 002-adopt-microservices.md + 003-use-react-native.md + README.md (index of all ADRs) +``` + +## Index Template + +```markdown +# Architecture Decision Records + +## Active +- [ADR-001: Use PostgreSQL for Primary Database](001-use-postgresql.md) +- [ADR-002: Adopt Microservices Architecture](002-adopt-microservices.md) + +## Superseded +- [ADR-003: Use Redux for State Management](003-use-redux.md) - Superseded by ADR-010 + +## Deprecated +- None +``` + +## Lightweight Alternative + +For smaller decisions, use a simplified format: + +```markdown +# Decision: {Title} + +## Context +Brief context (2-3 sentences) + +## Decision +What we're doing (2-3 sentences) + +## Trade-offs +- **Pro**: ... +- **Pro**: ... +- **Con**: ... +- **Con**: ... +``` + +## Review Checklist + +Before accepting an ADR: +- [ ] Context clearly explains the problem +- [ ] Decision is specific and actionable +- [ ] Consequences (positive and negative) are documented +- [ ] At least 2 alternatives were considered +- [ ] Trade-offs are honestly assessed +- [ ] Implementation notes provide enough detail +- [ ] References are included +- [ ] Stakeholders have reviewed +- [ ] ADR number is assigned +- [ ] Status is set correctly diff --git a/skills/api-doc-generator.md b/skills/api-doc-generator.md new file mode 100644 index 0000000..05f4dc1 --- /dev/null +++ b/skills/api-doc-generator.md @@ -0,0 +1,567 @@ +# API Documentation Generator Skill + +Automatically generate comprehensive API documentation from code. + +## OpenAPI 3.0 Generation + +### From Express.js/TypeScript + +```typescript +/** + * @openapi + * /api/users: + * get: + * summary: List all users + * tags: [Users] + * parameters: + * - in: query + * name: page + * schema: + * type: integer + * description: Page number + * - in: query + * name: limit + * schema: + * type: integer + * description: Items per page + * responses: + * 200: + * description: Success + * content: + * application/json: + * schema: + * type: object + * properties: + * users: + * type: array + * items: + * $ref: '#/components/schemas/User' + * pagination: + * $ref: '#/components/schemas/Pagination' + */ +app.get('/api/users', async (req, res) => { + // Implementation +}); +``` + +### Complete OpenAPI Spec Template + +```yaml +openapi: 3.0.0 +info: + title: My API + version: 1.0.0 + description: Comprehensive API for managing users and resources + contact: + name: API Support + email: support@example.com + license: + name: MIT + url: https://opensource.org/licenses/MIT + +servers: + - url: https://api.example.com/v1 + description: Production server + - url: https://staging-api.example.com/v1 + description: Staging server + - url: http://localhost:3000/v1 + description: Development server + +tags: + - name: Users + description: User management endpoints + - name: Authentication + description: Authentication endpoints + +paths: + /auth/login: + post: + summary: User login + tags: [Authentication] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + - password + properties: + email: + type: string + format: email + example: user@example.com + password: + type: string + format: password + example: SecurePass123! + responses: + '200': + description: Login successful + content: + application/json: + schema: + type: object + properties: + token: + type: string + example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... + user: + $ref: '#/components/schemas/User' + '401': + description: Invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /users: + get: + summary: List users + tags: [Users] + security: + - BearerAuth: [] + parameters: + - $ref: '#/components/parameters/PageParam' + - $ref: '#/components/parameters/LimitParam' + - in: query + name: search + schema: + type: string + description: Search term + responses: + '200': + description: Success + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/User' + pagination: + $ref: '#/components/schemas/Pagination' + + post: + summary: Create user + tags: [Users] + security: + - BearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateUserInput' + responses: + '201': + description: User created + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/BadRequest' + '401': + $ref: '#/components/responses/Unauthorized' + + /users/{id}: + parameters: + - $ref: '#/components/parameters/UserIdParam' + + get: + summary: Get user by ID + tags: [Users] + security: + - BearerAuth: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '404': + $ref: '#/components/responses/NotFound' + + patch: + summary: Update user + tags: [Users] + security: + - BearerAuth: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateUserInput' + responses: + '200': + description: User updated + content: + application/json: + schema: + $ref: '#/components/schemas/User' + + delete: + summary: Delete user + tags: [Users] + security: + - BearerAuth: [] + responses: + '204': + description: User deleted + '404': + $ref: '#/components/responses/NotFound' + +components: + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + parameters: + UserIdParam: + in: path + name: id + required: true + schema: + type: string + description: User ID + + PageParam: + in: query + name: page + schema: + type: integer + minimum: 1 + default: 1 + description: Page number + + LimitParam: + in: query + name: limit + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + description: Items per page + + schemas: + User: + type: object + required: + - id + - email + - name + properties: + id: + type: string + example: usr_123abc + email: + type: string + format: email + example: user@example.com + name: + type: string + example: John Doe + role: + type: string + enum: [user, admin] + default: user + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + + CreateUserInput: + type: object + required: + - email + - name + - password + properties: + email: + type: string + format: email + name: + type: string + minLength: 1 + maxLength: 100 + password: + type: string + format: password + minLength: 8 + + UpdateUserInput: + type: object + properties: + name: + type: string + email: + type: string + format: email + + Pagination: + type: object + properties: + page: + type: integer + limit: + type: integer + totalPages: + type: integer + totalItems: + type: integer + hasNext: + type: boolean + hasPrevious: + type: boolean + + Error: + type: object + properties: + code: + type: string + message: + type: string + details: + type: object + + responses: + BadRequest: + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + Unauthorized: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + NotFound: + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' +``` + +## Generate from Code + +### TypeScript/Express +```typescript +import swaggerJsdoc from 'swagger-jsdoc'; +import swaggerUi from 'swagger-ui-express'; + +const options = { + definition: { + openapi: '3.0.0', + info: { + title: 'My API', + version: '1.0.0', + }, + }, + apis: ['./src/routes/*.ts'], +}; + +const specs = swaggerJsdoc(options); +app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs)); +``` + +### Python/FastAPI (Auto-generated) +```python +from fastapi import FastAPI, Query +from pydantic import BaseModel + +app = FastAPI( + title="My API", + description="API documentation", + version="1.0.0" +) + +class User(BaseModel): + id: str + email: str + name: str + +@app.get("/users", response_model=list[User]) +async def list_users( + page: int = Query(1, ge=1, description="Page number"), + limit: int = Query(20, ge=1, le=100, description="Items per page") +): + """ + List all users with pagination. + + Returns a paginated list of users. + """ + pass +# Docs auto-generated at /docs +``` + +## README API Documentation + +```markdown +# API Documentation + +## Base URL +``` +https://api.example.com/v1 +``` + +## Authentication +All endpoints require Bearer token authentication: +``` +Authorization: Bearer YOUR_TOKEN_HERE +``` + +## Endpoints + +### List Users +```http +GET /users?page=1&limit=20 +``` + +**Query Parameters**: +- `page` (integer, optional): Page number, default 1 +- `limit` (integer, optional): Items per page, default 20, max 100 +- `search` (string, optional): Search term + +**Response 200**: +```json +{ + "data": [ + { + "id": "usr_123", + "email": "user@example.com", + "name": "John Doe", + "role": "user", + "createdAt": "2024-01-01T00:00:00Z" + } + ], + "pagination": { + "page": 1, + "totalPages": 5, + "totalItems": 95 + } +} +``` + +### Create User +```http +POST /users +Content-Type: application/json + +{ + "email": "newuser@example.com", + "name": "New User", + "password": "SecurePass123!" +} +``` + +**Response 201**: +```json +{ + "id": "usr_456", + "email": "newuser@example.com", + "name": "New User", + "role": "user", + "createdAt": "2024-01-01T00:00:00Z" +} +``` + +## Error Responses + +All errors follow this format: +```json +{ + "code": "ERROR_CODE", + "message": "Human-readable message", + "details": {} +} +``` + +### Status Codes +- `200` - Success +- `201` - Created +- `204` - No Content +- `400` - Bad Request +- `401` - Unauthorized +- `403` - Forbidden +- `404` - Not Found +- `422` - Validation Error +- `429` - Rate Limit Exceeded +- `500` - Internal Server Error + +## Rate Limiting +- 100 requests per minute per IP +- 1000 requests per hour per user + +## Code Examples + +### JavaScript/Fetch +```javascript +const response = await fetch('https://api.example.com/v1/users', { + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + } +}); +const data = await response.json(); +``` + +### Python/Requests +```python +import requests + +response = requests.get( + 'https://api.example.com/v1/users', + headers={'Authorization': f'Bearer {token}'} +) +data = response.json() +``` + +### cURL +```bash +curl -H "Authorization: Bearer YOUR_TOKEN" \ + https://api.example.com/v1/users +``` +``` + +## Postman Collection + +Generate Postman collection from OpenAPI: +```bash +openapi2postmanv2 -s openapi.yaml -o postman_collection.json +``` + +## Best Practices + +1. **Be Comprehensive**: Document all endpoints, parameters, and responses +2. **Provide Examples**: Include real request/response examples +3. **Document Errors**: Show all possible error responses +4. **Code Samples**: Provide examples in multiple languages +5. **Keep Updated**: Auto-generate from code when possible +6. **Version APIs**: Include version in URL or headers +7. **Security**: Document authentication clearly +8. **Rate Limits**: Specify rate limiting rules +9. **Changelog**: Maintain API changelog +10. **Interactive Docs**: Use Swagger UI or similar + +## Tools + +- **Swagger UI**: Interactive API documentation +- **Redoc**: Beautiful API documentation +- **Postman**: API testing and documentation +- **Insomnia**: API client and documentation +- **Stoplight**: API design and documentation platform diff --git a/skills/code-review.md b/skills/code-review.md new file mode 100644 index 0000000..1a3b8ab --- /dev/null +++ b/skills/code-review.md @@ -0,0 +1,220 @@ +# Code Review Skill + +Perform comprehensive code reviews following industry best practices. + +## Review Checklist + +### 1. Code Quality +- [ ] Follows coding standards and style guide +- [ ] No code duplication (DRY principle) +- [ ] Functions are small and focused (SRP) +- [ ] Meaningful variable and function names +- [ ] Appropriate use of comments (why, not what) +- [ ] No magic numbers or strings +- [ ] Proper error handling + +### 2. Architecture & Design +- [ ] SOLID principles applied +- [ ] Appropriate design patterns used +- [ ] Separation of concerns +- [ ] Dependency injection where appropriate +- [ ] No circular dependencies +- [ ] Interfaces used for abstraction +- [ ] Proper layering/modularity + +### 3. Security +- [ ] No hardcoded secrets or credentials +- [ ] Input validation and sanitization +- [ ] SQL injection prevention +- [ ] XSS prevention +- [ ] CSRF protection where needed +- [ ] Proper authentication/authorization +- [ ] Secure data transmission +- [ ] No sensitive data in logs + +### 4. Performance +- [ ] Efficient algorithms and data structures +- [ ] No N+1 queries +- [ ] Proper indexing for database queries +- [ ] Caching implemented where appropriate +- [ ] No unnecessary computations +- [ ] Lazy loading where appropriate +- [ ] Resource cleanup (connections, files) + +### 5. Testing +- [ ] Unit tests present and passing +- [ ] Integration tests where needed +- [ ] Test coverage is adequate (>80% for critical paths) +- [ ] Edge cases tested +- [ ] Error conditions tested +- [ ] Tests are maintainable +- [ ] No flaky tests + +### 6. Error Handling +- [ ] All errors properly caught and handled +- [ ] Meaningful error messages +- [ ] Proper logging at appropriate levels +- [ ] No swallowed exceptions +- [ ] Graceful degradation +- [ ] Retry logic where appropriate + +### 7. Documentation +- [ ] README updated if needed +- [ ] API documentation present +- [ ] Complex logic explained +- [ ] Public APIs documented +- [ ] Breaking changes noted +- [ ] Migration guide if needed + +### 8. Dependencies +- [ ] No unnecessary dependencies +- [ ] Dependencies are up to date +- [ ] No known vulnerabilities +- [ ] License compatibility checked +- [ ] Bundle size impact considered + +### 9. Database +- [ ] Migrations are reversible +- [ ] Indexes on foreign keys +- [ ] No missing indexes for queries +- [ ] Proper transaction handling +- [ ] Connection pooling used +- [ ] Data validation at DB level + +### 10. API Design +- [ ] RESTful principles followed +- [ ] Consistent naming conventions +- [ ] Proper HTTP methods and status codes +- [ ] Versioning strategy in place +- [ ] Rate limiting considered +- [ ] Pagination for list endpoints + +## Review Process + +1. **Understand the Context** + - Read the PR/commit description + - Understand what problem is being solved + - Review linked issues/tickets + +2. **High-Level Review** + - Check overall architecture + - Verify design decisions + - Look for major issues + +3. **Detailed Review** + - Go through code line by line + - Check against checklist above + - Note issues by severity + +4. **Security Review** + - Look for security vulnerabilities + - Check authentication/authorization + - Verify input validation + +5. **Performance Review** + - Look for performance issues + - Check database queries + - Review caching strategy + +6. **Test Review** + - Verify test coverage + - Check test quality + - Run tests locally + +7. **Provide Feedback** + - Categorize by severity: Critical, Major, Minor, Suggestion + - Be specific and constructive + - Provide examples or alternatives + - Acknowledge good practices + +## Severity Levels + +**Critical**: Must be fixed before merge +- Security vulnerabilities +- Data loss scenarios +- Breaking changes without migration +- Production-breaking bugs + +**Major**: Should be fixed before merge +- Performance issues +- Architectural violations +- Missing error handling +- Inadequate test coverage + +**Minor**: Can be fixed later +- Code style issues +- Missing comments +- Minor refactoring opportunities + +**Suggestion**: Optional improvements +- Alternative approaches +- Future enhancements +- Code organization ideas + +## Example Review Comments + +### Good Comments +✅ "Consider using a Map instead of nested loops here for O(1) lookups. Current implementation is O(n²) which could be slow with large datasets." + +✅ "This endpoint is missing authentication. Should we add the @RequireAuth decorator?" + +✅ "Great use of the strategy pattern here! This makes adding new payment methods much easier." + +### Bad Comments +❌ "This is wrong." +❌ "Why did you do it this way?" +❌ "I would have done X instead." + +## Automated Checks + +Run these before manual review: +```bash +# Linting +npm run lint + +# Type checking +npm run type-check + +# Tests +npm run test + +# Security scan +npm audit + +# Code coverage +npm run test:coverage +``` + +## Focus Areas by Language + +### JavaScript/TypeScript +- Proper use of async/await +- No console.log in production +- TypeScript types used correctly +- React hooks rules followed + +### Python +- PEP 8 compliance +- Type hints used +- Virtual environment used +- Requirements.txt updated + +### Go +- Error handling (don't ignore errors) +- Proper defer usage +- Channel and goroutine safety +- Context usage for cancellation + +### Rust +- Ownership rules followed +- No unsafe blocks without justification +- Error handling with Result/Option +- Lifetime annotations correct + +## Post-Review + +After review is complete: +- Mark as approved if all critical/major issues resolved +- Request changes if issues remain +- Follow up on suggested improvements +- Document any technical debt created diff --git a/skills/performance-profiler.md b/skills/performance-profiler.md new file mode 100644 index 0000000..a68415f --- /dev/null +++ b/skills/performance-profiler.md @@ -0,0 +1,421 @@ +# Performance Profiler Skill + +Analyze code performance and provide optimization recommendations. + +## Performance Analysis Checklist + +### 1. Algorithm Complexity +- [ ] Time complexity documented (O(n), O(n²), etc.) +- [ ] Space complexity analyzed +- [ ] No nested loops where not necessary +- [ ] Efficient data structures chosen +- [ ] Binary search used instead of linear where possible + +### 2. Database Performance +- [ ] Queries use appropriate indexes +- [ ] No N+1 query problems +- [ ] Connection pooling implemented +- [ ] Batch operations used for bulk updates +- [ ] Query execution plans analyzed + +### 3. Caching +- [ ] Expensive computations cached +- [ ] API responses cached appropriately +- [ ] Cache invalidation strategy in place +- [ ] CDN used for static assets +- [ ] Redis/Memcached for distributed caching + +### 4. Network & I/O +- [ ] API calls batched where possible +- [ ] Compression enabled (gzip, brotli) +- [ ] HTTP/2 or HTTP/3 used +- [ ] Keep-alive connections +- [ ] Parallel requests for independent data + +### 5. Frontend Performance +- [ ] Code splitting implemented +- [ ] Lazy loading for routes/components +- [ ] Images optimized and lazy loaded +- [ ] Virtual scrolling for long lists +- [ ] Debouncing/throttling on events +- [ ] Memoization for expensive renders + +### 6. Memory Management +- [ ] No memory leaks +- [ ] Event listeners cleaned up +- [ ] Large objects garbage collected +- [ ] Streams used for large files +- [ ] WeakMap/WeakSet for cached objects + +## Performance Profiling Tools + +### Node.js +```javascript +// Built-in profiler +node --prof app.js +node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt + +// Chrome DevTools +node --inspect app.js +// Then open chrome://inspect + +// Clinic.js +clinic doctor -- node app.js +clinic flame -- node app.js +clinic bubbleprof -- node app.js +``` + +### Browser +```javascript +// Performance API +performance.mark('start'); +// ... code to measure +performance.mark('end'); +performance.measure('myOperation', 'start', 'end'); +const measures = performance.getEntriesByType('measure'); +console.log(measures[0].duration); + +// Chrome DevTools Performance tab +// Record → Run code → Stop → Analyze flame graph +``` + +### Python +```python +import cProfile +import pstats + +# Profile function +cProfile.run('my_function()', 'output.prof') + +# Analyze results +stats = pstats.Stats('output.prof') +stats.sort_stats('cumulative') +stats.print_stats(20) # Top 20 functions + +# Line profiler +from line_profiler import LineProfiler +lp = LineProfiler() +lp.add_function(my_function) +lp.run('my_function()') +lp.print_stats() +``` + +## Common Performance Issues & Fixes + +### Issue 1: N+1 Queries +```typescript +// ❌ Bad: N+1 queries +const users = await User.findAll(); +for (const user of users) { + user.posts = await Post.findAll({ where: { userId: user.id } }); +} + +// ✅ Good: Single query with join +const users = await User.findAll({ + include: [{ model: Post }] +}); + +// ✅ Better: DataLoader for batching +const postLoader = new DataLoader(async (userIds) => { + const posts = await Post.findAll({ + where: { userId: { $in: userIds } } + }); + return userIds.map(id => posts.filter(p => p.userId === id)); +}); +``` + +### Issue 2: Inefficient Loops +```typescript +// ❌ Bad: O(n²) +function findDuplicates(arr: number[]): number[] { + const duplicates = []; + for (let i = 0; i < arr.length; i++) { + for (let j = i + 1; j < arr.length; j++) { + if (arr[i] === arr[j]) { + duplicates.push(arr[i]); + } + } + } + return duplicates; +} + +// ✅ Good: O(n) +function findDuplicates(arr: number[]): number[] { + const seen = new Set(); + const duplicates = new Set(); + for (const num of arr) { + if (seen.has(num)) { + duplicates.add(num); + } + seen.add(num); + } + return Array.from(duplicates); +} +``` + +### Issue 3: Large Lists Without Virtualization +```typescript +// ❌ Bad: Renders all 10,000 items +{items.map(item => )} + +// ✅ Good: Virtual scrolling +import { FixedSizeList } from 'react-window'; + + + {({ index, style }) => ( +
+ +
+ )} +
+``` + +### Issue 4: Unnecessary Re-renders +```typescript +// ❌ Bad: Re-renders on every parent render +function ExpensiveComponent({ data }) { + const processed = processData(data); // Runs every render + return
{processed}
; +} + +// ✅ Good: Memoized +const ExpensiveComponent = React.memo(({ data }) => { + const processed = useMemo(() => processData(data), [data]); + return
{processed}
; +}); +``` + +### Issue 5: Blocking Operations +```typescript +// ❌ Bad: Blocks event loop +function processLargeFile() { + const data = fs.readFileSync('large-file.json'); // Blocks! + return JSON.parse(data); +} + +// ✅ Good: Async +async function processLargeFile() { + const data = await fs.promises.readFile('large-file.json', 'utf8'); + return JSON.parse(data); +} + +// ✅ Better: Streaming +function processLargeFileStream() { + return new Promise((resolve, reject) => { + const stream = fs.createReadStream('large-file.json'); + let data = ''; + stream.on('data', chunk => data += chunk); + stream.on('end', () => resolve(JSON.parse(data))); + stream.on('error', reject); + }); +} +``` + +## Performance Benchmarking + +### JavaScript/TypeScript +```typescript +import Benchmark from 'benchmark'; + +const suite = new Benchmark.Suite(); + +suite + .add('Array.forEach', () => { + const arr = Array.from({ length: 1000 }, (_, i) => i); + arr.forEach(x => x * 2); + }) + .add('for loop', () => { + const arr = Array.from({ length: 1000 }, (_, i) => i); + for (let i = 0; i < arr.length; i++) { + arr[i] * 2; + } + }) + .add('Array.map', () => { + const arr = Array.from({ length: 1000 }, (_, i) => i); + arr.map(x => x * 2); + }) + .on('cycle', (event) => { + console.log(String(event.target)); + }) + .on('complete', function() { + console.log('Fastest is ' + this.filter('fastest').map('name')); + }) + .run(); +``` + +### Python +```python +import timeit + +def method1(): + return [x * 2 for x in range(1000)] + +def method2(): + return list(map(lambda x: x * 2, range(1000))) + +time1 = timeit.timeit(method1, number=10000) +time2 = timeit.timeit(method2, number=10000) + +print(f"Method 1: {time1:.4f}s") +print(f"Method 2: {time2:.4f}s") +``` + +## Database Query Optimization + +### Analyze Slow Queries +```sql +-- PostgreSQL: Enable slow query logging +ALTER SYSTEM SET log_min_duration_statement = 1000; -- Log queries > 1s +SELECT pg_reload_conf(); + +-- View slow queries +SELECT + calls, + total_exec_time, + mean_exec_time, + max_exec_time, + query +FROM pg_stat_statements +ORDER BY mean_exec_time DESC +LIMIT 20; + +-- Explain query +EXPLAIN ANALYZE +SELECT u.*, COUNT(p.id) as post_count +FROM users u +LEFT JOIN posts p ON u.id = p.user_id +GROUP BY u.id; +``` + +### Add Indexes +```sql +-- Before: Sequential scan +SELECT * FROM users WHERE email = 'user@example.com'; +-- Seq Scan on users (cost=0.00..180.00 rows=1) + +-- Add index +CREATE INDEX idx_users_email ON users(email); + +-- After: Index scan +-- Index Scan using idx_users_email on users (cost=0.42..8.44 rows=1) +``` + +## Memory Leak Detection + +### Node.js +```javascript +// Detect memory leaks +const heapdump = require('heapdump'); + +// Take heap snapshot +heapdump.writeSnapshot(`./heap-${Date.now()}.heapsnapshot`); + +// Compare snapshots in Chrome DevTools +// Memory → Load → Compare snapshots + +// Monitor memory usage +setInterval(() => { + const used = process.memoryUsage(); + console.log({ + rss: `${Math.round(used.rss / 1024 / 1024)}MB`, + heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`, + heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`, + external: `${Math.round(used.external / 1024 / 1024)}MB`, + }); +}, 5000); +``` + +## Performance Budget + +Define acceptable performance metrics: + +### Web Application +- **First Contentful Paint (FCP)**: < 1.8s +- **Largest Contentful Paint (LCP)**: < 2.5s +- **Time to Interactive (TTI)**: < 3.8s +- **Total Blocking Time (TBT)**: < 200ms +- **Cumulative Layout Shift (CLS)**: < 0.1 +- **Bundle Size**: < 200KB (gzipped) + +### API +- **Response Time (p50)**: < 100ms +- **Response Time (p95)**: < 500ms +- **Response Time (p99)**: < 1000ms +- **Throughput**: > 1000 req/s +- **Error Rate**: < 0.1% + +### Database +- **Query Time (avg)**: < 50ms +- **Connection Pool**: < 80% utilization +- **Cache Hit Rate**: > 90% + +## Optimization Priority + +1. **Measure First**: Profile before optimizing +2. **Focus on Bottlenecks**: 20% of code causes 80% of issues +3. **User-Facing First**: Optimize what users experience +4. **Low-Hanging Fruit**: Easy wins first +5. **Monitor Continuously**: Set up alerts for regressions + +## Performance Testing + +```typescript +// Load testing with autocannon +import autocannon from 'autocannon'; + +autocannon({ + url: 'http://localhost:3000/api/users', + connections: 100, + duration: 30, + headers: { + 'Authorization': 'Bearer token' + } +}, (err, result) => { + console.log('Requests/sec:', result.requests.average); + console.log('Latency p50:', result.latency.p50); + console.log('Latency p99:', result.latency.p99); +}); +``` + +## Report Template + +```markdown +# Performance Analysis Report + +## Executive Summary +- **Current Performance**: X req/s, Yms avg response +- **Target Performance**: A req/s, Bms avg response +- **Gap**: Need to improve by Z% + +## Findings + +### Critical Issues +1. **N+1 Query in /api/users** (Impact: High) + - Current: 500ms avg response time + - Each user triggers 10 additional queries + - **Recommendation**: Add eager loading with `include` + - **Expected Impact**: Reduce to 50ms (10x improvement) + +### Major Issues +2. **Large Bundle Size** (Impact: Medium) + - Current: 800KB (gzipped) + - **Recommendation**: Code splitting, lazy loading + - **Expected Impact**: Reduce to 200KB + +## Optimization Roadmap + +1. **Week 1**: Fix N+1 queries (High impact, Low effort) +2. **Week 2**: Implement caching (High impact, Medium effort) +3. **Week 3**: Code splitting (Medium impact, Medium effort) +4. **Week 4**: Database indexing (Medium impact, Low effort) + +## Success Metrics +- Response time reduced by 60% +- Throughput increased by 3x +- Error rate reduced to < 0.1% +``` diff --git a/skills/test-case-generator.md b/skills/test-case-generator.md new file mode 100644 index 0000000..1df8ccc --- /dev/null +++ b/skills/test-case-generator.md @@ -0,0 +1,346 @@ +# Test Case Generator Skill + +Generate comprehensive test cases from requirements and code. + +## Test Case Template + +```markdown +## Test Case: {ID} - {Title} + +**Priority**: Critical | High | Medium | Low +**Type**: Unit | Integration | E2E | Performance | Security +**Status**: Pending | Pass | Fail | Blocked + +### Preconditions +- System is running +- User is authenticated +- Database contains test data + +### Test Steps +1. Navigate to login page +2. Enter valid credentials +3. Click "Login" button +4. Verify redirect to dashboard + +### Expected Results +- User is logged in +- Dashboard displays user's name +- Session token is stored +- Analytics event is fired + +### Actual Results +{To be filled during test execution} + +### Test Data +```json +{ + "email": "test@example.com", + "password": "Test123!" +} +``` + +### Dependencies +- Database seeded with test user +- Email service mocked + +### Notes +- Tests authentication flow +- Covers happy path +``` + +## Generate Unit Tests + +### From Function Specification + +**Function**: `calculateDiscount(price: number, couponCode: string): number` + +**Requirements**: +- Apply 10% discount for "SAVE10" +- Apply 20% discount for "SAVE20" +- Return original price for invalid codes +- Throw error for negative prices + +**Generated Tests**: +```typescript +describe('calculateDiscount', () => { + it('should apply 10% discount with SAVE10 code', () => { + expect(calculateDiscount(100, 'SAVE10')).toBe(90); + }); + + it('should apply 20% discount with SAVE20 code', () => { + expect(calculateDiscount(100, 'SAVE20')).toBe(80); + }); + + it('should return original price for invalid code', () => { + expect(calculateDiscount(100, 'INVALID')).toBe(100); + }); + + it('should return original price for empty code', () => { + expect(calculateDiscount(100, '')).toBe(100); + }); + + it('should throw error for negative price', () => { + expect(() => calculateDiscount(-10, 'SAVE10')).toThrow('Price must be positive'); + }); + + it('should handle zero price', () => { + expect(calculateDiscount(0, 'SAVE10')).toBe(0); + }); + + it('should handle decimal prices', () => { + expect(calculateDiscount(99.99, 'SAVE10')).toBeCloseTo(89.99, 2); + }); + + it('should be case insensitive for coupon codes', () => { + expect(calculateDiscount(100, 'save10')).toBe(90); + }); +}); +``` + +## Test Matrix Generation + +### Feature: User Registration + +| Test Case | Email | Password | Name | Expected Result | +|-----------|-------|----------|------|-----------------| +| TC-001 | valid@email.com | Password123! | John Doe | Success | +| TC-002 | invalid-email | Password123! | John Doe | Validation Error | +| TC-003 | valid@email.com | short | John Doe | Password too short | +| TC-004 | valid@email.com | nouppercasenumber! | John Doe | Password requirements not met | +| TC-005 | valid@email.com | Password123! | "" | Name required error | +| TC-006 | duplicate@email.com | Password123! | Jane Doe | Email already exists | +| TC-007 | valid@email.com | Password123! | A | Success (minimum length) | +| TC-008 | valid@email.com | Password123! | {101 chars} | Name too long error | + +## Edge Cases Identification + +For any feature, generate tests for: + +### Input Validation +- Minimum boundary (0, 1, "") +- Maximum boundary (MAX_INT, max length) +- Just below minimum (-1, empty string) +- Just above maximum (MAX_INT + 1, max length + 1) +- Invalid types (null, undefined, NaN) +- Special characters (', ", <, >, &, SQL injection) +- Unicode characters (emoji, RTL text) + +### State Transitions +- Initial state → Valid transition → Expected state +- Invalid state transitions +- Concurrent state changes +- Idempotency (multiple identical requests) + +### Error Conditions +- Network failures +- Timeout scenarios +- Partial data +- Corrupted data +- Permission denied +- Resource exhaustion + +### Performance +- Single item +- Empty list +- Large dataset (10K+ items) +- Concurrent requests +- Memory leaks +- Long-running operations + +## Integration Test Generation + +### API Endpoint Testing + +```typescript +describe('POST /api/users', () => { + beforeEach(async () => { + await db.reset(); + }); + + it('should create user with valid data', async () => { + const response = await request(app) + .post('/api/users') + .send({ + email: 'test@example.com', + name: 'Test User', + password: 'Test123!' + }); + + expect(response.status).toBe(201); + expect(response.body).toHaveProperty('id'); + expect(response.body.email).toBe('test@example.com'); + + // Verify in database + const user = await db.users.findByEmail('test@example.com'); + expect(user).toBeDefined(); + }); + + it('should reject duplicate email', async () => { + await db.users.create({ email: 'existing@example.com' }); + + const response = await request(app) + .post('/api/users') + .send({ email: 'existing@example.com', name: 'Test', password: 'Test123!' }); + + expect(response.status).toBe(409); + expect(response.body.code).toBe('EMAIL_EXISTS'); + }); + + it('should hash password before storing', async () => { + const password = 'PlainTextPassword'; + + await request(app) + .post('/api/users') + .send({ email: 'test@example.com', name: 'Test', password }); + + const user = await db.users.findByEmail('test@example.com'); + expect(user.password).not.toBe(password); + expect(user.password).toMatch(/^\$2[aby]\$.{56}$/); // bcrypt format + }); +}); +``` + +## E2E Test Scenarios + +### User Journey: Complete Purchase + +```typescript +test('user can complete purchase from product page to confirmation', async ({ page }) => { + // 1. Login + await page.goto('/login'); + await page.fill('[name="email"]', 'buyer@example.com'); + await page.fill('[name="password"]', 'Test123!'); + await page.click('button[type="submit"]'); + await expect(page).toHaveURL('/dashboard'); + + // 2. Browse and add to cart + await page.goto('/products/laptop-pro'); + await page.click('[data-testid="add-to-cart"]'); + await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1'); + + // 3. Go to cart + await page.click('[data-testid="cart-icon"]'); + await expect(page).toHaveURL('/cart'); + await expect(page.locator('[data-testid="cart-item"]')).toHaveCount(1); + + // 4. Proceed to checkout + await page.click('[data-testid="checkout-button"]'); + await expect(page).toHaveURL('/checkout'); + + // 5. Fill shipping info + await page.fill('[name="address"]', '123 Main St'); + await page.fill('[name="city"]', 'New York'); + await page.fill('[name="zip"]', '10001'); + await page.click('[data-testid="continue-payment"]'); + + // 6. Fill payment info (test card) + await page.fill('[name="cardNumber"]', '4242424242424242'); + await page.fill('[name="expiry"]', '12/25'); + await page.fill('[name="cvc"]', '123'); + + // 7. Place order + await page.click('[data-testid="place-order"]'); + + // 8. Verify confirmation + await expect(page).toHaveURL(/\/orders\/[a-zA-Z0-9]+/); + await expect(page.locator('text=Order Confirmed')).toBeVisible(); + + // 9. Verify email sent (mock) + expect(emailService.send).toHaveBeenCalledWith( + expect.objectContaining({ + to: 'buyer@example.com', + subject: expect.stringContaining('Order Confirmation') + }) + ); +}); +``` + +## Test Data Generation + +### Factory Pattern + +```typescript +class UserFactory { + static create(overrides?: Partial): User { + return { + id: faker.datatype.uuid(), + email: faker.internet.email(), + name: faker.name.fullName(), + role: 'user', + createdAt: new Date(), + ...overrides + }; + } + + static createAdmin(overrides?: Partial): User { + return this.create({ role: 'admin', ...overrides }); + } + + static createMany(count: number): User[] { + return Array.from({ length: count }, () => this.create()); + } +} + +// Usage +const user = UserFactory.create({ email: 'specific@example.com' }); +const admin = UserFactory.createAdmin(); +const users = UserFactory.createMany(100); +``` + +## Checklist for Complete Test Coverage + +### Functionality +- [ ] Happy path (expected usage) +- [ ] Alternative paths +- [ ] Error conditions +- [ ] Edge cases +- [ ] Boundary conditions + +### Data +- [ ] Valid data +- [ ] Invalid data +- [ ] Missing data (null, undefined) +- [ ] Empty data +- [ ] Extreme values + +### State +- [ ] Initial state +- [ ] Valid state transitions +- [ ] Invalid state transitions +- [ ] Final/terminal states + +### Integration +- [ ] Database operations +- [ ] External API calls +- [ ] File system operations +- [ ] Third-party services + +### Security +- [ ] Authentication required +- [ ] Authorization enforced +- [ ] Input sanitization +- [ ] SQL injection prevention +- [ ] XSS prevention + +### Performance +- [ ] Response time acceptable +- [ ] Handles high load +- [ ] No memory leaks +- [ ] Efficient queries + +### Usability +- [ ] Error messages clear +- [ ] Loading states shown +- [ ] Success feedback provided +- [ ] Accessibility requirements met + +## Best Practices + +1. **Test Behavior, Not Implementation**: Focus on what the code does, not how +2. **One Assert Per Test**: Makes failures easier to diagnose +3. **Descriptive Names**: Test name should describe what and why +4. **Arrange-Act-Assert**: Clear test structure +5. **Independent Tests**: No dependencies between tests +6. **Fast Tests**: Unit tests should run in milliseconds +7. **Deterministic**: Same input always produces same output +8. **Readable**: Tests serve as documentation