# refactor: restructure .cursor directory for improved organization and clarity ## Description This PR refactors the `.cursor` directory to enhance organization, clarity, and maintainability. ### Problem The existing `.cursor` directory lacked clear organization, making it difficult to find specific files, understand their purpose, and add new components consistently. ### Solution A comprehensive restructuring: #### New Directory Structure ``` .cursor/ ├── settings.json # Main configuration file ├── docs/ # Documentation │ ├── guides/ # In-depth guides │ ├── references/ # Quick references │ └── practices/ # Best practices ├── rules/ # Rule definitions │ ├── commit/ # Commit-related rules │ ├── quality/ # Code quality rules │ ├── testing/ # Testing rules │ └── verification/ # Verification rules └── hooks/ # Git hooks and scripts ``` #### Key Changes 1. **Logical Categorization**: Organized files into clear categories based on purpose 2. **Improved Documentation**: Added comprehensive README files for each directory 3. **Standardized Naming**: Implemented consistent kebab-case naming convention 4. **Reference Updates**: Updated all internal references to point to new file locations ### Benefits - **Easier Navigation**: Clear categorization makes finding files intuitive - **Improved Understanding**: Comprehensive documentation explains purpose and usage - **Simplified Maintenance**: Logical structure makes updates and additions easier - **Better Onboarding**: New team members can quickly understand the system This refactoring sets a solid foundation for all Cursor AI-related configurations and rules, making it easier for the team to leverage Cursor's capabilities.
628 lines
18 KiB
Plaintext
628 lines
18 KiB
Plaintext
---
|
|
description:
|
|
globs:
|
|
alwaysApply: true
|
|
---
|
|
# Feature Implementation Verifier
|
|
|
|
```yaml
|
|
name: Feature Implementation Verifier
|
|
description: Verifies that new features are properly implemented and tested
|
|
author: Cursor AI
|
|
version: 1.0.0
|
|
tags:
|
|
- feature
|
|
- implementation
|
|
- verification
|
|
- acceptance-criteria
|
|
activation:
|
|
always: true
|
|
event:
|
|
- pull_request
|
|
- command
|
|
triggers:
|
|
- pull_request.created
|
|
- pull_request.updated
|
|
- pull_request.labeled:feature
|
|
- command: "verify_feature"
|
|
```
|
|
|
|
## Rule Definition
|
|
|
|
This rule ensures that new feature implementations meet all requirements, follow best practices, and include appropriate tests.
|
|
|
|
## Verification Logic
|
|
|
|
```javascript
|
|
// Main function to verify feature implementation
|
|
function verifyFeatureImplementation(files, tests, requirements) {
|
|
const results = {
|
|
requirementsCoverage: checkRequirementsCoverage(files, requirements),
|
|
testCoverage: checkTestCoverage(files, tests),
|
|
codeQuality: checkCodeQuality(files),
|
|
documentation: checkDocumentation(files, requirements),
|
|
performance: checkPerformance(files),
|
|
score: 0,
|
|
issues: [],
|
|
recommendations: []
|
|
};
|
|
|
|
// Calculate overall score
|
|
results.score = calculateScore(results);
|
|
|
|
// Generate issues and recommendations
|
|
results.issues = identifyIssues(results);
|
|
results.recommendations = generateRecommendations(results.issues);
|
|
|
|
return {
|
|
...results,
|
|
summary: generateSummary(results)
|
|
};
|
|
}
|
|
|
|
// Check if all requirements are implemented
|
|
function checkRequirementsCoverage(files, requirements) {
|
|
const results = {
|
|
implementedRequirements: [],
|
|
missingRequirements: [],
|
|
implementationRate: 0
|
|
};
|
|
|
|
if (!requirements || requirements.length === 0) {
|
|
results.missingRequirements.push('requirements definition');
|
|
return results;
|
|
}
|
|
|
|
// For each requirement, check if it's implemented
|
|
for (const req of requirements) {
|
|
const isImplemented = files.some(file => fileImplementsRequirement(file, req));
|
|
|
|
if (isImplemented) {
|
|
results.implementedRequirements.push(req);
|
|
} else {
|
|
results.missingRequirements.push(req);
|
|
}
|
|
}
|
|
|
|
results.implementationRate = requirements.length > 0
|
|
? (results.implementedRequirements.length / requirements.length) * 100
|
|
: 0;
|
|
|
|
return results;
|
|
}
|
|
|
|
// Helper to check if a file implements a specific requirement
|
|
function fileImplementsRequirement(file, requirement) {
|
|
// This would contain complex analysis logic to match code to requirements
|
|
// For now, we'll use a simple text matching approach
|
|
return file.content.includes(requirement.id) ||
|
|
file.content.toLowerCase().includes(requirement.description.toLowerCase());
|
|
}
|
|
|
|
// Check if tests cover all the new functionality
|
|
function checkTestCoverage(files, tests) {
|
|
const results = {
|
|
testedFiles: [],
|
|
untestedFiles: [],
|
|
coverage: 0
|
|
};
|
|
|
|
if (!tests || tests.length === 0) {
|
|
files.forEach(file => {
|
|
if (shouldHaveTests(file)) {
|
|
results.untestedFiles.push(file.path);
|
|
}
|
|
});
|
|
|
|
return results;
|
|
}
|
|
|
|
// Check each file to see if it has test coverage
|
|
for (const file of files) {
|
|
const hasTests = tests.some(test => testCoversFile(test, file));
|
|
|
|
if (hasTests || !shouldHaveTests(file)) {
|
|
results.testedFiles.push(file.path);
|
|
} else {
|
|
results.untestedFiles.push(file.path);
|
|
}
|
|
}
|
|
|
|
const filesToTest = files.filter(file => shouldHaveTests(file)).length;
|
|
results.coverage = filesToTest > 0
|
|
? (results.testedFiles.length / filesToTest) * 100
|
|
: 100;
|
|
|
|
return results;
|
|
}
|
|
|
|
// Helper to determine if a test covers a specific file
|
|
function testCoversFile(test, file) {
|
|
// This would contain complex analysis to determine test coverage
|
|
// For now, we'll use a simple path matching approach
|
|
const filePath = file.path.replace(/\.(js|ts|jsx|tsx|java)$/, '');
|
|
const testPath = test.path;
|
|
|
|
return testPath.includes(filePath) ||
|
|
test.content.includes(file.path) ||
|
|
test.content.includes(filePath);
|
|
}
|
|
|
|
// Helper to determine if a file should have tests
|
|
function shouldHaveTests(file) {
|
|
// Skip certain files that don't need tests
|
|
const skipPaths = [
|
|
'app/client/public/',
|
|
'app/client/src/assets/',
|
|
'app/client/src/styles/',
|
|
'app/client/src/constants/',
|
|
'app/client/src/types/'
|
|
];
|
|
|
|
if (skipPaths.some(path => file.path.includes(path))) {
|
|
return false;
|
|
}
|
|
|
|
// Skip certain file types
|
|
const skipExtensions = ['.md', '.json', '.yml', '.yaml', '.svg', '.png', '.jpg'];
|
|
if (skipExtensions.some(ext => file.path.endsWith(ext))) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Check the code quality of the implementation
|
|
function checkCodeQuality(files) {
|
|
const results = {
|
|
qualityIssues: [],
|
|
issueCount: 0,
|
|
qualityScore: 100
|
|
};
|
|
|
|
// Check each file for quality issues
|
|
for (const file of files) {
|
|
const fileIssues = analyzeCodeQuality(file);
|
|
|
|
if (fileIssues.length > 0) {
|
|
results.qualityIssues.push({
|
|
file: file.path,
|
|
issues: fileIssues
|
|
});
|
|
|
|
results.issueCount += fileIssues.length;
|
|
results.qualityScore -= Math.min(fileIssues.length * 5, 20); // Max 20 points deduction per file
|
|
}
|
|
}
|
|
|
|
results.qualityScore = Math.max(0, results.qualityScore);
|
|
|
|
return results;
|
|
}
|
|
|
|
// Helper to analyze code quality in a file
|
|
function analyzeCodeQuality(file) {
|
|
const issues = [];
|
|
const content = file.content;
|
|
|
|
// Check for common code quality issues
|
|
if (file.path.includes('.js') || file.path.includes('.ts')) {
|
|
// Check for console.log statements
|
|
if (content.includes('console.log')) {
|
|
issues.push({
|
|
type: 'debugging',
|
|
line: findLineForPattern(content, 'console.log'),
|
|
description: 'Remove console.log statements before committing'
|
|
});
|
|
}
|
|
|
|
// Check for TODO comments
|
|
if (content.includes('TODO')) {
|
|
issues.push({
|
|
type: 'incomplete',
|
|
line: findLineForPattern(content, 'TODO'),
|
|
description: 'Resolve TODO comments before committing'
|
|
});
|
|
}
|
|
|
|
// Check for commented out code
|
|
if (content.match(/\/\/\s*[a-zA-Z0-9]+/)) {
|
|
issues.push({
|
|
type: 'cleanliness',
|
|
line: findLineForPattern(content, '//'),
|
|
description: 'Remove commented out code before committing'
|
|
});
|
|
}
|
|
}
|
|
|
|
// Check for proper indentation and formatting
|
|
const lines = content.split('\n');
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i];
|
|
if (line.length > 120) {
|
|
issues.push({
|
|
type: 'formatting',
|
|
line: i + 1,
|
|
description: 'Line exceeds 120 characters'
|
|
});
|
|
}
|
|
|
|
// Check for inconsistent indentation
|
|
if (i > 0 && line.match(/^\s+/) && lines[i-1].match(/^\s+/)) {
|
|
const currentIndent = line.match(/^\s+/)[0].length;
|
|
const prevIndent = lines[i-1].match(/^\s+/)[0].length;
|
|
|
|
if (Math.abs(currentIndent - prevIndent) % 2 !== 0 && Math.abs(currentIndent - prevIndent) !== 0) {
|
|
issues.push({
|
|
type: 'formatting',
|
|
line: i + 1,
|
|
description: 'Inconsistent indentation'
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return issues;
|
|
}
|
|
|
|
// Helper to find the line number for a pattern
|
|
function findLineForPattern(content, pattern) {
|
|
const lines = content.split('\n');
|
|
for (let i = 0; i < lines.length; i++) {
|
|
if (lines[i].includes(pattern)) {
|
|
return i + 1;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
// Check for appropriate documentation
|
|
function checkDocumentation(files, requirements) {
|
|
const results = {
|
|
documentedFiles: [],
|
|
undocumentedFiles: [],
|
|
documentationScore: 100
|
|
};
|
|
|
|
// Check each file for documentation
|
|
for (const file of files) {
|
|
if (shouldHaveDocumentation(file)) {
|
|
if (hasAdequateDocumentation(file)) {
|
|
results.documentedFiles.push(file.path);
|
|
} else {
|
|
results.undocumentedFiles.push(file.path);
|
|
results.documentationScore -= 10; // 10 points deduction per undocumented file
|
|
}
|
|
}
|
|
}
|
|
|
|
results.documentationScore = Math.max(0, results.documentationScore);
|
|
|
|
return results;
|
|
}
|
|
|
|
// Helper to determine if a file should have documentation
|
|
function shouldHaveDocumentation(file) {
|
|
// Public APIs, complex components, and services should have documentation
|
|
return file.path.includes('/api/') ||
|
|
file.path.includes('/services/') ||
|
|
file.path.includes('/components/') ||
|
|
file.path.endsWith('.java');
|
|
}
|
|
|
|
// Helper to check if a file has adequate documentation
|
|
function hasAdequateDocumentation(file) {
|
|
const content = file.content;
|
|
|
|
// Check for JSDoc, JavaDoc, or other documentation patterns
|
|
if (file.path.includes('.js') || file.path.includes('.ts')) {
|
|
return content.includes('/**') && content.includes('*/');
|
|
}
|
|
|
|
if (file.path.includes('.java')) {
|
|
return content.includes('/**') && content.includes('*/') && content.includes('@param');
|
|
}
|
|
|
|
// For other files, check for comment blocks
|
|
return content.includes('/*') && content.includes('*/');
|
|
}
|
|
|
|
// Check for performance implications
|
|
function checkPerformance(files) {
|
|
// This would have comprehensive performance analysis
|
|
// For now, return an empty array for performance issues
|
|
return {
|
|
performanceIssues: [],
|
|
issueCount: 0
|
|
};
|
|
}
|
|
|
|
// Calculate overall score based on all checks
|
|
function calculateScore(results) {
|
|
let score = 100;
|
|
|
|
// Deduct for missing requirements
|
|
if (results.requirementsCoverage.implementationRate < 100) {
|
|
score -= (100 - results.requirementsCoverage.implementationRate) * 0.3;
|
|
}
|
|
|
|
// Deduct for missing tests
|
|
if (results.testCoverage.coverage < 80) {
|
|
score -= (80 - results.testCoverage.coverage) * 0.3;
|
|
}
|
|
|
|
// Deduct for code quality issues
|
|
score -= (100 - results.codeQuality.qualityScore) * 0.2;
|
|
|
|
// Deduct for documentation issues
|
|
score -= (100 - results.documentation.documentationScore) * 0.2;
|
|
|
|
return Math.max(0, Math.round(score));
|
|
}
|
|
|
|
// Identify issues from all verification checks
|
|
function identifyIssues(results) {
|
|
const issues = [];
|
|
|
|
// Add missing requirements as issues
|
|
results.requirementsCoverage.missingRequirements.forEach(req => {
|
|
issues.push({
|
|
type: 'requirements',
|
|
severity: 'high',
|
|
message: `Missing implementation for requirement: ${req.id || req}`
|
|
});
|
|
});
|
|
|
|
// Add test coverage issues
|
|
if (results.testCoverage.untestedFiles.length > 0) {
|
|
issues.push({
|
|
type: 'testing',
|
|
severity: 'high',
|
|
message: `Missing tests for ${results.testCoverage.untestedFiles.length} files`
|
|
});
|
|
|
|
results.testCoverage.untestedFiles.forEach(file => {
|
|
issues.push({
|
|
type: 'testing',
|
|
severity: 'medium',
|
|
message: `No tests for file: ${file}`
|
|
});
|
|
});
|
|
}
|
|
|
|
// Add code quality issues
|
|
results.codeQuality.qualityIssues.forEach(fileIssue => {
|
|
fileIssue.issues.forEach(issue => {
|
|
issues.push({
|
|
type: 'code_quality',
|
|
severity: 'medium',
|
|
message: `${issue.description} in ${fileIssue.file} at line ${issue.line}`
|
|
});
|
|
});
|
|
});
|
|
|
|
// Add documentation issues
|
|
results.documentation.undocumentedFiles.forEach(file => {
|
|
issues.push({
|
|
type: 'documentation',
|
|
severity: 'medium',
|
|
message: `Missing or inadequate documentation in ${file}`
|
|
});
|
|
});
|
|
|
|
return issues;
|
|
}
|
|
|
|
// Generate recommendations based on identified issues
|
|
function generateRecommendations(issues) {
|
|
const recommendations = [];
|
|
|
|
// Group issues by type
|
|
const issuesByType = {};
|
|
issues.forEach(issue => {
|
|
if (!issuesByType[issue.type]) {
|
|
issuesByType[issue.type] = [];
|
|
}
|
|
issuesByType[issue.type].push(issue);
|
|
});
|
|
|
|
// Generate recommendations for requirements issues
|
|
if (issuesByType.requirements) {
|
|
recommendations.push({
|
|
type: 'requirements',
|
|
title: 'Complete the implementation of requirements',
|
|
steps: [
|
|
'Review the missing requirements and ensure they are implemented',
|
|
'Verify that the implementation matches the acceptance criteria',
|
|
'Update the code to address all missing requirements'
|
|
]
|
|
});
|
|
}
|
|
|
|
// Generate recommendations for testing issues
|
|
if (issuesByType.testing) {
|
|
recommendations.push({
|
|
type: 'testing',
|
|
title: 'Improve test coverage',
|
|
steps: [
|
|
'Add unit tests for untested files',
|
|
'Create integration tests where appropriate',
|
|
'Ensure all edge cases are covered in tests'
|
|
]
|
|
});
|
|
}
|
|
|
|
// Generate recommendations for code quality issues
|
|
if (issuesByType.code_quality) {
|
|
recommendations.push({
|
|
type: 'code_quality',
|
|
title: 'Address code quality issues',
|
|
steps: [
|
|
'Remove debugging code (console.log, TODO comments)',
|
|
'Fix formatting and indentation issues',
|
|
'Follow project coding standards and best practices'
|
|
]
|
|
});
|
|
}
|
|
|
|
// Generate recommendations for documentation issues
|
|
if (issuesByType.documentation) {
|
|
recommendations.push({
|
|
type: 'documentation',
|
|
title: 'Improve documentation',
|
|
steps: [
|
|
'Add JSDoc or JavaDoc comments to public APIs and classes',
|
|
'Document complex components and their usage',
|
|
'Ensure all services have proper documentation'
|
|
]
|
|
});
|
|
}
|
|
|
|
return recommendations;
|
|
}
|
|
|
|
// Generate a summary of the verification results
|
|
function generateSummary(results) {
|
|
const score = results.score;
|
|
let status = '';
|
|
|
|
if (score >= 90) {
|
|
status = 'EXCELLENT';
|
|
} else if (score >= 70) {
|
|
status = 'GOOD';
|
|
} else if (score >= 50) {
|
|
status = 'NEEDS IMPROVEMENT';
|
|
} else {
|
|
status = 'INCOMPLETE';
|
|
}
|
|
|
|
return {
|
|
score,
|
|
status,
|
|
issues: results.issues.length,
|
|
critical: results.issues.filter(issue => issue.severity === 'high').length,
|
|
recommendations: results.recommendations.length,
|
|
message: generateSummaryMessage(score, status, results)
|
|
};
|
|
}
|
|
|
|
// Generate a summary message based on results
|
|
function generateSummaryMessage(score, status, results) {
|
|
if (status === 'EXCELLENT') {
|
|
return 'Feature implementation meets or exceeds all requirements and standards. Good job!';
|
|
} else if (status === 'GOOD') {
|
|
return `Feature implementation is good overall but has ${results.issues.length} issues to address.`;
|
|
} else if (status === 'NEEDS IMPROVEMENT') {
|
|
const critical = results.issues.filter(issue => issue.severity === 'high').length;
|
|
return `Feature implementation needs significant improvement with ${critical} critical issues.`;
|
|
} else {
|
|
return 'Feature implementation is incomplete and does not meet minimum requirements.';
|
|
}
|
|
}
|
|
|
|
// Run on activation
|
|
function activate(context) {
|
|
// Register event handlers
|
|
context.on('pull_request.created', (event) => {
|
|
const files = context.getPullRequestFiles(event.pullRequest.id);
|
|
const tests = context.getPullRequestTests(event.pullRequest.id);
|
|
const requirements = context.getFeatureRequirements(event.pullRequest);
|
|
return verifyFeatureImplementation(files, tests, requirements);
|
|
});
|
|
|
|
context.on('pull_request.updated', (event) => {
|
|
const files = context.getPullRequestFiles(event.pullRequest.id);
|
|
const tests = context.getPullRequestTests(event.pullRequest.id);
|
|
const requirements = context.getFeatureRequirements(event.pullRequest);
|
|
return verifyFeatureImplementation(files, tests, requirements);
|
|
});
|
|
|
|
context.on('pull_request.labeled:feature', (event) => {
|
|
const files = context.getPullRequestFiles(event.pullRequest.id);
|
|
const tests = context.getPullRequestTests(event.pullRequest.id);
|
|
const requirements = context.getFeatureRequirements(event.pullRequest);
|
|
return verifyFeatureImplementation(files, tests, requirements);
|
|
});
|
|
|
|
context.registerCommand('verify_feature', (args) => {
|
|
const prId = args.pullRequest;
|
|
if (!prId) {
|
|
return {
|
|
status: "error",
|
|
message: "No pull request specified"
|
|
};
|
|
}
|
|
|
|
const files = context.getPullRequestFiles(prId);
|
|
const tests = context.getPullRequestTests(prId);
|
|
const requirements = context.getFeatureRequirements({ id: prId });
|
|
return verifyFeatureImplementation(files, tests, requirements);
|
|
});
|
|
}
|
|
|
|
// Export functions
|
|
module.exports = {
|
|
activate,
|
|
verifyFeatureImplementation,
|
|
checkRequirementsCoverage,
|
|
checkTestCoverage,
|
|
checkCodeQuality,
|
|
checkDocumentation,
|
|
checkPerformance
|
|
};
|
|
```
|
|
|
|
## When It Runs
|
|
|
|
This rule can be triggered:
|
|
- When a new feature pull request is created
|
|
- When a pull request is updated
|
|
- When a pull request is labeled with 'feature'
|
|
- When a developer runs the `verify_feature` command in Cursor
|
|
- Before merging a feature implementation
|
|
|
|
## Usage Example
|
|
|
|
1. Create a pull request for a new feature
|
|
2. Run `verify_feature --pullRequest=123` in Cursor
|
|
3. Review the verification results
|
|
4. Address any identified issues
|
|
5. Re-run verification to confirm all issues are resolved
|
|
|
|
## Feature Implementation Checklist
|
|
|
|
### Requirements
|
|
- [ ] Understand the feature requirements and acceptance criteria
|
|
- [ ] Design a solution that meets all requirements
|
|
- [ ] Create a plan for implementing the feature
|
|
- [ ] Consider edge cases and potential issues
|
|
|
|
### Implementation
|
|
- [ ] Follow the project's coding standards and architecture
|
|
- [ ] Write clean, efficient, and maintainable code
|
|
- [ ] Handle errors and edge cases gracefully
|
|
- [ ] Ensure the feature integrates well with existing functionality
|
|
|
|
### Testing
|
|
- [ ] Write unit tests for all components
|
|
- [ ] Create integration tests for complex interactions
|
|
- [ ] Test across different environments if applicable
|
|
- [ ] Verify that the feature meets all acceptance criteria
|
|
|
|
### Review
|
|
- [ ] Self-review the code before submission
|
|
- [ ] Address feedback from automated checks
|
|
- [ ] Ensure documentation is complete and accurate
|
|
- [ ] Verify test coverage is adequate
|
|
|
|
## Example: Verifying Acceptance Criteria
|
|
|
|
For a file upload feature, the verifier would check for:
|
|
|
|
- UI components for selecting files
|
|
- Upload progress indicators
|
|
- Success and error states
|
|
- Backend API for handling file uploads
|
|
- File validation and error handling
|
|
- Tests for valid and invalid uploads
|
|
- Performance considerations for large files |