- GovernanceRule: Remove duplicate category index (uses compound index) - VerificationLog: Remove duplicate verifiedAt index (uses compound + TTL) - VariableValue: Remove duplicate category index (standalone index exists) Eliminates 3 Mongoose duplicate index warnings on server startup Server now starts with zero warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
518 lines
12 KiB
JavaScript
518 lines
12 KiB
JavaScript
/**
|
|
* GovernanceRule Model
|
|
*
|
|
* Stores Tractatus governance instructions (inst_001, inst_016, etc.)
|
|
* Replaces filesystem-based .claude/instruction-history.json
|
|
*
|
|
* Benefits over filesystem:
|
|
* - Fast indexed queries by ID, quadrant, persistence
|
|
* - Atomic updates (no race conditions)
|
|
* - Aggregation for analytics
|
|
* - Built-in replication/backup
|
|
* - Transaction support
|
|
*/
|
|
|
|
const mongoose = require('mongoose');
|
|
|
|
const governanceRuleSchema = new mongoose.Schema({
|
|
// Rule identification
|
|
id: {
|
|
type: String,
|
|
required: true,
|
|
unique: true,
|
|
index: true,
|
|
description: 'Unique rule identifier (e.g., inst_016, inst_017)'
|
|
},
|
|
|
|
// Rule content
|
|
text: {
|
|
type: String,
|
|
required: true,
|
|
description: 'The governance instruction text'
|
|
},
|
|
|
|
// Multi-project governance fields
|
|
scope: {
|
|
type: String,
|
|
enum: ['UNIVERSAL', 'PROJECT_SPECIFIC'],
|
|
default: 'PROJECT_SPECIFIC',
|
|
index: true,
|
|
description: 'Whether this rule applies universally or to specific projects'
|
|
},
|
|
|
|
applicableProjects: {
|
|
type: [String],
|
|
default: ['*'],
|
|
description: 'Project IDs this rule applies to (* = all projects)'
|
|
},
|
|
|
|
variables: {
|
|
type: [String],
|
|
default: [],
|
|
description: 'Variable names used in rule text (e.g., ["DB_TYPE", "DB_PORT"])'
|
|
},
|
|
|
|
// Classification
|
|
quadrant: {
|
|
type: String,
|
|
required: true,
|
|
enum: ['STRATEGIC', 'OPERATIONAL', 'TACTICAL', 'SYSTEM', 'STORAGE'],
|
|
index: true,
|
|
description: 'Tractatus quadrant classification'
|
|
},
|
|
|
|
persistence: {
|
|
type: String,
|
|
required: true,
|
|
enum: ['HIGH', 'MEDIUM', 'LOW'],
|
|
index: true,
|
|
description: 'Persistence level - how long this rule remains active'
|
|
},
|
|
|
|
// Metadata
|
|
category: {
|
|
type: String,
|
|
enum: ['content', 'security', 'privacy', 'technical', 'process', 'values', 'other'],
|
|
default: 'other',
|
|
// Note: Indexed via compound index { category: 1, active: 1 } below
|
|
description: 'Category for filtering and organization'
|
|
},
|
|
|
|
priority: {
|
|
type: Number,
|
|
default: 50,
|
|
min: 0,
|
|
max: 100,
|
|
description: 'Priority level (100 = highest, 0 = lowest)'
|
|
},
|
|
|
|
// Temporal scope
|
|
temporalScope: {
|
|
type: String,
|
|
enum: ['IMMEDIATE', 'SESSION', 'PROJECT', 'PERMANENT'],
|
|
default: 'PERMANENT',
|
|
description: 'How long this rule applies (IMMEDIATE = one-time, SESSION = this conversation, PROJECT = this project, PERMANENT = always)'
|
|
},
|
|
|
|
expiresAt: {
|
|
type: Date,
|
|
default: null,
|
|
description: 'When this rule expires (null = never)'
|
|
},
|
|
|
|
// AI Optimization Scores
|
|
clarityScore: {
|
|
type: Number,
|
|
default: null,
|
|
min: 0,
|
|
max: 100,
|
|
description: 'AI-calculated clarity score (0-100)'
|
|
},
|
|
|
|
specificityScore: {
|
|
type: Number,
|
|
default: null,
|
|
min: 0,
|
|
max: 100,
|
|
description: 'AI-calculated specificity score (0-100)'
|
|
},
|
|
|
|
actionabilityScore: {
|
|
type: Number,
|
|
default: null,
|
|
min: 0,
|
|
max: 100,
|
|
description: 'AI-calculated actionability score (0-100)'
|
|
},
|
|
|
|
lastOptimized: {
|
|
type: Date,
|
|
default: null,
|
|
description: 'When this rule was last optimized'
|
|
},
|
|
|
|
optimizationHistory: {
|
|
type: [{
|
|
timestamp: Date,
|
|
before: String,
|
|
after: String,
|
|
reason: String,
|
|
scores: {
|
|
clarity: Number,
|
|
specificity: Number,
|
|
actionability: Number
|
|
}
|
|
}],
|
|
default: [],
|
|
description: 'History of AI-driven optimizations'
|
|
},
|
|
|
|
// Validation Results
|
|
validationStatus: {
|
|
type: String,
|
|
enum: ['PASSED', 'FAILED', 'NEEDS_REVIEW', 'NOT_VALIDATED'],
|
|
default: 'NOT_VALIDATED',
|
|
description: 'Result of last validation against framework'
|
|
},
|
|
|
|
lastValidated: {
|
|
type: Date,
|
|
default: null,
|
|
description: 'When this rule was last validated'
|
|
},
|
|
|
|
validationResults: {
|
|
type: {
|
|
classification: {
|
|
passed: Boolean,
|
|
expected: Object,
|
|
actual: Object
|
|
},
|
|
parameterExtraction: {
|
|
passed: Boolean,
|
|
params: Object
|
|
},
|
|
conflictDetection: {
|
|
passed: Boolean,
|
|
conflicts: [String]
|
|
},
|
|
boundaryCheck: {
|
|
passed: Boolean,
|
|
allowed: Boolean
|
|
},
|
|
overallScore: Number
|
|
},
|
|
default: null,
|
|
description: 'Detailed validation test results'
|
|
},
|
|
|
|
// Usage Statistics
|
|
usageStats: {
|
|
type: {
|
|
referencedInProjects: {
|
|
type: [String],
|
|
default: []
|
|
},
|
|
timesEnforced: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
conflictsDetected: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
lastEnforced: {
|
|
type: Date,
|
|
default: null
|
|
}
|
|
},
|
|
default: () => ({
|
|
referencedInProjects: [],
|
|
timesEnforced: 0,
|
|
conflictsDetected: 0,
|
|
lastEnforced: null
|
|
}),
|
|
description: 'Statistics about rule usage across projects'
|
|
},
|
|
|
|
// Status
|
|
active: {
|
|
type: Boolean,
|
|
default: true,
|
|
index: true,
|
|
description: 'Whether this rule is currently enforced'
|
|
},
|
|
|
|
// Source tracking
|
|
source: {
|
|
type: String,
|
|
enum: ['user_instruction', 'framework_default', 'automated', 'migration', 'claude_md_migration', 'test'],
|
|
default: 'framework_default',
|
|
description: 'How this rule was created'
|
|
},
|
|
|
|
createdBy: {
|
|
type: String,
|
|
default: 'system',
|
|
description: 'Who created this rule'
|
|
},
|
|
|
|
// Enforcement statistics
|
|
stats: {
|
|
timesChecked: {
|
|
type: Number,
|
|
default: 0,
|
|
description: 'How many times this rule has been evaluated'
|
|
},
|
|
timesViolated: {
|
|
type: Number,
|
|
default: 0,
|
|
description: 'How many times this rule was violated'
|
|
},
|
|
lastChecked: {
|
|
type: Date,
|
|
default: null,
|
|
description: 'When this rule was last evaluated'
|
|
},
|
|
lastViolated: {
|
|
type: Date,
|
|
default: null,
|
|
description: 'When this rule was last violated'
|
|
}
|
|
},
|
|
|
|
// Additional context
|
|
examples: {
|
|
type: [String],
|
|
default: [],
|
|
description: 'Example scenarios where this rule applies'
|
|
},
|
|
|
|
relatedRules: {
|
|
type: [String],
|
|
default: [],
|
|
description: 'IDs of related rules (e.g., inst_016 relates to inst_017)'
|
|
},
|
|
|
|
notes: {
|
|
type: String,
|
|
default: '',
|
|
description: 'Additional notes or clarifications'
|
|
}
|
|
|
|
}, {
|
|
timestamps: true, // Adds createdAt and updatedAt automatically
|
|
collection: 'governanceRules'
|
|
});
|
|
|
|
// Indexes for common queries
|
|
governanceRuleSchema.index({ quadrant: 1, persistence: 1 });
|
|
governanceRuleSchema.index({ active: 1, priority: -1 });
|
|
governanceRuleSchema.index({ category: 1, active: 1 });
|
|
governanceRuleSchema.index({ expiresAt: 1 }, { sparse: true }); // Sparse index for expiry queries
|
|
|
|
// Multi-project governance indexes
|
|
governanceRuleSchema.index({ scope: 1, active: 1 });
|
|
governanceRuleSchema.index({ validationStatus: 1, active: 1 });
|
|
governanceRuleSchema.index({ clarityScore: -1 }, { sparse: true }); // Descending, for sorting by quality
|
|
governanceRuleSchema.index({ 'applicableProjects': 1 }); // For project-specific filtering
|
|
|
|
// Virtual for checking if rule is expired
|
|
governanceRuleSchema.virtual('isExpired').get(function() {
|
|
if (!this.expiresAt) return false;
|
|
return new Date() > this.expiresAt;
|
|
});
|
|
|
|
// Static methods
|
|
|
|
/**
|
|
* Find all active rules
|
|
*/
|
|
governanceRuleSchema.statics.findActive = function(options = {}) {
|
|
const query = { active: true };
|
|
|
|
// Filter out expired rules
|
|
query.$or = [
|
|
{ expiresAt: null },
|
|
{ expiresAt: { $gt: new Date() } }
|
|
];
|
|
|
|
return this.find(query)
|
|
.sort({ priority: -1, id: 1 })
|
|
.limit(options.limit || 0);
|
|
};
|
|
|
|
/**
|
|
* Find rules by quadrant
|
|
*/
|
|
governanceRuleSchema.statics.findByQuadrant = function(quadrant, activeOnly = true) {
|
|
const query = { quadrant };
|
|
|
|
if (activeOnly) {
|
|
query.active = true;
|
|
query.$or = [
|
|
{ expiresAt: null },
|
|
{ expiresAt: { $gt: new Date() } }
|
|
];
|
|
}
|
|
|
|
return this.find(query).sort({ priority: -1, id: 1 });
|
|
};
|
|
|
|
/**
|
|
* Find rules by persistence level
|
|
*/
|
|
governanceRuleSchema.statics.findByPersistence = function(persistence, activeOnly = true) {
|
|
const query = { persistence };
|
|
|
|
if (activeOnly) {
|
|
query.active = true;
|
|
query.$or = [
|
|
{ expiresAt: null },
|
|
{ expiresAt: { $gt: new Date() } }
|
|
];
|
|
}
|
|
|
|
return this.find(query).sort({ priority: -1, id: 1 });
|
|
};
|
|
|
|
/**
|
|
* Find universal rules (apply to all projects)
|
|
*/
|
|
governanceRuleSchema.statics.findUniversal = function(activeOnly = true) {
|
|
const query = { scope: 'UNIVERSAL' };
|
|
|
|
if (activeOnly) {
|
|
query.active = true;
|
|
query.$or = [
|
|
{ expiresAt: null },
|
|
{ expiresAt: { $gt: new Date() } }
|
|
];
|
|
}
|
|
|
|
return this.find(query).sort({ priority: -1, id: 1 });
|
|
};
|
|
|
|
/**
|
|
* Find rules by scope
|
|
*/
|
|
governanceRuleSchema.statics.findByScope = function(scope, activeOnly = true) {
|
|
const query = { scope };
|
|
|
|
if (activeOnly) {
|
|
query.active = true;
|
|
query.$or = [
|
|
{ expiresAt: null },
|
|
{ expiresAt: { $gt: new Date() } }
|
|
];
|
|
}
|
|
|
|
return this.find(query).sort({ priority: -1, id: 1 });
|
|
};
|
|
|
|
/**
|
|
* Find rules applicable to a specific project
|
|
*/
|
|
governanceRuleSchema.statics.findByProject = function(projectId, activeOnly = true) {
|
|
const query = {
|
|
$or: [
|
|
{ scope: 'UNIVERSAL' },
|
|
{ applicableProjects: projectId },
|
|
{ applicableProjects: '*' }
|
|
]
|
|
};
|
|
|
|
if (activeOnly) {
|
|
query.active = true;
|
|
query.$and = [
|
|
{
|
|
$or: [
|
|
{ expiresAt: null },
|
|
{ expiresAt: { $gt: new Date() } }
|
|
]
|
|
}
|
|
];
|
|
}
|
|
|
|
return this.find(query).sort({ priority: -1, id: 1 });
|
|
};
|
|
|
|
/**
|
|
* Find rule by ID
|
|
*/
|
|
governanceRuleSchema.statics.findByRuleId = function(ruleId) {
|
|
return this.findOne({ id: ruleId, active: true });
|
|
};
|
|
|
|
/**
|
|
* Get rule statistics summary (enhanced for multi-project)
|
|
*/
|
|
governanceRuleSchema.statics.getStatistics = async function() {
|
|
const stats = await this.aggregate([
|
|
{ $match: { active: true } },
|
|
{
|
|
$group: {
|
|
_id: null,
|
|
totalRules: { $sum: 1 },
|
|
byQuadrant: {
|
|
$push: {
|
|
quadrant: '$quadrant',
|
|
count: 1
|
|
}
|
|
},
|
|
byPersistence: {
|
|
$push: {
|
|
persistence: '$persistence',
|
|
count: 1
|
|
}
|
|
},
|
|
byScope: {
|
|
$push: {
|
|
scope: '$scope',
|
|
count: 1
|
|
}
|
|
},
|
|
byValidationStatus: {
|
|
$push: {
|
|
status: '$validationStatus',
|
|
count: 1
|
|
}
|
|
},
|
|
avgClarityScore: { $avg: '$clarityScore' },
|
|
avgSpecificityScore: { $avg: '$specificityScore' },
|
|
avgActionabilityScore: { $avg: '$actionabilityScore' },
|
|
totalChecks: { $sum: '$stats.timesChecked' },
|
|
totalViolations: { $sum: '$stats.timesViolated' }
|
|
}
|
|
}
|
|
]);
|
|
|
|
return stats[0] || null;
|
|
};
|
|
|
|
/**
|
|
* Increment check counter
|
|
*/
|
|
governanceRuleSchema.methods.incrementChecked = async function() {
|
|
this.stats.timesChecked += 1;
|
|
this.stats.lastChecked = new Date();
|
|
return this.save();
|
|
};
|
|
|
|
/**
|
|
* Increment violation counter
|
|
*/
|
|
governanceRuleSchema.methods.incrementViolated = async function() {
|
|
this.stats.timesViolated += 1;
|
|
this.stats.lastViolated = new Date();
|
|
return this.save();
|
|
};
|
|
|
|
/**
|
|
* Deactivate rule (soft delete)
|
|
*/
|
|
governanceRuleSchema.methods.deactivate = async function() {
|
|
this.active = false;
|
|
return this.save();
|
|
};
|
|
|
|
/**
|
|
* Activate rule
|
|
*/
|
|
governanceRuleSchema.methods.activate = async function() {
|
|
this.active = true;
|
|
return this.save();
|
|
};
|
|
|
|
// Pre-save hook to validate expiration
|
|
governanceRuleSchema.pre('save', function(next) {
|
|
// If expiresAt is in the past, deactivate the rule
|
|
if (this.expiresAt && this.expiresAt < new Date()) {
|
|
this.active = false;
|
|
}
|
|
next();
|
|
});
|
|
|
|
const GovernanceRule = mongoose.model('GovernanceRule', governanceRuleSchema);
|
|
|
|
module.exports = GovernanceRule;
|