/* RFC-1031: thin kernel command handlers for evolution.candidate.* commands. Each handler delegates to the evolution controller and wraps the result in KernelCommandResult. Records bordbuch candidate events on state transitions. Does not implement evolution logic — all logic lives in controller.ts. Does not register commands — registration lives in evolution.module.ts. RFC-1031: initial implementation — 9 evolution command handlers. RFC-1249: wire werkstatt.commands.validate into packages.check + retire CMD-OUTPUT debt */ import type { KernelCommandInput, KernelCommandResult, KernelRuntimeContext, } from "@warpgogol/werkstatt-shared/kernel"; import { createEvolutionController, type EvolutionControllerV1 } from "./controller.ts"; import type { CapabilityCandidateV1, CandidateEvidenceV1 } from "./contracts.ts"; import { appendBordbuchEntry } from "../bordbuch/bordbuch-io.ts"; import { byteHash } from "@warpgogol/werkstatt-shared/fingerprint"; import { applyOverlay, removeOverlay } from "../runtime/overlay-store.ts"; import { failResult } from "@warpgogol/werkstatt-shared/checks/result-helpers"; let controller: EvolutionControllerV1 | null = null; function getController(): EvolutionControllerV1 { if (!controller) { controller = createEvolutionController(); } return controller; } function flagString(input: KernelCommandInput, name: string): string { const v = input.flags[name]; return typeof v === "string" ? v : ""; } function flagBool(input: KernelCommandInput, name: string): boolean { return input.flags[name] === true; } function flagNumber(input: KernelCommandInput, name: string): number { const v = input.flags[name]; return typeof v === "string" ? parseInt(v, 10) : 0; } const ZERO_HASH = `sha256:${"0".repeat(64)}` as never; function emptySnapshot() { return { schema: "werkstatt/inspection-snapshot@1" as const, currentArtifactHash: ZERO_HASH, observedMetrics: [], activeIncidents: [], snapshotHash: ZERO_HASH, }; } function makeIntent(intentId: string, description: string, scope: string) { return { schema: "werkstatt/bounded-intent@1" as const, intentId, description, scope, constraints: [], intentHash: byteHash(intentId) as never, }; } function recordBordbuchCandidateEvent( context: KernelRuntimeContext, candidateId: string, stage: string, artifactHash: string, ): Promise { const systemId = context.site?.name ?? "default"; return appendBordbuchEntry( context.workspaceRoot, systemId, "candidate", `Candidate ${candidateId} transitioned to ${stage}`, "agent", { writerRole: "evolution", metadata: { candidateId, state: stage, artifactHash, }, }, ) .then(() => undefined) .catch((err) => { context.logger.warn(`[evolution] Bordbuch candidate event failed: ${(err as Error).message}`); }); } export async function runCandidateDefine( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const componentId = flagString(input, "component-id"); const version = flagString(input, "version"); const artifact = flagString(input, "artifact"); const allowAgentWritten = flagBool(input, "allow-agent-written"); if (!componentId || !version || !artifact) { return { ...failResult("evolution.commands", [ "EVOLUTION-CMD-01: --component-id, --version, and --artifact are required", ]), data: { candidateId: "", stage: "" }, }; } const intent = makeIntent( `define-${componentId}`, `Define candidate for ${componentId}`, allowAgentWritten ? "agent-authored" : "human-authored", ); const artifactHash = `sha256:${artifact.padEnd(64, "0").slice(0, 64)}` as never; const parentHash = `sha256:${"0".repeat(64)}` as never; const policyHash = `sha256:${"0".repeat(64)}` as never; const result = ctl.defineCandidate( emptySnapshot(), intent, artifactHash, parentHash, policyHash, componentId, version, "", allowAgentWritten, ); if (!result.ok) { return { ...failResult("evolution.commands", [`${result.ruleId}: ${result.message}`]), data: { candidateId: "", stage: "" }, }; } await recordBordbuchCandidateEvent( context, result.candidate.candidateId, result.candidate.stage, result.candidate.artifactHash, ); return { data: { candidateId: result.candidate.candidateId, stage: result.candidate.stage }, exitCode: 0, summary: `[evolution.commands] Candidate ${result.candidate.candidateId} defined in stage ${result.candidate.stage}`, }; } export async function runCandidateShadow( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const candidateId = flagString(input, "candidate-id"); const metric = flagString(input, "metric") || "latency"; if (!candidateId) { return { ...failResult("evolution.commands", ["EVOLUTION-CMD-02: --candidate-id is required"]), data: { evidence: null }, }; } try { const evidence = await ctl.shadow(candidateId, metric); const candidate = ctl.getCandidate(candidateId); await recordBordbuchCandidateEvent( context, candidateId, "shadowing", candidate?.artifactHash ?? "", ); return { data: { evidence }, exitCode: 0, summary: `[evolution.commands] Shadow execution completed for candidate ${candidateId}`, }; } catch (err) { return { ...failResult("evolution.commands", [`Shadow execution failed: ${(err as Error).message}`]), data: { evidence: null }, }; } } export async function runCandidateTest( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const candidateId = flagString(input, "candidate-id"); const scenarios = flagString(input, "scenarios") || "src/evolution/fixtures"; if (!candidateId) { return { ...failResult("evolution.commands", ["EVOLUTION-CMD-03: --candidate-id is required"]), data: { evidenceCount: 0 }, }; } try { const evidence = await ctl.test(candidateId, scenarios); const candidate = ctl.getCandidate(candidateId); await recordBordbuchCandidateEvent( context, candidateId, "testing", candidate?.artifactHash ?? "", ); return { data: { evidenceCount: evidence.length }, exitCode: 0, summary: `[evolution.commands] Test execution completed for candidate ${candidateId} (${evidence.length} scenarios)`, }; } catch (err) { return { ...failResult("evolution.commands", [`Test execution failed: ${(err as Error).message}`]), data: { evidenceCount: 0 }, }; } } export async function runCandidateCanary( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const candidateId = flagString(input, "candidate-id"); const trafficPercent = flagNumber(input, "traffic-percent") || 10; if (!candidateId) { return { ...failResult("evolution.commands", ["EVOLUTION-CMD-04: --candidate-id is required"]), data: { trafficPercent: 0 }, }; } try { await ctl.canary(candidateId, trafficPercent); const candidate = ctl.getCandidate(candidateId); await recordBordbuchCandidateEvent( context, candidateId, "canary", candidate?.artifactHash ?? "", ); return { data: { trafficPercent }, exitCode: 0, summary: `[evolution.commands] Canary routing at ${trafficPercent}% for candidate ${candidateId}`, }; } catch (err) { return { ...failResult("evolution.commands", [`Canary activation failed: ${(err as Error).message}`]), data: { trafficPercent: 0 }, }; } } export async function runCandidateActivate( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const candidateId = flagString(input, "candidate-id"); if (!candidateId) { return { ...failResult("evolution.commands", ["EVOLUTION-CMD-05: --candidate-id is required"]), data: { candidateId: "", stage: "" }, }; } try { await ctl.activate(candidateId); const candidate = ctl.getCandidate(candidateId); applyOverlay({ id: `evolution-${candidateId}`, scope: "per-workshop", context: { scope: "per-workshop" }, addOrReplace: new Map(), remove: [], priority: 200, }); await recordBordbuchCandidateEvent( context, candidateId, "active", candidate?.artifactHash ?? "", ); return { data: { candidateId, stage: "active" }, exitCode: 0, summary: `[evolution.commands] Candidate ${candidateId} activated`, }; } catch (err) { return { ...failResult("evolution.commands", [`Activation failed: ${(err as Error).message}`]), data: { candidateId, stage: "" }, }; } } export async function runCandidatePromote( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const candidateId = flagString(input, "candidate-id"); const missionId = flagString(input, "mission-id"); if (!candidateId || !missionId) { return { ...failResult("evolution.commands", [ "EVOLUTION-CMD-06: --candidate-id and --mission-id are required", ]), data: { missionId: "", stage: "" }, }; } try { await ctl.promote(candidateId, missionId); const candidate = ctl.getCandidate(candidateId); await recordBordbuchCandidateEvent( context, candidateId, "promoted", candidate?.artifactHash ?? "", ); return { data: { missionId, stage: "promoted" }, exitCode: 0, summary: `[evolution.commands] Candidate ${candidateId} promoted via mission ${missionId}`, }; } catch (err) { return { ...failResult("evolution.commands", [`Promotion failed: ${(err as Error).message}`]), data: { missionId, stage: "" }, }; } } export async function runCandidateRollback( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const componentId = flagString(input, "component-id"); if (!componentId) { return { ...failResult("evolution.commands", ["EVOLUTION-CMD-07: --component-id is required"]), data: { componentId: "", stage: "" }, }; } try { await ctl.rollback(componentId); removeOverlay(`evolution-${componentId}`); await recordBordbuchCandidateEvent(context, componentId, "rolled-back", ""); return { data: { componentId, stage: "rolled-back" }, exitCode: 0, summary: `[evolution.commands] Component ${componentId} rolled back`, }; } catch (err) { return { ...failResult("evolution.commands", [`Rollback failed: ${(err as Error).message}`]), data: { componentId, stage: "" }, }; } } export async function runCandidateQuarantine( input: KernelCommandInput, context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const candidateId = flagString(input, "candidate-id"); const reason = flagString(input, "reason") || "unspecified"; if (!candidateId) { return { ...failResult("evolution.commands", ["EVOLUTION-CMD-08: --candidate-id is required"]), data: { candidateId: "", stage: "", reason: "" }, }; } try { await ctl.quarantine(candidateId, reason); const candidate = ctl.getCandidate(candidateId); await recordBordbuchCandidateEvent( context, candidateId, "quarantined", candidate?.artifactHash ?? "", ); return { data: { candidateId, stage: "quarantined", reason }, exitCode: 0, summary: `[evolution.commands] Candidate ${candidateId} quarantined: ${reason}`, }; } catch (err) { return { ...failResult("evolution.commands", [`Quarantine failed: ${(err as Error).message}`]), data: { candidateId, stage: "", reason }, }; } } export async function runCandidateInspect( _input: KernelCommandInput, _context: KernelRuntimeContext, ): Promise> { const ctl = getController(); const candidates = ctl.inspectAll(); return { data: { candidates }, exitCode: 0, summary: `[evolution.commands] ${candidates.length} candidate(s) registered`, }; }