import fs from 'fs/promises'; import path from 'path'; import chalk from 'chalk'; // --- Types --- export enum InterventionLevel { GHOST = 0, // Log only, silent NUDGE = 1, // Warn on commit/complete SENTINEL = 2 // Immediate SOFT_LOCK } export type LockStatus = 'OPEN' | 'SOFT_LOCK'; export interface GovernanceConfig { governance: { intervention_level: InterventionLevel; allow_overrides: boolean; }; } export interface SessionState { status: LockStatus; active_violation?: string | null; lock_reason?: string | null; last_updated: string; } const DEFAULT_CONFIG: GovernanceConfig = { governance: { intervention_level: InterventionLevel.GHOST, allow_overrides: true } }; const DEFAULT_SESSION: SessionState = { status: 'OPEN', active_violation: null, lock_reason: null, last_updated: new Date().toISOString() }; // --- Config Management --- export async function getGovernanceConfig(rootDir: string = process.cwd()): Promise { try { const configPath = path.join(rootDir, 'rigstate.config.json'); const content = await fs.readFile(configPath, 'utf-8'); const userConfig = JSON.parse(content); return { governance: { ...DEFAULT_CONFIG.governance, ...userConfig.governance } }; } catch (e) { return DEFAULT_CONFIG; } } // --- Session State Management --- export async function getSessionState(rootDir: string = process.cwd()): Promise { try { const sessionPath = path.join(rootDir, '.rigstate', 'session.json'); const content = await fs.readFile(sessionPath, 'utf-8'); return JSON.parse(content); } catch (e) { return DEFAULT_SESSION; } } export async function setSoftLock( reason: string, violationId: string, rootDir: string = process.cwd() ): Promise { const sessionPath = path.join(rootDir, '.rigstate', 'session.json'); const state: SessionState = { status: 'SOFT_LOCK', active_violation: violationId, lock_reason: reason, last_updated: new Date().toISOString() }; await fs.mkdir(path.dirname(sessionPath), { recursive: true }); await fs.writeFile(sessionPath, JSON.stringify(state, null, 2), 'utf-8'); } export async function clearSoftLock( rootDir: string = process.cwd() ): Promise { const sessionPath = path.join(rootDir, '.rigstate', 'session.json'); const state: SessionState = { ...DEFAULT_SESSION, last_updated: new Date().toISOString() }; await fs.mkdir(path.dirname(sessionPath), { recursive: true }); await fs.writeFile(sessionPath, JSON.stringify(state, null, 2), 'utf-8'); } /** * Checks if the user is authorized to perform an override * (For now, assumes CLI user is authorized, but logs it) */ export async function performOverride( violationId: string, reason: string, rootDir: string = process.cwd() ): Promise { const config = await getGovernanceConfig(rootDir); if (!config.governance.allow_overrides) { console.log(chalk.red('❌ Overrides are disabled for this project.')); return false; } // Security violations (SEC-*) cannot be overridden via CLI usually, // but the implementation here depends on how we define "Security". // For now, we allow overriding via this function, but the *Caller* should check violation type. await clearSoftLock(rootDir); // TODO: Add to Mission Report (Audit Log) // We will handle logging in the command handler itself return true; }