aios-core
Version:
Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework
330 lines (297 loc) • 9 kB
JavaScript
/**
* Checklist Generator
*
* Generates strategic review checklists based on:
* - Story type and complexity
* - Changed files
* - Previous layer results
*
* @module core/quality-gates/checklist-generator
* @version 1.0.0
* @story 2.10 - Quality Gate Manager
*/
/**
* Strategic review checklist generator
*/
class ChecklistGenerator {
/**
* Create a checklist generator
* @param {Object} config - Generator configuration
*/
constructor(config = {}) {
this.config = config;
this.template = config.template || 'strategic-review-checklist';
this.minItems = config.minItems || 5;
}
/**
* Generate a review checklist
* @param {Object} context - Generation context
* @param {string} context.storyId - Story identifier
* @param {Array} context.changedFiles - List of changed files
* @param {Array} context.layers - Previous layer results
* @returns {Promise<Object>} Generated checklist
*/
async generate(context = {}) {
const { storyId, changedFiles = [], layers = [] } = context;
const items = [];
// Add base review items
items.push(...this.getBaseItems());
// Add items based on changed files
items.push(...this.getFileBasedItems(changedFiles));
// Add items based on previous layer results
items.push(...this.getLayerBasedItems(layers));
// Add story-specific items
if (storyId) {
items.push(...this.getStoryBasedItems(storyId));
}
// Ensure minimum items
while (items.length < this.minItems) {
items.push({
id: `additional-${items.length}`,
text: 'General code quality and standards compliance',
category: 'general',
priority: 'low',
checked: false,
});
}
return {
template: this.template,
storyId,
generatedAt: new Date().toISOString(),
items: items.map((item, index) => ({
...item,
order: index + 1,
})),
};
}
/**
* Get base checklist items
* @returns {Array} Base items
*/
getBaseItems() {
return [
{
id: 'architecture-alignment',
text: 'Changes align with documented architecture decisions',
category: 'architecture',
priority: 'high',
checked: false,
},
{
id: 'security-review',
text: 'No security vulnerabilities introduced (OWASP Top 10)',
category: 'security',
priority: 'critical',
checked: false,
},
{
id: 'performance-impact',
text: 'Performance impact assessed and acceptable',
category: 'performance',
priority: 'medium',
checked: false,
},
{
id: 'documentation-updated',
text: 'Relevant documentation updated or created',
category: 'documentation',
priority: 'medium',
checked: false,
},
{
id: 'backward-compatibility',
text: 'Backward compatibility maintained (or breaking changes documented)',
category: 'compatibility',
priority: 'high',
checked: false,
},
];
}
/**
* Get items based on changed files
* @param {Array} changedFiles - List of changed files
* @returns {Array} File-based items
*/
getFileBasedItems(changedFiles = []) {
const items = [];
const fileCategories = this.categorizeFiles(changedFiles);
if (fileCategories.tests.length > 0) {
items.push({
id: 'test-coverage',
text: `Test changes reviewed for coverage (${fileCategories.tests.length} test files)`,
category: 'testing',
priority: 'high',
checked: false,
});
}
if (fileCategories.configs.length > 0) {
items.push({
id: 'config-changes',
text: `Configuration changes validated (${fileCategories.configs.length} config files)`,
category: 'configuration',
priority: 'high',
checked: false,
});
}
if (fileCategories.agents.length > 0) {
items.push({
id: 'agent-changes',
text: `Agent definition changes reviewed (${fileCategories.agents.length} agent files)`,
category: 'agents',
priority: 'high',
checked: false,
});
}
if (fileCategories.api.length > 0) {
items.push({
id: 'api-changes',
text: `API changes reviewed for breaking changes (${fileCategories.api.length} API files)`,
category: 'api',
priority: 'critical',
checked: false,
});
}
if (fileCategories.database.length > 0) {
items.push({
id: 'database-changes',
text: `Database migrations reviewed (${fileCategories.database.length} migration files)`,
category: 'database',
priority: 'critical',
checked: false,
});
}
return items;
}
/**
* Categorize files by type
* @param {Array} files - List of file paths
* @returns {Object} Categorized files
*/
categorizeFiles(files = []) {
return {
tests: files.filter((f) => f.includes('test') || f.includes('spec')),
configs: files.filter((f) =>
f.endsWith('.yaml') || f.endsWith('.yml') || f.endsWith('.json') ||
f.includes('config') || f.includes('.env'),
),
agents: files.filter((f) =>
f.includes('agents/') || f.includes('agent'),
),
api: files.filter((f) =>
f.includes('/api/') || f.includes('routes') || f.includes('endpoints'),
),
database: files.filter((f) =>
f.includes('migration') || f.includes('schema') || f.includes('database'),
),
docs: files.filter((f) =>
f.endsWith('.md') || f.includes('/docs/'),
),
source: files.filter((f) =>
f.endsWith('.js') || f.endsWith('.ts') || f.endsWith('.jsx') || f.endsWith('.tsx'),
),
};
}
/**
* Get items based on previous layer results
* @param {Array} layers - Previous layer results
* @returns {Array} Layer-based items
*/
getLayerBasedItems(layers = []) {
const items = [];
layers.forEach((layer) => {
if (layer.checks?.warnings > 0) {
items.push({
id: `${layer.layer}-warnings`,
text: `Review ${layer.checks.warnings} warnings from ${layer.layer}`,
category: 'quality',
priority: 'medium',
checked: false,
});
}
// Check for specific issues
layer.results?.forEach((result) => {
if (result.check === 'coderabbit' && result.issues?.high > 0) {
items.push({
id: 'coderabbit-high-issues',
text: `Address ${result.issues.high} HIGH severity issues from CodeRabbit`,
category: 'quality',
priority: 'high',
checked: false,
});
}
});
});
return items;
}
/**
* Get items based on story type
* @param {string} storyId - Story identifier
* @returns {Array} Story-based items
*/
getStoryBasedItems(storyId) {
const items = [];
// Add story completion check
items.push({
id: 'story-completion',
text: `All acceptance criteria for ${storyId} verified`,
category: 'story',
priority: 'critical',
checked: false,
});
// Infer story type from ID pattern
if (storyId.includes('2.')) {
// Sprint 2 - Architecture/Infrastructure
items.push({
id: 'architecture-compliance',
text: 'Implementation follows modular architecture guidelines',
category: 'architecture',
priority: 'high',
checked: false,
});
}
return items;
}
/**
* Format checklist for display
* @param {Object} checklist - Generated checklist
* @returns {string} Formatted checklist
*/
format(checklist) {
const lines = [
'# Strategic Review Checklist',
`Story: ${checklist.storyId || 'N/A'}`,
`Generated: ${checklist.generatedAt}`,
'',
'## Review Items',
'',
];
const byCategory = {};
checklist.items.forEach((item) => {
if (!byCategory[item.category]) {
byCategory[item.category] = [];
}
byCategory[item.category].push(item);
});
Object.entries(byCategory).forEach(([category, items]) => {
lines.push(`### ${this.formatCategory(category)}`);
items.forEach((item) => {
const checkbox = item.checked ? '[x]' : '[ ]';
const priority = item.priority === 'critical' ? '🔴' :
item.priority === 'high' ? '🟠' :
item.priority === 'medium' ? '🟡' : '🟢';
lines.push(`- ${checkbox} ${priority} ${item.text}`);
});
lines.push('');
});
return lines.join('\n');
}
/**
* Format category name for display
* @param {string} category - Category name
* @returns {string} Formatted category
*/
formatCategory(category) {
return category.charAt(0).toUpperCase() + category.slice(1);
}
}
module.exports = { ChecklistGenerator };