/*
Provides lightweight structured pipeline log events for build-time content helpers.
- Do not persist logs outside the current Node.js process.
- Do not silence actionable warnings or errors.
- RFC-0254: add structured expected-fallback log transport for build/check paths.
*/
export type PipelineLogSeverity = "debug" | "info" | "notice" | "warning" | "error";
export type PipelineLogKind =
"progress" | "expected-fallback" | "advisory" | "external-tool" | "diagnostic" | "error";
export interface PipelineLogEvent {
severity: PipelineLogSeverity;
kind: PipelineLogKind;
message: string;
command?: string;
pipeline?: string;
app?: string;
packageName?: string;
module?: string;
file?: string;
line?: number;
ruleId?: string;
dedupeKey?: string;
count?: number;
data?: Record;
}
interface PipelineLogState {
events: PipelineLogEvent[];
counts: Map;
}
const STATE_KEY = "__gogolPipelineLogState";
function getState(): PipelineLogState {
const root = globalThis as typeof globalThis & { __gogolPipelineLogState?: PipelineLogState };
if (!root[STATE_KEY]) {
root[STATE_KEY] = { events: [], counts: new Map() };
}
return root[STATE_KEY];
}
function renderEvent(event: PipelineLogEvent, count: number): string {
const prefix = event.kind === "expected-fallback" ? "fallback" : event.kind;
const suffix = count > 1 ? ` (${count} occurrence(s))` : "";
return `[${event.severity}:${prefix}] ${event.message}${suffix}`;
}
export function emitPipelineLogEvent(event: PipelineLogEvent): void {
const state = getState();
const key = event.dedupeKey ?? `${event.kind}:${event.severity}:${event.message}`;
const count = (state.counts.get(key) ?? 0) + 1;
state.counts.set(key, count);
state.events.push({ ...event, count });
if (event.severity === "debug") return;
if (event.kind === "expected-fallback" && count > 1) return;
const rendered = renderEvent(event, count);
if (event.severity === "error") {
console.error(rendered);
return;
}
if (event.severity === "warning") {
console.warn(rendered);
return;
}
console.log(rendered);
}
export function getPipelineLogEvents(): PipelineLogEvent[] {
return getState().events.map((event) => ({ ...event }));
}