/* evolution controller — drive evolution stages through their guards and reducers. Do not evaluate guards inline — the controller delegates to guards.ts. RFC-1097: sweep — werkstatt-engine clean Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics. */ import type { Sha256Digest } from "@warpgogol/werkstatt-shared/fingerprint"; import type { CapabilityCandidateV1, TransitionRequestV1, TransitionRecordV1, InspectionSnapshotV1, BoundedIntentV1, KillSwitchStateV1, EvolutionStage, CandidateEvidenceV1, } from "./contracts.ts"; import { createEvolutionReducerState, applyTransition, registerCandidate, activateKillSwitch, type ReducerStateV1, type TransitionOutcomeV1, } from "./reducer.ts"; import { checkSelfChangeBoundary, runAllGuards, type GuardResultV1 } from "./guards.ts"; import { createShadowExecutor, type ShadowExecutor } from "./shadow-executor.ts"; import { createHealthMonitor, type HealthMonitor } from "./health-monitor.ts"; export interface EvolutionControllerV1 { inspect(snapshot: InspectionSnapshotV1): InspectionOutcomeV1; defineCandidate( snapshot: InspectionSnapshotV1, intent: BoundedIntentV1, artifactHash: Sha256Digest, parentArtifactHash: Sha256Digest, policyHash: Sha256Digest, componentId: string, version: string, replacesComponentId: string, allowAgentWritten?: boolean, ): DefineCandidateOutcomeV1; requestTransition(request: TransitionRequestV1, timestamp: string): TransitionOutcomeV1; activateKillSwitch(reason: string, timestamp: string): void; getCandidate(candidateId: string): CapabilityCandidateV1 | null; getCandidateHistory(candidateId: string): readonly TransitionRecordV1[]; getKillSwitchState(): KillSwitchStateV1; getAllTransitions(): readonly TransitionRecordV1[]; shadow(candidateId: string, comparisonMetric: string): Promise; test(candidateId: string, scenariosPath: string): Promise; canary(candidateId: string, trafficPercent: number): Promise; activate(candidateId: string): Promise; promote(candidateId: string, missionId: string): Promise; rollback(componentId: string): Promise; quarantine(candidateId: string, reason: string): Promise; inspectAll(): readonly CapabilityCandidateV1[]; } export interface InspectionResultV1 { ok: true; snapshot: InspectionSnapshotV1; observations: readonly string[]; } export interface InspectionFailureV1 { ok: false; ruleId: string; message: string; } export type InspectionOutcomeV1 = InspectionResultV1 | InspectionFailureV1; export interface DefineCandidateResultV1 { ok: true; candidate: CapabilityCandidateV1; } export interface DefineCandidateFailureV1 { ok: false; ruleId: string; message: string; } export type DefineCandidateOutcomeV1 = DefineCandidateResultV1 | DefineCandidateFailureV1; export function createEvolutionController( maxCanaryDuration: number = 3600, minSampleSize: number = 100, quarantineThreshold: number = 3, ): EvolutionControllerV1 { const state: ReducerStateV1 = createEvolutionReducerState(); let killSwitch: KillSwitchStateV1 = { active: false, reason: "", activatedAt: "", }; const shadowExecutor: ShadowExecutor = createShadowExecutor(); const healthMonitor: HealthMonitor = createHealthMonitor(quarantineThreshold); return { inspect(snapshot: InspectionSnapshotV1): InspectionOutcomeV1 { const observations: string[] = []; if (snapshot.activeIncidents.some((i) => i.severity === "critical")) { observations.push("critical incidents detected — consider kill switch"); } if (snapshot.observedMetrics.some((m) => !m.passed)) { observations.push("some metrics failing — investigate before defining new candidate"); } return { ok: true, snapshot, observations }; }, defineCandidate( snapshot: InspectionSnapshotV1, intent: BoundedIntentV1, artifactHash: Sha256Digest, parentArtifactHash: Sha256Digest, policyHash: Sha256Digest, componentId: string, version: string, replacesComponentId: string, allowAgentWritten: boolean = false, ): DefineCandidateOutcomeV1 { const boundaryCheck = checkSelfChangeBoundary(intent); if (!boundaryCheck.ok) { return { ok: false, ruleId: boundaryCheck.ruleId, message: boundaryCheck.message, }; } if (!allowAgentWritten && intent.scope.includes("agent-authored")) { return { ok: false, ruleId: "EVOLUTION-01", message: "agent-written candidates require --allow-agent-written flag", }; } const candidateId = `${componentId}@${version}`; const candidate: CapabilityCandidateV1 = { schema: "werkstatt/capability-candidate@1", candidateId, componentId, version, parentArtifactHash, artifactHash, intentHash: intent.intentHash, policyHash, stage: "defined" as EvolutionStage, replacesComponentId, canaryTrafficPercent: 0, }; const result = registerCandidate(state, candidate); if (!result.ok) { return { ok: false, ruleId: (result as { ruleId: string }).ruleId, message: (result as { message: string }).message, }; } return { ok: true, candidate }; }, requestTransition(request: TransitionRequestV1, timestamp: string): TransitionOutcomeV1 { const candidate = state.candidates.get(request.candidateId); if (!candidate) { return { ok: false, ruleId: "CERT-EVO-02", message: `candidate "${request.candidateId}" not found`, }; } const guardResult: GuardResultV1 = runAllGuards( candidate, request, killSwitch, timestamp, maxCanaryDuration, minSampleSize, ); if (!guardResult.ok) { return { ok: false, ruleId: guardResult.ruleId, message: guardResult.message, }; } return applyTransition(state, request, timestamp); }, activateKillSwitch(reason: string, timestamp: string): void { killSwitch = { active: true, reason, activatedAt: timestamp, }; activateKillSwitch(state, reason, timestamp); }, getCandidate(candidateId: string): CapabilityCandidateV1 | null { return state.candidates.get(candidateId) ?? null; }, getCandidateHistory(candidateId: string): readonly TransitionRecordV1[] { return state.transitions.filter((t) => t.candidateId === candidateId); }, getKillSwitchState(): KillSwitchStateV1 { return killSwitch; }, getAllTransitions(): readonly TransitionRecordV1[] { return [...state.transitions]; }, async shadow(candidateId: string, comparisonMetric: string): Promise { const candidate = state.candidates.get(candidateId); if (!candidate) { throw new Error(`candidate "${candidateId}" not found`); } return shadowExecutor.execute( candidateId, comparisonMetric, (input: unknown) => input, (input: unknown) => input, { candidateId, comparisonMetric }, ); }, async test(candidateId: string, _scenariosPath: string): Promise { const candidate = state.candidates.get(candidateId); if (!candidate) { throw new Error(`candidate "${candidateId}" not found`); } throw new Error( `evolution.candidate.test not implemented: scenario loading from "${_scenariosPath}" is not yet wired`, ); }, async canary(candidateId: string, trafficPercent: number): Promise { const candidate = state.candidates.get(candidateId); if (!candidate) { throw new Error(`candidate "${candidateId}" not found`); } const updated: CapabilityCandidateV1 = { ...candidate, canaryTrafficPercent: trafficPercent, }; state.candidates.set(candidateId, updated); }, async activate(candidateId: string): Promise { const candidate = state.candidates.get(candidateId); if (!candidate) { throw new Error(`candidate "${candidateId}" not found`); } const updated: CapabilityCandidateV1 = { ...candidate, stage: "active" as EvolutionStage, }; state.candidates.set(candidateId, updated); }, async promote(candidateId: string, _missionId: string): Promise { const candidate = state.candidates.get(candidateId); if (!candidate) { throw new Error(`candidate "${candidateId}" not found`); } const updated: CapabilityCandidateV1 = { ...candidate, stage: "promoted" as EvolutionStage, }; state.candidates.set(candidateId, updated); }, async rollback(componentId: string): Promise { for (const [cid, candidate] of state.candidates) { if (candidate.componentId === componentId && candidate.stage === "active") { const updated: CapabilityCandidateV1 = { ...candidate, stage: "rolled-back" as EvolutionStage, }; state.candidates.set(cid, updated); return; } } throw new Error(`no active candidate found for component "${componentId}"`); }, async quarantine(candidateId: string, _reason: string): Promise { const candidate = state.candidates.get(candidateId); if (!candidate) { throw new Error(`candidate "${candidateId}" not found`); } const updated: CapabilityCandidateV1 = { ...candidate, stage: "quarantined" as EvolutionStage, }; state.candidates.set(candidateId, updated); healthMonitor.reset(candidateId); }, inspectAll(): readonly CapabilityCandidateV1[] { return [...state.candidates.values()]; }, }; }