/******************************************************************************* Implements a logging utility for kernel events with customizable output formats. Do not manage log persistence beyond in-memory storage. Do not handle raw content parsing or external configuration management. Log output format is selectable — text for humans, JSON for machine consumers. RFC-1097: step 6 — compass.migrate codemod run Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order. 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 { KernelLogEvent, KernelLogLevel, KernelLogger, KernelOutputFormat, } from "@warpgogol/werkstatt-shared/kernel"; function formatPrettyLine(level: KernelLogLevel, message: string): string { if (level === "section") { return `\n== ${message} ==`; } const prefix = { info: "[INFO]", warn: "[WARN]", error: "[ERROR]", success: "[OK]", section: "==", } satisfies Record; return `${prefix[level]} ${message}`; } export function createKernelLogger(outputFormat: KernelOutputFormat = "pretty"): KernelLogger { const events: KernelLogEvent[] = []; const dedupeCounts = new Map(); const write = (level: KernelLogLevel, message: string, details?: unknown) => { const event: KernelLogEvent = { level, message, details, timestamp: new Date().toISOString(), }; events.push(event); if (outputFormat === "json") { return; } const line = formatPrettyLine(level, message); if (level === "error") { console.error(line); if (details !== undefined) { console.error(details); } return; } if (level === "warn") { console.warn(line); if (details !== undefined) { console.warn(details); } return; } console.log(line); if (details !== undefined) { console.log(details); } }; const writeEvent = ( event: Omit & { level?: KernelLogLevel }, ) => { const key = event.dedupeKey ?? `${event.kind ?? event.level ?? "info"}:${event.message}`; const count = (dedupeCounts.get(key) ?? 0) + 1; dedupeCounts.set(key, count); const level = event.level ?? (event.severity === "error" ? "error" : event.severity === "warning" ? "warn" : "info"); const fullEvent: KernelLogEvent = { ...event, level, count, timestamp: new Date().toISOString(), }; events.push(fullEvent); if (outputFormat === "json" || event.severity === "debug") return; if (event.kind === "expected-fallback" && count > 1) return; const rendered = event.kind === "expected-fallback" ? `${event.message}${count > 1 ? ` (${count} occurrence(s))` : ""}` : event.message; const line = formatPrettyLine(level, rendered); if (level === "error") { console.error(line); if (event.details !== undefined) console.error(event.details); return; } if (level === "warn") { console.warn(line); if (event.details !== undefined) console.warn(event.details); return; } console.log(line); if (event.details !== undefined) console.log(event.details); }; return { section: (message, details) => write("section", message, details), info: (message, details) => write("info", message, details), warn: (message, details) => write("warn", message, details), error: (message, details) => write("error", message, details), success: (message, details) => write("success", message, details), event: (event) => writeEvent(event), getEvents: () => [...events], }; }