Major Features:
- Multi-project governance with Rule Manager web UI
- Project Manager for organizing governance across projects
- Variable substitution system (${VAR_NAME} in rules)
- Claude.md analyzer for instruction extraction
- Rule quality scoring and optimization
Admin UI Components:
- /admin/rule-manager.html - Full-featured rule management interface
- /admin/project-manager.html - Multi-project administration
- /admin/claude-md-migrator.html - Import rules from Claude.md files
- Dashboard enhancements for governance analytics
Backend Implementation:
- Controllers: projects, rules, variables
- Models: Project, VariableValue, enhanced GovernanceRule
- Routes: /api/projects, /api/rules with full CRUD
- Services: ClaudeMdAnalyzer, RuleOptimizer, VariableSubstitution
- Utilities: mongoose helpers
Documentation:
- User guides for Rule Manager and Projects
- Complete API documentation (PROJECTS_API, RULES_API)
- Phase 3 planning and architecture diagrams
- Test results and error analysis
- Coding best practices summary
Testing & Scripts:
- Integration tests for projects API
- Unit tests for variable substitution
- Database migration scripts
- Seed data generation
- Test token generator
Key Capabilities:
✅ UNIVERSAL scope rules apply across all projects
✅ PROJECT_SPECIFIC rules override for individual projects
✅ Variable substitution per-project (e.g., ${DB_PORT} → 27017)
✅ Real-time validation and quality scoring
✅ Advanced filtering and search
✅ Import from existing Claude.md files
Technical Details:
- MongoDB-backed governance persistence
- RESTful API with Express
- JWT authentication for admin endpoints
- CSP-compliant frontend (no inline handlers)
- Responsive Tailwind UI
This implements Phase 3 architecture as documented in planning docs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
174 lines
5.1 KiB
JavaScript
174 lines
5.1 KiB
JavaScript
/**
|
|
* Migration: Enhance Governance Rules Schema
|
|
* Adds multi-project governance fields to existing rules
|
|
*
|
|
* New fields:
|
|
* - scope (UNIVERSAL | PROJECT_SPECIFIC)
|
|
* - applicableProjects (array)
|
|
* - variables (array)
|
|
* - clarityScore, specificityScore, actionabilityScore
|
|
* - validationStatus, lastValidated, validationResults
|
|
* - usageStats
|
|
* - optimizationHistory
|
|
*/
|
|
|
|
const mongoose = require('mongoose');
|
|
const GovernanceRule = require('../../src/models/GovernanceRule.model');
|
|
|
|
// Database connection
|
|
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/tractatus_dev';
|
|
|
|
async function up() {
|
|
console.log('🔄 Starting migration: 001-enhance-governance-rules');
|
|
console.log(' Database:', MONGODB_URI);
|
|
|
|
try {
|
|
await mongoose.connect(MONGODB_URI);
|
|
console.log('✓ Connected to MongoDB');
|
|
|
|
// Get all existing rules (use lean() to get raw documents without schema defaults)
|
|
const rules = await GovernanceRule.find({}).lean();
|
|
console.log(`\n📊 Found ${rules.length} rules to migrate`);
|
|
|
|
let updatedCount = 0;
|
|
let skippedCount = 0;
|
|
|
|
for (const ruleDoc of rules) {
|
|
// Check if rule already has new fields in database (not just schema defaults)
|
|
if (ruleDoc.scope !== undefined && ruleDoc.scope !== null) {
|
|
console.log(` ⏩ Skipping ${ruleDoc.id} (already migrated)`);
|
|
skippedCount++;
|
|
continue;
|
|
}
|
|
|
|
// Load the rule with Mongoose model to apply schema methods
|
|
const rule = await GovernanceRule.findById(ruleDoc._id);
|
|
|
|
// Auto-detect variables in rule text (${VAR_NAME} pattern)
|
|
const variables = [];
|
|
const varPattern = /\$\{([A-Z_]+)\}/g;
|
|
let match;
|
|
while ((match = varPattern.exec(rule.text)) !== null) {
|
|
if (!variables.includes(match[1])) {
|
|
variables.push(match[1]);
|
|
}
|
|
}
|
|
|
|
// Determine scope based on variables
|
|
// If rule has variables, it's likely UNIVERSAL (will be customized per project)
|
|
// If no variables and rule mentions specific values, it's PROJECT_SPECIFIC
|
|
const hasVariables = variables.length > 0;
|
|
const scope = hasVariables ? 'UNIVERSAL' : 'PROJECT_SPECIFIC';
|
|
|
|
// Update rule with new fields
|
|
rule.scope = scope;
|
|
rule.applicableProjects = ['*']; // Apply to all projects by default
|
|
rule.variables = variables;
|
|
|
|
// Initialize AI optimization fields
|
|
rule.clarityScore = null; // Will be calculated by AI optimizer
|
|
rule.specificityScore = null;
|
|
rule.actionabilityScore = null;
|
|
rule.lastOptimized = null;
|
|
rule.optimizationHistory = [];
|
|
|
|
// Initialize validation fields
|
|
rule.validationStatus = 'NOT_VALIDATED';
|
|
rule.lastValidated = null;
|
|
rule.validationResults = null;
|
|
|
|
// Initialize usage stats
|
|
rule.usageStats = {
|
|
referencedInProjects: [],
|
|
timesEnforced: 0,
|
|
conflictsDetected: 0,
|
|
lastEnforced: null
|
|
};
|
|
|
|
await rule.save();
|
|
|
|
console.log(` ✓ ${rule.id}: ${scope} (${variables.length} variables)`);
|
|
updatedCount++;
|
|
}
|
|
|
|
console.log(`\n✅ Migration complete!`);
|
|
console.log(` Updated: ${updatedCount}`);
|
|
console.log(` Skipped: ${skippedCount}`);
|
|
console.log(` Total: ${rules.length}`);
|
|
|
|
// Create indexes for new fields
|
|
console.log('\n📊 Creating indexes for new fields...');
|
|
await GovernanceRule.createIndexes();
|
|
console.log(' ✓ Indexes created');
|
|
|
|
return { success: true, updated: updatedCount, skipped: skippedCount };
|
|
|
|
} catch (error) {
|
|
console.error('\n❌ Migration failed:', error);
|
|
throw error;
|
|
} finally {
|
|
await mongoose.disconnect();
|
|
console.log('\n✓ Disconnected from MongoDB');
|
|
}
|
|
}
|
|
|
|
async function down() {
|
|
console.log('🔄 Rolling back migration: 001-enhance-governance-rules');
|
|
|
|
try {
|
|
await mongoose.connect(MONGODB_URI);
|
|
console.log('✓ Connected to MongoDB');
|
|
|
|
// Remove new fields from all rules
|
|
const result = await GovernanceRule.updateMany(
|
|
{},
|
|
{
|
|
$unset: {
|
|
scope: '',
|
|
applicableProjects: '',
|
|
variables: '',
|
|
clarityScore: '',
|
|
specificityScore: '',
|
|
actionabilityScore: '',
|
|
lastOptimized: '',
|
|
optimizationHistory: '',
|
|
validationStatus: '',
|
|
lastValidated: '',
|
|
validationResults: '',
|
|
usageStats: ''
|
|
}
|
|
}
|
|
);
|
|
|
|
console.log(`✓ Rollback complete! Removed fields from ${result.modifiedCount} rules`);
|
|
|
|
return { success: true, modified: result.modifiedCount };
|
|
|
|
} catch (error) {
|
|
console.error('❌ Rollback failed:', error);
|
|
throw error;
|
|
} finally {
|
|
await mongoose.disconnect();
|
|
console.log('✓ Disconnected from MongoDB');
|
|
}
|
|
}
|
|
|
|
// CLI interface
|
|
if (require.main === module) {
|
|
const command = process.argv[2] || 'up';
|
|
|
|
if (command === 'up') {
|
|
up()
|
|
.then(() => process.exit(0))
|
|
.catch(() => process.exit(1));
|
|
} else if (command === 'down') {
|
|
down()
|
|
.then(() => process.exit(0))
|
|
.catch(() => process.exit(1));
|
|
} else {
|
|
console.error('Usage: node 001-enhance-governance-rules.js [up|down]');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
module.exports = { up, down };
|