/** Spec origin — exposed as part of `peaks loop spec` output. */ export type SpecOrigin = { kind: 'project'; path: string; } | { kind: 'global'; path: string; } | { kind: 'missing'; }; export interface SpecEvaluatorEntry { readonly kind: string; readonly gate?: string; readonly scope?: string; } export interface SpecSlaEntry { readonly evaluator: string; readonly maxScore: number; } export type SpecTerminationStrategy = 'max-cycles' | 'monotonic-violation' | 'manual'; /** Default termination strategy — wired by `peaks loop run` so a * spec.yaml produced by `loop spec bootstrap` actually drives the * loop driver. Previously the string was declared-and-validated but * never consumed (P0 in dogfood audit). */ export declare const MONOTONIC_TERMINATION: SpecTerminationStrategy; /** Default max-cycles value (used when the strategy is `max-cycles` * and the spec doesn't pin a value). Mirrors the slice dispatch * prompt's `termination.maxCycles` default. */ export declare const DEFAULT_MAX_CYCLES = 5; export interface SpecTermination { readonly strategy: SpecTerminationStrategy; readonly maxCycles?: number; } export interface LoopSpec { readonly schemaVersion: 1; readonly rid: string; readonly evaluators: readonly SpecEvaluatorEntry[]; readonly sla: readonly SpecSlaEntry[]; readonly termination: SpecTermination; } export interface SpecLintReport { readonly ok: boolean; readonly errors: readonly string[]; readonly warnings: readonly string[]; readonly normalizedSpec?: LoopSpec; } /** Resolve a `LoopSpec` from the project-level origin. Returns * `{kind:'missing'}` when no file exists. The CLI layer then chooses * to bootstrap a fresh spec or fail. */ export declare function resolveLoopSpec(projectRoot: string, sid: string, rid: string): { origin: SpecOrigin; spec: LoopSpec | null; }; export declare function buildSpec(input: Partial, expectedRid: string): LoopSpec; /** Lint a LoopSpec — returns a report with semantic errors / warnings. * * Refactored 2026-08-07 (PRD-002b slice 3 commit A — extract-method): * the original function had complexity 14. Each validation phase now lives * in its own helper, dropping the orchestrator to complexity ~5. * Behavior is byte-for-byte preserved: same error/warning strings, same * ordering, same return shape. */ export declare function lintLoopSpec(spec: LoopSpec): SpecLintReport; /** Serialize a LoopSpec to a stable YAML representation. Pure. */ export declare function serializeSpec(spec: LoopSpec): string; /** Persist a LoopSpec to disk at the project-level path; ensures the * parent directory exists. Returns the resolved path. */ export declare function persistSpec(projectRoot: string, sid: string, spec: LoopSpec): string; /** Lint a spec file from an explicit path — used by `peaks loop spec * lint `. Returns the lint report plus the parsed spec. */ export declare function lintSpecFile(filePath: string, expectedRid?: string): { raw: string; spec: LoopSpec | null; report: SpecLintReport; }; /** * Tiny subset of YAML: indented objects + nested arrays of inline objects. * Mirrors the workflow yaml parser's shape, with two extensions: * - tolerates inline `{ key: value, key: value }` objects (used for * evaluator entries and termination.strategy/maxCycles), and * - accepts `- kind: foo, gate: bar, scope: baz` (inline objects on * array items). * * Karpathy §2: hand-rolled to avoid a new dep, same approach as * `src/services/workflow/workflow-spec.ts`. */ export declare function parseSpecYaml(raw: string, expectedRid: string): LoopSpec; export declare function specPath(projectRoot: string, sid: string, rid: string): string; /** Force a path to be inside the project root — guards against the * `peaks loop spec lint ` flag accepting arbitrary paths. The * caller decides whether the resulting abs path is in-bounds. */ export declare function pathIsInside(child: string, parent: string): boolean;