// Shared internal types and small pure helpers used across the workflow pipeline stages (the
// model loop, the verify stage, and the report stages). Kept private to the module — none of these
// are re-exported from index.ts. Splitting them out keeps each pipeline file under the LOC limit
// while leaving a single source of truth for the resolved RunState and the loop result shape.
import { createEventEmitter } from "./emit.js";
import { DEFAULT_WORKFLOW_LIMITS, } from "./types.js";
// A no-op sink used when the caller injects none. emit is synchronous (ADR-0004 EventSink contract).
export const NO_OP_SINK = { emit: () => undefined };
// The zero-progress loop used to assemble a cancelled/failed report before the model loop ran.
export const EMPTY_LOOP = {
    accepted: undefined,
    modelCallCount: 0,
    patchRetryCount: 0,
    lastRejectionCode: undefined,
};
export function resolveLimits(input) {
    return { ...DEFAULT_WORKFLOW_LIMITS, ...input.limits };
}
export function buildRunState(input, deps, fingerprint) {
    const now = deps.now ?? Date.now;
    const idSource = deps.idSource ?? (() => crypto.randomUUID());
    return {
        input,
        deps,
        limits: resolveLimits(input),
        signal: deps.signal ?? new AbortController().signal,
        now,
        emitter: createEventEmitter(deps.sink ?? NO_OP_SINK, idSource(), fingerprint, now),
        startedAt: now(),
        progress: { modelCallCount: 0, patchRetryCount: 0 },
    };
}
// UI-renderable next actions for the report. Pure.
export function nextActionsFor(applied, files) {
    const first = files[0] ?? "the generated test file";
    if (applied) {
        return [`Review the generated tests in ${first}`, "Run `keiko verify` to confirm they pass"];
    }
    return [
        `Review the proposed tests for ${first}`,
        "Re-run with --apply to write the tests and verify",
    ];
}
