tasq/node_modules/@claude-flow/guidance/dist/meta-governance.js

348 lines
12 KiB
JavaScript

/**
* @fileoverview Meta-Governance Module
*
* Provides constitutional governance over the governance system itself.
* Manages invariants, amendments, and optimizer constraints to prevent
* governance drift and ensure constitutional stability.
*
* Features:
* - Constitutional invariants with severity levels
* - Amendment proposal and voting system
* - Optimizer action validation
* - Rate limiting and supermajority requirements
* - Built-in constitutional protections
*
* Core capabilities:
* - Constitutional invariant checking
* - Amendment lifecycle (propose → vote → resolve → enact)
* - Optimizer constraint enforcement
* - Supermajority voting
* - Emergency veto power
* - Immutability protection
*
* @module @claude-flow/guidance/meta-governance
* @author Claude Flow Team
*/
import { randomUUID } from 'node:crypto';
/**
* Meta-Governor: Governs the governance system itself
*
* Enforces constitutional invariants, manages amendments,
* and constrains optimizer behavior to prevent governance drift.
*/
export class MetaGovernor {
invariants = new Map();
amendments = new Map();
amendmentHistory = [];
optimizerConstraints;
lastOptimizerAction = 0;
optimizerActionsThisCycle = new Map();
supermajorityThreshold;
maxAmendmentsPerWindow;
amendmentWindowMs;
signingKey;
constructor(config = {}) {
this.supermajorityThreshold = config.supermajorityThreshold ?? 0.75;
this.maxAmendmentsPerWindow = config.maxAmendmentsPerWindow ?? 3;
this.amendmentWindowMs = config.amendmentWindowMs ?? 24 * 60 * 60 * 1000; // 24 hours
this.signingKey = config.signingKey;
// Initialize optimizer constraints with defaults
this.optimizerConstraints = {
id: 'default-optimizer-constraints',
name: 'Default Optimizer Constraints',
description: 'Default constraints on optimizer behavior',
maxDriftPerCycle: 0.1, // 10% change max
maxPromotionRate: 2,
maxDemotionRate: 1,
cooldownMs: 3600000, // 1 hour
...config.optimizerConstraints,
};
// Add built-in invariants
this.addBuiltInInvariants();
}
/**
* Add built-in constitutional invariants
*/
addBuiltInInvariants() {
// 1. Constitution size limit
this.addInvariant({
id: 'constitution-size-limit',
name: 'Constitution Size Limit',
description: 'Constitution must not exceed 60 lines',
severity: 'critical',
immutable: true,
check: (state) => {
const holds = state.constitutionSize <= 60;
return {
holds,
violation: holds ? undefined : `Constitution size ${state.constitutionSize} exceeds limit of 60 lines`,
details: { constitutionSize: state.constitutionSize, limit: 60 },
};
},
});
// 2. Gate minimum
this.addInvariant({
id: 'gate-minimum',
name: 'Minimum Gate Count',
description: 'At least 4 gates must be active',
severity: 'critical',
immutable: true,
check: (state) => {
const holds = state.gateCount >= 4;
return {
holds,
violation: holds ? undefined : `Gate count ${state.gateCount} is below minimum of 4`,
details: { gateCount: state.gateCount, minimum: 4 },
};
},
});
// 3. Rule count sanity
this.addInvariant({
id: 'rule-count-sanity',
name: 'Rule Count Sanity Check',
description: 'Total rules should not exceed 1000',
severity: 'warning',
immutable: false,
check: (state) => {
const holds = state.ruleCount <= 1000;
return {
holds,
violation: holds ? undefined : `Rule count ${state.ruleCount} exceeds recommended limit of 1000`,
details: { ruleCount: state.ruleCount, recommendedLimit: 1000 },
};
},
});
// 4. Optimizer bounds
this.addInvariant({
id: 'optimizer-bounds',
name: 'Optimizer Drift Bounds',
description: 'Optimizer must operate within reasonable drift bounds',
severity: 'warning',
immutable: false,
check: (state) => {
if (!state.optimizerEnabled) {
return { holds: true, details: { optimizerEnabled: false } };
}
const reasonableDrift = this.optimizerConstraints.maxDriftPerCycle <= 0.2;
return {
holds: reasonableDrift,
violation: reasonableDrift ? undefined : `Optimizer drift ${this.optimizerConstraints.maxDriftPerCycle} exceeds reasonable bounds`,
details: { maxDrift: this.optimizerConstraints.maxDriftPerCycle, reasonableLimit: 0.2 },
};
},
});
}
/**
* Add a constitutional invariant
*/
addInvariant(invariant) {
this.invariants.set(invariant.id, invariant);
}
/**
* Remove an invariant (only if not immutable)
*/
removeInvariant(id) {
const invariant = this.invariants.get(id);
if (!invariant) {
return false;
}
if (invariant.immutable) {
throw new Error(`Cannot remove immutable invariant: ${id}`);
}
return this.invariants.delete(id);
}
/**
* Check all constitutional invariants against current state
*/
checkAllInvariants(state) {
const results = [];
let allHold = true;
for (const invariant of this.invariants.values()) {
const result = invariant.check(state);
results.push({ invariant, result });
if (!result.holds) {
allHold = false;
}
}
return {
allHold,
results,
timestamp: Date.now(),
};
}
/**
* Propose a new amendment
*/
proposeAmendment(proposal) {
// Check rate limiting
const now = Date.now();
const recentAmendments = this.amendmentHistory.filter((a) => now - a.timestamp < this.amendmentWindowMs);
if (recentAmendments.length >= this.maxAmendmentsPerWindow) {
throw new Error(`Amendment rate limit exceeded: ${this.maxAmendmentsPerWindow} per ${this.amendmentWindowMs}ms`);
}
const amendment = {
id: randomUUID(),
timestamp: now,
status: 'proposed',
votes: new Map(),
...proposal,
};
this.amendments.set(amendment.id, amendment);
return amendment;
}
/**
* Vote on an amendment
*/
voteOnAmendment(amendmentId, voterId, approve) {
const amendment = this.amendments.get(amendmentId);
if (!amendment) {
throw new Error(`Amendment not found: ${amendmentId}`);
}
if (amendment.status !== 'proposed') {
throw new Error(`Cannot vote on amendment with status: ${amendment.status}`);
}
amendment.votes.set(voterId, approve);
}
/**
* Resolve an amendment (check if supermajority reached)
*/
resolveAmendment(amendmentId) {
const amendment = this.amendments.get(amendmentId);
if (!amendment) {
throw new Error(`Amendment not found: ${amendmentId}`);
}
if (amendment.status !== 'proposed') {
throw new Error(`Amendment already resolved: ${amendment.status}`);
}
const totalVotes = amendment.votes.size;
const approvals = Array.from(amendment.votes.values()).filter((v) => v).length;
const approvalRate = totalVotes > 0 ? approvals / totalVotes : 0;
if (approvalRate >= this.supermajorityThreshold && approvals >= amendment.requiredApprovals) {
amendment.status = 'approved';
}
else {
amendment.status = 'rejected';
}
return amendment;
}
/**
* Enact an approved amendment
* Returns true if enacted successfully
*/
enactAmendment(amendmentId) {
const amendment = this.amendments.get(amendmentId);
if (!amendment) {
throw new Error(`Amendment not found: ${amendmentId}`);
}
if (amendment.status !== 'approved') {
throw new Error(`Cannot enact amendment with status: ${amendment.status}`);
}
// Check if any changes would violate immutable invariants
for (const change of amendment.changes) {
if (change.type === 'remove-rule' || change.type === 'modify-rule') {
const invariant = this.invariants.get(change.target);
if (invariant?.immutable) {
throw new Error(`Cannot modify immutable invariant: ${change.target}`);
}
}
}
amendment.status = 'enacted';
this.amendmentHistory.push(amendment);
this.amendments.delete(amendmentId);
return true;
}
/**
* Emergency veto of an amendment
*/
vetoAmendment(amendmentId, reason) {
const amendment = this.amendments.get(amendmentId);
if (!amendment) {
throw new Error(`Amendment not found: ${amendmentId}`);
}
amendment.status = 'vetoed';
amendment.metadata = {
...amendment.metadata,
vetoReason: reason,
vetoedAt: Date.now(),
};
this.amendmentHistory.push(amendment);
this.amendments.delete(amendmentId);
}
/**
* Get full amendment history
*/
getAmendmentHistory() {
return [...this.amendmentHistory];
}
/**
* Validate an optimizer action against constraints
*/
validateOptimizerAction(action) {
const violations = [];
const now = Date.now();
// Check cooldown
if (now - this.lastOptimizerAction < this.optimizerConstraints.cooldownMs) {
violations.push(`Cooldown not met: ${now - this.lastOptimizerAction}ms < ${this.optimizerConstraints.cooldownMs}ms`);
}
// Track actions this cycle
const cycleKey = `${action.type}-${action.targetRuleId}`;
const actionsThisCycle = this.optimizerActionsThisCycle.get(cycleKey) ?? 0;
// Check promotion rate
if (action.type === 'promote') {
if (actionsThisCycle >= this.optimizerConstraints.maxPromotionRate) {
violations.push(`Promotion rate exceeded: ${actionsThisCycle} >= ${this.optimizerConstraints.maxPromotionRate}`);
}
}
// Check demotion rate
if (action.type === 'demote') {
if (actionsThisCycle >= this.optimizerConstraints.maxDemotionRate) {
violations.push(`Demotion rate exceeded: ${actionsThisCycle} >= ${this.optimizerConstraints.maxDemotionRate}`);
}
}
// Check drift magnitude
if (action.magnitude > this.optimizerConstraints.maxDriftPerCycle) {
violations.push(`Drift magnitude ${action.magnitude} exceeds limit ${this.optimizerConstraints.maxDriftPerCycle}`);
}
const allowed = violations.length === 0;
if (allowed) {
this.lastOptimizerAction = now;
this.optimizerActionsThisCycle.set(cycleKey, actionsThisCycle + 1);
}
return {
allowed,
reason: allowed ? 'Action permitted' : `Constraint violations: ${violations.join(', ')}`,
constraintViolations: violations,
};
}
/**
* Get current optimizer constraints
*/
getConstraints() {
return { ...this.optimizerConstraints };
}
/**
* Reset optimizer action tracking (call at cycle boundaries)
*/
resetOptimizerTracking() {
this.optimizerActionsThisCycle.clear();
}
/**
* Get all invariants
*/
getInvariants() {
return Array.from(this.invariants.values());
}
/**
* Get pending amendments
*/
getPendingAmendments() {
return Array.from(this.amendments.values()).filter((a) => a.status === 'proposed');
}
}
/**
* Factory function to create a MetaGovernor instance
*/
export function createMetaGovernor(config) {
return new MetaGovernor(config);
}
//# sourceMappingURL=meta-governance.js.map