import * as crypto from "node:crypto"; import { Decision, DecisionCategory, Alternative, confidenceToLevel } from "../types/decisions.js"; import { CIConfig } from "../types/config.js"; import { logDecision } from "./audit.js"; export interface DecisionInput { decision: string; rationale: string; confidence: number; category: DecisionCategory; alternatives_considered: Alternative[]; learnship_equivalent: string; phase?: string; task?: string; } export interface DecisionResult { decision: Decision; escalated: boolean; reason?: string; } export class DecisionEngine { private config: CIConfig; private projectPath: string; private currentPhase: number; private decisionCounter: number; constructor(config: CIConfig, projectPath: string) { this.config = config; this.projectPath = projectPath; this.currentPhase = 0; this.decisionCounter = 0; } setPhase(phase: number): void { this.currentPhase = phase; } makeDecision(input: DecisionInput): DecisionResult { const id = `D-${String(++this.decisionCounter).padStart(3, "0")}`; const threshold = this.config.autonomy.decision_confidence_threshold; const decision: Decision = { id, timestamp: new Date().toISOString(), decision: input.decision, rationale: input.rationale, confidence: input.confidence, category: input.category, alternatives_considered: input.alternatives_considered, learnship_equivalent: input.learnship_equivalent, human_override: null, phase: input.phase, task: input.task, }; logDecision(this.projectPath, this.currentPhase, decision); const confidenceLevel = confidenceToLevel(input.confidence); if (input.confidence < threshold) { return { decision, escalated: true, reason: `Confidence ${input.confidence.toFixed(2)} below threshold ${threshold} (${confidenceLevel})`, }; } return { decision, escalated: false }; } makeHighConfidenceDecision( decision: string, rationale: string, category: DecisionCategory, alternatives: Alternative[] = [], learnship_equivalent: string = "" ): DecisionResult { return this.makeDecision({ decision, rationale, confidence: 0.95, category, alternatives_considered: alternatives, learnship_equivalent, }); } makeMediumConfidenceDecision( decision: string, rationale: string, category: DecisionCategory, alternatives: Alternative[] = [], learnship_equivalent: string = "" ): DecisionResult { return this.makeDecision({ decision, rationale, confidence: 0.7, category, alternatives_considered: alternatives, learnship_equivalent, }); } shouldAutoDecide(confidence: number): boolean { return confidence >= this.config.autonomy.decision_confidence_threshold; } isIrreversibleAction(action: string): boolean { return this.config.autonomy.escalation_hooks.some((hook) => action.toLowerCase().includes(hook.toLowerCase()) ); } }